From b907d21851af9031264b5b5e7380a3b430e68f7c Mon Sep 17 00:00:00 2001 From: hkfires <10558748+hkfires@users.noreply.github.com> Date: Mon, 2 Mar 2026 12:54:15 +0800 Subject: [PATCH] revert(executor): revert antigravity_executor.go changes from PR #1735 --- .../runtime/executor/antigravity_executor.go | 177 +++--------------- 1 file changed, 24 insertions(+), 153 deletions(-) diff --git a/internal/runtime/executor/antigravity_executor.go b/internal/runtime/executor/antigravity_executor.go index bd32a422..919d96fa 100644 --- a/internal/runtime/executor/antigravity_executor.go +++ b/internal/runtime/executor/antigravity_executor.go @@ -8,7 +8,6 @@ import ( "bytes" "context" "crypto/sha256" - "crypto/tls" "encoding/binary" "encoding/json" "errors" @@ -46,10 +45,10 @@ const ( antigravityModelsPath = "/v1internal:fetchAvailableModels" antigravityClientID = "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com" antigravityClientSecret = "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" - defaultAntigravityAgent = "antigravity/1.19.6 windows/amd64" + defaultAntigravityAgent = "antigravity/1.104.0 darwin/arm64" antigravityAuthType = "antigravity" refreshSkew = 3000 * time.Second - systemInstruction = " You are Antigravity, a powerful agentic AI coding assistant designed by the Google Deepmind team working on Advanced Agentic Coding. You are pair programming with a USER to solve their coding task. The task may require creating a new codebase, modifying or debugging an existing codebase, or simply answering a question. The USER will send you requests, which you must always prioritize addressing. Along with each USER request, we will attach additional metadata about their current state, such as what files they have open and where their cursor is. This information may or may not be relevant to the coding task, it is up for you to decide. " + systemInstruction = "You are Antigravity, a powerful agentic AI coding assistant designed by the Google Deepmind team working on Advanced Agentic Coding.You are pair programming with a USER to solve their coding task. The task may require creating a new codebase, modifying or debugging an existing codebase, or simply answering a question.**Absolute paths only****Proactiveness**" ) var ( @@ -143,62 +142,6 @@ func NewAntigravityExecutor(cfg *config.Config) *AntigravityExecutor { return &AntigravityExecutor{cfg: cfg} } -// antigravityTransport is a singleton HTTP/1.1 transport shared by all Antigravity requests. -// It is initialized once via antigravityTransportOnce to avoid leaking a new connection pool -// (and the goroutines managing it) on every request. -var ( - antigravityTransport *http.Transport - antigravityTransportOnce sync.Once -) - -func cloneTransportWithHTTP11(base *http.Transport) *http.Transport { - if base == nil { - return nil - } - - clone := base.Clone() - clone.ForceAttemptHTTP2 = false - // Wipe TLSNextProto to prevent implicit HTTP/2 upgrade. - clone.TLSNextProto = make(map[string]func(authority string, c *tls.Conn) http.RoundTripper) - if clone.TLSClientConfig == nil { - clone.TLSClientConfig = &tls.Config{} - } else { - clone.TLSClientConfig = clone.TLSClientConfig.Clone() - } - // Actively advertise only HTTP/1.1 in the ALPN handshake. - clone.TLSClientConfig.NextProtos = []string{"http/1.1"} - return clone -} - -// initAntigravityTransport creates the shared HTTP/1.1 transport exactly once. -func initAntigravityTransport() { - base, ok := http.DefaultTransport.(*http.Transport) - if !ok { - base = &http.Transport{} - } - antigravityTransport = cloneTransportWithHTTP11(base) -} - -// newAntigravityHTTPClient creates an HTTP client specifically for Antigravity, -// enforcing HTTP/1.1 by disabling HTTP/2 to perfectly mimic Node.js https defaults. -// The underlying Transport is a singleton to avoid leaking connection pools. -func newAntigravityHTTPClient(ctx context.Context, cfg *config.Config, auth *cliproxyauth.Auth, timeout time.Duration) *http.Client { - antigravityTransportOnce.Do(initAntigravityTransport) - - client := newProxyAwareHTTPClient(ctx, cfg, auth, timeout) - // If no transport is set, use the shared HTTP/1.1 transport. - if client.Transport == nil { - client.Transport = antigravityTransport - return client - } - - // Preserve proxy settings from proxy-aware transports while forcing HTTP/1.1. - if transport, ok := client.Transport.(*http.Transport); ok { - client.Transport = cloneTransportWithHTTP11(transport) - } - return client -} - // Identifier returns the executor identifier. func (e *AntigravityExecutor) Identifier() string { return antigravityAuthType } @@ -219,8 +162,6 @@ func (e *AntigravityExecutor) PrepareRequest(req *http.Request, auth *cliproxyau } // HttpRequest injects Antigravity credentials into the request and executes it. -// It uses a whitelist approach: all incoming headers are stripped and only -// the minimum set required by the Antigravity protocol is explicitly set. func (e *AntigravityExecutor) HttpRequest(ctx context.Context, auth *cliproxyauth.Auth, req *http.Request) (*http.Response, error) { if req == nil { return nil, fmt.Errorf("antigravity executor: request is nil") @@ -229,29 +170,10 @@ func (e *AntigravityExecutor) HttpRequest(ctx context.Context, auth *cliproxyaut ctx = req.Context() } httpReq := req.WithContext(ctx) - - // --- Whitelist: save only the headers we need from the original request --- - contentType := httpReq.Header.Get("Content-Type") - - // Wipe ALL incoming headers - for k := range httpReq.Header { - delete(httpReq.Header, k) - } - - // --- Set only the headers Antigravity actually sends --- - if contentType != "" { - httpReq.Header.Set("Content-Type", contentType) - } - // Content-Length is managed automatically by Go's http.Client from the Body - httpReq.Header.Set("User-Agent", resolveUserAgent(auth)) - httpReq.Close = true // sends Connection: close - - // Inject Authorization: Bearer if err := e.PrepareRequest(httpReq, auth); err != nil { return nil, err } - - httpClient := newAntigravityHTTPClient(ctx, e.cfg, auth, 0) + httpClient := newProxyAwareHTTPClient(ctx, e.cfg, auth, 0) return httpClient.Do(httpReq) } @@ -263,7 +185,7 @@ func (e *AntigravityExecutor) Execute(ctx context.Context, auth *cliproxyauth.Au baseModel := thinking.ParseSuffix(req.Model).ModelName isClaude := strings.Contains(strings.ToLower(baseModel), "claude") - if isClaude || strings.Contains(baseModel, "gemini-3-pro") || strings.Contains(baseModel, "gemini-3.1-flash-image") { + if isClaude || strings.Contains(baseModel, "gemini-3-pro") { return e.executeClaudeNonStream(ctx, auth, req, opts) } @@ -298,7 +220,7 @@ func (e *AntigravityExecutor) Execute(ctx context.Context, auth *cliproxyauth.Au translated = applyPayloadConfigWithRoot(e.cfg, baseModel, "antigravity", "request", translated, originalTranslated, requestedModel) baseURLs := antigravityBaseURLFallbackOrder(auth) - httpClient := newAntigravityHTTPClient(ctx, e.cfg, auth, 0) + httpClient := newProxyAwareHTTPClient(ctx, e.cfg, auth, 0) attempts := antigravityRetryAttempts(auth, e.cfg) @@ -440,7 +362,7 @@ func (e *AntigravityExecutor) executeClaudeNonStream(ctx context.Context, auth * translated = applyPayloadConfigWithRoot(e.cfg, baseModel, "antigravity", "request", translated, originalTranslated, requestedModel) baseURLs := antigravityBaseURLFallbackOrder(auth) - httpClient := newAntigravityHTTPClient(ctx, e.cfg, auth, 0) + httpClient := newProxyAwareHTTPClient(ctx, e.cfg, auth, 0) attempts := antigravityRetryAttempts(auth, e.cfg) @@ -832,7 +754,7 @@ func (e *AntigravityExecutor) ExecuteStream(ctx context.Context, auth *cliproxya translated = applyPayloadConfigWithRoot(e.cfg, baseModel, "antigravity", "request", translated, originalTranslated, requestedModel) baseURLs := antigravityBaseURLFallbackOrder(auth) - httpClient := newAntigravityHTTPClient(ctx, e.cfg, auth, 0) + httpClient := newProxyAwareHTTPClient(ctx, e.cfg, auth, 0) attempts := antigravityRetryAttempts(auth, e.cfg) @@ -1034,7 +956,7 @@ func (e *AntigravityExecutor) CountTokens(ctx context.Context, auth *cliproxyaut payload = deleteJSONField(payload, "request.safetySettings") baseURLs := antigravityBaseURLFallbackOrder(auth) - httpClient := newAntigravityHTTPClient(ctx, e.cfg, auth, 0) + httpClient := newProxyAwareHTTPClient(ctx, e.cfg, auth, 0) var authID, authLabel, authType, authValue string if auth != nil { @@ -1065,10 +987,10 @@ func (e *AntigravityExecutor) CountTokens(ctx context.Context, auth *cliproxyaut if errReq != nil { return cliproxyexecutor.Response{}, errReq } - httpReq.Close = true httpReq.Header.Set("Content-Type", "application/json") httpReq.Header.Set("Authorization", "Bearer "+token) httpReq.Header.Set("User-Agent", resolveUserAgent(auth)) + httpReq.Header.Set("Accept", "application/json") if host := resolveHost(base); host != "" { httpReq.Host = host } @@ -1162,26 +1084,14 @@ func FetchAntigravityModels(ctx context.Context, auth *cliproxyauth.Auth, cfg *c } baseURLs := antigravityBaseURLFallbackOrder(auth) - httpClient := newAntigravityHTTPClient(ctx, cfg, auth, 0) + httpClient := newProxyAwareHTTPClient(ctx, cfg, auth, 0) for idx, baseURL := range baseURLs { modelsURL := baseURL + antigravityModelsPath - - var payload []byte - if auth != nil && auth.Metadata != nil { - if pid, ok := auth.Metadata["project_id"].(string); ok && strings.TrimSpace(pid) != "" { - payload = []byte(fmt.Sprintf(`{"project": "%s"}`, strings.TrimSpace(pid))) - } - } - if len(payload) == 0 { - payload = []byte(`{}`) - } - - httpReq, errReq := http.NewRequestWithContext(ctx, http.MethodPost, modelsURL, bytes.NewReader(payload)) + httpReq, errReq := http.NewRequestWithContext(ctx, http.MethodPost, modelsURL, bytes.NewReader([]byte(`{}`))) if errReq != nil { return fallbackAntigravityPrimaryModels() } - httpReq.Close = true httpReq.Header.Set("Content-Type", "application/json") httpReq.Header.Set("Authorization", "Bearer "+token) httpReq.Header.Set("User-Agent", resolveUserAgent(auth)) @@ -1242,8 +1152,7 @@ func FetchAntigravityModels(ctx context.Context, auth *cliproxyauth.Auth, cfg *c continue } switch modelID { - case "chat_20706", "chat_23310", "gemini-2.5-flash-thinking", "gemini-3-pro-low", "gemini-2.5-pro", - "tab_jump_flash_lite_preview", "tab_flash_lite_preview", "gemini-2.5-flash-lite": + case "chat_20706", "chat_23310", "tab_flash_lite_preview", "tab_jump_flash_lite_preview", "gemini-2.5-flash-thinking", "gemini-2.5-pro": continue } modelCfg := modelConfig[modelID] @@ -1265,29 +1174,6 @@ func FetchAntigravityModels(ctx context.Context, auth *cliproxyauth.Auth, cfg *c OwnedBy: antigravityAuthType, Type: antigravityAuthType, } - - // Build input modalities from upstream capability flags. - inputModalities := []string{"TEXT"} - if modelData.Get("supportsImages").Bool() { - inputModalities = append(inputModalities, "IMAGE") - } - if modelData.Get("supportsVideo").Bool() { - inputModalities = append(inputModalities, "VIDEO") - } - modelInfo.SupportedInputModalities = inputModalities - modelInfo.SupportedOutputModalities = []string{"TEXT"} - - // Token limits from upstream. - if maxTok := modelData.Get("maxTokens").Int(); maxTok > 0 { - modelInfo.InputTokenLimit = int(maxTok) - } - if maxOut := modelData.Get("maxOutputTokens").Int(); maxOut > 0 { - modelInfo.OutputTokenLimit = int(maxOut) - } - - // Supported generation methods (Gemini v1beta convention). - modelInfo.SupportedGenerationMethods = []string{"generateContent", "countTokens"} - // Look up Thinking support from static config using upstream model name. if modelCfg != nil { if modelCfg.Thinking != nil { @@ -1355,11 +1241,10 @@ func (e *AntigravityExecutor) refreshToken(ctx context.Context, auth *cliproxyau return auth, errReq } httpReq.Header.Set("Host", "oauth2.googleapis.com") + httpReq.Header.Set("User-Agent", defaultAntigravityAgent) httpReq.Header.Set("Content-Type", "application/x-www-form-urlencoded") - // Real Antigravity uses Go's default User-Agent for OAuth token refresh - httpReq.Header.Set("User-Agent", "Go-http-client/2.0") - httpClient := newAntigravityHTTPClient(ctx, e.cfg, auth, 0) + httpClient := newProxyAwareHTTPClient(ctx, e.cfg, auth, 0) httpResp, errDo := httpClient.Do(httpReq) if errDo != nil { return auth, errDo @@ -1430,7 +1315,7 @@ func (e *AntigravityExecutor) ensureAntigravityProjectID(ctx context.Context, au return nil } - httpClient := newAntigravityHTTPClient(ctx, e.cfg, auth, 0) + httpClient := newProxyAwareHTTPClient(ctx, e.cfg, auth, 0) projectID, errFetch := sdkAuth.FetchAntigravityProjectID(ctx, token, httpClient) if errFetch != nil { return errFetch @@ -1484,7 +1369,7 @@ func (e *AntigravityExecutor) buildRequest(ctx context.Context, auth *cliproxyau payload = geminiToAntigravity(modelName, payload, projectID) payload, _ = sjson.SetBytes(payload, "model", modelName) - useAntigravitySchema := strings.Contains(modelName, "claude") || strings.Contains(modelName, "gemini-3-pro-high") || strings.Contains(modelName, "gemini-3.1-pro") + useAntigravitySchema := strings.Contains(modelName, "claude") || strings.Contains(modelName, "gemini-3-pro-high") payloadStr := string(payload) paths := make([]string, 0) util.Walk(gjson.Parse(payloadStr), "", "parametersJsonSchema", &paths) @@ -1521,10 +1406,14 @@ func (e *AntigravityExecutor) buildRequest(ctx context.Context, auth *cliproxyau if errReq != nil { return nil, errReq } - httpReq.Close = true httpReq.Header.Set("Content-Type", "application/json") httpReq.Header.Set("Authorization", "Bearer "+token) httpReq.Header.Set("User-Agent", resolveUserAgent(auth)) + if stream { + httpReq.Header.Set("Accept", "text/event-stream") + } else { + httpReq.Header.Set("Accept", "application/json") + } if host := resolveHost(base); host != "" { httpReq.Host = host } @@ -1736,16 +1625,7 @@ func resolveCustomAntigravityBaseURL(auth *cliproxyauth.Auth) string { func geminiToAntigravity(modelName string, payload []byte, projectID string) []byte { template, _ := sjson.Set(string(payload), "model", modelName) template, _ = sjson.Set(template, "userAgent", "antigravity") - - isImageModel := strings.Contains(modelName, "image") - - var reqType string - if isImageModel { - reqType = "image_gen" - } else { - reqType = "agent" - } - template, _ = sjson.Set(template, "requestType", reqType) + template, _ = sjson.Set(template, "requestType", "agent") // Use real project ID from auth if available, otherwise generate random (legacy fallback) if projectID != "" { @@ -1753,13 +1633,8 @@ func geminiToAntigravity(modelName string, payload []byte, projectID string) []b } else { template, _ = sjson.Set(template, "project", generateProjectID()) } - - if isImageModel { - template, _ = sjson.Set(template, "requestId", generateImageGenRequestID()) - } else { - template, _ = sjson.Set(template, "requestId", generateRequestID()) - template, _ = sjson.Set(template, "request.sessionId", generateStableSessionID(payload)) - } + template, _ = sjson.Set(template, "requestId", generateRequestID()) + template, _ = sjson.Set(template, "request.sessionId", generateStableSessionID(payload)) template, _ = sjson.Delete(template, "request.safetySettings") if toolConfig := gjson.Get(template, "toolConfig"); toolConfig.Exists() && !gjson.Get(template, "request.toolConfig").Exists() { @@ -1773,10 +1648,6 @@ func generateRequestID() string { return "agent-" + uuid.NewString() } -func generateImageGenRequestID() string { - return fmt.Sprintf("image_gen/%d/%s/12", time.Now().UnixMilli(), uuid.NewString()) -} - func generateSessionID() string { randSourceMutex.Lock() n := randSource.Int63n(9_000_000_000_000_000_000)