// 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 }