fix(ai): antigravity endpoint cascade on 403/404, add autopush fallback, strip extra headers

closes #1830
This commit is contained in:
Mario Zechner 2026-03-05 21:59:43 +01:00
parent 8f2af2ae7e
commit cfbb15876a
3 changed files with 25 additions and 10 deletions

View file

@ -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;