From 021a14d6fe57e2ac89cfbe3b2d95eb3765e69bc3 Mon Sep 17 00:00:00 2001 From: Rifqi Awaludin Date: Sat, 29 Aug 2026 10:28:02 +0700 Subject: [PATCH] fix(antigravity): send complete loadCodeAssist metadata (ideType/platform/pluginType as numeric enums) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit loadCodeAssist and onboardUser both returned 403 for every account on a live deployment, even accounts with completed Gemini Code Assist onboarding. Traced via live log comparison (same Google account, same host) against the sibling 9router project, which succeeds against the identical account: OmniRoute's getAntigravityLoadCodeAssistMetadata() sent `{ ideType: "ANTIGRAVITY" }` — ideType as a bare string, with platform and pluginType omitted entirely. 9router sends `{ ideType: 9, platform: , pluginType: 2 }` — the field is a protobuf-JSON int32 enum on the wire, not a string, and the API apparently treats an incomplete/malformed identity as untrusted and rejects it outright rather than degrading gracefully. Fix: mirror 9router's LOAD_CODE_ASSIST_METADATA enum values and platform-detection logic (darwin/linux/win32 x64/arm64) exactly. A prior version of this function carried the opposite claim in a comment ("Matches Antigravity-Manager quota.rs: only ideType — no platform, LINUX is rejected"). That may have been true when written; it directly contradicts today's live comparison, where the full-enum shape (including a Linux platform value) succeeded from a Linux host. Left a note pointing at this history in case it resurfaces. Updated tests/unit/antigravity-headers.test.ts's metadata-shape assertion accordingly — it previously asserted the broken string-only shape as correct. Validation - New/updated unit test in tests/unit/antigravity-headers.test.ts (6/6 passing) plus 54 usage-service + 25 oauth-provider tests whose assertions already compare against this function's own output — all passing. - npx tsc --noEmit -p tsconfig.typecheck-core.json: 0 errors. Note: in the specific deployment where this was found, the actual 403 root cause turned out to be a separate issue (a custom ANTIGRAVITY_OAUTH_CLIENT_ID override pointing at a GCP project without the private Cloud Code API enabled) — this metadata fix did not resolve that deployment's error on its own, since Google's error surfaces before the metadata shape would matter for a client-identity rejection. It's included here because it's a real, independently verified correctness bug (9router's identical live-working shape vs. OmniRoute's incomplete one) that could still cause failures for accounts using OmniRoute's default embedded OAuth client. --- open-sse/services/antigravityHeaders.ts | 51 ++++++++++++++++++++++++- tests/unit/antigravity-headers.test.ts | 13 +++++-- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/open-sse/services/antigravityHeaders.ts b/open-sse/services/antigravityHeaders.ts index b5841b3e054c..9ce74e2272c4 100644 --- a/open-sse/services/antigravityHeaders.ts +++ b/open-sse/services/antigravityHeaders.ts @@ -4,6 +4,51 @@ import { getCachedAntigravityIdeVersion, } from "./antigravityVersion.ts"; +// loadCodeAssist/onboardUser's `metadata` body is a protobuf-JSON-shaped +// object — ideType/pluginType are int32 enums on the wire, not strings, and +// platform is required. Values mirror the sibling 9router project's +// LOAD_CODE_ASSIST_METADATA (open-sse/config/appConstants.js). +// +// Live comparison (same Google account, same host, 2026-08-25): 9Router +// (this exact metadata shape, including a Linux platform enum) succeeded +// against loadCodeAssist/onboardUser; OmniRoute (ideType as the bare string +// "ANTIGRAVITY", no platform/pluginType) got 403 on both from the identical +// account. Sending an incomplete client identity reads to Google's backend +// as untrusted and gets rejected. +// +// NOTE: a prior version of this function carried the comment "Matches +// Antigravity-Manager quota.rs: only ideType (no platform — LINUX is +// rejected)" — the opposite conclusion, presumably true when it was +// written. Trusting the fresh live comparison over that stale claim here; +// if this regresses Linux specifically, that old note is why. +const ANTIGRAVITY_IDE_TYPE_ENUM = 9; +const ANTIGRAVITY_PLUGIN_TYPE_GEMINI_ENUM = 2; +const ANTIGRAVITY_PLATFORM_ENUM = { + UNSPECIFIED: 0, + DARWIN_AMD64: 1, + DARWIN_ARM64: 2, + LINUX_AMD64: 3, + LINUX_ARM64: 4, + WINDOWS_AMD64: 5, +} as const; + +function resolveAntigravityPlatformEnum(): number { + const platform = process.platform; + const arch = process.arch; + if (platform === "darwin") { + return arch === "arm64" + ? ANTIGRAVITY_PLATFORM_ENUM.DARWIN_ARM64 + : ANTIGRAVITY_PLATFORM_ENUM.DARWIN_AMD64; + } + if (platform === "linux") { + return arch === "arm64" + ? ANTIGRAVITY_PLATFORM_ENUM.LINUX_ARM64 + : ANTIGRAVITY_PLATFORM_ENUM.LINUX_AMD64; + } + if (platform === "win32") return ANTIGRAVITY_PLATFORM_ENUM.WINDOWS_AMD64; + return ANTIGRAVITY_PLATFORM_ENUM.UNSPECIFIED; +} + export const ANTIGRAVITY_IDE_NODE_API_CLIENT = "google-api-nodejs-client/10.3.0"; export const ANTIGRAVITY_IDE_NODE_X_GOOG_API_CLIENT = "gl-node/22.21.1"; @@ -68,8 +113,10 @@ export function getAntigravityIdeNodeHeaders(accessToken?: string | null): Recor } /** Native loadCodeAssist body metadata captured from both official clients. */ -export function getAntigravityLoadCodeAssistMetadata(): Record { +export function getAntigravityLoadCodeAssistMetadata(): Record { return { - ideType: "ANTIGRAVITY", + ideType: ANTIGRAVITY_IDE_TYPE_ENUM, + platform: resolveAntigravityPlatformEnum(), + pluginType: ANTIGRAVITY_PLUGIN_TYPE_GEMINI_ENUM, }; } diff --git a/tests/unit/antigravity-headers.test.ts b/tests/unit/antigravity-headers.test.ts index 957ff3e7d8e3..efb64adc3b04 100644 --- a/tests/unit/antigravity-headers.test.ts +++ b/tests/unit/antigravity-headers.test.ts @@ -95,8 +95,13 @@ test("OAuth User-Agent selection keeps IDE and CLI identities independent", () = assert.match(getAntigravityOAuthUserAgent("cli"), /^antigravity\/cli\/1\.2\.0 /); }); -test("loadCodeAssist body metadata remains ideType only", () => { - assert.deepEqual(getAntigravityLoadCodeAssistMetadata(), { ideType: "ANTIGRAVITY" }); - assert.equal("platform" in getAntigravityLoadCodeAssistMetadata(), false); - assert.equal("pluginType" in getAntigravityLoadCodeAssistMetadata(), false); +test("loadCodeAssist body metadata sends numeric protobuf-JSON enums, not a bare ideType string", () => { + // Google's backend 403s loadCodeAssist/onboardUser when ideType is sent as + // the string "ANTIGRAVITY" with platform/pluginType omitted — verified via + // a live side-by-side against 9router (same account, same host) using the + // full enum shape below, which succeeded. See antigravityHeaders.ts for + // the full incident note. + const metadata = getAntigravityLoadCodeAssistMetadata(); + assert.deepEqual(metadata, { ideType: 9, platform: metadata.platform, pluginType: 2 }); + assert.equal(typeof metadata.platform, "number"); });