From ce8b0da9a2cc7075b1d143813a128e20ea675a43 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 6 May 2026 09:33:20 +0100 Subject: [PATCH] test: slim secret runtime coverage --- src/secrets/runtime.coverage.test.ts | 190 ++++++++++++++++++++++++++- 1 file changed, 188 insertions(+), 2 deletions(-) diff --git a/src/secrets/runtime.coverage.test.ts b/src/secrets/runtime.coverage.test.ts index 45b275be97e..a2a89b8473a 100644 --- a/src/secrets/runtime.coverage.test.ts +++ b/src/secrets/runtime.coverage.test.ts @@ -3,7 +3,11 @@ import path from "node:path"; import { afterAll, beforeAll, describe, expect, it, vi } from "vitest"; import type { AuthProfileStore } from "../agents/auth-profiles.js"; import type { OpenClawConfig } from "../config/config.js"; -import type { PluginOrigin } from "../plugins/types.js"; +import type { + PluginOrigin, + PluginWebFetchProviderEntry, + PluginWebSearchProviderEntry, +} from "../plugins/types.js"; import { getPath, setPathCreateStrict } from "./path-utils.js"; import { canonicalizeSecretTargetCoverageId } from "./target-registry-test-helpers.js"; @@ -11,6 +15,171 @@ vi.mock("../plugins/installed-plugin-index-records.js", () => ({ loadInstalledPluginIndexInstallRecordsSync: () => ({}), })); +function createCoverageWebSearchProvider(params: { + pluginId: string; + id: string; + envVar: string; + order: number; +}): PluginWebSearchProviderEntry { + const credentialPath = `plugins.entries.${params.pluginId}.config.webSearch.apiKey`; + const readConfiguredCredential = (config?: OpenClawConfig): unknown => + (config?.plugins?.entries?.[params.pluginId]?.config as { webSearch?: { apiKey?: unknown } }) + ?.webSearch?.apiKey; + return { + pluginId: params.pluginId, + id: params.id, + label: params.id, + hint: `${params.id} coverage provider`, + envVars: [params.envVar], + placeholder: `${params.id}-key`, + signupUrl: `https://example.com/${params.id}`, + autoDetectOrder: params.order, + credentialPath, + inactiveSecretPaths: [credentialPath], + getCredentialValue: () => undefined, + setCredentialValue: () => {}, + getConfiguredCredentialValue: readConfiguredCredential, + setConfiguredCredentialValue: (configTarget, value) => { + setPathCreateStrict( + configTarget, + ["plugins", "entries", params.pluginId, "config", "webSearch", "apiKey"], + value, + ); + }, + createTool: () => null, + }; +} + +function createCoverageWebFetchProvider(params: { + pluginId: string; + id: string; + envVar: string; +}): PluginWebFetchProviderEntry { + const credentialPath = `plugins.entries.${params.pluginId}.config.webFetch.apiKey`; + const readConfiguredCredential = (config?: OpenClawConfig): unknown => + (config?.plugins?.entries?.[params.pluginId]?.config as { webFetch?: { apiKey?: unknown } }) + ?.webFetch?.apiKey; + return { + pluginId: params.pluginId, + id: params.id, + label: params.id, + hint: `${params.id} coverage fetch provider`, + envVars: [params.envVar], + placeholder: `${params.id}-key`, + signupUrl: `https://example.com/${params.id}`, + autoDetectOrder: 10, + credentialPath, + inactiveSecretPaths: [credentialPath], + getCredentialValue: () => undefined, + setCredentialValue: () => {}, + getConfiguredCredentialValue: readConfiguredCredential, + setConfiguredCredentialValue: (configTarget, value) => { + setPathCreateStrict( + configTarget, + ["plugins", "entries", params.pluginId, "config", "webFetch", "apiKey"], + value, + ); + }, + createTool: () => null, + }; +} + +const COVERAGE_WEB_SEARCH_PROVIDERS = new Map( + [ + createCoverageWebSearchProvider({ + pluginId: "brave", + id: "brave", + envVar: "BRAVE_API_KEY", + order: 10, + }), + createCoverageWebSearchProvider({ + pluginId: "google", + id: "gemini", + envVar: "GEMINI_API_KEY", + order: 20, + }), + createCoverageWebSearchProvider({ + pluginId: "xai", + id: "grok", + envVar: "XAI_API_KEY", + order: 30, + }), + createCoverageWebSearchProvider({ + pluginId: "moonshot", + id: "kimi", + envVar: "MOONSHOT_API_KEY", + order: 40, + }), + createCoverageWebSearchProvider({ + pluginId: "perplexity", + id: "perplexity", + envVar: "PERPLEXITY_API_KEY", + order: 50, + }), + createCoverageWebSearchProvider({ + pluginId: "firecrawl", + id: "firecrawl", + envVar: "FIRECRAWL_API_KEY", + order: 60, + }), + createCoverageWebSearchProvider({ + pluginId: "exa", + id: "exa", + envVar: "EXA_API_KEY", + order: 65, + }), + createCoverageWebSearchProvider({ + pluginId: "minimax", + id: "minimax", + envVar: "MINIMAX_API_KEY", + order: 70, + }), + createCoverageWebSearchProvider({ + pluginId: "tavily", + id: "tavily", + envVar: "TAVILY_API_KEY", + order: 80, + }), + ].map((provider) => [provider.pluginId, provider]), +); + +const COVERAGE_WEB_FETCH_PROVIDERS = new Map( + [ + createCoverageWebFetchProvider({ + pluginId: "firecrawl", + id: "firecrawl", + envVar: "FIRECRAWL_API_KEY", + }), + ].map((provider) => [provider.pluginId, provider]), +); + +vi.mock("../plugins/web-provider-public-artifacts.explicit.js", () => ({ + resolveBundledExplicitWebFetchProvidersFromPublicArtifacts: (params: { + onlyPluginIds: readonly string[]; + }) => { + const providers = params.onlyPluginIds.map((pluginId) => + COVERAGE_WEB_FETCH_PROVIDERS.get(pluginId), + ); + return providers.every( + (provider): provider is PluginWebFetchProviderEntry => provider !== undefined, + ) + ? providers + : null; + }, + resolveBundledExplicitWebSearchProvidersFromPublicArtifacts: (params: { + onlyPluginIds: readonly string[]; + }) => { + const providers = params.onlyPluginIds.map((pluginId) => + COVERAGE_WEB_SEARCH_PROVIDERS.get(pluginId), + ); + return providers.every( + (provider): provider is PluginWebSearchProviderEntry => provider !== undefined, + ) + ? providers + : null; + }, +})); + type SecretRegistryEntry = { id: string; configFile: "openclaw.json" | "auth-profiles.json"; @@ -159,6 +328,23 @@ function buildCoverageLoadablePluginOrigins( return origins; } +function resolveCoverageLoadablePluginOrigins( + entries: readonly SecretRegistryEntry[], +): ReadonlyMap | undefined { + const origins = new Map(); + for (const entry of entries) { + if (!entry.id.startsWith("plugins.entries.")) { + continue; + } + const pluginId = entry.id.split(".")[2]; + const origin = pluginId ? COVERAGE_LOADABLE_PLUGIN_ORIGINS.get(pluginId) : undefined; + if (pluginId && origin) { + origins.set(pluginId, origin); + } + } + return origins.size > 0 ? origins : undefined; +} + function resolveCoverageBatchKey(entry: SecretRegistryEntry): string { if (entry.id.startsWith("agents.defaults.")) { return entry.id; @@ -569,7 +755,7 @@ async function expectOpenClawCoverageEntriesResolved( const snapshot = await prepareConfigCoverageSnapshot({ config, env, - loadablePluginOrigins: COVERAGE_LOADABLE_PLUGIN_ORIGINS, + loadablePluginOrigins: resolveCoverageLoadablePluginOrigins(batch), includeRuntimeWebTools: batchNeedsRuntimeWebTools(batch), skipConfigCollectors: batchUsesRuntimeWebToolsOnly(batch), });