Merge PR #126: feat(antigravity): 添加 models 端点支持
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/Wei-Shaw/sub2api/internal/pkg/antigravity"
|
||||||
"github.com/Wei-Shaw/sub2api/internal/pkg/claude"
|
"github.com/Wei-Shaw/sub2api/internal/pkg/claude"
|
||||||
"github.com/Wei-Shaw/sub2api/internal/pkg/openai"
|
"github.com/Wei-Shaw/sub2api/internal/pkg/openai"
|
||||||
middleware2 "github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
middleware2 "github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
||||||
@@ -445,6 +446,15 @@ func (h *GatewayHandler) Models(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AntigravityModels 返回 Antigravity 支持的全部模型
|
||||||
|
// GET /antigravity/models
|
||||||
|
func (h *GatewayHandler) AntigravityModels(c *gin.Context) {
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"object": "list",
|
||||||
|
"data": antigravity.DefaultModels(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Usage handles getting account balance for CC Switch integration
|
// Usage handles getting account balance for CC Switch integration
|
||||||
// GET /v1/usage
|
// GET /v1/usage
|
||||||
func (h *GatewayHandler) Usage(c *gin.Context) {
|
func (h *GatewayHandler) Usage(c *gin.Context) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/Wei-Shaw/sub2api/internal/pkg/antigravity"
|
||||||
"github.com/Wei-Shaw/sub2api/internal/pkg/gemini"
|
"github.com/Wei-Shaw/sub2api/internal/pkg/gemini"
|
||||||
"github.com/Wei-Shaw/sub2api/internal/pkg/googleapi"
|
"github.com/Wei-Shaw/sub2api/internal/pkg/googleapi"
|
||||||
"github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
"github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
||||||
@@ -32,9 +33,9 @@ func (h *GatewayHandler) GeminiV1BetaListModels(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 强制 antigravity 模式:直接返回静态模型列表
|
// 强制 antigravity 模式:返回 antigravity 支持的模型列表
|
||||||
if forcePlatform == service.PlatformAntigravity {
|
if forcePlatform == service.PlatformAntigravity {
|
||||||
c.JSON(http.StatusOK, gemini.FallbackModelsList())
|
c.JSON(http.StatusOK, antigravity.FallbackGeminiModelsList())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,9 +85,9 @@ func (h *GatewayHandler) GeminiV1BetaGetModel(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 强制 antigravity 模式:直接返回静态模型信息
|
// 强制 antigravity 模式:返回 antigravity 模型信息
|
||||||
if forcePlatform == service.PlatformAntigravity {
|
if forcePlatform == service.PlatformAntigravity {
|
||||||
c.JSON(http.StatusOK, gemini.FallbackModel(modelName))
|
c.JSON(http.StatusOK, antigravity.FallbackGeminiModel(modelName))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -138,3 +138,91 @@ type ErrorDetail struct {
|
|||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// modelDef Antigravity 模型定义(内部使用)
|
||||||
|
type modelDef struct {
|
||||||
|
ID string
|
||||||
|
DisplayName string
|
||||||
|
CreatedAt string // 仅 Claude API 格式使用
|
||||||
|
}
|
||||||
|
|
||||||
|
// Antigravity 支持的 Claude 模型
|
||||||
|
var claudeModels = []modelDef{
|
||||||
|
{ID: "claude-opus-4-5-thinking", DisplayName: "Claude Opus 4.5 Thinking", CreatedAt: "2025-11-01T00:00:00Z"},
|
||||||
|
{ID: "claude-sonnet-4-5", DisplayName: "Claude Sonnet 4.5", CreatedAt: "2025-09-29T00:00:00Z"},
|
||||||
|
{ID: "claude-sonnet-4-5-thinking", DisplayName: "Claude Sonnet 4.5 Thinking", CreatedAt: "2025-09-29T00:00:00Z"},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Antigravity 支持的 Gemini 模型
|
||||||
|
var geminiModels = []modelDef{
|
||||||
|
{ID: "gemini-2.5-flash", DisplayName: "Gemini 2.5 Flash", CreatedAt: "2025-01-01T00:00:00Z"},
|
||||||
|
{ID: "gemini-2.5-flash-lite", DisplayName: "Gemini 2.5 Flash Lite", CreatedAt: "2025-01-01T00:00:00Z"},
|
||||||
|
{ID: "gemini-2.5-flash-thinking", DisplayName: "Gemini 2.5 Flash Thinking", CreatedAt: "2025-01-01T00:00:00Z"},
|
||||||
|
{ID: "gemini-3-flash", DisplayName: "Gemini 3 Flash", CreatedAt: "2025-06-01T00:00:00Z"},
|
||||||
|
{ID: "gemini-3-pro-low", DisplayName: "Gemini 3 Pro Low", CreatedAt: "2025-06-01T00:00:00Z"},
|
||||||
|
{ID: "gemini-3-pro-high", DisplayName: "Gemini 3 Pro High", CreatedAt: "2025-06-01T00:00:00Z"},
|
||||||
|
{ID: "gemini-3-pro-preview", DisplayName: "Gemini 3 Pro Preview", CreatedAt: "2025-06-01T00:00:00Z"},
|
||||||
|
{ID: "gemini-3-pro-image", DisplayName: "Gemini 3 Pro Image", CreatedAt: "2025-06-01T00:00:00Z"},
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== Claude API 格式 (/v1/models) ==========
|
||||||
|
|
||||||
|
// ClaudeModel Claude API 模型格式
|
||||||
|
type ClaudeModel struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
CreatedAt string `json:"created_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultModels 返回 Claude API 格式的模型列表(Claude + Gemini)
|
||||||
|
func DefaultModels() []ClaudeModel {
|
||||||
|
all := append(claudeModels, geminiModels...)
|
||||||
|
result := make([]ClaudeModel, len(all))
|
||||||
|
for i, m := range all {
|
||||||
|
result[i] = ClaudeModel{ID: m.ID, Type: "model", DisplayName: m.DisplayName, CreatedAt: m.CreatedAt}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== Gemini v1beta 格式 (/v1beta/models) ==========
|
||||||
|
|
||||||
|
// GeminiModel Gemini v1beta 模型格式
|
||||||
|
type GeminiModel struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
DisplayName string `json:"displayName,omitempty"`
|
||||||
|
SupportedGenerationMethods []string `json:"supportedGenerationMethods,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GeminiModelsListResponse Gemini v1beta 模型列表响应
|
||||||
|
type GeminiModelsListResponse struct {
|
||||||
|
Models []GeminiModel `json:"models"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultGeminiMethods = []string{"generateContent", "streamGenerateContent"}
|
||||||
|
|
||||||
|
// DefaultGeminiModels 返回 Gemini v1beta 格式的模型列表(仅 Gemini 模型)
|
||||||
|
func DefaultGeminiModels() []GeminiModel {
|
||||||
|
result := make([]GeminiModel, len(geminiModels))
|
||||||
|
for i, m := range geminiModels {
|
||||||
|
result[i] = GeminiModel{Name: "models/" + m.ID, DisplayName: m.DisplayName, SupportedGenerationMethods: defaultGeminiMethods}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// FallbackGeminiModelsList 返回 Gemini v1beta 格式的模型列表响应
|
||||||
|
func FallbackGeminiModelsList() GeminiModelsListResponse {
|
||||||
|
return GeminiModelsListResponse{Models: DefaultGeminiModels()}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FallbackGeminiModel 返回单个模型信息(v1beta 格式)
|
||||||
|
func FallbackGeminiModel(model string) GeminiModel {
|
||||||
|
if model == "" {
|
||||||
|
return GeminiModel{Name: "models/unknown", SupportedGenerationMethods: defaultGeminiMethods}
|
||||||
|
}
|
||||||
|
name := model
|
||||||
|
if len(model) < 7 || model[:7] != "models/" {
|
||||||
|
name = "models/" + model
|
||||||
|
}
|
||||||
|
return GeminiModel{Name: name, SupportedGenerationMethods: defaultGeminiMethods}
|
||||||
|
}
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ func RegisterGatewayRoutes(
|
|||||||
// OpenAI Responses API(不带v1前缀的别名)
|
// OpenAI Responses API(不带v1前缀的别名)
|
||||||
r.POST("/responses", bodyLimit, gin.HandlerFunc(apiKeyAuth), h.OpenAIGateway.Responses)
|
r.POST("/responses", bodyLimit, gin.HandlerFunc(apiKeyAuth), h.OpenAIGateway.Responses)
|
||||||
|
|
||||||
|
// Antigravity 模型列表
|
||||||
|
r.GET("/antigravity/models", gin.HandlerFunc(apiKeyAuth), h.Gateway.AntigravityModels)
|
||||||
|
|
||||||
// Antigravity 专用路由(仅使用 antigravity 账户,不混合调度)
|
// Antigravity 专用路由(仅使用 antigravity 账户,不混合调度)
|
||||||
antigravityV1 := r.Group("/antigravity/v1")
|
antigravityV1 := r.Group("/antigravity/v1")
|
||||||
antigravityV1.Use(bodyLimit)
|
antigravityV1.Use(bodyLimit)
|
||||||
@@ -55,7 +58,7 @@ func RegisterGatewayRoutes(
|
|||||||
{
|
{
|
||||||
antigravityV1.POST("/messages", h.Gateway.Messages)
|
antigravityV1.POST("/messages", h.Gateway.Messages)
|
||||||
antigravityV1.POST("/messages/count_tokens", h.Gateway.CountTokens)
|
antigravityV1.POST("/messages/count_tokens", h.Gateway.CountTokens)
|
||||||
antigravityV1.GET("/models", h.Gateway.Models)
|
antigravityV1.GET("/models", h.Gateway.AntigravityModels)
|
||||||
antigravityV1.GET("/usage", h.Gateway.Usage)
|
antigravityV1.GET("/usage", h.Gateway.Usage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user