From b0a8d798446e491aa5e376d3998fd89678de7591 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Fri, 6 Feb 2026 18:44:57 +0100 Subject: [PATCH] fix(ai): guard google oauth node http imports for browser bundlers closes #1330 --- .../ai/src/utils/oauth/google-antigravity.ts | 21 +++++++++++++++++-- .../ai/src/utils/oauth/google-gemini-cli.ts | 21 +++++++++++++++++-- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/packages/ai/src/utils/oauth/google-antigravity.ts b/packages/ai/src/utils/oauth/google-antigravity.ts index 70033fa3..e9ef3c74 100644 --- a/packages/ai/src/utils/oauth/google-antigravity.ts +++ b/packages/ai/src/utils/oauth/google-antigravity.ts @@ -6,7 +6,7 @@ * It is only intended for CLI use, not browser environments. */ -import type { Server } from "http"; +import type { Server } from "node:http"; import { generatePKCE } from "./pkce.js"; import type { OAuthCredentials, OAuthLoginCallbacks, OAuthProviderInterface } from "./types.js"; @@ -14,6 +14,14 @@ type AntigravityCredentials = OAuthCredentials & { projectId: string; }; +let _createServer: typeof import("node:http").createServer | null = null; +let _httpImportPromise: Promise | null = null; +if (typeof process !== "undefined" && (process.versions?.node || process.versions?.bun)) { + _httpImportPromise = import("node:http").then((m) => { + _createServer = m.createServer; + }); +} + // Antigravity OAuth credentials (different from Gemini CLI) const decode = (s: string) => atob(s); const CLIENT_ID = decode( @@ -46,8 +54,17 @@ type CallbackServerInfo = { /** * Start a local HTTP server to receive the OAuth callback */ +async function getNodeCreateServer(): Promise { + if (_createServer) return _createServer; + if (_httpImportPromise) { + await _httpImportPromise; + } + if (_createServer) return _createServer; + throw new Error("Antigravity OAuth is only available in Node.js environments"); +} + async function startCallbackServer(): Promise { - const { createServer } = await import("http"); + const createServer = await getNodeCreateServer(); return new Promise((resolve, reject) => { let result: { code: string; state: string } | null = null; diff --git a/packages/ai/src/utils/oauth/google-gemini-cli.ts b/packages/ai/src/utils/oauth/google-gemini-cli.ts index 29fdc710..a90524fe 100644 --- a/packages/ai/src/utils/oauth/google-gemini-cli.ts +++ b/packages/ai/src/utils/oauth/google-gemini-cli.ts @@ -6,7 +6,7 @@ * It is only intended for CLI use, not browser environments. */ -import type { Server } from "http"; +import type { Server } from "node:http"; import { generatePKCE } from "./pkce.js"; import type { OAuthCredentials, OAuthLoginCallbacks, OAuthProviderInterface } from "./types.js"; @@ -14,6 +14,14 @@ type GeminiCredentials = OAuthCredentials & { projectId: string; }; +let _createServer: typeof import("node:http").createServer | null = null; +let _httpImportPromise: Promise | null = null; +if (typeof process !== "undefined" && (process.versions?.node || process.versions?.bun)) { + _httpImportPromise = import("node:http").then((m) => { + _createServer = m.createServer; + }); +} + const decode = (s: string) => atob(s); const CLIENT_ID = decode( "NjgxMjU1ODA5Mzk1LW9vOGZ0Mm9wcmRybnA5ZTNhcWY2YXYzaG1kaWIxMzVqLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29t", @@ -38,8 +46,17 @@ type CallbackServerInfo = { /** * Start a local HTTP server to receive the OAuth callback */ +async function getNodeCreateServer(): Promise { + if (_createServer) return _createServer; + if (_httpImportPromise) { + await _httpImportPromise; + } + if (_createServer) return _createServer; + throw new Error("Gemini CLI OAuth is only available in Node.js environments"); +} + async function startCallbackServer(): Promise { - const { createServer } = await import("http"); + const createServer = await getNodeCreateServer(); return new Promise((resolve, reject) => { let result: { code: string; state: string } | null = null;