151 lines
4.3 KiB
Go
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))
|
|
}
|