diff --git a/extensions/googlechat/npm-shrinkwrap.json b/extensions/googlechat/npm-shrinkwrap.json index 0eca5a1217d2..235fd9629db8 100644 --- a/extensions/googlechat/npm-shrinkwrap.json +++ b/extensions/googlechat/npm-shrinkwrap.json @@ -8,7 +8,6 @@ "name": "@openclaw/googlechat", "version": "2026.7.2", "dependencies": { - "gaxios": "7.1.5", "google-auth-library": "10.9.0", "zod": "4.4.3" }, diff --git a/extensions/googlechat/package.json b/extensions/googlechat/package.json index 4de940eaa32f..2a3b3ed05888 100644 --- a/extensions/googlechat/package.json +++ b/extensions/googlechat/package.json @@ -8,7 +8,6 @@ }, "type": "module", "dependencies": { - "gaxios": "7.1.5", "google-auth-library": "10.9.0", "zod": "4.4.3" }, diff --git a/extensions/googlechat/src/auth.ts b/extensions/googlechat/src/auth.ts index 9c66e9d109e6..d726f4761b71 100644 --- a/extensions/googlechat/src/auth.ts +++ b/extensions/googlechat/src/auth.ts @@ -30,18 +30,8 @@ async function readGoogleChatCertsResponse(response: Response): Promise>; type GoogleAuthInstance = InstanceType; -type GoogleAuthOptions = ConstructorParameters[0]; -type GoogleAuthTransport = NonNullable["clientOptions"] extends { - transporter?: infer T; -} - ? T - : never; type OAuth2ClientInstance = InstanceType; const authCache = new Map(); @@ -54,9 +44,7 @@ async function getVerifyClient(): Promise { verifyClientPromise = (async () => { try { const { OAuth2Client } = await loadGoogleAuthRuntime(); - // google-auth-library types its transporter through gaxios' CJS surface, - // while the plugin imports the ESM entrypoint directly. - const transporter = (await getGoogleAuthTransport()) as unknown as GoogleAuthTransport; + const transporter = await getGoogleAuthTransport(); return new OAuth2Client({ transporter }); } catch (error) { verifyClientPromise = null; @@ -83,12 +71,11 @@ async function getAuthInstance(account: ResolvedGoogleChatAccount): Promise { if (authCache.size > MAX_AUTH_CACHE_SIZE) { diff --git a/extensions/googlechat/src/google-auth.runtime.test.ts b/extensions/googlechat/src/google-auth.runtime.test.ts index 70174fcd7561..8eb6a7db348b 100644 --- a/extensions/googlechat/src/google-auth.runtime.test.ts +++ b/extensions/googlechat/src/google-auth.runtime.test.ts @@ -36,8 +36,8 @@ vi.mock("openclaw/plugin-sdk/ssrf-runtime", () => ({ fetchWithSsrFGuard: mocks.fetchWithSsrFGuard, })); -vi.mock("gaxios", () => ({ - Gaxios: mocks.gaxiosCtor, +vi.mock("google-auth-library", () => ({ + gaxios: { Gaxios: mocks.gaxiosCtor }, })); let testing: typeof import("./google-auth.runtime.js").testing; @@ -69,7 +69,7 @@ afterEach(() => { afterAll(() => { vi.doUnmock("openclaw/plugin-sdk/ssrf-runtime"); - vi.doUnmock("gaxios"); + vi.doUnmock("google-auth-library"); vi.resetModules(); }); diff --git a/extensions/googlechat/src/google-auth.runtime.ts b/extensions/googlechat/src/google-auth.runtime.ts index 3eb6dc3be709..f122a35389d1 100644 --- a/extensions/googlechat/src/google-auth.runtime.ts +++ b/extensions/googlechat/src/google-auth.runtime.ts @@ -10,33 +10,16 @@ import { import { resolveUserPath } from "openclaw/plugin-sdk/text-utility-runtime"; import type { ResolvedGoogleChatAccount } from "./accounts.js"; -type ProxyRule = RegExp | URL | string; type TlsCert = ConnectionOptions["cert"]; type TlsKey = ConnectionOptions["key"]; type FetchLike = (input: RequestInfo | URL, init?: RequestInit) => Promise; -type GoogleAuthModule = typeof import("google-auth-library"); -type GaxiosModule = typeof import("gaxios"); -type GoogleAuthRuntime = { - Gaxios: GaxiosModule["Gaxios"]; - GoogleAuth: GoogleAuthModule["GoogleAuth"]; - OAuth2Client: GoogleAuthModule["OAuth2Client"]; -}; -type GoogleAuthTransport = InstanceType; -type GoogleAuthRequestWithUnknownHeaders = RequestInit & { - headers?: unknown; -}; -type GoogleAuthResponseWithUnknownHeaders = { - headers?: unknown; -}; -type GuardedGoogleAuthRequestInit = RequestInit & { - agent?: unknown; - cert?: unknown; - dispatcher?: unknown; - fetchImplementation?: unknown; - key?: unknown; - noProxy?: unknown; - proxy?: unknown; -}; +type GoogleAuthRuntime = typeof import("google-auth-library"); +type GoogleAuthTransport = InstanceType; +type GoogleAuthTransportOptions = NonNullable< + ConstructorParameters[0] +>; +type GoogleAuthTransportInit = GoogleAuthTransportOptions & { dispatcher?: unknown }; +type ProxyRule = NonNullable[number]; type TlsOptions = { cert?: TlsCert; key?: TlsKey; @@ -48,16 +31,11 @@ type ProxyAgentLike = { type TlsAgentLike = { options?: TlsOptions; }; -type GoogleChatServiceAccountCredentials = Record & { - auth_provider_x509_cert_url?: string; - auth_uri?: string; - client_email: string; - client_x509_cert_url?: string; - private_key: string; - token_uri?: string; - type?: string; - universe_domain?: string; -}; +type GoogleChatServiceAccountCredentials = Record & + import("google-auth-library").JWTInput & { + client_email: string; + private_key: string; + }; const GOOGLE_AUTH_ALLOWED_HOST_SUFFIXES = ["accounts.google.com", "googleapis.com"]; const GOOGLE_AUTH_POLICY = buildHostnameAllowlistPolicyFromSuffixAllowlist( @@ -74,7 +52,7 @@ const MAX_GOOGLE_CHAT_SERVICE_ACCOUNT_FILE_BYTES = 64 * 1024; let googleAuthRuntimePromise: Promise | null = null; -function normalizeGoogleAuthPreparedRequestHeaders( +function normalizeGoogleAuthPreparedRequestHeaders( config: T, ): T & { headers: Headers } { if (!(config.headers instanceof Headers)) { @@ -83,7 +61,7 @@ function normalizeGoogleAuthPreparedRequestHeaders( +function normalizeGoogleAuthResponseHeaders( response: T, ): T & { headers: Headers } { if (!(response.headers instanceof Headers)) { @@ -118,7 +96,7 @@ function hasTlsAgentShape(value: unknown): value is TlsAgentLike { return record !== null && asNullableObjectRecord(record.options) !== null; } -function resolveGoogleAuthAgent(init: GuardedGoogleAuthRequestInit, url: URL): unknown { +function resolveGoogleAuthAgent(init: GoogleAuthTransportOptions, url: URL): unknown { return typeof init.agent === "function" ? init.agent(url) : init.agent; } @@ -126,10 +104,10 @@ function hasTlsOptions(options: TlsOptions): boolean { return options.cert !== undefined || options.key !== undefined; } -function resolveGoogleAuthTlsOptions(init: GuardedGoogleAuthRequestInit, url: URL): TlsOptions { +function resolveGoogleAuthTlsOptions(init: GoogleAuthTransportOptions, url: URL): TlsOptions { const explicit = { - cert: init.cert as TlsCert | undefined, - key: init.key as TlsKey | undefined, + cert: init.cert, + key: init.key, }; if (hasTlsOptions(explicit)) { return explicit; @@ -305,7 +283,7 @@ function validateGoogleChatServiceAccountCredentials( assertExactUrlField(credentials, "token_uri", GOOGLE_AUTH_TOKEN_URI); assertUrlPrefixField(credentials, "client_x509_cert_url", GOOGLE_CLIENT_CERTS_URL_PREFIX); - return credentials as GoogleChatServiceAccountCredentials; + return credentials as unknown as GoogleChatServiceAccountCredentials; } async function readCredentialsFile(filePath: string): Promise> { @@ -360,11 +338,11 @@ async function readCredentialsFile(filePath: string): Promise { - if (!googleAuthRuntimePromise) { - googleAuthRuntimePromise = (async () => { - try { - const [googleAuthModule, gaxiosModule] = await Promise.all([ - import("google-auth-library"), - import("gaxios"), - ]); - return { - Gaxios: gaxiosModule.Gaxios, - GoogleAuth: googleAuthModule.GoogleAuth, - OAuth2Client: googleAuthModule.OAuth2Client, - }; - } catch (error) { - googleAuthRuntimePromise = null; - throw error; - } - })(); - } + googleAuthRuntimePromise ??= import("google-auth-library").catch((error) => { + googleAuthRuntimePromise = null; + throw error; + }); return await googleAuthRuntimePromise; } export async function getGoogleAuthTransport(): Promise { - const { Gaxios } = await loadGoogleAuthRuntime(); + const { gaxios } = await loadGoogleAuthRuntime(); return installGoogleAuthHeaderCompatibilityInterceptor( - new Gaxios({ + new gaxios.Gaxios({ fetchImplementation: createGoogleAuthFetch(), }), ); diff --git a/extensions/googlechat/src/targets.test.ts b/extensions/googlechat/src/targets.test.ts index d57533ac874e..f5e7b7d1dd3b 100644 --- a/extensions/googlechat/src/targets.test.ts +++ b/extensions/googlechat/src/targets.test.ts @@ -44,22 +44,21 @@ vi.mock("openclaw/plugin-sdk/ssrf-runtime", () => { }; }); -vi.mock("gaxios", () => ({ - Gaxios: class { - defaults: unknown; - interceptors = { - request: { add: vi.fn() }, - response: { add: vi.fn() }, - }; - - constructor(defaults?: unknown) { - this.defaults = defaults; - mocks.gaxiosCtor(defaults); - } - }, -})); - vi.mock("google-auth-library", () => ({ + gaxios: { + Gaxios: class { + defaults: unknown; + interceptors = { + request: { add: vi.fn() }, + response: { add: vi.fn() }, + }; + + constructor(defaults?: unknown) { + this.defaults = defaults; + mocks.gaxiosCtor(defaults); + } + }, + }, GoogleAuth: class { constructor(options?: unknown) { mocks.googleAuthCtor(options); @@ -92,7 +91,6 @@ const { testing: authTesting, getGoogleChatAccessToken, verifyGoogleChatRequest afterAll(() => { vi.doUnmock("openclaw/plugin-sdk/ssrf-runtime"); - vi.doUnmock("gaxios"); vi.doUnmock("google-auth-library"); vi.doUnmock("./auth.js"); vi.resetModules(); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f622da913c8f..ac031c6ef5a5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -872,9 +872,6 @@ importers: extensions/googlechat: dependencies: - gaxios: - specifier: 7.1.5 - version: 7.1.5 google-auth-library: specifier: 10.9.0 version: 10.9.0 diff --git a/src/plugins/contracts/package-manifest.contract.test.ts b/src/plugins/contracts/package-manifest.contract.test.ts index d52a5bd0b0bb..a8c146677254 100644 --- a/src/plugins/contracts/package-manifest.contract.test.ts +++ b/src/plugins/contracts/package-manifest.contract.test.ts @@ -18,7 +18,7 @@ const packageManifestContractTests: PackageManifestContractParams[] = [ { pluginId: "google-meet" }, { pluginId: "googlechat", - pluginLocalRuntimeDeps: ["gaxios", "google-auth-library"], + pluginLocalRuntimeDeps: ["google-auth-library"], minHostVersionBaseline: "2026.3.22", }, { pluginId: "irc", minHostVersionBaseline: "2026.3.22" },