diff --git a/src/agents/tools/web-fetch.ts b/src/agents/tools/web-fetch.ts index 0944523c6a6..2a9f7419701 100644 --- a/src/agents/tools/web-fetch.ts +++ b/src/agents/tools/web-fetch.ts @@ -34,6 +34,7 @@ import { resolveTimeoutSeconds, writeCache, } from "./web-shared.js"; +import { resolveWebFetchToolRuntimeContext } from "./web-tool-runtime-context.js"; const EXTRACT_MODES = ["markdown", "text"] as const; diff --git a/src/agents/tools/web-tool-runtime-context.ts b/src/agents/tools/web-tool-runtime-context.ts new file mode 100644 index 00000000000..45454f781f6 --- /dev/null +++ b/src/agents/tools/web-tool-runtime-context.ts @@ -0,0 +1,123 @@ +import type { OpenClawConfig } from "../../config/types.openclaw.js"; +import { resolveManifestContractOwnerPluginId } from "../../plugins/plugin-registry.js"; +import { getActiveRuntimeWebToolsMetadata } from "../../secrets/runtime-web-tools-state.js"; +import type { + RuntimeWebFetchMetadata, + RuntimeWebSearchMetadata, +} from "../../secrets/runtime-web-tools.types.js"; +import { getActiveSecretsRuntimeSnapshot } from "../../secrets/runtime.js"; + +type WebProviderKind = "fetch" | "search"; + +type WebProviderRuntimeMetadata = RuntimeWebFetchMetadata | RuntimeWebSearchMetadata; + +type WebProviderContract = "webFetchProviders" | "webSearchProviders"; + +type ResolvedWebToolRuntimeContext = { + config?: OpenClawConfig; + preferRuntimeProviders: boolean; + runtimeMetadata?: TMetadata; +}; + +function resolveConfiguredWebProviderId( + config: OpenClawConfig | undefined, + kind: WebProviderKind, +): string { + const provider = config?.tools?.web?.[kind]?.provider; + return typeof provider === "string" ? provider.trim().toLowerCase() : ""; +} + +function resolveRuntimeWebProviderId(metadata: WebProviderRuntimeMetadata | undefined): string { + return metadata?.selectedProvider ?? metadata?.providerConfigured ?? ""; +} + +function resolveWebProviderContract(kind: WebProviderKind): WebProviderContract { + return kind === "fetch" ? "webFetchProviders" : "webSearchProviders"; +} + +function shouldPreferRuntimeProviders(params: { + config?: OpenClawConfig; + kind: WebProviderKind; + providerSelectionId: string; +}): boolean { + if (!params.providerSelectionId) { + return true; + } + return !resolveManifestContractOwnerPluginId({ + contract: resolveWebProviderContract(params.kind), + value: params.providerSelectionId, + origin: "bundled", + config: params.config, + }); +} + +function resolveWebToolRuntimeContext(params: { + capturedConfig?: OpenClawConfig; + capturedRuntimeMetadata?: TMetadata; + kind: WebProviderKind; + lateBindRuntimeConfig?: boolean; +}): ResolvedWebToolRuntimeContext { + const activeWebTools = + params.lateBindRuntimeConfig === true ? getActiveRuntimeWebToolsMetadata() : null; + const runtimeMetadata = (activeWebTools?.[params.kind] ?? params.capturedRuntimeMetadata) as + | TMetadata + | undefined; + const config = + params.lateBindRuntimeConfig === true + ? (getActiveSecretsRuntimeSnapshot()?.config ?? params.capturedConfig) + : params.capturedConfig; + const providerSelectionId = + resolveRuntimeWebProviderId(runtimeMetadata) || + resolveConfiguredWebProviderId(config, params.kind); + return { + config, + preferRuntimeProviders: shouldPreferRuntimeProviders({ + config, + kind: params.kind, + providerSelectionId, + }), + runtimeMetadata, + }; +} + +export function resolveWebSearchToolRuntimeContext(params: { + config?: OpenClawConfig; + lateBindRuntimeConfig?: boolean; + runtimeWebSearch?: RuntimeWebSearchMetadata; +}): ResolvedWebToolRuntimeContext & { + runtimeWebSearch?: RuntimeWebSearchMetadata; +} { + const resolved = resolveWebToolRuntimeContext({ + capturedConfig: params.config, + capturedRuntimeMetadata: params.runtimeWebSearch, + kind: "search", + lateBindRuntimeConfig: params.lateBindRuntimeConfig, + }); + return { + config: resolved.config, + preferRuntimeProviders: resolved.preferRuntimeProviders, + runtimeMetadata: resolved.runtimeMetadata, + runtimeWebSearch: resolved.runtimeMetadata, + }; +} + +export function resolveWebFetchToolRuntimeContext(params: { + config?: OpenClawConfig; + lateBindRuntimeConfig?: boolean; + runtimeWebFetch?: RuntimeWebFetchMetadata; +}): ResolvedWebToolRuntimeContext & { + runtimeWebFetch?: RuntimeWebFetchMetadata; +} { + const resolved = resolveWebToolRuntimeContext({ + capturedConfig: params.config, + capturedRuntimeMetadata: params.runtimeWebFetch, + kind: "fetch", + lateBindRuntimeConfig: params.lateBindRuntimeConfig, + }); + return { + config: resolved.config, + preferRuntimeProviders: resolved.preferRuntimeProviders, + runtimeMetadata: resolved.runtimeMetadata, + runtimeWebFetch: resolved.runtimeMetadata, + }; +}