- 侧栏 Ask|Agent 分段;Ask 仍走 /api/ai/chat,Agent 走 /api/ai/agent - RunAgent 多轮 tool call → 进程内 aitools(与 MCP 同源只读/白名单/审计) - 回复下步骤时间线;openai-chat tools(DeepSeek);agent-accept 冒烟
116 lines
3.8 KiB
Go
116 lines
3.8 KiB
Go
package aitools
|
||
|
||
// ToolSpec 工具元数据:MCP stdio 与侧栏 Agent(OpenAI tools)共用同一份契约。 // Logan.Li
|
||
type ToolSpec struct {
|
||
Name string
|
||
Description string
|
||
Properties map[string]any
|
||
Required []string
|
||
}
|
||
|
||
// ToolSpecs P0 七工具 schema(顺序与 ToolNames 一致)。
|
||
func ToolSpecs() []ToolSpec {
|
||
connID := map[string]any{"type": "string", "description": "Saved connection id from opsxdb_list_connections"}
|
||
database := map[string]any{"type": "string", "description": "Database / schema / Redis DB index"}
|
||
return []ToolSpec{
|
||
{
|
||
Name: ToolListConnections,
|
||
Description: "List whitelisted OpsxDB connections (id/name/driver/host/port/database; never passwords).",
|
||
Properties: map[string]any{},
|
||
},
|
||
{
|
||
Name: ToolListDatabases,
|
||
Description: "List databases for a connection.",
|
||
Properties: map[string]any{"connection_id": connID},
|
||
Required: []string{"connection_id"},
|
||
},
|
||
{
|
||
Name: ToolListTables,
|
||
Description: "List tables/views (or engine equivalents) in a database.",
|
||
Properties: map[string]any{"connection_id": connID, "database": database},
|
||
Required: []string{"connection_id"},
|
||
},
|
||
{
|
||
Name: ToolDescribeTable,
|
||
Description: "Describe columns and metadata for a table.",
|
||
Properties: map[string]any{
|
||
"connection_id": connID,
|
||
"database": database,
|
||
"table": map[string]any{"type": "string", "description": "Table name"},
|
||
},
|
||
Required: []string{"connection_id", "table"},
|
||
},
|
||
{
|
||
Name: ToolGetSchemaContext,
|
||
Description: "Compact schema text for LLM context (capped ~4k chars).",
|
||
Properties: map[string]any{
|
||
"connection_id": connID,
|
||
"database": database,
|
||
"max_tables": map[string]any{"type": "integer", "description": "Max tables to include (default 40)"},
|
||
},
|
||
Required: []string{"connection_id"},
|
||
},
|
||
{
|
||
Name: ToolExecuteQuery,
|
||
Description: "Execute a READ-ONLY SQL query (SELECT/SHOW/EXPLAIN/WITH…SELECT). Writes and DDL are rejected in P0. Default limit 100, max 500.",
|
||
Properties: map[string]any{
|
||
"connection_id": connID,
|
||
"sql": map[string]any{"type": "string", "description": "Read-only SQL"},
|
||
"database": database,
|
||
"limit": map[string]any{"type": "integer", "description": "Row limit (default 100, max 500)"},
|
||
},
|
||
Required: []string{"connection_id", "sql"},
|
||
},
|
||
{
|
||
Name: ToolExecuteRedisCommand,
|
||
Description: "Execute a READ-ONLY Redis command (GET/SCAN/TYPE/TTL/…). FLUSH*/KEYS and writes are rejected in P0.",
|
||
Properties: map[string]any{
|
||
"connection_id": connID,
|
||
"command": map[string]any{"type": "string", "description": "Single Redis command line"},
|
||
"database": database,
|
||
},
|
||
Required: []string{"connection_id", "command"},
|
||
},
|
||
}
|
||
}
|
||
|
||
// InputSchema 返回 JSON Schema object(MCP raw schema / OpenAI parameters)。
|
||
func (t ToolSpec) InputSchema() map[string]any {
|
||
schema := map[string]any{
|
||
"type": "object",
|
||
"properties": t.Properties,
|
||
}
|
||
if len(t.Required) > 0 {
|
||
schema["required"] = t.Required
|
||
}
|
||
if t.Properties == nil {
|
||
schema["properties"] = map[string]any{}
|
||
}
|
||
return schema
|
||
}
|
||
|
||
// OpenAITool OpenAI chat.completions tools[] 一项。
|
||
type OpenAITool struct {
|
||
Type string `json:"type"`
|
||
Function struct {
|
||
Name string `json:"name"`
|
||
Description string `json:"description"`
|
||
Parameters map[string]any `json:"parameters"`
|
||
} `json:"function"`
|
||
}
|
||
|
||
// OpenAITools 供 Agent / DeepSeek 等 openai-chat 兼容协议挂载。
|
||
func OpenAITools() []OpenAITool {
|
||
specs := ToolSpecs()
|
||
out := make([]OpenAITool, 0, len(specs))
|
||
for _, s := range specs {
|
||
var t OpenAITool
|
||
t.Type = "function"
|
||
t.Function.Name = s.Name
|
||
t.Function.Description = s.Description
|
||
t.Function.Parameters = s.InputSchema()
|
||
out = append(out, t)
|
||
}
|
||
return out
|
||
}
|