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>
This commit is contained in:
attackerandClaude committed 2026-06-27 09:55:17 +08:00
1 parent f2069fe3f0
commit 92a2247390
37 files changed
+6449 -6

No files matched your search

+109
View File
@@ -0,0 +1,109 @@
// Package agentcli 是 Agent CLI 引擎的顶层入口。 // Logan.Li
// 组装 llm 客户端 + 工具注册中心(含 ssh_execute)+ 安全控制器 + Evolver + ReAct 核心,
// 对外暴露 Engine,由 controller 通过依赖注入(EventCallback / ConfirmFn / SSH 凭据)驱动。
//
// 设计原则(参考 opsxcli,适配为 aiops 后端库):
// - 零业务依赖:不 import model/controller,所有持久化与 WS 由 controller 层负责。
// - 复用 aiops 既有能力:LLM 走 OpenAI 兼容(model.LLMConfig),SSH 走 pkg/remoteexec。
// - 安全:危险命令黑名单硬拒,高危命令经 ConfirmFn 由前端确认。
// - 自进化:Evolver 异步学习经验并注入下次 Prompt,失败优雅降级。
package agentcli
import (
"context"
"ezops/pkg/agentcli/core"
"ezops/pkg/agentcli/evolver"
"ezops/pkg/agentcli/llm"
"ezops/pkg/agentcli/safety"
"ezops/pkg/agentcli/tools"
"ezops/pkg/remoteexec"
)
// EngineConfig 引擎配置(由 controller 从 model.LLMConfig + model.Server 构建后注入) // Logan.Li
type EngineConfig struct {
LLM llm.Config // LLM 客户端配置(endpoint 已解析)
SSH remoteexec.SSHConfig // 目标主机 SSH 配置(含凭据)
SafetyMode safety.Mode // 安全模式(默认 balanced)
Core *core.Config // ReAct 配置(nil 用默认)
MemoryDir string // Evolver 记忆目录(空则 data/agentcli)
}
// Engine Agent CLI 引擎实例(每个 WebSocket 连接 / 任务一个) // Logan.Li
type Engine struct {
agent *core.Agent
safety *safety.Controller
tools *tools.Registry
evolver *evolver.EvolverEngine
}
// NewEngine 组装引擎并注册默认工具集 // Logan.Li
func NewEngine(cfg EngineConfig) (*Engine, error) {
coreCfg := cfg.Core
if coreCfg == nil {
coreCfg = core.DefaultConfig()
}
if cfg.MemoryDir != "" {
coreCfg.MemoryDir = cfg.MemoryDir
}
mode := cfg.SafetyMode
if mode == "" {
mode = safety.ModeBalanced
}
// LLM 客户端
client := llm.NewClient(cfg.LLM)
// 工具注册中心:ssh_execute(注入目标主机凭据)+ analyze_output
registry := tools.NewRegistry()
registry.Register(tools.NewSSHExecuteTool(cfg.SSH, coreCfg.ToolTimeout))
registry.Register(tools.NewAnalyzeOutputTool())
// 安全控制器
sc := safety.NewController(mode)
// Evolver(LLM 可用时启用学习;失败降级)
ev, err := evolver.NewEvolverEngine(coreCfg.MemoryDir, client)
if err != nil {
ev = nil // 降级:无自学习,不影响主流程
}
agent := core.NewAgent(client, registry, coreCfg, sc, ev)
return &Engine{agent: agent, safety: sc, tools: registry, evolver: ev}, nil
}
// SetCallback 注入事件回调(驱动前端渲染 + DB 持久化) // Logan.Li
func (e *Engine) SetCallback(cb core.EventCallback) { e.agent.SetCallback(cb) }
// SetConfirmFn 注入高危确认回调(controller 推 WS confirm 事件并阻塞等前端回传) // Logan.Li
func (e *Engine) SetConfirmFn(fn safety.ConfirmFn) { e.safety.SetConfirmFn(fn) }
// SetAutoApprove 测试用:自动批准(生产禁用) // Logan.Li
func (e *Engine) SetAutoApprove(b bool) { e.safety.SetAutoApprove(b) }
// Run 执行任务(ReAct 循环),serverInfo 为目标主机摘要(注入 system prompt) // Logan.Li
func (e *Engine) Run(ctx context.Context, query, serverInfo string) (string, error) {
res, err := e.agent.Run(ctx, query, serverInfo)
if err != nil {
return "", err
}
if res != nil {
return res.Output, nil
}
return "", nil
}
// EvolveStats 进化统计(供审计展示) // Logan.Li
func (e *Engine) EvolveStats() map[string]interface{} {
if e.evolver == nil {
return map[string]interface{}{"enabled": false}
}
return e.evolver.GetStats()
}
// Close 释放资源 // Logan.Li
func (e *Engine) Close() {
if e.agent != nil {
e.agent.Close()
}
}