后端引擎 backend/pkg/agentcli/(纯引擎库,零业务依赖,剥离 CLI/TUI 外壳): - llm: OpenAI 兼容客户端,复用 model.LLMConfig - tools: ssh_execute(复用 pkg/remoteexec)+ analyze_output + 风险评估黑名单 - safety: 三级安全模式 + 五级风险 + WebSocket 异步确认 - prompt: 五层 System Prompt - core: ReAct 16 轮循环 + 自适应检查点 + 循环检测 - evolver: 四层记忆 + 进化循环,data/agentcli/ 文件存储 集成层: - controller/agent_cli.go: WebSocket 控制器(事件流推流 + 高危确认 + 会话持久化) - model/agent_cli.go: agent_cli_sessions/messages 表 + AutoMigrate - 路由 /ws/agent-cli + /api/v1/aiops/agent-cli/sessions - seed 权限 aiops:agent-cli / aiops:llm-config 前端: - AgentCLI.tsx: 对话流 + 工具块 + 高危确认 + 四模块 tips 面板 - LLMConfig.tsx: 大模型设置独立页 - api/agentCli.ts + Sidebar/App 菜单路由 文档: - docs/agent/ 11 篇(opsxcli 同名文档适配改写 + 00-README 映射总览) 其他: - CLAUDE.md 补充 agent-cli 模块说明 - 修正 .gitignore 根级二进制规则(前导 /,避免误伤 frontend/src/components/aiops/) Co-Authored-By: Claude <noreply@anthropic.com>
107 lines
3.3 KiB
Go
107 lines
3.3 KiB
Go
// builtin.go - 内置只读工具 // Logan.Li
|
||
// analyze_output:对冗长命令输出做摘要/错误提取,避免 token 爆炸,辅助 LLM 聚焦关键线索。
|
||
package tools
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"strings"
|
||
)
|
||
|
||
// AnalyzeOutputTool 输出分析工具(只读,Safe) // Logan.Li
|
||
type AnalyzeOutputTool struct{}
|
||
|
||
// NewAnalyzeOutputTool 创建输出分析工具 // Logan.Li
|
||
func NewAnalyzeOutputTool() *AnalyzeOutputTool { return &AnalyzeOutputTool{} }
|
||
|
||
// Name 工具名 // Logan.Li
|
||
func (t *AnalyzeOutputTool) Name() string { return "analyze_output" }
|
||
|
||
// Description 给 LLM 的说明 // Logan.Li
|
||
func (t *AnalyzeOutputTool) Description() string {
|
||
return "分析一段(可能很长的)命令输出文本:统计行数、提取疑似错误/告警行、必要时截断保留首尾。" +
|
||
"当 ssh_execute 返回内容过长时调用此工具提炼关键信息再继续推理。"
|
||
}
|
||
|
||
// Parameters 参数定义 // Logan.Li
|
||
func (t *AnalyzeOutputTool) Parameters() map[string]interface{} {
|
||
return map[string]interface{}{
|
||
"type": "object",
|
||
"properties": map[string]interface{}{
|
||
"output": map[string]interface{}{
|
||
"type": "string",
|
||
"description": "待分析的文本输出",
|
||
},
|
||
"focus": map[string]interface{}{
|
||
"type": "string",
|
||
"description": "可选关注点,如 error、memory、disk",
|
||
},
|
||
},
|
||
"required": []string{"output"},
|
||
}
|
||
}
|
||
|
||
// RiskLevel 静态风险(只读安全) // Logan.Li
|
||
func (t *AnalyzeOutputTool) RiskLevel() RiskLevel { return RiskSafe }
|
||
|
||
// Execute 执行输出分析 // Logan.Li
|
||
func (t *AnalyzeOutputTool) Execute(ctx context.Context, args map[string]interface{}) (*Result, error) {
|
||
output := StringParam(args, "output")
|
||
focus := strings.ToLower(StringParam(args, "focus"))
|
||
if output == "" {
|
||
return &Result{Success: true, Output: "(空输出)"}, nil
|
||
}
|
||
|
||
lines := strings.Split(output, "\n")
|
||
total := len(lines)
|
||
|
||
// 超长截断:保留前 40 + 后 40 行,中间用省略标注
|
||
truncated := false
|
||
if total > 120 {
|
||
head := lines[:40]
|
||
tail := lines[total-40:]
|
||
lines = append(append(head, fmt.Sprintf("... [已省略 %d 行] ...", total-80)), tail...)
|
||
truncated = true
|
||
}
|
||
|
||
// 提取疑似错误/告警行
|
||
errorKeywords := []string{"error", "fail", "exception", "traceback", "denied",
|
||
"permission", "timeout", "refused", "unavailable", "critical", "fatal",
|
||
"错误", "失败", "拒绝", "超时", "无法", "异常"}
|
||
if focus != "" {
|
||
errorKeywords = append([]string{focus}, errorKeywords...)
|
||
}
|
||
var errorLines []string
|
||
for _, line := range lines {
|
||
low := strings.ToLower(line)
|
||
for _, kw := range errorKeywords {
|
||
if strings.Contains(low, kw) {
|
||
errorLines = append(errorLines, strings.TrimSpace(line))
|
||
break
|
||
}
|
||
}
|
||
}
|
||
if len(errorLines) > 20 {
|
||
errorLines = errorLines[:20]
|
||
}
|
||
|
||
// 组装分析摘要
|
||
var sb strings.Builder
|
||
sb.WriteString(fmt.Sprintf("总行数: %d", total))
|
||
if truncated {
|
||
sb.WriteString("(已截断保留首尾)")
|
||
}
|
||
sb.WriteString("\n")
|
||
if len(errorLines) > 0 {
|
||
sb.WriteString(fmt.Sprintf("疑似错误/告警行 (%d):\n", len(errorLines)))
|
||
for _, l := range errorLines {
|
||
sb.WriteString(" " + l + "\n")
|
||
}
|
||
} else {
|
||
sb.WriteString("未发现明显错误关键词\n")
|
||
}
|
||
sb.WriteString("\n输出片段:\n" + strings.Join(lines, "\n"))
|
||
|
||
return &Result{Success: true, Output: sb.String()}, nil
|
||
}
|