package handler import ( "errors" "net/http" "strings" "ai-agent-scaffold-go/internal/service" "ai-agent-scaffold-go/pkg/types" "github.com/gin-gonic/gin" ) // Envelope 统一响应格式 type Envelope struct { Code string `json:"code"` Info string `json:"info"` Data interface{} `json:"data,omitempty"` } // AiAgentConfigResponse Agent 配置查询响应 type AiAgentConfigResponse struct { AgentID string `json:"agentId"` AgentName string `json:"agentName"` AgentDesc string `json:"agentDesc"` } // CreateSessionRequest 创建会话请求 type CreateSessionRequest struct { AgentID string `json:"agentId"` UserID string `json:"userId"` } // CreateSessionResponse 创建会话响应 type CreateSessionResponse struct { SessionID string `json:"sessionId"` } // ChatRequest 聊天请求 type ChatRequest struct { AgentID string `json:"agentId"` UserID string `json:"userId"` SessionID string `json:"sessionId"` Message string `json:"message"` } // ChatResponse 聊天响应 type ChatResponse struct { Content string `json:"content"` } // RegisterRoutes 注册 HTTP 路由 func RegisterRoutes(router gin.IRouter, chatService *service.ChatService) { group := router.Group("/api/v1") group.GET("/query_ai_agent_config_list", queryAgentConfigList(chatService)) group.POST("/create_session", createSession(chatService)) group.GET("/create_session", createSessionQuery(chatService)) group.POST("/chat", chatMessage(chatService)) group.POST("/chat_stream", chatStream(chatService)) } func queryAgentConfigList(s *service.ChatService) gin.HandlerFunc { return func(c *gin.Context) { agents := s.QueryAgentConfigList() responses := make([]AiAgentConfigResponse, 0, len(agents)) for _, agent := range agents { responses = append(responses, AiAgentConfigResponse{ AgentID: agent.AgentID, AgentName: agent.AgentName, AgentDesc: agent.AgentDesc, }) } c.JSON(http.StatusOK, success(responses)) } } func createSession(s *service.ChatService) gin.HandlerFunc { return func(c *gin.Context) { var req CreateSessionRequest if err := c.ShouldBindJSON(&req); err != nil { writeError(c, types.NewAppError(types.CodeIllegalParameter, err.Error())) return } sessionID, err := s.CreateSession(req.AgentID, req.UserID) if err != nil { writeError(c, err) return } c.JSON(http.StatusOK, success(CreateSessionResponse{SessionID: sessionID})) } } func createSessionQuery(s *service.ChatService) gin.HandlerFunc { return func(c *gin.Context) { sessionID, err := s.CreateSession(c.Query("agentId"), c.Query("userId")) if err != nil { writeError(c, err) return } c.JSON(http.StatusOK, success(CreateSessionResponse{SessionID: sessionID})) } } func chatMessage(s *service.ChatService) gin.HandlerFunc { return func(c *gin.Context) { var req ChatRequest if err := c.ShouldBindJSON(&req); err != nil { writeError(c, types.NewAppError(types.CodeIllegalParameter, err.Error())) return } outputs, err := s.HandleMessage(req.AgentID, req.UserID, req.SessionID, req.Message) if err != nil { writeError(c, err) return } c.JSON(http.StatusOK, success(ChatResponse{Content: strings.Join(outputs, "\n")})) } } func chatStream(s *service.ChatService) gin.HandlerFunc { return func(c *gin.Context) { var req ChatRequest if err := c.ShouldBindJSON(&req); err != nil { writeError(c, types.NewAppError(types.CodeIllegalParameter, err.Error())) return } outputs, errs := s.HandleMessageStream(req.AgentID, req.UserID, req.SessionID, req.Message) c.Header("Content-Type", "text/event-stream") c.Header("Cache-Control", "no-cache") c.Header("Connection", "keep-alive") for output := range outputs { c.SSEvent("message", output) c.Writer.Flush() } if err, ok := <-errs; ok && err != nil { c.SSEvent("error", err.Error()) c.Writer.Flush() } } } func success(data interface{}) Envelope { return Envelope{Code: types.CodeSuccess, Info: types.InfoSuccess, Data: data} } func writeError(c *gin.Context, err error) { var appErr *types.AppError if errors.As(err, &appErr) { c.JSON(http.StatusOK, Envelope{Code: appErr.Code, Info: appErr.Info}) return } c.JSON(http.StatusOK, Envelope{Code: types.CodeUnknownError, Info: err.Error()}) }