UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

873 lines (872 loc) 34.2 kB
import { a as normalizeLowercaseStringOrEmpty, s as normalizeOptionalLowercaseString } from "./string-coerce-mnp54Vah.js"; import { g as sortUniqueStrings } from "./string-normalization-WNUDCpXX.js"; import { c as isRecord } from "./utils-CCC-BEJH.js"; import { m as resolveSecretInputRef } from "./types.secrets-_0JOMGE5.js"; import { n as loadInstalledPluginIndexInstallRecordsSync } from "./installed-plugin-index-record-reader-CPHayOZI.js"; import { c as secretRefKey } from "./ref-contract-BAa3qHwr.js"; import { o as resolveSecretRefValues } from "./resolve-DPFnV1p0.js"; import "./shared-CuqTS6Vs.js"; import { c as pushInactiveSurfaceWarning, l as pushWarning } from "./runtime-shared-DR5938Io.js"; import { i as setPathExistingStrict } from "./path-utils-BBmSOFBL.js"; import "./installed-plugin-index-records-DXbAzXDd.js"; import { n as normalizeSecretInput } from "./normalize-secret-input-OwRUfByL.js"; import { a as createLazyRuntimeSurface, i as createLazyRuntimeNamedExport } from "./lazy-runtime-D-7_JraP.js"; import { o as sortWebFetchProvidersForAutoDetect, r as sortWebSearchProvidersForAutoDetect } from "./web-search-providers.shared-DMAveALG.js"; import { i as resolveBundledExplicitWebSearchProvidersFromPublicArtifacts, r as resolveBundledExplicitWebFetchProvidersFromPublicArtifacts } from "./web-provider-public-artifacts.explicit-BNgX1hwM.js"; import { t as hasCredentialBearingObjectValue } from "./runtime-secret-scan-CsGyxO5u.js"; //#region src/secrets/runtime-web-tools.shared.ts /** Shared helpers for web-tool secret metadata resolution. */ const loadResolveManifestContractOwnerPluginId = createLazyRuntimeNamedExport(() => import("./runtime-web-tools-manifest.runtime.js"), "resolveManifestContractOwnerPluginId"); function pushInactiveProviderCredentialWarnings(params) { for (const provider of params.selection.providers) { if (provider.id === params.skipProviderId) continue; const value = params.selection.readConfiguredCredential({ provider, config: params.selection.sourceConfig, toolConfig: params.selection.toolConfig }); if (!params.selection.hasConfiguredSecretRef(value, params.selection.defaults)) continue; for (const path of params.selection.inactivePathsForProvider(provider)) pushInactiveSurfaceWarning({ context: params.selection.context, path, details: params.details }); } } /** * Ensures a nested config object exists and returns it for mutation. */ function ensureObject(target, key) { const current = target[key]; if (isRecord(current)) return current; const next = {}; target[key] = next; return next; } function normalizeKnownProvider(value, providers) { const normalized = normalizeOptionalLowercaseString(value); if (!normalized) return; if (providers.some((provider) => provider.id === normalized)) return normalized; } /** * Returns whether a configured value or sibling ref field contains a SecretRef. */ function hasConfiguredSecretRef(value, defaults) { return Boolean(resolveSecretInputRef({ value, defaults }).ref); } function getProviderEnvVars(provider) { return "envVars" in provider && Array.isArray(provider.envVars) ? provider.envVars : []; } function setResolvedCredentialPath(params) { const pathSegments = params.path.split(".").map((segment) => segment.trim()).filter((segment) => segment.length > 0); if (pathSegments.length === 0) return; try { setPathExistingStrict(params.resolvedConfig, pathSegments, params.value); } catch {} } /** * Resolves available providers, configured provider validity, and whether the surface is active. */ async function resolveRuntimeWebProviderSurface(params) { let configuredBundledPluginId = params.configuredBundledPluginIdHint; if (!configuredBundledPluginId && params.rawProvider) configuredBundledPluginId = (await loadResolveManifestContractOwnerPluginId())({ contract: params.contract, value: params.rawProvider, origin: "bundled", config: params.sourceConfig, env: { ...process.env, ...params.context.env } }); let allProviders = params.sortProviders(await params.resolveProviders({ configuredBundledPluginId })); if (params.rawProvider && params.configuredBundledPluginIdHint && configuredBundledPluginId && !allProviders.some((provider) => provider.id === params.rawProvider)) configuredBundledPluginId = void 0; if (params.rawProvider && !configuredBundledPluginId && !allProviders.some((provider) => provider.id === params.rawProvider)) { configuredBundledPluginId = (await loadResolveManifestContractOwnerPluginId())({ contract: params.contract, value: params.rawProvider, origin: "bundled", config: params.sourceConfig, env: { ...process.env, ...params.context.env } }); allProviders = params.sortProviders(await params.resolveProviders({ configuredBundledPluginId })); } const hasConfiguredSurface = Boolean(params.toolConfig) || allProviders.some((provider) => { if (params.ignoreKeylessProvidersForConfiguredSurface && provider.requiresCredential === false) return false; return params.readConfiguredCredential({ provider, config: params.sourceConfig, toolConfig: params.toolConfig }) !== void 0 || params.readConfiguredCredentialFallback?.({ provider, config: params.sourceConfig, toolConfig: params.toolConfig })?.value !== void 0; }); const providers = hasConfiguredSurface || !params.emptyProvidersWhenSurfaceMissing ? allProviders : []; const configuredProvider = normalizeKnownProvider(params.rawProvider, params.normalizeConfiguredProviderAgainstActiveProviders ? providers : allProviders); if (params.rawProvider && !configuredProvider) { const diagnostic = { code: params.invalidAutoDetectCode, message: `${params.providerPath} is "${params.rawProvider}". Falling back to auto-detect precedence.`, path: params.providerPath }; params.diagnostics.push(diagnostic); params.metadataDiagnostics.push(diagnostic); pushWarning(params.context, { code: params.invalidAutoDetectCode, path: params.providerPath, message: diagnostic.message }); } return { providers, configuredProvider, enabled: hasConfiguredSurface && (!isRecord(params.toolConfig) || params.toolConfig.enabled !== false), hasConfiguredSurface }; } /** * Selects a configured or auto-detected provider and materializes its resolved credential. */ async function resolveRuntimeWebProviderSelection(params) { if (params.configuredProvider) { params.metadata.providerConfigured = params.configuredProvider; params.metadata.providerSource = "configured"; } if (params.enabled) { const candidates = params.configuredProvider ? params.providers.filter((provider) => provider.id === params.configuredProvider) : params.providers; const unresolvedWithoutFallback = []; let selectedProvider; let selectedResolution; let keylessFallbackProvider; for (const provider of candidates) { if (provider.requiresCredential === false) { if (params.deferKeylessFallback && !params.configuredProvider) { keylessFallbackProvider ||= provider; continue; } selectedProvider = provider.id; selectedResolution = { source: "missing", secretRefConfigured: false, fallbackUsedAfterRefFailure: false }; break; } const path = params.inactivePathsForProvider(provider)[0] ?? ""; const value = params.readConfiguredCredential({ provider, config: params.sourceConfig, toolConfig: params.toolConfig }); const resolution = await params.resolveSecretInput({ value, path, envVars: getProviderEnvVars(provider) }); let selectedCandidatePath = path; let selectedCandidateResolution = resolution; if (!resolution.value && !resolution.secretRefConfigured) { const fallback = params.readConfiguredCredentialFallback?.({ provider, config: params.sourceConfig, toolConfig: params.toolConfig }); if (fallback?.value !== void 0) { selectedCandidatePath = fallback.path; selectedCandidateResolution = await params.resolveSecretInput({ value: fallback.value, path: fallback.path, envVars: getProviderEnvVars(provider) }); } } else if (resolution.source === "env" && !resolution.secretRefConfigured) { const fallback = params.readConfiguredCredentialFallback?.({ provider, config: params.sourceConfig, toolConfig: params.toolConfig }); if (fallback?.value !== void 0 && params.hasConfiguredSecretRef(fallback.value, params.defaults)) { const fallbackResolution = await params.resolveSecretInput({ value: fallback.value, path: fallback.path, envVars: getProviderEnvVars(provider) }); if (fallbackResolution.source === "secretRef" && fallbackResolution.value) setResolvedCredentialPath({ resolvedConfig: params.resolvedConfig, path: fallback.path, value: fallbackResolution.value }); } } if (selectedCandidateResolution.secretRefConfigured && selectedCandidateResolution.fallbackUsedAfterRefFailure) { const diagnostic = { code: params.fallbackUsedCode, message: `${selectedCandidatePath} SecretRef could not be resolved; using ${selectedCandidateResolution.fallbackEnvVar ?? "env fallback"}. ` + (selectedCandidateResolution.unresolvedRefReason ?? "").trim(), path: selectedCandidatePath }; params.diagnostics.push(diagnostic); params.metadata.diagnostics.push(diagnostic); pushWarning(params.context, { code: params.fallbackUsedCode, path: selectedCandidatePath, message: diagnostic.message }); } if (selectedCandidateResolution.secretRefConfigured && !selectedCandidateResolution.value && selectedCandidateResolution.unresolvedRefReason) unresolvedWithoutFallback.push({ provider: provider.id, path: selectedCandidatePath, reason: selectedCandidateResolution.unresolvedRefReason }); if (params.configuredProvider) { selectedProvider = provider.id; selectedResolution = selectedCandidateResolution; if (selectedCandidateResolution.value) { setResolvedCredentialPath({ resolvedConfig: params.resolvedConfig, path: selectedCandidatePath, value: selectedCandidateResolution.value }); params.setResolvedCredential({ resolvedConfig: params.resolvedConfig, provider, value: selectedCandidateResolution.value }); } break; } if (selectedCandidateResolution.value) { selectedProvider = provider.id; selectedResolution = selectedCandidateResolution; setResolvedCredentialPath({ resolvedConfig: params.resolvedConfig, path: selectedCandidatePath, value: selectedCandidateResolution.value }); params.setResolvedCredential({ resolvedConfig: params.resolvedConfig, provider, value: selectedCandidateResolution.value }); break; } } if (!selectedProvider && keylessFallbackProvider) { selectedProvider = keylessFallbackProvider.id; selectedResolution = { source: "missing", secretRefConfigured: false, fallbackUsedAfterRefFailure: false }; } const failUnresolvedNoFallback = (unresolved) => { const diagnostic = { code: params.noFallbackCode, message: unresolved.reason, path: unresolved.path }; params.diagnostics.push(diagnostic); params.metadata.diagnostics.push(diagnostic); pushWarning(params.context, { code: params.noFallbackCode, path: unresolved.path, message: unresolved.reason }); throw new Error(`[${params.noFallbackCode}] ${unresolved.reason}`); }; if (params.configuredProvider) { const unresolved = unresolvedWithoutFallback[0]; if (unresolved) failUnresolvedNoFallback(unresolved); } else { if (!selectedProvider && unresolvedWithoutFallback.length > 0) failUnresolvedNoFallback(unresolvedWithoutFallback[0]); if (selectedProvider) { const selectedDetails = params.providers.find((entry) => entry.id === selectedProvider)?.requiresCredential === false ? `${params.scopePath} auto-detected keyless provider "${selectedProvider}" as the default fallback.` : `${params.scopePath} auto-detected provider "${selectedProvider}" from available credentials.`; const diagnostic = { code: params.autoDetectSelectedCode, message: selectedDetails, path: `${params.scopePath}.provider` }; params.diagnostics.push(diagnostic); params.metadata.diagnostics.push(diagnostic); } } if (selectedProvider) { params.metadata.selectedProvider = selectedProvider; params.metadata.selectedProviderKeySource = selectedResolution?.source; if (!params.configuredProvider) params.metadata.providerSource = "auto-detect"; const provider = params.providers.find((entry) => entry.id === selectedProvider); if (provider && params.mergeRuntimeMetadata) await params.mergeRuntimeMetadata({ provider, metadata: params.metadata, toolConfig: params.toolConfig, selectedResolution }); } } if (params.enabled && !params.configuredProvider && params.metadata.selectedProvider) pushInactiveProviderCredentialWarnings({ selection: params, skipProviderId: params.metadata.selectedProvider, details: `${params.scopePath} auto-detected provider is "${params.metadata.selectedProvider}".` }); else if (params.toolConfig && !params.enabled) pushInactiveProviderCredentialWarnings({ selection: params, details: `${params.scopePath} is disabled.` }); if (params.enabled && params.toolConfig && params.configuredProvider) pushInactiveProviderCredentialWarnings({ selection: params, skipProviderId: params.configuredProvider, details: `${params.scopePath}.provider is "${params.configuredProvider}".` }); } //#endregion //#region src/secrets/runtime-web-tools.ts /** Builds web-tool secret metadata from config, plugins, and provider contracts. */ const loadRuntimeWebToolsFallbackProviders = createLazyRuntimeSurface(() => import("./runtime-web-tools-fallback.runtime.js"), ({ runtimeWebToolsFallbackProviders }) => runtimeWebToolsFallbackProviders); const loadRuntimeWebToolsPublicArtifacts = createLazyRuntimeSurface(() => import("./runtime-web-tools-public-artifacts.runtime.js"), (mod) => mod); const loadRuntimeWebToolsManifest = createLazyRuntimeSurface(() => import("./runtime-web-tools-manifest.runtime.js"), (mod) => mod); function needsRuntimeWebFetchProviderDiscovery(params) { if (isRecord(params.fetch) && params.fetch.enabled === false) return false; if (params.hasPluginWebFetchConfig) return true; if (!isRecord(params.fetch)) return false; if (params.rawProvider) return true; return hasCredentialBearingObjectValue(params.fetch, params.defaults); } function hasPluginScopedWebToolConfig(config, key) { const entries = config.plugins?.entries; if (!entries) return false; return Object.values(entries).some((entry) => { if (!isRecord(entry)) return false; const pluginConfig = isRecord(entry.config) ? entry.config : void 0; return Boolean(pluginConfig?.[key]); }); } function inferSingleBundledPluginScopedWebToolConfigOwner(config, key) { const entries = config.plugins?.entries; if (!entries) return; const matches = []; for (const [pluginId, entry] of Object.entries(entries)) { if (!isRecord(entry) || entry.enabled === false) continue; if (!isRecord((isRecord(entry.config) ? entry.config : void 0)?.[key])) continue; matches.push(pluginId); if (matches.length > 1) return; } return matches[0]; } function inferExactBundledPluginScopedWebToolConfigOwner(params) { const entry = params.config.plugins?.entries?.[params.pluginId]; if (!isRecord(entry) || entry.enabled === false) return; return isRecord((isRecord(entry.config) ? entry.config : void 0)?.[params.key]) ? params.pluginId : void 0; } async function hasCustomWebProviderPluginRisk(params) { const installRecords = loadInstalledPluginIndexInstallRecordsSync({ env: params.env }); if (Object.keys(installRecords).length > 0) return true; const plugins = params.config.plugins; if (!plugins) return false; if (Array.isArray(plugins.load?.paths) && plugins.load.paths.length > 0) return true; const { resolveManifestContractPluginIds } = await loadRuntimeWebToolsManifest(); const bundledPluginIds = new Set(resolveManifestContractPluginIds({ contract: params.contract, origin: "bundled", config: params.config, env: params.env })); const hasNonBundledPluginId = (pluginId) => !bundledPluginIds.has(pluginId.trim()); if (Array.isArray(plugins.allow) && plugins.allow.some(hasNonBundledPluginId)) return true; if (Array.isArray(plugins.deny) && plugins.deny.some(hasNonBundledPluginId)) return true; if (plugins.entries && Object.keys(plugins.entries).some(hasNonBundledPluginId)) return true; return false; } function readNonEmptyEnvValue(env, names) { for (const envVar of names) { const value = normalizeSecretInput(env[envVar]); if (value) return { value, envVar }; } return {}; } function buildUnresolvedReason(params) { if (params.kind === "non-string") return `${params.path} SecretRef resolved to a non-string value.`; if (params.kind === "empty") return `${params.path} SecretRef resolved to an empty value.`; return `${params.path} SecretRef is unresolved (${params.refLabel}).`; } async function resolveSecretInputWithEnvFallback(params) { const { ref } = resolveSecretInputRef({ value: params.value, defaults: params.defaults }); if (!ref) { const configValue = normalizeSecretInput(params.value); if (configValue) return { value: configValue, source: "config", secretRefConfigured: false, fallbackUsedAfterRefFailure: false }; const fallback = readNonEmptyEnvValue(params.context.env, params.envVars); if (fallback.value) return { value: fallback.value, source: "env", fallbackEnvVar: fallback.envVar, secretRefConfigured: false, fallbackUsedAfterRefFailure: false }; return { source: "missing", secretRefConfigured: false, fallbackUsedAfterRefFailure: false }; } const refLabel = `${ref.source}:${ref.provider}:${ref.id}`; let resolvedFromRef; let unresolvedRefReason; if (params.restrictEnvRefsToEnvVars === true && ref.source === "env" && !params.envVars.includes(ref.id)) unresolvedRefReason = `${params.path} SecretRef env var "${ref.id}" is not allowed.`; else try { const resolvedValue = (await resolveSecretRefValues([ref], { config: params.sourceConfig, env: params.context.env, cache: params.context.cache, manifestRegistry: params.context.manifestRegistry })).get(secretRefKey(ref)); if (typeof resolvedValue !== "string") unresolvedRefReason = buildUnresolvedReason({ path: params.path, kind: "non-string", refLabel }); else { resolvedFromRef = normalizeSecretInput(resolvedValue); if (!resolvedFromRef) unresolvedRefReason = buildUnresolvedReason({ path: params.path, kind: "empty", refLabel }); } } catch { unresolvedRefReason = buildUnresolvedReason({ path: params.path, kind: "unresolved", refLabel }); } if (resolvedFromRef) return { value: resolvedFromRef, source: "secretRef", secretRefConfigured: true, fallbackUsedAfterRefFailure: false }; const fallback = readNonEmptyEnvValue(params.context.env, params.envVars); if (fallback.value) return { value: fallback.value, source: "env", fallbackEnvVar: fallback.envVar, unresolvedRefReason, secretRefConfigured: true, fallbackUsedAfterRefFailure: true }; return { source: "missing", unresolvedRefReason, secretRefConfigured: true, fallbackUsedAfterRefFailure: false }; } function setResolvedWebSearchApiKey(params) { if (params.provider.setConfiguredCredentialValue) { params.provider.setConfiguredCredentialValue(params.resolvedConfig, params.value); return; } const search = ensureObject(ensureObject(ensureObject(params.resolvedConfig, "tools"), "web"), "search"); params.provider.setCredentialValue(search, params.value); } async function resolveBundledWebSearchProviders(params) { const env = { ...process.env, ...params.context.env }; const onlyPluginIds = params.configuredBundledPluginId !== void 0 ? [params.configuredBundledPluginId] : params.onlyPluginIds && params.onlyPluginIds.length > 0 ? sortUniqueStrings(params.onlyPluginIds) : void 0; if (onlyPluginIds && onlyPluginIds.length > 0) { const bundled = resolveBundledExplicitWebSearchProvidersFromPublicArtifacts({ onlyPluginIds }); if (bundled && bundled.length > 0) return bundled; const { resolvePluginWebSearchProviders } = await loadRuntimeWebToolsFallbackProviders(); return resolvePluginWebSearchProviders({ config: params.sourceConfig, env, onlyPluginIds, origin: "bundled" }); } if (!params.hasCustomWebSearchPluginRisk) { const { resolveBundledWebSearchProvidersFromPublicArtifacts } = await loadRuntimeWebToolsPublicArtifacts(); const bundled = resolveBundledWebSearchProvidersFromPublicArtifacts({ config: params.sourceConfig, env }); if (bundled && bundled.length > 0) return bundled; const { resolvePluginWebSearchProviders } = await loadRuntimeWebToolsFallbackProviders(); return resolvePluginWebSearchProviders({ config: params.sourceConfig, env, origin: "bundled" }); } const { resolvePluginWebSearchProviders } = await loadRuntimeWebToolsFallbackProviders(); return resolvePluginWebSearchProviders({ config: params.sourceConfig, env }); } async function resolveBundledWebFetchProviders(params) { const env = { ...process.env, ...params.context.env }; if (params.configuredBundledPluginId) { const bundled = resolveBundledExplicitWebFetchProvidersFromPublicArtifacts({ onlyPluginIds: [params.configuredBundledPluginId] }); if (bundled && bundled.length > 0) return bundled; const { resolvePluginWebFetchProviders } = await loadRuntimeWebToolsFallbackProviders(); return resolvePluginWebFetchProviders({ config: params.sourceConfig, env, onlyPluginIds: [params.configuredBundledPluginId], origin: "bundled" }); } if (!params.hasCustomWebFetchPluginRisk) { const { resolveBundledWebFetchProvidersFromPublicArtifacts } = await loadRuntimeWebToolsPublicArtifacts(); const bundled = resolveBundledWebFetchProvidersFromPublicArtifacts({ config: params.sourceConfig, env }); if (bundled && bundled.length > 0) return bundled; const { resolvePluginWebFetchProviders } = await loadRuntimeWebToolsFallbackProviders(); return resolvePluginWebFetchProviders({ config: params.sourceConfig, env, origin: "bundled" }); } const { resolvePluginWebFetchProviders } = await loadRuntimeWebToolsFallbackProviders(); return resolvePluginWebFetchProviders({ config: params.sourceConfig, env, origin: "bundled" }); } function readConfiguredProviderCredential(params) { return params.provider.getConfiguredCredentialValue?.(params.config) ?? params.provider.getCredentialValue(params.search); } function readConfiguredProviderCredentialFallback(params) { return params.provider.getConfiguredCredentialFallback?.(params.config); } function inactivePathsForProvider(provider) { if (provider.requiresCredential === false) return []; return provider.inactiveSecretPaths?.length ? provider.inactiveSecretPaths : [provider.credentialPath]; } function setResolvedWebFetchApiKey(params) { const fetch = ensureObject(ensureObject(ensureObject(params.resolvedConfig, "tools"), "web"), "fetch"); if (params.provider.setConfiguredCredentialValue) { params.provider.setConfiguredCredentialValue(params.resolvedConfig, params.value); return; } params.provider.setCredentialValue(fetch, params.value); } function readConfiguredFetchProviderCredential(params) { return params.provider.getConfiguredCredentialValue?.(params.config) ?? params.provider.getCredentialValue(params.fetch); } function readConfiguredFetchProviderCredentialFallback(params) { return params.provider.getConfiguredCredentialFallback?.(params.config); } function inactivePathsForFetchProvider(provider) { if (provider.requiresCredential === false) return []; return provider.inactiveSecretPaths?.length ? provider.inactiveSecretPaths : [provider.credentialPath]; } /** * Resolves runtime web search/fetch provider metadata and writes selected credentials into a * cloned runtime config without mutating the source config. */ /** Resolves web search/fetch secret metadata from config, plugins, and fallback runtime providers. */ async function resolveRuntimeWebTools(params) { const defaults = params.sourceConfig.secrets?.defaults; const diagnostics = []; const env = { ...process.env, ...params.context.env }; const sourceTools = isRecord(params.sourceConfig.tools) ? params.sourceConfig.tools : void 0; const sourceWeb = isRecord(sourceTools?.web) ? sourceTools.web : void 0; const resolvedTools = isRecord(params.resolvedConfig.tools) ? params.resolvedConfig.tools : void 0; const resolvedWeb = isRecord(resolvedTools?.web) ? resolvedTools.web : void 0; let hasCustomWebSearchRisk; const getHasCustomWebSearchRisk = () => { hasCustomWebSearchRisk ??= hasCustomWebProviderPluginRisk({ contract: "webSearchProviders", config: params.sourceConfig, env }); return hasCustomWebSearchRisk; }; let hasCustomWebFetchRisk; const getHasCustomWebFetchRisk = () => { hasCustomWebFetchRisk ??= hasCustomWebProviderPluginRisk({ contract: "webFetchProviders", config: params.sourceConfig, env }); return hasCustomWebFetchRisk; }; const legacyXSearchSource = isRecord(sourceWeb?.x_search) ? sourceWeb.x_search : void 0; const legacyXSearchResolved = isRecord(resolvedWeb?.x_search) ? resolvedWeb.x_search : void 0; if (legacyXSearchSource && legacyXSearchResolved && Object.hasOwn(legacyXSearchSource, "apiKey")) { const legacyXSearchSourceRecord = legacyXSearchSource; const legacyXSearchResolvedRecord = legacyXSearchResolved; const resolution = await resolveSecretInputWithEnvFallback({ sourceConfig: params.sourceConfig, context: params.context, defaults, value: legacyXSearchSourceRecord.apiKey, path: "tools.web.x_search.apiKey", envVars: ["XAI_API_KEY"] }); if (resolution.value) legacyXSearchResolvedRecord.apiKey = resolution.value; } const hasPluginWebSearchConfig = hasPluginScopedWebToolConfig(params.sourceConfig, "webSearch"); const hasPluginWebFetchConfig = hasPluginScopedWebToolConfig(params.sourceConfig, "webFetch"); if (!sourceWeb && !hasPluginWebSearchConfig && !hasPluginWebFetchConfig) return { search: { providerSource: "none", diagnostics: [] }, fetch: { providerSource: "none", diagnostics: [] }, diagnostics }; const search = isRecord(sourceWeb?.search) ? sourceWeb.search : void 0; const fetch = isRecord(sourceWeb?.fetch) ? sourceWeb.fetch : void 0; if (!search && !fetch && !hasPluginWebSearchConfig && !hasPluginWebFetchConfig) return { search: { providerSource: "none", diagnostics: [] }, fetch: { providerSource: "none", diagnostics: [] }, diagnostics }; const rawProvider = normalizeLowercaseStringOrEmpty(search?.provider); let configuredBundledWebSearchPluginIdHint; if (hasPluginWebSearchConfig && !await getHasCustomWebSearchRisk()) { if (rawProvider) configuredBundledWebSearchPluginIdHint = inferExactBundledPluginScopedWebToolConfigOwner({ config: params.sourceConfig, key: "webSearch", pluginId: rawProvider }); configuredBundledWebSearchPluginIdHint ??= inferSingleBundledPluginScopedWebToolConfigOwner(params.sourceConfig, "webSearch"); } const searchMetadata = { providerSource: "none", diagnostics: [] }; if (search || hasPluginWebSearchConfig) { const searchSurface = await resolveRuntimeWebProviderSurface({ contract: "webSearchProviders", rawProvider, providerPath: "tools.web.search.provider", toolConfig: search, diagnostics, metadataDiagnostics: searchMetadata.diagnostics, invalidAutoDetectCode: "WEB_SEARCH_PROVIDER_INVALID_AUTODETECT", sourceConfig: params.sourceConfig, context: params.context, configuredBundledPluginIdHint: configuredBundledWebSearchPluginIdHint, resolveProviders: async ({ configuredBundledPluginId }) => resolveBundledWebSearchProviders({ sourceConfig: params.sourceConfig, context: params.context, configuredBundledPluginId, hasCustomWebSearchPluginRisk: await getHasCustomWebSearchRisk() }), sortProviders: sortWebSearchProvidersForAutoDetect, readConfiguredCredential: ({ provider, config, toolConfig }) => readConfiguredProviderCredential({ provider, config, search: toolConfig }), readConfiguredCredentialFallback: ({ provider, config, toolConfig }) => readConfiguredProviderCredentialFallback({ provider, config, search: toolConfig }), ignoreKeylessProvidersForConfiguredSurface: true, emptyProvidersWhenSurfaceMissing: true, normalizeConfiguredProviderAgainstActiveProviders: true }); await resolveRuntimeWebProviderSelection({ scopePath: "tools.web.search", toolConfig: search, enabled: searchSurface.enabled, providers: searchSurface.providers, configuredProvider: searchSurface.configuredProvider, metadata: searchMetadata, diagnostics, sourceConfig: params.sourceConfig, resolvedConfig: params.resolvedConfig, context: params.context, defaults, deferKeylessFallback: true, fallbackUsedCode: "WEB_SEARCH_KEY_UNRESOLVED_FALLBACK_USED", noFallbackCode: "WEB_SEARCH_KEY_UNRESOLVED_NO_FALLBACK", autoDetectSelectedCode: "WEB_SEARCH_AUTODETECT_SELECTED", readConfiguredCredential: ({ provider, config, toolConfig }) => readConfiguredProviderCredential({ provider, config, search: toolConfig }), readConfiguredCredentialFallback: ({ provider, config, toolConfig }) => readConfiguredProviderCredentialFallback({ provider, config, search: toolConfig }), resolveSecretInput: ({ value, path, envVars }) => resolveSecretInputWithEnvFallback({ sourceConfig: params.sourceConfig, context: params.context, defaults, value, path, envVars }), setResolvedCredential: ({ resolvedConfig, provider, value }) => setResolvedWebSearchApiKey({ resolvedConfig, provider, value }), inactivePathsForProvider, hasConfiguredSecretRef, mergeRuntimeMetadata: async ({ provider, metadata, toolConfig, selectedResolution }) => { if (!provider.resolveRuntimeMetadata) return; Object.assign(metadata, await provider.resolveRuntimeMetadata({ config: params.sourceConfig, searchConfig: toolConfig, runtimeMetadata: metadata, resolvedCredential: selectedResolution ? { value: selectedResolution.value, source: selectedResolution.source, fallbackEnvVar: selectedResolution.fallbackEnvVar } : void 0 })); } }); } const rawFetchProvider = normalizeLowercaseStringOrEmpty(fetch?.provider); const fetchMetadata = { providerSource: "none", diagnostics: [] }; if (needsRuntimeWebFetchProviderDiscovery({ fetch, rawProvider: rawFetchProvider, hasPluginWebFetchConfig, defaults })) { const fetchSurface = await resolveRuntimeWebProviderSurface({ contract: "webFetchProviders", rawProvider: rawFetchProvider, providerPath: "tools.web.fetch.provider", toolConfig: fetch, diagnostics, metadataDiagnostics: fetchMetadata.diagnostics, invalidAutoDetectCode: "WEB_FETCH_PROVIDER_INVALID_AUTODETECT", sourceConfig: params.sourceConfig, context: params.context, resolveProviders: async ({ configuredBundledPluginId }) => resolveBundledWebFetchProviders({ sourceConfig: params.sourceConfig, context: params.context, configuredBundledPluginId, hasCustomWebFetchPluginRisk: await getHasCustomWebFetchRisk() }), sortProviders: sortWebFetchProvidersForAutoDetect, readConfiguredCredential: ({ provider, config, toolConfig }) => readConfiguredFetchProviderCredential({ provider, config, fetch: toolConfig }), readConfiguredCredentialFallback: ({ provider, config, toolConfig }) => readConfiguredFetchProviderCredentialFallback({ provider, config, fetch: toolConfig }) }); await resolveRuntimeWebProviderSelection({ scopePath: "tools.web.fetch", toolConfig: fetch, enabled: fetchSurface.enabled, providers: fetchSurface.providers, configuredProvider: fetchSurface.configuredProvider, metadata: fetchMetadata, diagnostics, sourceConfig: params.sourceConfig, resolvedConfig: params.resolvedConfig, context: params.context, defaults, deferKeylessFallback: false, fallbackUsedCode: "WEB_FETCH_PROVIDER_KEY_UNRESOLVED_FALLBACK_USED", noFallbackCode: "WEB_FETCH_PROVIDER_KEY_UNRESOLVED_NO_FALLBACK", autoDetectSelectedCode: "WEB_FETCH_AUTODETECT_SELECTED", readConfiguredCredential: ({ provider, config, toolConfig }) => readConfiguredFetchProviderCredential({ provider, config, fetch: toolConfig }), readConfiguredCredentialFallback: ({ provider, config, toolConfig }) => readConfiguredFetchProviderCredentialFallback({ provider, config, fetch: toolConfig }), resolveSecretInput: ({ value, path, envVars }) => resolveSecretInputWithEnvFallback({ sourceConfig: params.sourceConfig, context: params.context, defaults, value, path, envVars, restrictEnvRefsToEnvVars: true }), setResolvedCredential: ({ resolvedConfig, provider, value }) => setResolvedWebFetchApiKey({ resolvedConfig, provider, value }), inactivePathsForProvider: inactivePathsForFetchProvider, hasConfiguredSecretRef, mergeRuntimeMetadata: async ({ provider, metadata, toolConfig, selectedResolution }) => { if (!provider.resolveRuntimeMetadata) return; Object.assign(metadata, await provider.resolveRuntimeMetadata({ config: params.sourceConfig, fetchConfig: toolConfig, runtimeMetadata: metadata, resolvedCredential: selectedResolution ? { value: selectedResolution.value, source: selectedResolution.source, fallbackEnvVar: selectedResolution.fallbackEnvVar } : void 0 })); } }); } return { search: searchMetadata, fetch: fetchMetadata, diagnostics }; } //#endregion export { resolveRuntimeWebTools as t };