package routes import ( "encoding/json" "log/slog" "net/http" "github.com/Wei-Shaw/sub2api/internal/service" "github.com/gin-gonic/gin" ) // RegisterAntigravityHTTPRoutes 注册 Antigravity HTTP API 路由 func RegisterAntigravityHTTPRoutes(v1 *gin.RouterGroup, langServerService *service.LanguageServerService) { logger := slog.Default() // 创建处理器 cascadeGroup := v1.Group("/cascade") { // 启动 Cascade 会话 cascadeGroup.POST("/start", func(c *gin.Context) { handleStartCascade(c, langServerService, logger) }) // 发送消息到 Cascade(流式响应) cascadeGroup.POST("/message", func(c *gin.Context) { handleSendMessage(c, langServerService, logger) }) // 取消 Cascade 会话 cascadeGroup.POST("/cancel", func(c *gin.Context) { handleCancelCascade(c, langServerService, logger) }) } // 模型列表 v1.GET("/models", func(c *gin.Context) { handleGetModels(c, langServerService, logger) }) // 健康检查 v1.GET("/health", func(c *gin.Context) { handleHealth(c, logger) }) } // handleStartCascade 处理启动 Cascade 请求 func handleStartCascade(c *gin.Context, svc *service.LanguageServerService, logger *slog.Logger) { type StartCascadeRequest struct { Model string `json:"model" binding:"required"` SystemPrompt string `json:"system_prompt"` Metadata map[string]string `json:"metadata"` } var req StartCascadeRequest if err := c.ShouldBindJSON(&req); err != nil { logger.Error("invalid start cascade request", "error", err) c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"}) return } // 获取 OAuth token token := c.GetHeader("Authorization") if token == "" { c.JSON(http.StatusUnauthorized, gin.H{"error": "missing authorization header"}) return } // 调用服务 cascadeID, err := svc.StartCascade( c.Request.Context(), req.Model, req.SystemPrompt, req.Metadata, token, ) if err != nil { logger.Error("start cascade failed", "error", err) c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"cascade_id": cascadeID}) } // handleSendMessage 处理发送消息请求(流式) func handleSendMessage(c *gin.Context, svc *service.LanguageServerService, logger *slog.Logger) { type SendMessageRequest struct { CascadeID string `json:"cascade_id" binding:"required"` Message string `json:"message" binding:"required"` } var req SendMessageRequest if err := c.ShouldBindJSON(&req); err != nil { logger.Error("invalid send message request", "error", err) c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"}) return } // 获取 OAuth token token := c.GetHeader("Authorization") if token == "" { c.JSON(http.StatusUnauthorized, gin.H{"error": "missing authorization header"}) return } // 调用服务并获取流式更新通道 updateChan, err := svc.SendUserMessage(c.Request.Context(), req.CascadeID, req.Message, token) if err != nil { logger.Error("send message failed", "error", err) c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } // 设置 SSE 响应头 c.Header("Content-Type", "text/event-stream") c.Header("Cache-Control", "no-cache") c.Header("Connection", "keep-alive") c.Header("X-Accel-Buffering", "no") c.Status(http.StatusOK) // 流式发送更新到客户端 flusher, ok := c.Writer.(http.Flusher) if !ok { logger.Error("response writer does not support flushing") return } for event := range updateChan { if event == nil { break } // 将事件序列化为 JSON eventJSON, err := marshalJSON(event) if err != nil { logger.Error("failed to marshal event", "error", err) continue } // 发送 SSE 格式的数据 _, _ = c.Writer.WriteString("data: " + string(eventJSON) + "\n\n") flusher.Flush() } } // handleCancelCascade 处理取消 Cascade 请求 func handleCancelCascade(c *gin.Context, svc *service.LanguageServerService, logger *slog.Logger) { type CancelRequest struct { CascadeID string `json:"cascade_id" binding:"required"` } var req CancelRequest if err := c.ShouldBindJSON(&req); err != nil { logger.Error("invalid cancel request", "error", err) c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"}) return } err := svc.CancelCascade(c.Request.Context(), req.CascadeID) if err != nil { logger.Error("cancel cascade failed", "error", err) c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "cascade cancelled"}) } // handleGetModels 处理获取模型列表请求 func handleGetModels(c *gin.Context, svc *service.LanguageServerService, logger *slog.Logger) { models, err := svc.GetAvailableModels(c.Request.Context()) if err != nil { logger.Error("get models failed", "error", err) c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{ "models": models, "default_model": "claude-opus-4-6", }) } // handleHealth 处理健康检查请求 func handleHealth(c *gin.Context, logger *slog.Logger) { c.JSON(http.StatusOK, gin.H{"status": "healthy"}) } // marshalJSON 辅助函数用于序列化事件 func marshalJSON(v interface{}) ([]byte, error) { return json.Marshal(v) }