diff --git a/src/cli/models-cli.ts b/src/cli/models-cli.ts index 814e1d613ce..18ff7be01a4 100644 --- a/src/cli/models-cli.ts +++ b/src/cli/models-cli.ts @@ -30,7 +30,7 @@ export function registerModelsCli(program: Command) { .description("List models (configured by default)") .option("--all", "Show full model catalog", false) .option("--local", "Filter to local models", false) - .option("--provider ", "Filter by provider") + .option("--provider ", "Filter by provider id") .option("--json", "Output JSON", false) .option("--plain", "Plain line output", false) .action(async (opts) => { diff --git a/src/plugins/provider-runtime.test.ts b/src/plugins/provider-runtime.test.ts index 9f90541aa63..973e67efb7f 100644 --- a/src/plugins/provider-runtime.test.ts +++ b/src/plugins/provider-runtime.test.ts @@ -36,6 +36,7 @@ const resolveExternalAuthProfileCompatFallbackPluginIdsMock = vi.fn((_) => [] as string[]); const resolveExternalAuthProfileProviderPluginIdsMock = vi.fn((_) => [] as string[]); +const providerRuntimeWarnMock = vi.fn(); let augmentModelCatalogWithProviderPlugins: typeof import("./provider-runtime.js").augmentModelCatalogWithProviderPlugins; let buildProviderAuthDoctorHintWithPlugin: typeof import("./provider-runtime.js").buildProviderAuthDoctorHintWithPlugin; @@ -256,6 +257,14 @@ describe("provider-runtime", () => { isPluginProvidersLoadInFlight: (params: unknown) => isPluginProvidersLoadInFlightMock(params as never), })); + vi.doMock("../logging/subsystem.js", () => ({ + createSubsystemLogger: () => ({ + debug: vi.fn(), + info: vi.fn(), + warn: providerRuntimeWarnMock, + error: vi.fn(), + }), + })); ({ augmentModelCatalogWithProviderPlugins, buildProviderAuthDoctorHintWithPlugin, @@ -317,6 +326,7 @@ describe("provider-runtime", () => { resolveExternalAuthProfileCompatFallbackPluginIdsMock.mockReturnValue([]); resolveExternalAuthProfileProviderPluginIdsMock.mockReset(); resolveExternalAuthProfileProviderPluginIdsMock.mockReturnValue([]); + providerRuntimeWarnMock.mockReset(); }); it("matches providers by alias for runtime hook lookup", () => { @@ -384,6 +394,45 @@ describe("provider-runtime", () => { expect(resolvePluginProvidersMock).not.toHaveBeenCalled(); }); + it("does not warn for declared external auth plugins with different provider ids", () => { + resolveExternalAuthProfileProviderPluginIdsMock.mockReturnValue(["demo-plugin"]); + resolvePluginProvidersMock.mockReturnValue([ + { + id: "demo-provider", + pluginId: "demo-plugin", + label: "Demo Provider", + auth: [], + resolveExternalAuthProfiles: () => [ + { + profileId: "demo-provider:external", + credential: { + type: "oauth", + provider: "demo-provider", + access: "access", + refresh: "refresh", + expires: Date.now() + 60_000, + }, + }, + ], + }, + ]); + + expect( + resolveExternalAuthProfilesWithPlugins({ + env: process.env, + context: { + env: process.env, + store: { version: 1, profiles: {} }, + }, + }), + ).toEqual([ + expect.objectContaining({ + profileId: "demo-provider:external", + }), + ]); + expect(providerRuntimeWarnMock).not.toHaveBeenCalled(); + }); + it("returns provider-prepared runtime auth for the matched provider", async () => { const prepareRuntimeAuth = vi.fn(async () => ({ apiKey: "runtime-token", diff --git a/src/plugins/provider-runtime.ts b/src/plugins/provider-runtime.ts index 7f80aa1b612..e11347cc140 100644 --- a/src/plugins/provider-runtime.ts +++ b/src/plugins/provider-runtime.ts @@ -795,13 +795,14 @@ export function resolveExternalAuthProfilesWithPlugins(params: { if (!profiles || profiles.length === 0) { continue; } - if (!declaredPluginIds.has(plugin.id) && !warnedExternalAuthFallbackPluginIds.has(plugin.id)) { - warnedExternalAuthFallbackPluginIds.add(plugin.id); + const pluginId = plugin.pluginId ?? plugin.id; + if (!declaredPluginIds.has(pluginId) && !warnedExternalAuthFallbackPluginIds.has(pluginId)) { + warnedExternalAuthFallbackPluginIds.add(pluginId); // Deprecated compatibility path for plugins that still implement // resolveExternalOAuthProfiles or omit contracts.externalAuthProviders. // Remove this warning with the fallback resolver after the migration window. log.warn( - `Provider plugin "${plugin.id}" uses external auth hooks without declaring contracts.externalAuthProviders. This compatibility fallback is deprecated and will be removed in a future release.`, + `Provider plugin "${pluginId}" uses external auth hooks without declaring contracts.externalAuthProviders. This compatibility fallback is deprecated and will be removed in a future release.`, ); } matches.push(...profiles);