diff --git a/extensions/google/gemini-cli-provider.test.ts b/extensions/google/gemini-cli-provider.test.ts index ad5969c7c4d..dd991e2b32d 100644 --- a/extensions/google/gemini-cli-provider.test.ts +++ b/extensions/google/gemini-cli-provider.test.ts @@ -8,22 +8,33 @@ import googlePlugin from "./index.js"; function registerGooglePlugin(): { provider: ProviderPlugin; + webSearchProvider: { + id: string; + envVars: string[]; + label: string; + } | null; webSearchProviderRegistered: boolean; } { let provider: ProviderPlugin | undefined; let webSearchProviderRegistered = false; + let webSearchProvider: { + id: string; + envVars: string[]; + label: string; + } | null = null; googlePlugin.register({ registerProvider(nextProvider: ProviderPlugin) { provider = nextProvider; }, - registerWebSearchProvider() { + registerWebSearchProvider(nextProvider: { id: string; envVars: string[]; label: string }) { webSearchProviderRegistered = true; + webSearchProvider = nextProvider; }, } as never); if (!provider) { throw new Error("provider registration missing"); } - return { provider, webSearchProviderRegistered }; + return { provider, webSearchProviderRegistered, webSearchProvider }; } describe("google plugin", () => { @@ -32,6 +43,11 @@ describe("google plugin", () => { expect(result.provider.id).toBe("google-gemini-cli"); expect(result.webSearchProviderRegistered).toBe(true); + expect(result.webSearchProvider).toMatchObject({ + id: "gemini", + label: "Gemini (Google Search)", + envVars: ["GEMINI_API_KEY"], + }); }); it("owns gemini 3.1 forward-compat resolution", () => { diff --git a/src/config/config.plugin-validation.test.ts b/src/config/config.plugin-validation.test.ts index efb84acdacf..42d473aed4e 100644 --- a/src/config/config.plugin-validation.test.ts +++ b/src/config/config.plugin-validation.test.ts @@ -281,6 +281,47 @@ describe("config plugin validation", () => { } }); + it("warns for removed google gemini auth plugin ids instead of failing validation", async () => { + const removedId = "google-gemini-cli-auth"; + const res = validateInSuite({ + agents: { list: [{ id: "pi" }] }, + plugins: { + enabled: false, + entries: { [removedId]: { enabled: true } }, + allow: [removedId], + deny: [removedId], + slots: { memory: removedId }, + }, + }); + expect(res.ok).toBe(true); + if (res.ok) { + expect(res.warnings).toEqual( + expect.arrayContaining([ + { + path: `plugins.entries.${removedId}`, + message: + "plugin removed: google-gemini-cli-auth (stale config entry ignored; remove it from plugins config)", + }, + { + path: "plugins.allow", + message: + "plugin removed: google-gemini-cli-auth (stale config entry ignored; remove it from plugins config)", + }, + { + path: "plugins.deny", + message: + "plugin removed: google-gemini-cli-auth (stale config entry ignored; remove it from plugins config)", + }, + { + path: "plugins.slots.memory", + message: + "plugin removed: google-gemini-cli-auth (stale config entry ignored; remove it from plugins config)", + }, + ]), + ); + } + }); + it("surfaces plugin config diagnostics", async () => { const res = validateInSuite({ agents: { list: [{ id: "pi" }] }, diff --git a/src/config/validation.ts b/src/config/validation.ts index e97bd8cbedf..2a2c08b96ee 100644 --- a/src/config/validation.ts +++ b/src/config/validation.ts @@ -24,7 +24,7 @@ import { findLegacyConfigIssues } from "./legacy.js"; import type { OpenClawConfig, ConfigValidationIssue } from "./types.js"; import { OpenClawSchema } from "./zod-schema.js"; -const LEGACY_REMOVED_PLUGIN_IDS = new Set(["google-antigravity-auth"]); +const LEGACY_REMOVED_PLUGIN_IDS = new Set(["google-antigravity-auth", "google-gemini-cli-auth"]); type UnknownIssueRecord = Record; type AllowedValuesCollection = { diff --git a/src/plugins/providers.test.ts b/src/plugins/providers.test.ts index 4e238c2193d..86ffb8e5ffc 100644 --- a/src/plugins/providers.test.ts +++ b/src/plugins/providers.test.ts @@ -11,7 +11,7 @@ describe("resolvePluginProviders", () => { beforeEach(() => { loadOpenClawPluginsMock.mockReset(); loadOpenClawPluginsMock.mockReturnValue({ - providers: [{ provider: { id: "demo-provider" } }], + providers: [{ pluginId: "google", provider: { id: "demo-provider" } }], }); }); @@ -23,7 +23,7 @@ describe("resolvePluginProviders", () => { env, }); - expect(providers).toEqual([{ id: "demo-provider" }]); + expect(providers).toEqual([{ id: "demo-provider", pluginId: "google" }]); expect(loadOpenClawPluginsMock).toHaveBeenCalledWith( expect.objectContaining({ workspaceDir: "/workspace/explicit", @@ -46,13 +46,12 @@ describe("resolvePluginProviders", () => { expect.objectContaining({ config: expect.objectContaining({ plugins: expect.objectContaining({ - allow: expect.arrayContaining(["openrouter", "kilocode", "moonshot"]), + allow: expect.arrayContaining(["openrouter", "google", "kilocode", "moonshot"]), }), }), }), ); }); - it("can enable bundled provider plugins under Vitest when no explicit plugin config exists", () => { resolvePluginProviders({ env: { VITEST: "1" } as NodeJS.ProcessEnv, @@ -70,4 +69,21 @@ describe("resolvePluginProviders", () => { }), ); }); + + it("does not reintroduce the retired google auth plugin id into compat allowlists", () => { + resolvePluginProviders({ + config: { + plugins: { + allow: ["openrouter"], + }, + }, + bundledProviderAllowlistCompat: true, + }); + + const call = loadOpenClawPluginsMock.mock.calls.at(-1)?.[0]; + const allow = call?.config?.plugins?.allow; + + expect(allow).toContain("google"); + expect(allow).not.toContain("google-gemini-cli-auth"); + }); });