diff --git a/docs/concepts/model-providers.md b/docs/concepts/model-providers.md index 3a29c373c1d..d20b5055763 100644 --- a/docs/concepts/model-providers.md +++ b/docs/concepts/model-providers.md @@ -176,16 +176,13 @@ OpenClaw ships with the pi‑ai catalog. These providers require **no** - Compatibility: legacy OpenClaw config using `google/gemini-3.1-flash-preview` is normalized to `google/gemini-3-flash-preview` - CLI: `openclaw onboard --auth-choice gemini-api-key` -### Google Vertex, Antigravity, and Gemini CLI +### Google Vertex and Gemini CLI -- Providers: `google-vertex`, `google-antigravity`, `google-gemini-cli` -- Auth: Vertex uses gcloud ADC; Antigravity/Gemini CLI use their respective auth flows -- Caution: Antigravity and Gemini CLI OAuth in OpenClaw are unofficial integrations. Some users have reported Google account restrictions after using third-party clients. Review Google terms and use a non-critical account if you choose to proceed. -- Antigravity OAuth is shipped as a bundled plugin (`google-antigravity-auth`, disabled by default). - - Enable: `openclaw plugins enable google-antigravity-auth` - - Login: `openclaw models auth login --provider google-antigravity --set-default` -- Gemini CLI OAuth is shipped as a bundled plugin (`google-gemini-cli-auth`, disabled by default). - - Enable: `openclaw plugins enable google-gemini-cli-auth` +- Providers: `google-vertex`, `google-gemini-cli` +- Auth: Vertex uses gcloud ADC; Gemini CLI uses its OAuth flow +- Caution: Gemini CLI OAuth in OpenClaw is an unofficial integration. Some users have reported Google account restrictions after using third-party clients. Review Google terms and use a non-critical account if you choose to proceed. +- Gemini CLI OAuth is shipped as part of the bundled `google` plugin. + - Enable: `openclaw plugins enable google` - Login: `openclaw models auth login --provider google-gemini-cli --set-default` - Note: you do **not** paste a client id or secret into `openclaw.json`. The CLI login flow stores tokens in auth profiles on the gateway host. diff --git a/docs/help/faq.md b/docs/help/faq.md index 236097634c1..c402230aaa3 100644 --- a/docs/help/faq.md +++ b/docs/help/faq.md @@ -783,7 +783,7 @@ Gemini CLI uses a **plugin auth flow**, not a client id or secret in `openclaw.j Steps: -1. Enable the plugin: `openclaw plugins enable google-gemini-cli-auth` +1. Enable the plugin: `openclaw plugins enable google` 2. Login: `openclaw models auth login --provider google-gemini-cli --set-default` This stores OAuth tokens in auth profiles on the gateway host. Details: [Model providers](/concepts/model-providers). diff --git a/docs/tools/plugin.md b/docs/tools/plugin.md index 8aa7beefa42..59752ddf253 100644 --- a/docs/tools/plugin.md +++ b/docs/tools/plugin.md @@ -167,8 +167,7 @@ Important trust note: - Anthropic provider runtime — bundled as `anthropic` (enabled by default) - BytePlus provider catalog — bundled as `byteplus` (enabled by default) - Cloudflare AI Gateway provider catalog — bundled as `cloudflare-ai-gateway` (enabled by default) -- Google Antigravity OAuth (provider auth) — bundled as `google-antigravity-auth` (disabled by default) -- Gemini CLI OAuth (provider auth) — bundled as `google-gemini-cli-auth` (disabled by default) +- Google web search + Gemini CLI OAuth — bundled as `google` (web search auto-loads it; provider auth stays opt-in) - GitHub Copilot provider runtime — bundled as `github-copilot` (enabled by default) - Hugging Face provider catalog — bundled as `huggingface` (enabled by default) - Kilo Gateway provider runtime — bundled as `kilocode` (enabled by default) @@ -521,8 +520,7 @@ authoring plugins: `openclaw/plugin-sdk/acpx`, `openclaw/plugin-sdk/bluebubbles`, `openclaw/plugin-sdk/copilot-proxy`, `openclaw/plugin-sdk/device-pair`, `openclaw/plugin-sdk/diagnostics-otel`, `openclaw/plugin-sdk/diffs`, - `openclaw/plugin-sdk/feishu`, - `openclaw/plugin-sdk/google-gemini-cli-auth`, `openclaw/plugin-sdk/googlechat`, + `openclaw/plugin-sdk/feishu`, `openclaw/plugin-sdk/googlechat`, `openclaw/plugin-sdk/irc`, `openclaw/plugin-sdk/llm-task`, `openclaw/plugin-sdk/lobster`, `openclaw/plugin-sdk/matrix`, `openclaw/plugin-sdk/mattermost`, `openclaw/plugin-sdk/memory-core`, diff --git a/extensions/google-gemini-cli-auth/README.md b/extensions/google-gemini-cli-auth/README.md deleted file mode 100644 index bbca53ba1ce..00000000000 --- a/extensions/google-gemini-cli-auth/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# Google Gemini CLI Auth (OpenClaw plugin) - -OAuth provider plugin for **Gemini CLI** (Google Code Assist). - -## Account safety caution - -- This plugin is an unofficial integration and is not endorsed by Google. -- Some users have reported account restrictions or suspensions after using third-party Gemini CLI and Antigravity OAuth clients. -- Use caution, review the applicable Google terms, and avoid using a mission-critical account. - -## Enable - -Bundled plugins are disabled by default. Enable this one: - -```bash -openclaw plugins enable google-gemini-cli-auth -``` - -Restart the Gateway after enabling. - -## Authenticate - -```bash -openclaw models auth login --provider google-gemini-cli --set-default -``` - -## Requirements - -Requires the Gemini CLI to be installed (credentials are extracted automatically): - -```bash -brew install gemini-cli -# or: npm install -g @google/gemini-cli -``` - -## Env vars (optional) - -Override auto-detected credentials with: - -- `OPENCLAW_GEMINI_OAUTH_CLIENT_ID` / `GEMINI_CLI_OAUTH_CLIENT_ID` -- `OPENCLAW_GEMINI_OAUTH_CLIENT_SECRET` / `GEMINI_CLI_OAUTH_CLIENT_SECRET` diff --git a/extensions/google-gemini-cli-auth/index.ts b/extensions/google-gemini-cli-auth/index.ts deleted file mode 100644 index 290cc19598f..00000000000 --- a/extensions/google-gemini-cli-auth/index.ts +++ /dev/null @@ -1,158 +0,0 @@ -import { - buildOauthProviderAuthResult, - emptyPluginConfigSchema, - type ProviderFetchUsageSnapshotContext, - type OpenClawPluginApi, - type ProviderAuthContext, - type ProviderResolveDynamicModelContext, - type ProviderRuntimeModel, -} from "openclaw/plugin-sdk/google-gemini-cli-auth"; -import { normalizeModelCompat } from "../../src/agents/model-compat.js"; -import { fetchGeminiUsage } from "../../src/infra/provider-usage.fetch.js"; -import { loginGeminiCliOAuth } from "./oauth.js"; - -const PROVIDER_ID = "google-gemini-cli"; -const PROVIDER_LABEL = "Gemini CLI OAuth"; -const DEFAULT_MODEL = "google-gemini-cli/gemini-3.1-pro-preview"; -const GEMINI_3_1_PRO_PREFIX = "gemini-3.1-pro"; -const GEMINI_3_1_FLASH_PREFIX = "gemini-3.1-flash"; -const GEMINI_3_1_PRO_TEMPLATE_IDS = ["gemini-3-pro-preview"] as const; -const GEMINI_3_1_FLASH_TEMPLATE_IDS = ["gemini-3-flash-preview"] as const; -const ENV_VARS = [ - "OPENCLAW_GEMINI_OAUTH_CLIENT_ID", - "OPENCLAW_GEMINI_OAUTH_CLIENT_SECRET", - "GEMINI_CLI_OAUTH_CLIENT_ID", - "GEMINI_CLI_OAUTH_CLIENT_SECRET", -]; - -function cloneFirstTemplateModel(params: { - modelId: string; - templateIds: readonly string[]; - ctx: ProviderResolveDynamicModelContext; -}): ProviderRuntimeModel | undefined { - const trimmedModelId = params.modelId.trim(); - for (const templateId of [...new Set(params.templateIds)].filter(Boolean)) { - const template = params.ctx.modelRegistry.find( - PROVIDER_ID, - templateId, - ) as ProviderRuntimeModel | null; - if (!template) { - continue; - } - return normalizeModelCompat({ - ...template, - id: trimmedModelId, - name: trimmedModelId, - reasoning: true, - } as ProviderRuntimeModel); - } - return undefined; -} - -function parseGoogleUsageToken(apiKey: string): string { - try { - const parsed = JSON.parse(apiKey) as { token?: unknown }; - if (typeof parsed?.token === "string") { - return parsed.token; - } - } catch { - // ignore - } - return apiKey; -} - -async function fetchGeminiCliUsage(ctx: ProviderFetchUsageSnapshotContext) { - return await fetchGeminiUsage(ctx.token, ctx.timeoutMs, ctx.fetchFn, PROVIDER_ID); -} - -function resolveGeminiCliForwardCompatModel( - ctx: ProviderResolveDynamicModelContext, -): ProviderRuntimeModel | undefined { - const trimmed = ctx.modelId.trim(); - const lower = trimmed.toLowerCase(); - - let templateIds: readonly string[]; - if (lower.startsWith(GEMINI_3_1_PRO_PREFIX)) { - templateIds = GEMINI_3_1_PRO_TEMPLATE_IDS; - } else if (lower.startsWith(GEMINI_3_1_FLASH_PREFIX)) { - templateIds = GEMINI_3_1_FLASH_TEMPLATE_IDS; - } else { - return undefined; - } - - return cloneFirstTemplateModel({ - modelId: trimmed, - templateIds, - ctx, - }); -} - -const geminiCliPlugin = { - id: "google-gemini-cli-auth", - name: "Google Gemini CLI Auth", - description: "OAuth flow for Gemini CLI (Google Code Assist)", - configSchema: emptyPluginConfigSchema(), - register(api: OpenClawPluginApi) { - api.registerProvider({ - id: PROVIDER_ID, - label: PROVIDER_LABEL, - docsPath: "/providers/models", - aliases: ["gemini-cli"], - envVars: ENV_VARS, - auth: [ - { - id: "oauth", - label: "Google OAuth", - hint: "PKCE + localhost callback", - kind: "oauth", - run: async (ctx: ProviderAuthContext) => { - const spin = ctx.prompter.progress("Starting Gemini CLI OAuth…"); - try { - const result = await loginGeminiCliOAuth({ - isRemote: ctx.isRemote, - openUrl: ctx.openUrl, - log: (msg) => ctx.runtime.log(msg), - note: ctx.prompter.note, - prompt: async (message) => String(await ctx.prompter.text({ message })), - progress: spin, - }); - - spin.stop("Gemini CLI OAuth complete"); - return buildOauthProviderAuthResult({ - providerId: PROVIDER_ID, - defaultModel: DEFAULT_MODEL, - access: result.access, - refresh: result.refresh, - expires: result.expires, - email: result.email, - credentialExtra: { projectId: result.projectId }, - notes: ["If requests fail, set GOOGLE_CLOUD_PROJECT or GOOGLE_CLOUD_PROJECT_ID."], - }); - } catch (err) { - spin.stop("Gemini CLI OAuth failed"); - await ctx.prompter.note( - "Trouble with OAuth? Ensure your Google account has Gemini CLI access.", - "OAuth help", - ); - throw err; - } - }, - }, - ], - resolveDynamicModel: (ctx) => resolveGeminiCliForwardCompatModel(ctx), - resolveUsageAuth: async (ctx) => { - const auth = await ctx.resolveOAuthToken(); - if (!auth) { - return null; - } - return { - ...auth, - token: parseGoogleUsageToken(auth.token), - }; - }, - fetchUsageSnapshot: async (ctx) => await fetchGeminiCliUsage(ctx), - }); - }, -}; - -export default geminiCliPlugin; diff --git a/extensions/google-gemini-cli-auth/openclaw.plugin.json b/extensions/google-gemini-cli-auth/openclaw.plugin.json deleted file mode 100644 index c8f632da0c8..00000000000 --- a/extensions/google-gemini-cli-auth/openclaw.plugin.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "id": "google-gemini-cli-auth", - "providers": ["google-gemini-cli"], - "configSchema": { - "type": "object", - "additionalProperties": false, - "properties": {} - } -} diff --git a/extensions/google-gemini-cli-auth/package.json b/extensions/google-gemini-cli-auth/package.json deleted file mode 100644 index 61ae5be803c..00000000000 --- a/extensions/google-gemini-cli-auth/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "@openclaw/google-gemini-cli-auth", - "version": "2026.3.14", - "private": true, - "description": "OpenClaw Gemini CLI OAuth provider plugin", - "type": "module", - "openclaw": { - "extensions": [ - "./index.ts" - ] - } -} diff --git a/extensions/google-gemini-cli-auth/index.test.ts b/extensions/google/gemini-cli-provider.test.ts similarity index 79% rename from extensions/google-gemini-cli-auth/index.test.ts rename to extensions/google/gemini-cli-provider.test.ts index d0542e3473c..ad5969c7c4d 100644 --- a/extensions/google-gemini-cli-auth/index.test.ts +++ b/extensions/google/gemini-cli-provider.test.ts @@ -4,24 +4,38 @@ import { createProviderUsageFetch, makeResponse, } from "../../src/test-utils/provider-usage-fetch.js"; -import geminiCliPlugin from "./index.js"; +import googlePlugin from "./index.js"; -function registerProvider(): ProviderPlugin { +function registerGooglePlugin(): { + provider: ProviderPlugin; + webSearchProviderRegistered: boolean; +} { let provider: ProviderPlugin | undefined; - geminiCliPlugin.register({ + let webSearchProviderRegistered = false; + googlePlugin.register({ registerProvider(nextProvider: ProviderPlugin) { provider = nextProvider; }, + registerWebSearchProvider() { + webSearchProviderRegistered = true; + }, } as never); if (!provider) { throw new Error("provider registration missing"); } - return provider; + return { provider, webSearchProviderRegistered }; } -describe("google-gemini-cli-auth plugin", () => { +describe("google plugin", () => { + it("registers both Gemini CLI auth and Gemini web search", () => { + const result = registerGooglePlugin(); + + expect(result.provider.id).toBe("google-gemini-cli"); + expect(result.webSearchProviderRegistered).toBe(true); + }); + it("owns gemini 3.1 forward-compat resolution", () => { - const provider = registerProvider(); + const { provider } = registerGooglePlugin(); const model = provider.resolveDynamicModel?.({ provider: "google-gemini-cli", modelId: "gemini-3.1-pro-preview", @@ -52,7 +66,7 @@ describe("google-gemini-cli-auth plugin", () => { }); it("owns usage-token parsing", async () => { - const provider = registerProvider(); + const { provider } = registerGooglePlugin(); await expect( provider.resolveUsageAuth?.({ config: {} as never, @@ -71,7 +85,7 @@ describe("google-gemini-cli-auth plugin", () => { }); it("owns usage snapshot fetching", async () => { - const provider = registerProvider(); + const { provider } = registerGooglePlugin(); const mockFetch = createProviderUsageFetch(async (url) => { if (url.includes("cloudcode-pa.googleapis.com/v1internal:retrieveUserQuota")) { return makeResponse(200, { diff --git a/extensions/google/gemini-cli-provider.ts b/extensions/google/gemini-cli-provider.ts new file mode 100644 index 00000000000..b4bb58f7d80 --- /dev/null +++ b/extensions/google/gemini-cli-provider.ts @@ -0,0 +1,149 @@ +import { normalizeModelCompat } from "../../src/agents/model-compat.js"; +import { fetchGeminiUsage } from "../../src/infra/provider-usage.fetch.js"; +import { buildOauthProviderAuthResult } from "../../src/plugin-sdk/provider-auth-result.js"; +import type { + OpenClawPluginApi, + ProviderAuthContext, + ProviderFetchUsageSnapshotContext, + ProviderResolveDynamicModelContext, + ProviderRuntimeModel, +} from "../../src/plugins/types.js"; +import { loginGeminiCliOAuth } from "./oauth.js"; + +const PROVIDER_ID = "google-gemini-cli"; +const PROVIDER_LABEL = "Gemini CLI OAuth"; +const DEFAULT_MODEL = "google-gemini-cli/gemini-3.1-pro-preview"; +const GEMINI_3_1_PRO_PREFIX = "gemini-3.1-pro"; +const GEMINI_3_1_FLASH_PREFIX = "gemini-3.1-flash"; +const GEMINI_3_1_PRO_TEMPLATE_IDS = ["gemini-3-pro-preview"] as const; +const GEMINI_3_1_FLASH_TEMPLATE_IDS = ["gemini-3-flash-preview"] as const; +const ENV_VARS = [ + "OPENCLAW_GEMINI_OAUTH_CLIENT_ID", + "OPENCLAW_GEMINI_OAUTH_CLIENT_SECRET", + "GEMINI_CLI_OAUTH_CLIENT_ID", + "GEMINI_CLI_OAUTH_CLIENT_SECRET", +]; + +function cloneFirstTemplateModel(params: { + modelId: string; + templateIds: readonly string[]; + ctx: ProviderResolveDynamicModelContext; +}): ProviderRuntimeModel | undefined { + const trimmedModelId = params.modelId.trim(); + for (const templateId of [...new Set(params.templateIds)].filter(Boolean)) { + const template = params.ctx.modelRegistry.find( + PROVIDER_ID, + templateId, + ) as ProviderRuntimeModel | null; + if (!template) { + continue; + } + return normalizeModelCompat({ + ...template, + id: trimmedModelId, + name: trimmedModelId, + reasoning: true, + } as ProviderRuntimeModel); + } + return undefined; +} + +function parseGoogleUsageToken(apiKey: string): string { + try { + const parsed = JSON.parse(apiKey) as { token?: unknown }; + if (typeof parsed?.token === "string") { + return parsed.token; + } + } catch { + // ignore + } + return apiKey; +} + +async function fetchGeminiCliUsage(ctx: ProviderFetchUsageSnapshotContext) { + return await fetchGeminiUsage(ctx.token, ctx.timeoutMs, ctx.fetchFn, PROVIDER_ID); +} + +function resolveGeminiCliForwardCompatModel( + ctx: ProviderResolveDynamicModelContext, +): ProviderRuntimeModel | undefined { + const trimmed = ctx.modelId.trim(); + const lower = trimmed.toLowerCase(); + + let templateIds: readonly string[]; + if (lower.startsWith(GEMINI_3_1_PRO_PREFIX)) { + templateIds = GEMINI_3_1_PRO_TEMPLATE_IDS; + } else if (lower.startsWith(GEMINI_3_1_FLASH_PREFIX)) { + templateIds = GEMINI_3_1_FLASH_TEMPLATE_IDS; + } else { + return undefined; + } + + return cloneFirstTemplateModel({ + modelId: trimmed, + templateIds, + ctx, + }); +} + +export function registerGoogleGeminiCliProvider(api: OpenClawPluginApi) { + api.registerProvider({ + id: PROVIDER_ID, + label: PROVIDER_LABEL, + docsPath: "/providers/models", + aliases: ["gemini-cli"], + envVars: ENV_VARS, + auth: [ + { + id: "oauth", + label: "Google OAuth", + hint: "PKCE + localhost callback", + kind: "oauth", + run: async (ctx: ProviderAuthContext) => { + const spin = ctx.prompter.progress("Starting Gemini CLI OAuth…"); + try { + const result = await loginGeminiCliOAuth({ + isRemote: ctx.isRemote, + openUrl: ctx.openUrl, + log: (msg) => ctx.runtime.log(msg), + note: ctx.prompter.note, + prompt: async (message) => String(await ctx.prompter.text({ message })), + progress: spin, + }); + + spin.stop("Gemini CLI OAuth complete"); + return buildOauthProviderAuthResult({ + providerId: PROVIDER_ID, + defaultModel: DEFAULT_MODEL, + access: result.access, + refresh: result.refresh, + expires: result.expires, + email: result.email, + credentialExtra: { projectId: result.projectId }, + notes: ["If requests fail, set GOOGLE_CLOUD_PROJECT or GOOGLE_CLOUD_PROJECT_ID."], + }); + } catch (err) { + spin.stop("Gemini CLI OAuth failed"); + await ctx.prompter.note( + "Trouble with OAuth? Ensure your Google account has Gemini CLI access.", + "OAuth help", + ); + throw err; + } + }, + }, + ], + resolveDynamicModel: (ctx) => resolveGeminiCliForwardCompatModel(ctx), + resolveUsageAuth: async (ctx) => { + const auth = await ctx.resolveOAuthToken(); + if (!auth) { + return null; + } + return { + ...auth, + token: parseGoogleUsageToken(auth.token), + }; + }, + fetchUsageSnapshot: async (ctx) => await fetchGeminiCliUsage(ctx), + }); +} diff --git a/extensions/google/index.ts b/extensions/google/index.ts index 5691137070b..806133b6419 100644 --- a/extensions/google/index.ts +++ b/extensions/google/index.ts @@ -5,6 +5,7 @@ import { } from "../../src/agents/tools/web-search-plugin-factory.js"; import { emptyPluginConfigSchema } from "../../src/plugins/config-schema.js"; import type { OpenClawPluginApi } from "../../src/plugins/types.js"; +import { registerGoogleGeminiCliProvider } from "./gemini-cli-provider.js"; const googlePlugin = { id: "google", @@ -12,6 +13,7 @@ const googlePlugin = { description: "Bundled Google plugin", configSchema: emptyPluginConfigSchema(), register(api: OpenClawPluginApi) { + registerGoogleGeminiCliProvider(api); api.registerWebSearchProvider( createPluginBackedWebSearchProvider({ id: "gemini", diff --git a/extensions/google-gemini-cli-auth/oauth.test.ts b/extensions/google/oauth.test.ts similarity index 99% rename from extensions/google-gemini-cli-auth/oauth.test.ts rename to extensions/google/oauth.test.ts index 02100b73b1f..8aec64d528d 100644 --- a/extensions/google-gemini-cli-auth/oauth.test.ts +++ b/extensions/google/oauth.test.ts @@ -1,8 +1,11 @@ import { join, parse } from "node:path"; import { describe, expect, it, vi, beforeEach, afterEach } from "vitest"; -vi.mock("openclaw/plugin-sdk/google-gemini-cli-auth", () => ({ +vi.mock("../../src/infra/wsl.js", () => ({ isWSL2Sync: () => false, +})); + +vi.mock("../../src/infra/net/fetch-guard.js", () => ({ fetchWithSsrFGuard: async (params: { url: string; init?: RequestInit; diff --git a/extensions/google-gemini-cli-auth/oauth.ts b/extensions/google/oauth.ts similarity index 99% rename from extensions/google-gemini-cli-auth/oauth.ts rename to extensions/google/oauth.ts index 62881ec3a73..5932b3a237b 100644 --- a/extensions/google-gemini-cli-auth/oauth.ts +++ b/extensions/google/oauth.ts @@ -2,7 +2,8 @@ import { createHash, randomBytes } from "node:crypto"; import { existsSync, readFileSync, readdirSync, realpathSync } from "node:fs"; import { createServer } from "node:http"; import { delimiter, dirname, join } from "node:path"; -import { fetchWithSsrFGuard, isWSL2Sync } from "openclaw/plugin-sdk/google-gemini-cli-auth"; +import { fetchWithSsrFGuard } from "../../src/infra/net/fetch-guard.js"; +import { isWSL2Sync } from "../../src/infra/wsl.js"; const CLIENT_ID_KEYS = ["OPENCLAW_GEMINI_OAUTH_CLIENT_ID", "GEMINI_CLI_OAUTH_CLIENT_ID"]; const CLIENT_SECRET_KEYS = [ diff --git a/extensions/google/openclaw.plugin.json b/extensions/google/openclaw.plugin.json index 40594e2f3f9..1a6d0dcd196 100644 --- a/extensions/google/openclaw.plugin.json +++ b/extensions/google/openclaw.plugin.json @@ -1,5 +1,6 @@ { "id": "google", + "providers": ["google-gemini-cli"], "configSchema": { "type": "object", "additionalProperties": false, diff --git a/package.json b/package.json index 2fc0ec447d0..86822b23bf1 100644 --- a/package.json +++ b/package.json @@ -108,10 +108,6 @@ "types": "./dist/plugin-sdk/feishu.d.ts", "default": "./dist/plugin-sdk/feishu.js" }, - "./plugin-sdk/google-gemini-cli-auth": { - "types": "./dist/plugin-sdk/google-gemini-cli-auth.d.ts", - "default": "./dist/plugin-sdk/google-gemini-cli-auth.js" - }, "./plugin-sdk/googlechat": { "types": "./dist/plugin-sdk/googlechat.d.ts", "default": "./dist/plugin-sdk/googlechat.js" diff --git a/scripts/check-no-raw-channel-fetch.mjs b/scripts/check-no-raw-channel-fetch.mjs index 788585b8c54..7b935d183e5 100644 --- a/scripts/check-no-raw-channel-fetch.mjs +++ b/scripts/check-no-raw-channel-fetch.mjs @@ -14,11 +14,6 @@ const allowedRawFetchCallsites = new Set([ "extensions/feishu/src/streaming-card.ts:101", "extensions/feishu/src/streaming-card.ts:143", "extensions/feishu/src/streaming-card.ts:199", - "extensions/google-gemini-cli-auth/oauth.ts:372", - "extensions/google-gemini-cli-auth/oauth.ts:408", - "extensions/google-gemini-cli-auth/oauth.ts:447", - "extensions/google-gemini-cli-auth/oauth.ts:507", - "extensions/google-gemini-cli-auth/oauth.ts:575", "extensions/googlechat/src/api.ts:22", "extensions/googlechat/src/api.ts:43", "extensions/googlechat/src/api.ts:63", diff --git a/scripts/check-plugin-sdk-exports.mjs b/scripts/check-plugin-sdk-exports.mjs index 03ff9dfde8f..93fc3fcb545 100755 --- a/scripts/check-plugin-sdk-exports.mjs +++ b/scripts/check-plugin-sdk-exports.mjs @@ -59,7 +59,6 @@ const requiredSubpathEntries = [ "diagnostics-otel", "diffs", "feishu", - "google-gemini-cli-auth", "googlechat", "irc", "llm-task", diff --git a/scripts/release-check.ts b/scripts/release-check.ts index 34d37634d6f..b8e4fa6706b 100755 --- a/scripts/release-check.ts +++ b/scripts/release-check.ts @@ -57,8 +57,6 @@ const requiredPathGroups = [ "dist/plugin-sdk/diffs.d.ts", "dist/plugin-sdk/feishu.js", "dist/plugin-sdk/feishu.d.ts", - "dist/plugin-sdk/google-gemini-cli-auth.js", - "dist/plugin-sdk/google-gemini-cli-auth.d.ts", "dist/plugin-sdk/googlechat.js", "dist/plugin-sdk/googlechat.d.ts", "dist/plugin-sdk/irc.js", diff --git a/scripts/write-plugin-sdk-entry-dts.ts b/scripts/write-plugin-sdk-entry-dts.ts index beb5db5481b..d0331377432 100644 --- a/scripts/write-plugin-sdk-entry-dts.ts +++ b/scripts/write-plugin-sdk-entry-dts.ts @@ -25,7 +25,6 @@ const entrypoints = [ "diagnostics-otel", "diffs", "feishu", - "google-gemini-cli-auth", "googlechat", "irc", "llm-task", diff --git a/src/commands/auth-choice.apply.google-gemini-cli.test.ts b/src/commands/auth-choice.apply.google-gemini-cli.test.ts index f07f970a18d..50a17014908 100644 --- a/src/commands/auth-choice.apply.google-gemini-cli.test.ts +++ b/src/commands/auth-choice.apply.google-gemini-cli.test.ts @@ -77,7 +77,7 @@ describe("applyAuthChoiceGoogleGeminiCli", () => { expect(result).toBe(expected); expect(mockedApplyAuthChoicePluginProvider).toHaveBeenCalledWith(params, { authChoice: "google-gemini-cli", - pluginId: "google-gemini-cli-auth", + pluginId: "google", providerId: "google-gemini-cli", methodId: "oauth", label: "Google Gemini CLI", diff --git a/src/commands/auth-choice.apply.google-gemini-cli.ts b/src/commands/auth-choice.apply.google-gemini-cli.ts index 5fcbc832338..e2aa1d02398 100644 --- a/src/commands/auth-choice.apply.google-gemini-cli.ts +++ b/src/commands/auth-choice.apply.google-gemini-cli.ts @@ -29,7 +29,7 @@ export async function applyAuthChoiceGoogleGeminiCli( return await applyAuthChoicePluginProvider(params, { authChoice: "google-gemini-cli", - pluginId: "google-gemini-cli-auth", + pluginId: "google", providerId: "google-gemini-cli", methodId: "oauth", label: "Google Gemini CLI", diff --git a/src/config/plugin-auto-enable.test.ts b/src/config/plugin-auto-enable.test.ts index c289417ce53..cae9b4e5c18 100644 --- a/src/config/plugin-auto-enable.test.ts +++ b/src/config/plugin-auto-enable.test.ts @@ -307,7 +307,7 @@ describe("applyPluginAutoEnable", () => { env: {}, }); - expect(result.config.plugins?.entries?.["google-gemini-cli-auth"]?.enabled).toBe(true); + expect(result.config.plugins?.entries?.google?.enabled).toBe(true); }); it("auto-enables acpx plugin when ACP is configured", () => { diff --git a/src/config/plugin-auto-enable.ts b/src/config/plugin-auto-enable.ts index 4e0cae1209f..72e1dede1ef 100644 --- a/src/config/plugin-auto-enable.ts +++ b/src/config/plugin-auto-enable.ts @@ -28,7 +28,7 @@ export type PluginAutoEnableResult = { }; const PROVIDER_PLUGIN_IDS: Array<{ pluginId: string; providerId: string }> = [ - { pluginId: "google-gemini-cli-auth", providerId: "google-gemini-cli" }, + { pluginId: "google", providerId: "google-gemini-cli" }, { pluginId: "qwen-portal-auth", providerId: "qwen-portal" }, { pluginId: "copilot-proxy", providerId: "copilot-proxy" }, { pluginId: "minimax-portal-auth", providerId: "minimax-portal" }, diff --git a/src/plugin-sdk/google-gemini-cli-auth.ts b/src/plugin-sdk/google-gemini-cli-auth.ts deleted file mode 100644 index a03002feaab..00000000000 --- a/src/plugin-sdk/google-gemini-cli-auth.ts +++ /dev/null @@ -1,15 +0,0 @@ -// Narrow plugin-sdk surface for the bundled google-gemini-cli-auth plugin. -// Keep this list additive and scoped to symbols used under extensions/google-gemini-cli-auth. - -export { fetchWithSsrFGuard } from "../infra/net/fetch-guard.js"; -export { isWSL2Sync } from "../infra/wsl.js"; -export { emptyPluginConfigSchema } from "../plugins/config-schema.js"; -export type { - OpenClawPluginApi, - ProviderAuthContext, - ProviderFetchUsageSnapshotContext, - ProviderResolveDynamicModelContext, - ProviderRuntimeModel, -} from "../plugins/types.js"; -export type { ProviderUsageSnapshot } from "../infra/provider-usage.types.js"; -export { buildOauthProviderAuthResult } from "./provider-auth-result.js"; diff --git a/src/plugin-sdk/index.test.ts b/src/plugin-sdk/index.test.ts index 61d1cccb10c..8fe13972e11 100644 --- a/src/plugin-sdk/index.test.ts +++ b/src/plugin-sdk/index.test.ts @@ -25,7 +25,6 @@ const pluginSdkEntrypoints = [ "diagnostics-otel", "diffs", "feishu", - "google-gemini-cli-auth", "googlechat", "irc", "llm-task", diff --git a/src/plugin-sdk/subpaths.test.ts b/src/plugin-sdk/subpaths.test.ts index 996c6b27188..09341c4e82b 100644 --- a/src/plugin-sdk/subpaths.test.ts +++ b/src/plugin-sdk/subpaths.test.ts @@ -18,10 +18,6 @@ const bundledExtensionSubpathLoaders = [ { id: "diagnostics-otel", load: () => import("openclaw/plugin-sdk/diagnostics-otel") }, { id: "diffs", load: () => import("openclaw/plugin-sdk/diffs") }, { id: "feishu", load: () => import("openclaw/plugin-sdk/feishu") }, - { - id: "google-gemini-cli-auth", - load: () => import("openclaw/plugin-sdk/google-gemini-cli-auth"), - }, { id: "googlechat", load: () => import("openclaw/plugin-sdk/googlechat") }, { id: "irc", load: () => import("openclaw/plugin-sdk/irc") }, { id: "llm-task", load: () => import("openclaw/plugin-sdk/llm-task") }, diff --git a/src/plugins/enable.test.ts b/src/plugins/enable.test.ts index 793ed1c7ffe..89259b8a583 100644 --- a/src/plugins/enable.test.ts +++ b/src/plugins/enable.test.ts @@ -5,9 +5,9 @@ import { enablePluginInConfig } from "./enable.js"; describe("enablePluginInConfig", () => { it("enables a plugin entry", () => { const cfg: OpenClawConfig = {}; - const result = enablePluginInConfig(cfg, "google-gemini-cli-auth"); + const result = enablePluginInConfig(cfg, "google"); expect(result.enabled).toBe(true); - expect(result.config.plugins?.entries?.["google-gemini-cli-auth"]?.enabled).toBe(true); + expect(result.config.plugins?.entries?.google?.enabled).toBe(true); }); it("adds plugin to allowlist when allowlist is configured", () => { @@ -16,18 +16,18 @@ describe("enablePluginInConfig", () => { allow: ["memory-core"], }, }; - const result = enablePluginInConfig(cfg, "google-gemini-cli-auth"); + const result = enablePluginInConfig(cfg, "google"); expect(result.enabled).toBe(true); - expect(result.config.plugins?.allow).toEqual(["memory-core", "google-gemini-cli-auth"]); + expect(result.config.plugins?.allow).toEqual(["memory-core", "google"]); }); it("refuses enable when plugin is denylisted", () => { const cfg: OpenClawConfig = { plugins: { - deny: ["google-gemini-cli-auth"], + deny: ["google"], }, }; - const result = enablePluginInConfig(cfg, "google-gemini-cli-auth"); + const result = enablePluginInConfig(cfg, "google"); expect(result.enabled).toBe(false); expect(result.reason).toBe("blocked by denylist"); }); diff --git a/src/plugins/providers.ts b/src/plugins/providers.ts index 68b83561461..7e18664067b 100644 --- a/src/plugins/providers.ts +++ b/src/plugins/providers.ts @@ -10,7 +10,7 @@ const BUNDLED_PROVIDER_ALLOWLIST_COMPAT_PLUGIN_IDS = [ "cloudflare-ai-gateway", "copilot-proxy", "github-copilot", - "google-gemini-cli-auth", + "google", "huggingface", "kilocode", "kimi-coding", diff --git a/tsconfig.plugin-sdk.dts.json b/tsconfig.plugin-sdk.dts.json index f938dcc8262..15828b8b7ad 100644 --- a/tsconfig.plugin-sdk.dts.json +++ b/tsconfig.plugin-sdk.dts.json @@ -31,7 +31,6 @@ "src/plugin-sdk/diagnostics-otel.ts", "src/plugin-sdk/diffs.ts", "src/plugin-sdk/feishu.ts", - "src/plugin-sdk/google-gemini-cli-auth.ts", "src/plugin-sdk/googlechat.ts", "src/plugin-sdk/irc.ts", "src/plugin-sdk/llm-task.ts", diff --git a/tsdown.config.ts b/tsdown.config.ts index 6ed9ccb930b..2b7c9dbe192 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -77,7 +77,6 @@ const pluginSdkEntrypoints = [ "diagnostics-otel", "diffs", "feishu", - "google-gemini-cli-auth", "googlechat", "irc", "llm-task", diff --git a/vitest.config.ts b/vitest.config.ts index 70011a6a0b8..c45f5f45c25 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -27,7 +27,6 @@ const pluginSdkSubpaths = [ "diagnostics-otel", "diffs", "feishu", - "google-gemini-cli-auth", "googlechat", "irc", "llm-task",