fix(oauth): scope antigravity header fixes to loadCodeAssist/onboardUser only
Google fingerprints User-Agent/Client-Metadata on loadCodeAssist and onboardUser, silently refusing to provision a cloudaicompanionProject when they don't match the real IDE. Split antigravity's headers out of the shared gemini-cli constants instead of overwriting them, so the fix doesn't touch gemini-cli or any other provider. Inspired by #3000 (thanks @stoXmod for flagging the resource-exhausted issue), rewritten to keep gemini-cli untouched.
This commit is contained in:
@@ -156,6 +156,13 @@ export const LOAD_CODE_ASSIST_HEADERS = {
|
|||||||
"Client-Metadata": JSON.stringify({ ideType: IDE_TYPE.ANTIGRAVITY, platform: getPlatformEnum(), pluginType: PLUGIN_TYPE.GEMINI }),
|
"Client-Metadata": JSON.stringify({ ideType: IDE_TYPE.ANTIGRAVITY, platform: getPlatformEnum(), pluginType: PLUGIN_TYPE.GEMINI }),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Real Antigravity IDE doesn't send X-Goog-Api-Client/Client-Metadata on loadCodeAssist/onboardUser —
|
||||||
|
// Google's backend fingerprints those and silently refuses to provision a cloudaicompanionProject.
|
||||||
|
export const ANTIGRAVITY_LOAD_CODE_ASSIST_HEADERS = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"User-Agent": ANTIGRAVITY_IDE_USER_AGENT,
|
||||||
|
};
|
||||||
|
|
||||||
export const LOAD_CODE_ASSIST_METADATA = {
|
export const LOAD_CODE_ASSIST_METADATA = {
|
||||||
ideType: IDE_TYPE.ANTIGRAVITY,
|
ideType: IDE_TYPE.ANTIGRAVITY,
|
||||||
platform: getPlatformEnum(),
|
platform: getPlatformEnum(),
|
||||||
|
|||||||
@@ -76,8 +76,7 @@ export default {
|
|||||||
apiVersion: "v1internal",
|
apiVersion: "v1internal",
|
||||||
loadCodeAssistEndpoint: "https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist",
|
loadCodeAssistEndpoint: "https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist",
|
||||||
onboardUserEndpoint: "https://cloudcode-pa.googleapis.com/v1internal:onboardUser",
|
onboardUserEndpoint: "https://cloudcode-pa.googleapis.com/v1internal:onboardUser",
|
||||||
loadCodeAssistUserAgent: "google-api-nodejs-client/9.15.1",
|
loadCodeAssistUserAgent: ANTIGRAVITY_IDE_USER_AGENT,
|
||||||
loadCodeAssistApiClient: "google-cloud-sdk vscode_cloudshelleditor/0.1",
|
|
||||||
refreshLeadMs: 300000,
|
refreshLeadMs: 300000,
|
||||||
},
|
},
|
||||||
features: {
|
features: {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
* This significantly reduces the risk of being flagged by Google's anti-abuse systems.
|
* This significantly reduces the risk of being flagged by Google's anti-abuse systems.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { CLOUD_CODE_API, LOAD_CODE_ASSIST_HEADERS, LOAD_CODE_ASSIST_METADATA } from "../config/appConstants.js";
|
import { CLOUD_CODE_API, LOAD_CODE_ASSIST_HEADERS, ANTIGRAVITY_LOAD_CODE_ASSIST_HEADERS, LOAD_CODE_ASSIST_METADATA } from "../config/appConstants.js";
|
||||||
|
|
||||||
// ─── Cache ────────────────────────────────────────────────────────────────────
|
// ─── Cache ────────────────────────────────────────────────────────────────────
|
||||||
// connectionId -> { projectId: string, fetchedAt: number }
|
// connectionId -> { projectId: string, fetchedAt: number }
|
||||||
@@ -157,9 +157,10 @@ export function removeConnection(connectionId) {
|
|||||||
*/
|
*/
|
||||||
async function fetchProjectId(accessToken, signal, provider) {
|
async function fetchProjectId(accessToken, signal, provider) {
|
||||||
const endpoints = CLOUD_CODE_API[provider] || CLOUD_CODE_API["gemini-cli"];
|
const endpoints = CLOUD_CODE_API[provider] || CLOUD_CODE_API["gemini-cli"];
|
||||||
|
const headers = provider === "antigravity" ? ANTIGRAVITY_LOAD_CODE_ASSIST_HEADERS : LOAD_CODE_ASSIST_HEADERS;
|
||||||
const response = await fetch(endpoints.loadCodeAssist, {
|
const response = await fetch(endpoints.loadCodeAssist, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { ...LOAD_CODE_ASSIST_HEADERS, "Authorization": `Bearer ${accessToken}` },
|
headers: { ...headers, "Authorization": `Bearer ${accessToken}` },
|
||||||
body: JSON.stringify({ metadata: LOAD_CODE_ASSIST_METADATA }),
|
body: JSON.stringify({ metadata: LOAD_CODE_ASSIST_METADATA }),
|
||||||
signal
|
signal
|
||||||
});
|
});
|
||||||
@@ -186,7 +187,7 @@ async function fetchProjectId(accessToken, signal, provider) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return onboardUser(accessToken, tierID, signal, endpoints);
|
return onboardUser(accessToken, tierID, signal, endpoints, provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -197,10 +198,11 @@ async function fetchProjectId(accessToken, signal, provider) {
|
|||||||
* @param {AbortSignal} externalSignal – propagated from the connection's AbortController
|
* @param {AbortSignal} externalSignal – propagated from the connection's AbortController
|
||||||
* @returns {Promise<string|null>}
|
* @returns {Promise<string|null>}
|
||||||
*/
|
*/
|
||||||
async function onboardUser(accessToken, tierID, externalSignal, endpoints) {
|
async function onboardUser(accessToken, tierID, externalSignal, endpoints, provider) {
|
||||||
console.log(`[ProjectId] Onboarding user with tier: ${tierID}`);
|
console.log(`[ProjectId] Onboarding user with tier: ${tierID}`);
|
||||||
|
|
||||||
const reqBody = { tierId: tierID, metadata: LOAD_CODE_ASSIST_METADATA };
|
const reqBody = { tierId: tierID, metadata: LOAD_CODE_ASSIST_METADATA };
|
||||||
|
const headers = provider === "antigravity" ? ANTIGRAVITY_LOAD_CODE_ASSIST_HEADERS : LOAD_CODE_ASSIST_HEADERS;
|
||||||
const MAX_ATTEMPTS = 5;
|
const MAX_ATTEMPTS = 5;
|
||||||
|
|
||||||
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
||||||
@@ -216,7 +218,7 @@ async function onboardUser(accessToken, tierID, externalSignal, endpoints) {
|
|||||||
try {
|
try {
|
||||||
const response = await fetch(endpoints.onboardUser, {
|
const response = await fetch(endpoints.onboardUser, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { ...LOAD_CODE_ASSIST_HEADERS, "Authorization": `Bearer ${accessToken}` },
|
headers: { ...headers, "Authorization": `Bearer ${accessToken}` },
|
||||||
body: JSON.stringify(reqBody),
|
body: JSON.stringify(reqBody),
|
||||||
signal: localCtrl.signal
|
signal: localCtrl.signal
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -39,13 +39,10 @@ const antigravity = {
|
|||||||
return await response.json();
|
return await response.json();
|
||||||
},
|
},
|
||||||
postExchange: async (tokens) => {
|
postExchange: async (tokens) => {
|
||||||
// Numeric enums matching Antigravity binary ClientMetadata
|
|
||||||
const loadHeaders = {
|
const loadHeaders = {
|
||||||
"Authorization": `Bearer ${tokens.access_token}`,
|
"Authorization": `Bearer ${tokens.access_token}`,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"User-Agent": ANTIGRAVITY_CONFIG.loadCodeAssistUserAgent,
|
"User-Agent": ANTIGRAVITY_CONFIG.loadCodeAssistUserAgent,
|
||||||
"X-Goog-Api-Client": ANTIGRAVITY_CONFIG.loadCodeAssistApiClient,
|
|
||||||
"Client-Metadata": ANTIGRAVITY_CONFIG.loadCodeAssistClientMetadata,
|
|
||||||
"x-request-source": "local",
|
"x-request-source": "local",
|
||||||
};
|
};
|
||||||
const metadata = getOAuthClientMetadata();
|
const metadata = getOAuthClientMetadata();
|
||||||
|
|||||||
@@ -85,8 +85,6 @@ export class AntigravityService {
|
|||||||
"Authorization": `Bearer ${accessToken}`,
|
"Authorization": `Bearer ${accessToken}`,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"User-Agent": this.config.loadCodeAssistUserAgent,
|
"User-Agent": this.config.loadCodeAssistUserAgent,
|
||||||
"X-Goog-Api-Client": this.config.loadCodeAssistApiClient,
|
|
||||||
"Client-Metadata": this.config.loadCodeAssistClientMetadata,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user