Files
2026-07-13 12:35:43 +08:00

151 lines
4.3 KiB
Go

package cliproxy
import (
"context"
"encoding/json"
"io"
"net/http"
"strings"
"github.com/router-for-me/CLIProxyAPI/v7/internal/misc"
coreauth "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/auth"
"github.com/router-for-me/CLIProxyAPI/v7/sdk/proxyutil"
log "github.com/sirupsen/logrus"
)
const (
antigravityModelBaseURLDaily = "https://daily-cloudcode-pa.googleapis.com"
antigravityModelBaseURLProd = "https://cloudcode-pa.googleapis.com"
antigravityModelsPath = "/v1internal:fetchAvailableModels"
)
type antigravityFetchAvailableModelsResponse struct {
WebSearchModelIDs []string `json:"webSearchModelIds"`
}
type antigravityModelCapabilityHints struct {
WebSearchModelIDs map[string]struct{}
}
func (s *Service) fetchAntigravityModelCapabilityHintsForAuth(ctx context.Context, auth *coreauth.Auth) antigravityModelCapabilityHints {
if auth == nil || auth.Metadata == nil {
return antigravityModelCapabilityHints{}
}
accessToken, _ := auth.Metadata["access_token"].(string)
accessToken = strings.TrimSpace(accessToken)
if accessToken == "" {
return antigravityModelCapabilityHints{}
}
client := &http.Client{}
if transport, _, errProxy := proxyutil.BuildHTTPTransport(s.antigravityModelFetchProxyURL(auth)); errProxy == nil && transport != nil {
client.Transport = transport
}
for _, baseURL := range antigravityModelBaseURLs(auth) {
req, errReq := http.NewRequestWithContext(ctx, http.MethodPost, strings.TrimRight(baseURL, "/")+antigravityModelsPath, strings.NewReader(`{}`))
if errReq != nil {
continue
}
req.Close = true
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("User-Agent", misc.AntigravityUserAgent())
resp, errDo := client.Do(req)
if errDo != nil {
continue
}
body, errRead := io.ReadAll(resp.Body)
if errClose := resp.Body.Close(); errClose != nil {
log.Debugf("antigravity model fetch: close response body: %v", errClose)
}
if errRead != nil {
continue
}
if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {
continue
}
hints := parseAntigravityModelCapabilityHints(body)
if len(hints.WebSearchModelIDs) > 0 {
return hints
}
}
return antigravityModelCapabilityHints{}
}
func (s *Service) antigravityModelFetchProxyURL(auth *coreauth.Auth) string {
if auth != nil {
if proxyURL := strings.TrimSpace(auth.ProxyURL); proxyURL != "" {
return proxyURL
}
}
if s != nil && s.cfg != nil {
return strings.TrimSpace(s.cfg.ProxyURL)
}
return ""
}
func antigravityModelBaseURLs(auth *coreauth.Auth) []string {
if baseURL := resolveAntigravityModelBaseURL(auth); baseURL != "" {
return []string{baseURL}
}
return []string{antigravityModelBaseURLDaily, antigravityModelBaseURLProd}
}
func resolveAntigravityModelBaseURL(auth *coreauth.Auth) string {
if auth == nil {
return ""
}
if auth.Attributes != nil {
if value := strings.TrimSpace(auth.Attributes["base_url"]); value != "" {
return strings.TrimRight(value, "/")
}
}
if auth.Metadata != nil {
if value, ok := auth.Metadata["base_url"].(string); ok {
value = strings.TrimSpace(value)
if value != "" {
return strings.TrimRight(value, "/")
}
}
}
return ""
}
func parseAntigravityModelCapabilityHints(body []byte) antigravityModelCapabilityHints {
var parsed antigravityFetchAvailableModelsResponse
if err := json.Unmarshal(body, &parsed); err != nil {
return antigravityModelCapabilityHints{}
}
webSearchModels := make(map[string]struct{}, len(parsed.WebSearchModelIDs))
for _, modelID := range parsed.WebSearchModelIDs {
modelID = normalizeAntigravityFetchedModelID(modelID)
if modelID != "" {
webSearchModels[modelID] = struct{}{}
}
}
return antigravityModelCapabilityHints{WebSearchModelIDs: webSearchModels}
}
func applyAntigravityFetchedModelCapabilities(models []*ModelInfo, hints antigravityModelCapabilityHints) []*ModelInfo {
if len(models) == 0 || len(hints.WebSearchModelIDs) == 0 {
return models
}
for _, model := range models {
if model == nil {
continue
}
modelID := normalizeAntigravityFetchedModelID(model.ID)
if _, ok := hints.WebSearchModelIDs[modelID]; ok {
model.SupportsWebSearch = true
}
}
return models
}
func normalizeAntigravityFetchedModelID(modelID string) string {
return strings.ToLower(strings.TrimSpace(modelID))
}