mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-19 12:50:51 +08:00
**chore(executor): update default agent version and simplify const formatting**
- Updated `defaultAntigravityAgent` to version `1.11.5`. - Adjusted const value formatting for improved readability. **feat(executor): introduce fallback mechanism for Antigravity base URLs** - Added retry logic with fallback order for Antigravity base URLs to handle request errors and rate limits. - Refactored base URL handling with `antigravityBaseURLFallbackOrder` and related utilities. - Enhanced error handling in non-streaming and streaming requests with retry support and improved metadata reporting. - Updated `buildRequest` to support dynamic base URL assignment.
This commit is contained in:
@@ -26,15 +26,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
antigravityBaseURL = "https://daily-cloudcode-pa.sandbox.googleapis.com"
|
antigravityBaseURLDaily = "https://daily-cloudcode-pa.sandbox.googleapis.com"
|
||||||
|
antigravityBaseURLAutopush = "https://autopush-cloudcode-pa.sandbox.googleapis.com"
|
||||||
|
antigravityBaseURLProd = "https://cloudcode-pa.googleapis.com"
|
||||||
antigravityStreamPath = "/v1internal:streamGenerateContent"
|
antigravityStreamPath = "/v1internal:streamGenerateContent"
|
||||||
antigravityGeneratePath = "/v1internal:generateContent"
|
antigravityGeneratePath = "/v1internal:generateContent"
|
||||||
antigravityModelsPath = "/v1internal:fetchAvailableModels"
|
antigravityModelsPath = "/v1internal:fetchAvailableModels"
|
||||||
antigravityClientID = "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com"
|
antigravityClientID = "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com"
|
||||||
antigravityClientSecret = "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"
|
antigravityClientSecret = "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"
|
||||||
defaultAntigravityAgent = "antigravity/1.11.3 windows/amd64"
|
defaultAntigravityAgent = "antigravity/1.11.5 windows/amd64"
|
||||||
antigravityAuthType = "antigravity"
|
antigravityAuthType = "antigravity"
|
||||||
refreshSkew = 5 * time.Minute
|
refreshSkew = 3000 * time.Second
|
||||||
streamScannerBuffer int = 20_971_520
|
streamScannerBuffer int = 20_971_520
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -73,33 +75,55 @@ func (e *AntigravityExecutor) Execute(ctx context.Context, auth *cliproxyauth.Au
|
|||||||
to := sdktranslator.FromString("antigravity")
|
to := sdktranslator.FromString("antigravity")
|
||||||
translated := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), false)
|
translated := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), false)
|
||||||
|
|
||||||
httpReq, errReq := e.buildRequest(ctx, auth, token, req.Model, translated, false, opts.Alt)
|
baseURLs := antigravityBaseURLFallbackOrder(auth)
|
||||||
|
httpClient := newProxyAwareHTTPClient(ctx, e.cfg, auth, 0)
|
||||||
|
|
||||||
|
var lastStatus int
|
||||||
|
var lastBody []byte
|
||||||
|
var lastErr error
|
||||||
|
|
||||||
|
for idx, baseURL := range baseURLs {
|
||||||
|
httpReq, errReq := e.buildRequest(ctx, auth, token, req.Model, translated, false, opts.Alt, baseURL)
|
||||||
if errReq != nil {
|
if errReq != nil {
|
||||||
return resp, errReq
|
err = errReq
|
||||||
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
httpClient := newProxyAwareHTTPClient(ctx, e.cfg, auth, 0)
|
|
||||||
httpResp, errDo := httpClient.Do(httpReq)
|
httpResp, errDo := httpClient.Do(httpReq)
|
||||||
if errDo != nil {
|
if errDo != nil {
|
||||||
recordAPIResponseError(ctx, e.cfg, errDo)
|
recordAPIResponseError(ctx, e.cfg, errDo)
|
||||||
return resp, errDo
|
lastStatus = 0
|
||||||
|
lastBody = nil
|
||||||
|
lastErr = errDo
|
||||||
|
if idx+1 < len(baseURLs) {
|
||||||
|
log.Debugf("antigravity executor: request error on base url %s, retrying with fallback base url: %s", baseURL, baseURLs[idx+1])
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
defer func() {
|
err = errDo
|
||||||
if errClose := httpResp.Body.Close(); errClose != nil {
|
return resp, err
|
||||||
log.Errorf("antigravity executor: close response body error: %v", errClose)
|
|
||||||
}
|
}
|
||||||
}()
|
|
||||||
|
|
||||||
recordAPIResponseMetadata(ctx, e.cfg, httpResp.StatusCode, httpResp.Header.Clone())
|
recordAPIResponseMetadata(ctx, e.cfg, httpResp.StatusCode, httpResp.Header.Clone())
|
||||||
bodyBytes, errRead := io.ReadAll(httpResp.Body)
|
bodyBytes, errRead := io.ReadAll(httpResp.Body)
|
||||||
|
if errClose := httpResp.Body.Close(); errClose != nil {
|
||||||
|
log.Errorf("antigravity executor: close response body error: %v", errClose)
|
||||||
|
}
|
||||||
if errRead != nil {
|
if errRead != nil {
|
||||||
recordAPIResponseError(ctx, e.cfg, errRead)
|
recordAPIResponseError(ctx, e.cfg, errRead)
|
||||||
return resp, errRead
|
err = errRead
|
||||||
|
return resp, err
|
||||||
}
|
}
|
||||||
appendAPIResponseChunk(ctx, e.cfg, bodyBytes)
|
appendAPIResponseChunk(ctx, e.cfg, bodyBytes)
|
||||||
|
|
||||||
if httpResp.StatusCode < http.StatusOK || httpResp.StatusCode >= http.StatusMultipleChoices {
|
if httpResp.StatusCode < http.StatusOK || httpResp.StatusCode >= http.StatusMultipleChoices {
|
||||||
log.Debugf("antigravity executor: upstream error status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), bodyBytes))
|
log.Debugf("antigravity executor: upstream error status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), bodyBytes))
|
||||||
|
lastStatus = httpResp.StatusCode
|
||||||
|
lastBody = append([]byte(nil), bodyBytes...)
|
||||||
|
lastErr = nil
|
||||||
|
if httpResp.StatusCode == http.StatusTooManyRequests && idx+1 < len(baseURLs) {
|
||||||
|
log.Debugf("antigravity executor: rate limited on base url %s, retrying with fallback base url: %s", baseURL, baseURLs[idx+1])
|
||||||
|
continue
|
||||||
|
}
|
||||||
err = statusErr{code: httpResp.StatusCode, msg: string(bodyBytes)}
|
err = statusErr{code: httpResp.StatusCode, msg: string(bodyBytes)}
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
@@ -112,6 +136,17 @@ func (e *AntigravityExecutor) Execute(ctx context.Context, auth *cliproxyauth.Au
|
|||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case lastStatus != 0:
|
||||||
|
err = statusErr{code: lastStatus, msg: string(lastBody)}
|
||||||
|
case lastErr != nil:
|
||||||
|
err = lastErr
|
||||||
|
default:
|
||||||
|
err = statusErr{code: http.StatusServiceUnavailable, msg: "antigravity executor: no base url available"}
|
||||||
|
}
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
// ExecuteStream handles streaming requests via the antigravity upstream.
|
// ExecuteStream handles streaming requests via the antigravity upstream.
|
||||||
func (e *AntigravityExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Auth, req cliproxyexecutor.Request, opts cliproxyexecutor.Options) (stream <-chan cliproxyexecutor.StreamChunk, err error) {
|
func (e *AntigravityExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Auth, req cliproxyexecutor.Request, opts cliproxyexecutor.Options) (stream <-chan cliproxyexecutor.StreamChunk, err error) {
|
||||||
ctx = context.WithValue(ctx, "alt", "")
|
ctx = context.WithValue(ctx, "alt", "")
|
||||||
@@ -131,38 +166,73 @@ func (e *AntigravityExecutor) ExecuteStream(ctx context.Context, auth *cliproxya
|
|||||||
to := sdktranslator.FromString("antigravity")
|
to := sdktranslator.FromString("antigravity")
|
||||||
translated := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), true)
|
translated := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), true)
|
||||||
|
|
||||||
httpReq, errReq := e.buildRequest(ctx, auth, token, req.Model, translated, true, opts.Alt)
|
baseURLs := antigravityBaseURLFallbackOrder(auth)
|
||||||
|
httpClient := newProxyAwareHTTPClient(ctx, e.cfg, auth, 0)
|
||||||
|
|
||||||
|
var lastStatus int
|
||||||
|
var lastBody []byte
|
||||||
|
var lastErr error
|
||||||
|
|
||||||
|
for idx, baseURL := range baseURLs {
|
||||||
|
httpReq, errReq := e.buildRequest(ctx, auth, token, req.Model, translated, true, opts.Alt, baseURL)
|
||||||
if errReq != nil {
|
if errReq != nil {
|
||||||
return nil, errReq
|
err = errReq
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
httpClient := newProxyAwareHTTPClient(ctx, e.cfg, auth, 0)
|
|
||||||
httpResp, errDo := httpClient.Do(httpReq)
|
httpResp, errDo := httpClient.Do(httpReq)
|
||||||
if errDo != nil {
|
if errDo != nil {
|
||||||
recordAPIResponseError(ctx, e.cfg, errDo)
|
recordAPIResponseError(ctx, e.cfg, errDo)
|
||||||
return nil, errDo
|
lastStatus = 0
|
||||||
|
lastBody = nil
|
||||||
|
lastErr = errDo
|
||||||
|
if idx+1 < len(baseURLs) {
|
||||||
|
log.Debugf("antigravity executor: request error on base url %s, retrying with fallback base url: %s", baseURL, baseURLs[idx+1])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
err = errDo
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
recordAPIResponseMetadata(ctx, e.cfg, httpResp.StatusCode, httpResp.Header.Clone())
|
recordAPIResponseMetadata(ctx, e.cfg, httpResp.StatusCode, httpResp.Header.Clone())
|
||||||
if httpResp.StatusCode < http.StatusOK || httpResp.StatusCode >= http.StatusMultipleChoices {
|
if httpResp.StatusCode < http.StatusOK || httpResp.StatusCode >= http.StatusMultipleChoices {
|
||||||
bodyBytes, _ := io.ReadAll(httpResp.Body)
|
bodyBytes, errRead := io.ReadAll(httpResp.Body)
|
||||||
appendAPIResponseChunk(ctx, e.cfg, bodyBytes)
|
|
||||||
if errClose := httpResp.Body.Close(); errClose != nil {
|
if errClose := httpResp.Body.Close(); errClose != nil {
|
||||||
log.Errorf("antigravity executor: close response body error: %v", errClose)
|
log.Errorf("antigravity executor: close response body error: %v", errClose)
|
||||||
}
|
}
|
||||||
|
if errRead != nil {
|
||||||
|
recordAPIResponseError(ctx, e.cfg, errRead)
|
||||||
|
lastStatus = 0
|
||||||
|
lastBody = nil
|
||||||
|
lastErr = errRead
|
||||||
|
if idx+1 < len(baseURLs) {
|
||||||
|
log.Debugf("antigravity executor: read error on base url %s, retrying with fallback base url: %s", baseURL, baseURLs[idx+1])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
err = errRead
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
appendAPIResponseChunk(ctx, e.cfg, bodyBytes)
|
||||||
|
lastStatus = httpResp.StatusCode
|
||||||
|
lastBody = append([]byte(nil), bodyBytes...)
|
||||||
|
lastErr = nil
|
||||||
|
if httpResp.StatusCode == http.StatusTooManyRequests && idx+1 < len(baseURLs) {
|
||||||
|
log.Debugf("antigravity executor: rate limited on base url %s, retrying with fallback base url: %s", baseURL, baseURLs[idx+1])
|
||||||
|
continue
|
||||||
|
}
|
||||||
err = statusErr{code: httpResp.StatusCode, msg: string(bodyBytes)}
|
err = statusErr{code: httpResp.StatusCode, msg: string(bodyBytes)}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
out := make(chan cliproxyexecutor.StreamChunk)
|
out := make(chan cliproxyexecutor.StreamChunk)
|
||||||
stream = out
|
stream = out
|
||||||
go func() {
|
go func(resp *http.Response) {
|
||||||
defer close(out)
|
defer close(out)
|
||||||
defer func() {
|
defer func() {
|
||||||
if errClose := httpResp.Body.Close(); errClose != nil {
|
if errClose := resp.Body.Close(); errClose != nil {
|
||||||
log.Errorf("antigravity executor: close response body error: %v", errClose)
|
log.Errorf("antigravity executor: close response body error: %v", errClose)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
scanner := bufio.NewScanner(httpResp.Body)
|
scanner := bufio.NewScanner(resp.Body)
|
||||||
scanner.Buffer(nil, streamScannerBuffer)
|
scanner.Buffer(nil, streamScannerBuffer)
|
||||||
var param any
|
var param any
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
@@ -198,10 +268,21 @@ func (e *AntigravityExecutor) ExecuteStream(ctx context.Context, auth *cliproxya
|
|||||||
} else {
|
} else {
|
||||||
reporter.ensurePublished(ctx)
|
reporter.ensurePublished(ctx)
|
||||||
}
|
}
|
||||||
}()
|
}(httpResp)
|
||||||
return stream, nil
|
return stream, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case lastStatus != 0:
|
||||||
|
err = statusErr{code: lastStatus, msg: string(lastBody)}
|
||||||
|
case lastErr != nil:
|
||||||
|
err = lastErr
|
||||||
|
default:
|
||||||
|
err = statusErr{code: http.StatusServiceUnavailable, msg: "antigravity executor: no base url available"}
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Refresh refreshes the OAuth token using the refresh token.
|
// Refresh refreshes the OAuth token using the refresh token.
|
||||||
func (e *AntigravityExecutor) Refresh(ctx context.Context, auth *cliproxyauth.Auth) (*cliproxyauth.Auth, error) {
|
func (e *AntigravityExecutor) Refresh(ctx context.Context, auth *cliproxyauth.Auth) (*cliproxyauth.Auth, error) {
|
||||||
if auth == nil {
|
if auth == nil {
|
||||||
@@ -230,7 +311,11 @@ func FetchAntigravityModels(ctx context.Context, auth *cliproxyauth.Auth, cfg *c
|
|||||||
auth = updatedAuth
|
auth = updatedAuth
|
||||||
}
|
}
|
||||||
|
|
||||||
modelsURL := buildBaseURL(auth) + antigravityModelsPath
|
baseURLs := antigravityBaseURLFallbackOrder(auth)
|
||||||
|
httpClient := newProxyAwareHTTPClient(ctx, cfg, auth, 0)
|
||||||
|
|
||||||
|
for idx, baseURL := range baseURLs {
|
||||||
|
modelsURL := baseURL + antigravityModelsPath
|
||||||
httpReq, errReq := http.NewRequestWithContext(ctx, http.MethodPost, modelsURL, bytes.NewReader([]byte(`{}`)))
|
httpReq, errReq := http.NewRequestWithContext(ctx, http.MethodPost, modelsURL, bytes.NewReader([]byte(`{}`)))
|
||||||
if errReq != nil {
|
if errReq != nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -238,26 +323,35 @@ func FetchAntigravityModels(ctx context.Context, auth *cliproxyauth.Auth, cfg *c
|
|||||||
httpReq.Header.Set("Content-Type", "application/json")
|
httpReq.Header.Set("Content-Type", "application/json")
|
||||||
httpReq.Header.Set("Authorization", "Bearer "+token)
|
httpReq.Header.Set("Authorization", "Bearer "+token)
|
||||||
httpReq.Header.Set("User-Agent", resolveUserAgent(auth))
|
httpReq.Header.Set("User-Agent", resolveUserAgent(auth))
|
||||||
if host := resolveHost(auth); host != "" {
|
if host := resolveHost(baseURL); host != "" {
|
||||||
httpReq.Host = host
|
httpReq.Host = host
|
||||||
}
|
}
|
||||||
|
|
||||||
httpClient := newProxyAwareHTTPClient(ctx, cfg, auth, 0)
|
|
||||||
httpResp, errDo := httpClient.Do(httpReq)
|
httpResp, errDo := httpClient.Do(httpReq)
|
||||||
if errDo != nil {
|
if errDo != nil {
|
||||||
|
if idx+1 < len(baseURLs) {
|
||||||
|
log.Debugf("antigravity executor: models request error on base url %s, retrying with fallback base url: %s", baseURL, baseURLs[idx+1])
|
||||||
|
continue
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
defer func() {
|
|
||||||
|
bodyBytes, errRead := io.ReadAll(httpResp.Body)
|
||||||
if errClose := httpResp.Body.Close(); errClose != nil {
|
if errClose := httpResp.Body.Close(); errClose != nil {
|
||||||
log.Errorf("antigravity executor: close response body error: %v", errClose)
|
log.Errorf("antigravity executor: close response body error: %v", errClose)
|
||||||
}
|
}
|
||||||
}()
|
|
||||||
|
|
||||||
bodyBytes, errRead := io.ReadAll(httpResp.Body)
|
|
||||||
if errRead != nil {
|
if errRead != nil {
|
||||||
|
if idx+1 < len(baseURLs) {
|
||||||
|
log.Debugf("antigravity executor: models read error on base url %s, retrying with fallback base url: %s", baseURL, baseURLs[idx+1])
|
||||||
|
continue
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if httpResp.StatusCode < http.StatusOK || httpResp.StatusCode >= http.StatusMultipleChoices {
|
if httpResp.StatusCode < http.StatusOK || httpResp.StatusCode >= http.StatusMultipleChoices {
|
||||||
|
if httpResp.StatusCode == http.StatusTooManyRequests && idx+1 < len(baseURLs) {
|
||||||
|
log.Debugf("antigravity executor: models request rate limited on base url %s, retrying with fallback base url: %s", baseURL, baseURLs[idx+1])
|
||||||
|
continue
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,6 +376,8 @@ func FetchAntigravityModels(ctx context.Context, auth *cliproxyauth.Auth, cfg *c
|
|||||||
}
|
}
|
||||||
return models
|
return models
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (e *AntigravityExecutor) ensureAccessToken(ctx context.Context, auth *cliproxyauth.Auth) (string, *cliproxyauth.Auth, error) {
|
func (e *AntigravityExecutor) ensureAccessToken(ctx context.Context, auth *cliproxyauth.Auth) (string, *cliproxyauth.Auth, error) {
|
||||||
if auth == nil {
|
if auth == nil {
|
||||||
@@ -366,12 +462,15 @@ func (e *AntigravityExecutor) refreshToken(ctx context.Context, auth *cliproxyau
|
|||||||
return auth, nil
|
return auth, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *AntigravityExecutor) buildRequest(ctx context.Context, auth *cliproxyauth.Auth, token, modelName string, payload []byte, stream bool, alt string) (*http.Request, error) {
|
func (e *AntigravityExecutor) buildRequest(ctx context.Context, auth *cliproxyauth.Auth, token, modelName string, payload []byte, stream bool, alt, baseURL string) (*http.Request, error) {
|
||||||
if token == "" {
|
if token == "" {
|
||||||
return nil, statusErr{code: http.StatusUnauthorized, msg: "missing access token"}
|
return nil, statusErr{code: http.StatusUnauthorized, msg: "missing access token"}
|
||||||
}
|
}
|
||||||
|
|
||||||
base := buildBaseURL(auth)
|
base := strings.TrimSuffix(baseURL, "/")
|
||||||
|
if base == "" {
|
||||||
|
base = buildBaseURL(auth)
|
||||||
|
}
|
||||||
path := antigravityGeneratePath
|
path := antigravityGeneratePath
|
||||||
if stream {
|
if stream {
|
||||||
path = antigravityStreamPath
|
path = antigravityStreamPath
|
||||||
@@ -405,7 +504,7 @@ func (e *AntigravityExecutor) buildRequest(ctx context.Context, auth *cliproxyau
|
|||||||
} else {
|
} else {
|
||||||
httpReq.Header.Set("Accept", "application/json")
|
httpReq.Header.Set("Accept", "application/json")
|
||||||
}
|
}
|
||||||
if host := resolveHost(auth); host != "" {
|
if host := resolveHost(base); host != "" {
|
||||||
httpReq.Host = host
|
httpReq.Host = host
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,26 +588,13 @@ func int64Value(value any) (int64, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func buildBaseURL(auth *cliproxyauth.Auth) string {
|
func buildBaseURL(auth *cliproxyauth.Auth) string {
|
||||||
if auth != nil {
|
if baseURLs := antigravityBaseURLFallbackOrder(auth); len(baseURLs) > 0 {
|
||||||
if auth.Attributes != nil {
|
return baseURLs[0]
|
||||||
if v := strings.TrimSpace(auth.Attributes["base_url"]); v != "" {
|
|
||||||
return strings.TrimSuffix(v, "/")
|
|
||||||
}
|
}
|
||||||
}
|
return antigravityBaseURLAutopush
|
||||||
if auth.Metadata != nil {
|
|
||||||
if v, ok := auth.Metadata["base_url"].(string); ok {
|
|
||||||
v = strings.TrimSpace(v)
|
|
||||||
if v != "" {
|
|
||||||
return strings.TrimSuffix(v, "/")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return antigravityBaseURL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveHost(auth *cliproxyauth.Auth) string {
|
func resolveHost(base string) string {
|
||||||
base := buildBaseURL(auth)
|
|
||||||
parsed, errParse := url.Parse(base)
|
parsed, errParse := url.Parse(base)
|
||||||
if errParse != nil {
|
if errParse != nil {
|
||||||
return ""
|
return ""
|
||||||
@@ -535,6 +621,37 @@ func resolveUserAgent(auth *cliproxyauth.Auth) string {
|
|||||||
return defaultAntigravityAgent
|
return defaultAntigravityAgent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func antigravityBaseURLFallbackOrder(auth *cliproxyauth.Auth) []string {
|
||||||
|
if base := resolveCustomAntigravityBaseURL(auth); base != "" {
|
||||||
|
return []string{base}
|
||||||
|
}
|
||||||
|
return []string{
|
||||||
|
antigravityBaseURLDaily,
|
||||||
|
antigravityBaseURLAutopush,
|
||||||
|
// antigravityBaseURLProd,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveCustomAntigravityBaseURL(auth *cliproxyauth.Auth) string {
|
||||||
|
if auth == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if auth.Attributes != nil {
|
||||||
|
if v := strings.TrimSpace(auth.Attributes["base_url"]); v != "" {
|
||||||
|
return strings.TrimSuffix(v, "/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if auth.Metadata != nil {
|
||||||
|
if v, ok := auth.Metadata["base_url"].(string); ok {
|
||||||
|
v = strings.TrimSpace(v)
|
||||||
|
if v != "" {
|
||||||
|
return strings.TrimSuffix(v, "/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func geminiToAntigravity(modelName string, payload []byte) []byte {
|
func geminiToAntigravity(modelName string, payload []byte) []byte {
|
||||||
template, _ := sjson.Set(string(payload), "model", modelName)
|
template, _ := sjson.Set(string(payload), "model", modelName)
|
||||||
template, _ = sjson.Set(template, "userAgent", "antigravity")
|
template, _ = sjson.Set(template, "userAgent", "antigravity")
|
||||||
@@ -613,7 +730,7 @@ func modelName2Alias(modelName string) string {
|
|||||||
return "gemini-claude-sonnet-4-5"
|
return "gemini-claude-sonnet-4-5"
|
||||||
case "claude-sonnet-4-5-thinking":
|
case "claude-sonnet-4-5-thinking":
|
||||||
return "gemini-claude-sonnet-4-5-thinking"
|
return "gemini-claude-sonnet-4-5-thinking"
|
||||||
case "chat_20706", "chat_23310", "gemini-2.5-flash-thinking", "gemini-3-pro-low":
|
case "chat_20706", "chat_23310", "gemini-2.5-flash-thinking", "gemini-3-pro-low", "gemini-2.5-pro":
|
||||||
return ""
|
return ""
|
||||||
default:
|
default:
|
||||||
return modelName
|
return modelName
|
||||||
|
|||||||
Reference in New Issue
Block a user