Files
GoLoom/backend/internal/handler/handler.go
hhs 8c515a8b3e
All checks were successful
GoLoom CI / Lint (push) Successful in 3m7s
GoLoom CI / Test (push) Successful in 5s
GoLoom CI / Build (push) Successful in 24s
refactor: 重构目录结构,后端代码统一到 backend/ 目录
2026-06-10 15:35:32 +08:00

155 lines
4.2 KiB
Go

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()})
}