From cfbb15876aa5a766d2309741f92a8c19d5749e72 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Thu, 5 Mar 2026 21:59:43 +0100 Subject: [PATCH] fix(ai): antigravity endpoint cascade on 403/404, add autopush fallback, strip extra headers closes #1830 --- packages/ai/CHANGELOG.md | 1 + .../ai/src/providers/google-gemini-cli.ts | 33 +++++++++++++------ packages/coding-agent/CHANGELOG.md | 1 + 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index fddab649..dc9036f2 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixed - Preserved OpenAI Responses assistant `phase` metadata (`commentary`, `final_answer`) across turns by encoding `id` and `phase` in `textSignature` for session persistence and replay, with backward compatibility for legacy plain signatures ([#1819](https://github.com/badlogic/pi-mono/issues/1819)). +- Fixed Antigravity endpoint fallback: 403/404 responses now cascade to the next endpoint instead of throwing immediately, added `autopush-cloudcode-pa.sandbox` endpoint to the fallback list, and removed extra fingerprint headers (`X-Goog-Api-Client`, `Client-Metadata`) from Antigravity requests ([#1830](https://github.com/badlogic/pi-mono/issues/1830)). ## [0.56.1] - 2026-03-05 diff --git a/packages/ai/src/providers/google-gemini-cli.ts b/packages/ai/src/providers/google-gemini-cli.ts index 411daac8..feacb16f 100644 --- a/packages/ai/src/providers/google-gemini-cli.ts +++ b/packages/ai/src/providers/google-gemini-cli.ts @@ -59,7 +59,12 @@ export interface GoogleGeminiCliOptions extends StreamOptions { const DEFAULT_ENDPOINT = "https://cloudcode-pa.googleapis.com"; const ANTIGRAVITY_DAILY_ENDPOINT = "https://daily-cloudcode-pa.sandbox.googleapis.com"; -const ANTIGRAVITY_ENDPOINT_FALLBACKS = [ANTIGRAVITY_DAILY_ENDPOINT, DEFAULT_ENDPOINT] as const; +const ANTIGRAVITY_AUTOPUSH_ENDPOINT = "https://autopush-cloudcode-pa.sandbox.googleapis.com"; +const ANTIGRAVITY_ENDPOINT_FALLBACKS = [ + ANTIGRAVITY_DAILY_ENDPOINT, + ANTIGRAVITY_AUTOPUSH_ENDPOINT, + DEFAULT_ENDPOINT, +] as const; // Headers for Gemini CLI (prod endpoint) const GEMINI_CLI_HEADERS = { "User-Agent": "google-cloud-sdk vscode_cloudshelleditor/0.1", @@ -78,12 +83,6 @@ function getAntigravityHeaders() { const version = process.env.PI_AI_ANTIGRAVITY_VERSION || DEFAULT_ANTIGRAVITY_VERSION; return { "User-Agent": `antigravity/${version} darwin/arm64`, - "X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1", - "Client-Metadata": JSON.stringify({ - ideType: "IDE_UNSPECIFIED", - platform: "PLATFORM_UNSPECIFIED", - pluginType: "GEMINI", - }), }; } @@ -385,10 +384,13 @@ export const streamGoogleGeminiCli: StreamFunction<"google-gemini-cli", GoogleGe }; const requestBodyJson = JSON.stringify(requestBody); - // Fetch with retry logic for rate limits and transient errors + // Fetch with retry logic for rate limits, transient errors, and endpoint fallbacks. + // On 403/404, immediately try the next endpoint (no delay). + // On 429/5xx, retry with backoff on the same or next endpoint. let response: Response | undefined; let lastError: Error | undefined; let requestUrl: string | undefined; + let endpointIndex = 0; for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) { if (options?.signal?.aborted) { @@ -396,7 +398,7 @@ export const streamGoogleGeminiCli: StreamFunction<"google-gemini-cli", GoogleGe } try { - const endpoint = endpoints[Math.min(attempt, endpoints.length - 1)]; + const endpoint = endpoints[endpointIndex]; requestUrl = `${endpoint}/v1internal:streamGenerateContent?alt=sse`; response = await fetch(requestUrl, { method: "POST", @@ -411,8 +413,19 @@ export const streamGoogleGeminiCli: StreamFunction<"google-gemini-cli", GoogleGe const errorText = await response.text(); - // Check if retryable + // On 403/404, cascade to the next endpoint immediately (no delay) + if ((response.status === 403 || response.status === 404) && endpointIndex < endpoints.length - 1) { + endpointIndex++; + continue; + } + + // Check if retryable (429, 5xx, network patterns) if (attempt < MAX_RETRIES && isRetryableError(response.status, errorText)) { + // Advance endpoint if possible + if (endpointIndex < endpoints.length - 1) { + endpointIndex++; + } + // Use server-provided delay or exponential backoff const serverDelay = extractRetryDelay(errorText, response); const delayMs = serverDelay ?? BASE_DELAY_MS * 2 ** attempt; diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 11326e98..d9372a99 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixed - Fixed GPT-5.3 Codex follow-up turns dropping OpenAI Responses assistant `phase` metadata by preserving replayable signatures in session history and forwarding `phase` back to the Responses API ([#1819](https://github.com/badlogic/pi-mono/issues/1819)). +- Fixed Antigravity reliability: endpoint cascade on 403/404, added autopush sandbox fallback, removed extra fingerprint headers ([#1830](https://github.com/badlogic/pi-mono/issues/1830)). - Fixed editor/footer visibility drift during terminal resize by forcing full redraws when terminal width or height changes ([#1844](https://github.com/badlogic/pi-mono/pull/1844) by [@ghoulr](https://github.com/ghoulr)). - Fixed footer width truncation for wide Unicode text (session name, model, provider) to prevent TUI crashes from rendered lines exceeding terminal width ([#1833](https://github.com/badlogic/pi-mono/issues/1833)).