Files
X-Agents/server/internal/handler/agent_handler.go
DESKTOP-72TV0V4\caoxiaozhu 5dc2e403e9 feat: 更新后端服务
- agent_handler.go: 新增agent管理接口
- agent_service.go: 扩展agent服务逻辑
- skill_handler.go: 更新skill接口
- chat_service.go: 更新chat服务
- model相关: 新增model仓库和服务
- main.go: 更新路由配置

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:18:46 +08:00

346 lines
9.6 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 handler
import (
"net/http"
"x-agents/server/internal/service"
"github.com/gin-gonic/gin"
)
// AgentHandler Agent 处理器
type AgentHandler struct {
agentService *service.AgentService
}
// NewAgentHandler 创建 Agent 处理器
func NewAgentHandler(agentService *service.AgentService) *AgentHandler {
return &AgentHandler{
agentService: agentService,
}
}
// ChatRequest 对话请求
type ChatRequest struct {
AgentID int `json:"agent_id" binding:"required"`
Message string `json:"message" binding:"required"`
SessionID string `json:"session_id"`
ModelID string `json:"model_id"`
UseXBot bool `json:"use_xbot"`
}
// ChatResponse 对话响应
type ChatResponse struct {
AgentID int `json:"agent_id"`
Reply string `json:"reply"`
ToolsUsed []string `json:"tools_used"`
SessionID string `json:"session_id"`
TokensUsed int `json:"tokens_used"`
DurationMs int `json:"duration_ms"`
Metadata interface{} `json:"metadata"`
}
// CreateAgentResponse 创建智能体响应
type CreateAgentResponse struct {
AgentID int `json:"agent_id"`
Name string `json:"name"`
Message string `json:"message"`
}
// ListAgentsResponse 获取智能体列表响应
type ListAgentsResponse struct {
Agents []interface{} `json:"agents"`
}
// Chat 单智能体对话
// @Summary 单智能体对话
// @Tags 智能体管理
// @Accept json
// @Produce json
// @Param request body ChatRequest true "对话请求"
// @Success 200 {object} ChatResponse
// @Router /api/agent/chat [post]
func (h *AgentHandler) Chat(c *gin.Context) {
var req ChatRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 获取用户 ID从认证中间件获取
userID := 1 // TODO: 从 c.Get("user_id") 获取
pythonReq := service.AgentChatRequest{
AgentID: req.AgentID,
Message: req.Message,
UserID: userID,
SessionID: req.SessionID,
ModelID: req.ModelID,
UseXBot: req.UseXBot,
}
result, err := h.agentService.Chat(pythonReq)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// 转换工具调用
toolsUsed := make([]string, 0)
for _, tool := range result.ToolCalls {
if toolMap, ok := tool.(map[string]interface{}); ok {
if skillID, ok := toolMap["skill_id"].(string); ok {
toolsUsed = append(toolsUsed, skillID)
}
}
}
c.JSON(http.StatusOK, ChatResponse{
AgentID: result.AgentID,
Reply: result.Response,
ToolsUsed: toolsUsed,
SessionID: result.SessionID,
TokensUsed: result.TokensUsed,
DurationMs: result.DurationMs,
Metadata: nil,
})
}
// ChatStream 单智能体对话(流式输出)
// @Summary 单智能体对话(流式输出)
// @Tags 智能体管理
// @Accept json
// @Produce text/event-stream
// @Param request body ChatRequest true "对话请求"
// @Router /api/agent/chat/stream [post]
func (h *AgentHandler) ChatStream(c *gin.Context) {
var req ChatRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 获取用户 ID
userID := 1 // TODO: 从 c.Get("user_id") 获取
// 构建 SSE 流
c.Header("Content-Type", "text/event-stream")
c.Header("Cache-Control", "no-cache")
c.Header("Connection", "keep-alive")
c.Header("Access-Control-Allow-Origin", "*")
// 调用 Python 服务的流式端点
err := h.agentService.ChatStream(c, req.AgentID, req.Message, req.SessionID, req.ModelID, userID)
if err != nil && !c.IsAborted() {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
}
}
// TeamChatRequest 多智能体群聊请求
type TeamChatRequest struct {
SupervisorAgentID int `json:"supervisor_agent_id" binding:"required"`
MemberAgentIDs []int `json:"member_agent_ids" binding:"required"`
Message string `json:"message" binding:"required"`
SessionID string `json:"session_id"`
Strategy string `json:"strategy"`
}
// TeamChatResponse 多智能体群聊响应
type TeamChatResponse struct {
SupervisorAgentID int `json:"supervisor_agent_id"`
Reply string `json:"reply"`
SubtaskResults interface{} `json:"subtask_results"`
Strategy string `json:"strategy"`
SessionID string `json:"session_id"`
DurationMs int `json:"duration_ms"`
Metadata interface{} `json:"metadata"`
}
// TeamChat 多智能体群聊
// @Summary 多智能体群聊
// @Tags 智能体管理
// @Accept json
// @Produce json
// @Param request body TeamChatRequest true "群聊请求"
// @Success 200 {object} TeamChatResponse
// @Router /api/agent/team/chat [post]
func (h *AgentHandler) TeamChat(c *gin.Context) {
var req TeamChatRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 获取用户 ID
userID := 1 // TODO: 从 c.Get("user_id") 获取
pythonReq := service.TeamChatRequest{
SupervisorAgentID: req.SupervisorAgentID,
MemberAgentIDs: req.MemberAgentIDs,
Message: req.Message,
UserID: userID,
SessionID: req.SessionID,
Strategy: req.Strategy,
}
result, err := h.agentService.TeamChat(pythonReq)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, TeamChatResponse{
SupervisorAgentID: result.SupervisorAgentID,
Reply: result.Response,
SubtaskResults: result.SubtaskResults,
Strategy: result.Strategy,
SessionID: result.SessionID,
DurationMs: result.DurationMs,
Metadata: nil,
})
}
// CreateAgent 创建智能体
// @Summary 创建智能体
// @Tags 智能体管理
// @Accept json
// @Produce json
// @Param request body CreateAgentRequest true "创建智能体请求"
// @Success 200 {object} CreateAgentResponse
// @Router /api/agent/create [post]
func (h *AgentHandler) CreateAgent(c *gin.Context) {
var req service.CreateAgentRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 获取用户 ID
userID := 1 // TODO: 从 c.Get("user_id") 获取
result, err := h.agentService.CreateAgent(req, userID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, result)
}
// ListAgents 获取智能体列表
// @Summary 获取智能体列表
// @Tags 智能体管理
// @Produce json
// @Success 200 {object} ListAgentsResponse
// @Router /api/agent/list [get]
func (h *AgentHandler) ListAgents(c *gin.Context) {
result, err := h.agentService.ListAgents()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, result)
}
// UpdateAgentStatusRequest 更新状态请求
type UpdateAgentStatusRequest struct {
IsActive bool `json:"is_active"`
}
// UpdateAgentStatus 更新智能体状态
// @Summary 更新智能体状态
// @Tags 智能体管理
// @Accept json
// @Produce json
// @Param id path string true "Agent ID"
// @Param request body UpdateAgentStatusRequest true "状态请求"
// @Success 200 {object} gin.H
// @Router /api/agent/{id}/status [put]
func (h *AgentHandler) UpdateAgentStatus(c *gin.Context) {
agentID := c.Param("id")
if agentID == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "agent id is required"})
return
}
var req UpdateAgentStatusRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
err := h.agentService.UpdateAgentStatus(agentID, req.IsActive)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "status updated successfully"})
}
// DeleteAgent 删除智能体
// @Summary 删除智能体
// @Tags 智能体管理
// @Produce json
// @Param id path string true "Agent ID"
// @Success 200 {object} gin.H
// @Router /api/agent/{id} [delete]
func (h *AgentHandler) DeleteAgent(c *gin.Context) {
agentID := c.Param("id")
if agentID == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "agent id is required"})
return
}
err := h.agentService.DeleteAgent(agentID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "agent deleted successfully"})
}
// UpdateAgentRequest 更新智能体请求
type UpdateAgentRequest struct {
Name string `json:"name"`
Description string `json:"description"`
Skills []string `json:"skills"`
RoleDescription string `json:"role_description"`
ModelProvider string `json:"model_provider"`
ModelName string `json:"model_name"`
}
// UpdateAgent 更新智能体
// @Summary 更新智能体
// @Tags 智能体管理
// @Accept json
// @Produce json
// @Param id path string true "Agent ID"
// @Param request body UpdateAgentRequest true "更新请求"
// @Success 200 {object} gin.H
// @Router /api/agent/{id} [put]
func (h *AgentHandler) UpdateAgent(c *gin.Context) {
agentID := c.Param("id")
if agentID == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "agent id is required"})
return
}
var req UpdateAgentRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
err := h.agentService.UpdateAgent(agentID, req.Name, req.Description, req.Skills, req.RoleDescription, req.ModelProvider, req.ModelName)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "agent updated successfully"})
}