diff --git a/src/commands/doctor/shared/legacy-web-search-migrate.ts b/src/commands/doctor/shared/legacy-web-search-migrate.ts index 873cd99300e..392d61c3f54 100644 --- a/src/commands/doctor/shared/legacy-web-search-migrate.ts +++ b/src/commands/doctor/shared/legacy-web-search-migrate.ts @@ -17,13 +17,23 @@ const MODERN_SCOPED_WEB_SEARCH_KEYS = new Set(["openaiCodex"]); // Tavily only ever used the plugin-owned config path, so there is no legacy // `tools.web.search.tavily.*` shape to migrate. const NON_MIGRATED_LEGACY_WEB_SEARCH_PROVIDER_IDS = new Set(["tavily"]); -const LEGACY_WEB_SEARCH_PROVIDER_IDS = loadPluginManifestRegistry({ cache: true }) - .plugins.filter((plugin) => plugin.origin === "bundled") - .flatMap((plugin) => plugin.contracts?.webSearchProviders ?? []) - .filter((providerId) => !NON_MIGRATED_LEGACY_WEB_SEARCH_PROVIDER_IDS.has(providerId)) - .toSorted((left, right) => left.localeCompare(right)); -const LEGACY_WEB_SEARCH_PROVIDER_ID_SET = new Set(LEGACY_WEB_SEARCH_PROVIDER_IDS); const LEGACY_GLOBAL_WEB_SEARCH_PROVIDER_ID = "brave"; +let legacyWebSearchProviderIdsCache: string[] | undefined; +let legacyWebSearchProviderIdSetCache: Set | undefined; + +function getLegacyWebSearchProviderIds(): string[] { + legacyWebSearchProviderIdsCache ??= loadPluginManifestRegistry({ cache: true }) + .plugins.filter((plugin) => plugin.origin === "bundled") + .flatMap((plugin) => plugin.contracts?.webSearchProviders ?? []) + .filter((providerId) => !NON_MIGRATED_LEGACY_WEB_SEARCH_PROVIDER_IDS.has(providerId)) + .toSorted((left, right) => left.localeCompare(right)); + return legacyWebSearchProviderIdsCache; +} + +function getLegacyWebSearchProviderIdSet(): Set { + legacyWebSearchProviderIdSetCache ??= new Set(getLegacyWebSearchProviderIds()); + return legacyWebSearchProviderIdSetCache; +} function resolveLegacySearchConfig(raw: unknown): JsonRecord | undefined { if (!isRecord(raw)) { @@ -47,7 +57,7 @@ function hasMappedLegacyWebSearchConfig(raw: unknown): boolean { if (hasOwnKey(search, "apiKey")) { return true; } - return LEGACY_WEB_SEARCH_PROVIDER_IDS.some((providerId) => isRecord(search[providerId])); + return getLegacyWebSearchProviderIds().some((providerId) => isRecord(search[providerId])); } function resolveLegacyGlobalWebSearchMigration(search: JsonRecord): { @@ -136,7 +146,7 @@ export function listLegacyWebSearchConfigPaths(raw: unknown): string[] { if ("apiKey" in search) { paths.push("tools.web.search.apiKey"); } - for (const providerId of LEGACY_WEB_SEARCH_PROVIDER_IDS) { + for (const providerId of getLegacyWebSearchProviderIds()) { const scoped = search[providerId]; if (isRecord(scoped)) { for (const key of Object.keys(scoped)) { @@ -192,7 +202,7 @@ function normalizeLegacyWebSearchConfigRecord( if (key === "apiKey") { continue; } - if (LEGACY_WEB_SEARCH_PROVIDER_ID_SET.has(key) && isRecord(value)) { + if (getLegacyWebSearchProviderIdSet().has(key) && isRecord(value)) { continue; } if (MODERN_SCOPED_WEB_SEARCH_KEYS.has(key) || !isRecord(value)) { @@ -213,7 +223,7 @@ function normalizeLegacyWebSearchConfigRecord( }); } - for (const providerId of LEGACY_WEB_SEARCH_PROVIDER_IDS) { + for (const providerId of getLegacyWebSearchProviderIds()) { if (providerId === LEGACY_GLOBAL_WEB_SEARCH_PROVIDER_ID) { continue; }