perf(secrets): fast-path exact bundled web providers

This commit is contained in:
Vincent Koc
2026-04-08 08:01:10 +01:00
parent dc1e07ea41
commit 2205153ee8
2 changed files with 76 additions and 5 deletions

View File

@@ -822,6 +822,53 @@ describe("runtime web tools resolution", () => {
expect(resolvePluginWebSearchProvidersMock).not.toHaveBeenCalled();
});
it("uses exact plugin-id hints for configured bundled provider entries without manifest owner lookup", async () => {
const { metadata } = await runRuntimeWebTools({
config: asConfig({
tools: {
web: {
search: {
enabled: true,
provider: "brave",
},
},
},
plugins: {
entries: {
brave: {
enabled: true,
config: {
webSearch: {
apiKey: { source: "env", provider: "default", id: "BRAVE_PROVIDER_REF" },
},
},
},
google: {
enabled: true,
config: {
webSearch: {
apiKey: { source: "env", provider: "default", id: "GOOGLE_PROVIDER_REF" },
},
},
},
},
},
}),
env: {
BRAVE_PROVIDER_REF: "brave-provider-key",
GOOGLE_PROVIDER_REF: "google-provider-key",
},
});
expect(metadata.search.selectedProvider).toBe("brave");
expect(resolveBundledExplicitWebSearchProvidersFromPublicArtifactsMock).toHaveBeenCalledWith({
onlyPluginIds: ["brave"],
});
expect(resolveManifestContractOwnerPluginIdMock).not.toHaveBeenCalled();
expect(resolveBundledWebSearchProvidersFromPublicArtifactsMock).not.toHaveBeenCalled();
expect(resolvePluginWebSearchProvidersMock).not.toHaveBeenCalled();
});
it("limits legacy top-level web search apiKey auto-detect to compatibility owners", async () => {
const { metadata } = await runRuntimeWebTools({
config: asConfig({

View File

@@ -107,6 +107,19 @@ function inferSingleBundledPluginScopedWebToolConfigOwner(
return matches[0];
}
function inferExactBundledPluginScopedWebToolConfigOwner(params: {
config: OpenClawConfig;
key: "webSearch" | "webFetch";
pluginId: string;
}): string | undefined {
const entry = params.config.plugins?.entries?.[params.pluginId];
if (!isRecord(entry) || entry.enabled === false) {
return undefined;
}
const pluginConfig = isRecord(entry.config) ? entry.config : undefined;
return isRecord(pluginConfig?.[params.key]) ? params.pluginId : undefined;
}
function hasCustomWebSearchPluginRisk(config: OpenClawConfig): boolean {
const plugins = config.plugins;
if (!plugins) {
@@ -459,6 +472,11 @@ export async function resolveRuntimeWebTools(params: {
? params.resolvedConfig.tools
: undefined;
const resolvedWeb = isRecord(resolvedTools?.web) ? resolvedTools.web : undefined;
let hasCustomWebSearchRisk: boolean | undefined;
const getHasCustomWebSearchRisk = (): boolean => {
hasCustomWebSearchRisk ??= hasCustomWebSearchPluginRisk(params.sourceConfig);
return hasCustomWebSearchRisk;
};
const legacyXSearchSource = isRecord(sourceWeb?.x_search) ? sourceWeb.x_search : undefined;
const legacyXSearchResolved = isRecord(resolvedWeb?.x_search) ? resolvedWeb.x_search : undefined;
@@ -501,7 +519,6 @@ export async function resolveRuntimeWebTools(params: {
}
const search = isRecord(sourceWeb?.search) ? sourceWeb.search : undefined;
const fetch = isRecord(sourceWeb?.fetch) ? (sourceWeb.fetch as FetchConfig) : undefined;
const hasCustomWebSearchRisk = hasCustomWebSearchPluginRisk(params.sourceConfig);
if (!search && !fetch && !hasPluginWebSearchConfig && !hasPluginWebFetchConfig) {
return {
search: {
@@ -517,8 +534,15 @@ export async function resolveRuntimeWebTools(params: {
}
const rawProvider = normalizeLowercaseStringOrEmpty(search?.provider);
const configuredBundledWebSearchPluginIdHint =
rawProvider && hasPluginWebSearchConfig && !hasCustomWebSearchRisk
? inferSingleBundledPluginScopedWebToolConfigOwner(params.sourceConfig, "webSearch")
rawProvider && hasPluginWebSearchConfig
? (inferExactBundledPluginScopedWebToolConfigOwner({
config: params.sourceConfig,
key: "webSearch",
pluginId: rawProvider,
}) ??
(!getHasCustomWebSearchRisk()
? inferSingleBundledPluginScopedWebToolConfigOwner(params.sourceConfig, "webSearch")
: undefined))
: undefined;
const searchMetadata: RuntimeWebSearchMetadata = {
providerSource: "none",
@@ -557,10 +581,10 @@ export async function resolveRuntimeWebTools(params: {
onlyPluginIds:
configuredBundledPluginId === undefined &&
searchCompatibilityOnlyPluginIds.length > 0 &&
!hasCustomWebSearchRisk
!getHasCustomWebSearchRisk()
? searchCompatibilityOnlyPluginIds
: undefined,
hasCustomWebSearchPluginRisk: hasCustomWebSearchRisk,
hasCustomWebSearchPluginRisk: getHasCustomWebSearchRisk(),
}),
sortProviders: sortWebSearchProvidersForAutoDetect,
readConfiguredCredential: ({ provider, config, toolConfig }) =>