Files
aiops/backend/pkg/agentcli/tools/registry.go
T
attackerandClaude 92a2247390 feat: 新增 Agent CLI — Web 版 AI 运维 Agent(参考 opsxcli 移植)
后端引擎 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>
2026-06-27 09:55:17 +08:00

170 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package tools 提供 Agent CLI 引擎的工具注册中心与工具接口。 // Logan.Li
// 设计参考 opsxcli/internal/agent/tools,剥离 CLI 专属工具(local_bash 本地执行、scp)。
// Web 版聚焦远程运维:ssh_execute(目标主机执行)+ analyze_output(输出分析)。
// 风险评估逻辑(黑名单 + AssessBashRisk)置于本包,避免与 safety 包形成循环依赖。
package tools
import (
"context"
"fmt"
"sync"
"ezops/pkg/agentcli/llm"
)
// RiskLevel 工具风险等级 // Logan.Li
type RiskLevel int
const (
RiskSafe RiskLevel = iota // 只读操作(cat/grep/df/ps)
RiskLow // 低风险(mkdir/touch)
RiskMedium // 中风险(chmod/文件修改)
RiskHigh // 高风险(远程服务控制/reboot)
RiskCritical // 危险操作(rm -rf //mkfs/dd)
)
// String 返回风险等级字符串 // Logan.Li
func (r RiskLevel) String() string {
switch r {
case RiskSafe:
return "safe"
case RiskLow:
return "low"
case RiskMedium:
return "medium"
case RiskHigh:
return "high"
case RiskCritical:
return "critical"
default:
return "unknown"
}
}
// Display 返回风险等级中文显示 // Logan.Li
func (r RiskLevel) Display() string {
switch r {
case RiskSafe:
return "安全"
case RiskLow:
return "低风险"
case RiskMedium:
return "中风险"
case RiskHigh:
return "高风险"
case RiskCritical:
return "危险"
default:
return "未知"
}
}
// Result 工具执行结果 // Logan.Li
type Result struct {
Success bool `json:"success"`
Output string `json:"output"`
Error string `json:"error,omitempty"`
}
// Tool 核心工具接口(5 方法) // Logan.Li
type Tool interface {
Name() string // 工具名
Description() string // 给 LLM 看的描述
Parameters() map[string]interface{} // JSON Schema 参数定义
RiskLevel() RiskLevel // 静态风险等级
Execute(ctx context.Context, args map[string]interface{}) (*Result, error)
}
// DynamicRiskTool 动态风险评估接口 // Logan.Li
// 工具可额外实现此接口,依据运行时参数动态计算风险(如 ssh_execute 看具体命令)。
// 安全控制器 Check 时优先调用此接口。
type DynamicRiskTool interface {
Tool
RiskLevelForArgs(args map[string]interface{}) RiskLevel
}
// Registry 工具注册中心(线程安全) // Logan.Li
type Registry struct {
tools map[string]Tool
mu sync.RWMutex
}
// NewRegistry 创建空注册中心 // Logan.Li
func NewRegistry() *Registry {
return &Registry{tools: make(map[string]Tool)}
}
// Register 注册工具 // Logan.Li
func (r *Registry) Register(tool Tool) {
r.mu.Lock()
defer r.mu.Unlock()
r.tools[tool.Name()] = tool
}
// Get 按名获取工具 // Logan.Li
func (r *Registry) Get(name string) (Tool, error) {
r.mu.RLock()
defer r.mu.RUnlock()
t, ok := r.tools[name]
if !ok {
return nil, fmt.Errorf("工具未找到: %s", name)
}
return t, nil
}
// List 列出所有工具 // Logan.Li
func (r *Registry) List() []Tool {
r.mu.RLock()
defer r.mu.RUnlock()
list := make([]Tool, 0, len(r.tools))
for _, t := range r.tools {
list = append(list, t)
}
return list
}
// ToLLMTools 转换为 LLM function calling 格式 // Logan.Li
func (r *Registry) ToLLMTools() []llm.Tool {
r.mu.RLock()
defer r.mu.RUnlock()
out := make([]llm.Tool, 0, len(r.tools))
for _, t := range r.tools {
out = append(out, llm.Tool{
Type: "function",
Function: llm.ToolFunction{
Name: t.Name(),
Description: t.Description(),
Parameters: t.Parameters(),
},
})
}
return out
}
// ---- 参数解析辅助 ---- // Logan.Li
// StringParam 取字符串参数 // Logan.Li
func StringParam(args map[string]interface{}, key string) string {
if v, ok := args[key]; ok {
if s, ok := v.(string); ok {
return s
}
}
return ""
}
// IntParam 取整型参数(兼容 int/float64/int64) // Logan.Li
func IntParam(args map[string]interface{}, key string) int {
if v, ok := args[key]; ok {
switch val := v.(type) {
case int:
return val
case float64:
return int(val)
case int64:
return int(val)
}
}
return 0
}