Files
aiops/backend/controller/agent_cli_api.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

71 lines
2.4 KiB
Go

// agent_cli_api.go - Agent CLI 会话历史 REST 接口 // Logan.Li
// 供前端展示历史任务列表与回放某次任务的完整推理过程。
package controller
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"ezops/middleware"
"ezops/model"
)
// ListSessions 会话列表(按当前用户隔离) // Logan.Li
// GET /api/v1/aiops/agent-cli/sessions?server_id=&page=&page_size=
func (h *AgentCLIHandler) ListSessions(c *gin.Context) {
uid := middleware.GetUserID(c)
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
if page < 1 {
page = 1
}
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
if pageSize <= 0 || pageSize > 100 {
pageSize = 20
}
q := h.db.Model(&model.AgentCLISession{}).Where("user_id = ?", uid)
if sid := c.Query("server_id"); sid != "" {
q = q.Where("server_id = ?", sid)
}
var total int64
q.Count(&total)
var sessions []model.AgentCLISession
if err := q.Order("created_at DESC").Offset((page - 1) * pageSize).Limit(pageSize).Find(&sessions).Error; err != nil {
c.JSON(http.StatusOK, model.Response{Code: 500, Message: "查询失败: " + err.Error()})
return
}
c.JSON(http.StatusOK, model.Response{Code: 200, Data: gin.H{"list": sessions, "total": total}})
}
// GetSession 会话详情(含完整推理消息,供回放) // Logan.Li
// GET /api/v1/aiops/agent-cli/sessions/:id
func (h *AgentCLIHandler) GetSession(c *gin.Context) {
id := c.Param("id")
var sess model.AgentCLISession
if err := h.db.First(&sess, id).Error; err != nil {
c.JSON(http.StatusOK, model.Response{Code: 404, Message: "会话不存在"})
return
}
var msgs []model.AgentCLIMessage
h.db.Where("session_id = ?", id).Order("id ASC").Find(&msgs)
c.JSON(http.StatusOK, model.Response{Code: 200, Data: gin.H{"session": sess, "messages": msgs}})
}
// DeleteSession 删除会话及其消息 // Logan.Li
// DELETE /api/v1/aiops/agent-cli/sessions/:id
func (h *AgentCLIHandler) DeleteSession(c *gin.Context) {
id := c.Param("id")
if err := h.db.Where("session_id = ?", id).Delete(&model.AgentCLIMessage{}).Error; err != nil {
c.JSON(http.StatusOK, model.Response{Code: 500, Message: "删除消息失败: " + err.Error()})
return
}
if err := h.db.Delete(&model.AgentCLISession{}, id).Error; err != nil {
c.JSON(http.StatusOK, model.Response{Code: 500, Message: "删除会话失败: " + err.Error()})
return
}
c.JSON(http.StatusOK, model.Response{Code: 200, Message: "已删除"})
}