diff --git a/src/plugins/provider-discovery.runtime.test.ts b/src/plugins/provider-discovery.runtime.test.ts index 0c3339713c9..783e6b2eb90 100644 --- a/src/plugins/provider-discovery.runtime.test.ts +++ b/src/plugins/provider-discovery.runtime.test.ts @@ -67,7 +67,7 @@ function createManifestPlugin(id: string): PluginManifestRecord { function createManifestPluginWithModelCatalog( id: string, - discovery: "static" | "runtime" = "static", + discovery: "static" | "refreshable" | "runtime" = "static", ): PluginManifestRecord { return { ...createManifestPluginWithoutDiscovery({ id }), @@ -263,6 +263,38 @@ describe("resolvePluginDiscoveryProvidersRuntime", () => { expect(mocks.resolvePluginProviders).not.toHaveBeenCalled(); }); + it("does not synthesize manifest entry providers for refreshable catalogs", () => { + mocks.resolveDiscoveredProviderPluginIds.mockReturnValue(["token-plan"]); + mocks.loadPluginMetadataSnapshot.mockReturnValue({ + index: { plugins: [] }, + manifestRegistry: { + plugins: [createManifestPluginWithModelCatalog("token-plan", "refreshable")], + diagnostics: [], + }, + }); + + expect(resolvePluginDiscoveryProvidersRuntime({ discoveryEntriesOnly: true })).toStrictEqual( + [], + ); + expect(mocks.resolvePluginProviders).not.toHaveBeenCalled(); + }); + + it("loads the full plugin for refreshable manifest catalog rows", () => { + const refreshableProvider = createProvider({ id: "token-plan", mode: "catalog" }); + mocks.resolveDiscoveredProviderPluginIds.mockReturnValue(["token-plan"]); + mocks.resolvePluginProviders.mockReturnValue([refreshableProvider]); + mocks.loadPluginMetadataSnapshot.mockReturnValue({ + index: { plugins: [] }, + manifestRegistry: { + plugins: [createManifestPluginWithModelCatalog("token-plan", "refreshable")], + diagnostics: [], + }, + }); + + expect(resolvePluginDiscoveryProvidersRuntime({})).toStrictEqual([refreshableProvider]); + expect(requireResolvePluginProvidersParams().onlyPluginIds).toEqual(["token-plan"]); + }); + it("loads the full plugin when one manifest catalog provider is runtime-owned", () => { const runtimeProvider = createProvider({ id: "xiaomi-token-plan", mode: "catalog" }); mocks.resolveDiscoveredProviderPluginIds.mockReturnValue(["xiaomi"]); diff --git a/src/plugins/provider-discovery.runtime.ts b/src/plugins/provider-discovery.runtime.ts index a1c97bd1669..545c1e3c30d 100644 --- a/src/plugins/provider-discovery.runtime.ts +++ b/src/plugins/provider-discovery.runtime.ts @@ -217,7 +217,7 @@ function resolveManifestModelCatalogProviders( } const plan = planManifestModelCatalogRows({ registry: { plugins: [plugin] } }); for (const entry of plan.entries) { - if (entry.rows.length === 0 || entry.discovery === "runtime") { + if (entry.rows.length === 0 || entry.discovery === "runtime" || entry.discovery === "refreshable") { continue; } const providerConfig = providerConfigFromManifestRows(entry.rows); @@ -249,7 +249,7 @@ function resolveRuntimeManifestCatalogPluginIds( ); const ownsRuntimeDiscovery = Object.entries(plugin.modelCatalog?.discovery ?? {}).some( ([provider, discovery]) => - discovery === "runtime" && ownedProviders.has(normalizeProviderId(provider)), + (discovery === "runtime" || discovery === "refreshable") && ownedProviders.has(normalizeProviderId(provider)), ); if (ownsRuntimeDiscovery) { pluginIds.add(plugin.id); @@ -259,7 +259,7 @@ function resolveRuntimeManifestCatalogPluginIds( continue; } const plan = planManifestModelCatalogRows({ registry: { plugins: [plugin] } }); - if (plan.entries.some((entry) => entry.discovery === "runtime")) { + if (plan.entries.some((entry) => entry.discovery === "runtime" || entry.discovery === "refreshable")) { pluginIds.add(plugin.id); } }