feat(ai): 阶段 2 Ask|Agent 共用 aitools Runtime 真查库

- 侧栏 Ask|Agent 分段;Ask 仍走 /api/ai/chat,Agent 走 /api/ai/agent
- RunAgent 多轮 tool call → 进程内 aitools(与 MCP 同源只读/白名单/审计)
- 回复下步骤时间线;openai-chat tools(DeepSeek);agent-accept 冒烟
This commit is contained in:
logan committed 2026-10-15 11:51:39 +08:00
1 parent b8134c4503
commit cd319ce7bd
14 files changed
+1270 -182

No files matched your search

+115
View File
@@ -0,0 +1,115 @@
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
}