perf(test): trim secrets runtime coverage

This commit is contained in:
Peter Steinberger 2026-04-06 06:44:35 +01:00
parent a1eb677241
commit b432dc5af9
No known key found for this signature in database
6 changed files with 194 additions and 252 deletions

View File

@ -0,0 +1 @@
export { loadPluginManifestRegistry } from "../plugins/manifest-registry.js";

View File

@ -0,0 +1,5 @@
export { resolveSecretRefValues } from "./resolve.js";
export { collectAuthStoreAssignments } from "./runtime-auth-collectors.js";
export { collectConfigAssignments } from "./runtime-config-collectors.js";
export { applyResolvedAssignments, createResolverContext } from "./runtime-shared.js";
export { resolveRuntimeWebTools } from "./runtime-web-tools.js";

View File

@ -0,0 +1,119 @@
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../config/config.js";
import type { PluginWebSearchProviderEntry } from "../plugins/types.js";
const { resolvePluginWebSearchProvidersMock } = vi.hoisted(() => ({
resolvePluginWebSearchProvidersMock: vi.fn<() => PluginWebSearchProviderEntry[]>(() => [
{
pluginId: "google",
id: "gemini",
label: "gemini",
hint: "gemini test provider",
envVars: ["GEMINI_API_KEY"],
placeholder: "gemini-...",
signupUrl: "https://example.com/gemini",
autoDetectOrder: 20,
credentialPath: "plugins.entries.google.config.webSearch.apiKey",
inactiveSecretPaths: ["plugins.entries.google.config.webSearch.apiKey"],
getCredentialValue: (searchConfig) => searchConfig?.apiKey,
setCredentialValue: (searchConfigTarget, value) => {
searchConfigTarget.apiKey = value;
},
getConfiguredCredentialValue: (config) =>
(config?.plugins?.entries?.google?.config as { webSearch?: { apiKey?: unknown } })
?.webSearch?.apiKey,
setConfiguredCredentialValue: (configTarget, value) => {
const plugins = (configTarget.plugins ??= {}) as { entries?: Record<string, unknown> };
const entries = (plugins.entries ??= {});
const entry = (entries.google ??= {}) as { config?: Record<string, unknown> };
const config = (entry.config ??= {});
const webSearch = (config.webSearch ??= {}) as { apiKey?: unknown };
webSearch.apiKey = value;
},
createTool: () => null,
},
]),
}));
vi.mock("../plugins/web-search-providers.runtime.js", () => ({
resolvePluginWebSearchProviders: resolvePluginWebSearchProvidersMock,
}));
function asConfig(value: unknown): OpenClawConfig {
return value as OpenClawConfig;
}
let clearConfigCache: typeof import("../config/config.js").clearConfigCache;
let clearRuntimeConfigSnapshot: typeof import("../config/config.js").clearRuntimeConfigSnapshot;
let activateSecretsRuntimeSnapshot: typeof import("./runtime.js").activateSecretsRuntimeSnapshot;
let clearSecretsRuntimeSnapshot: typeof import("./runtime.js").clearSecretsRuntimeSnapshot;
let getActiveRuntimeWebToolsMetadata: typeof import("./runtime.js").getActiveRuntimeWebToolsMetadata;
let prepareSecretsRuntimeSnapshot: typeof import("./runtime.js").prepareSecretsRuntimeSnapshot;
describe("runtime web tools state", () => {
beforeAll(async () => {
({ clearConfigCache, clearRuntimeConfigSnapshot } = await import("../config/config.js"));
({
activateSecretsRuntimeSnapshot,
clearSecretsRuntimeSnapshot,
getActiveRuntimeWebToolsMetadata,
prepareSecretsRuntimeSnapshot,
} = await import("./runtime.js"));
});
afterEach(() => {
clearSecretsRuntimeSnapshot();
clearRuntimeConfigSnapshot();
clearConfigCache();
});
it("exposes active runtime web tool metadata as a defensive clone", async () => {
const snapshot = await prepareSecretsRuntimeSnapshot({
config: asConfig({
tools: {
web: {
search: {
provider: "gemini",
},
},
},
plugins: {
entries: {
google: {
config: {
webSearch: {
apiKey: {
source: "env",
provider: "default",
id: "WEB_SEARCH_GEMINI_API_KEY",
},
},
},
},
},
},
}),
env: {
WEB_SEARCH_GEMINI_API_KEY: "web-search-gemini-ref",
},
agentDirs: ["/tmp/openclaw-agent-main"],
loadAuthStore: () => ({ version: 1, profiles: {} }),
});
activateSecretsRuntimeSnapshot(snapshot);
const first = getActiveRuntimeWebToolsMetadata();
expect(first?.search.providerConfigured).toBe("gemini");
expect(first?.search.selectedProvider).toBe("gemini");
expect(first?.search.selectedProviderKeySource).toBe("secretRef");
if (!first) {
throw new Error("missing runtime web tools metadata");
}
first.search.providerConfigured = "brave";
first.search.selectedProvider = "brave";
const second = getActiveRuntimeWebToolsMetadata();
expect(second?.search.providerConfigured).toBe("gemini");
expect(second?.search.selectedProvider).toBe("gemini");
});
});

View File

@ -370,6 +370,48 @@ describe("runtime web tools resolution", () => {
},
);
it("resolves selected provider SecretRef even when provider config is disabled", async () => {
const { metadata, resolvedConfig, context } = await runRuntimeWebTools({
config: asConfig({
tools: {
web: {
search: {
enabled: true,
provider: "gemini",
},
},
},
plugins: {
entries: {
google: {
enabled: true,
config: {
webSearch: {
enabled: false,
apiKey: {
source: "env",
provider: "default",
id: "WEB_SEARCH_GEMINI_API_KEY",
},
},
},
},
},
},
}),
env: {
WEB_SEARCH_GEMINI_API_KEY: "web-search-gemini-ref",
},
});
expect(metadata.search.providerConfigured).toBe("gemini");
expect(metadata.search.selectedProvider).toBe("gemini");
expect(readProviderKey(resolvedConfig, "gemini")).toBe("web-search-gemini-ref");
expect(context.warnings.map((warning) => warning.path)).not.toContain(
"plugins.entries.google.config.webSearch.apiKey",
);
});
it("auto-detects provider precedence across all configured providers", async () => {
const { metadata, resolvedConfig, context } = await runRuntimeWebTools({
config: asConfig({

View File

@ -92,7 +92,6 @@ let clearConfigCache: typeof import("../config/config.js").clearConfigCache;
let clearRuntimeConfigSnapshot: typeof import("../config/config.js").clearRuntimeConfigSnapshot;
let activateSecretsRuntimeSnapshot: typeof import("./runtime.js").activateSecretsRuntimeSnapshot;
let clearSecretsRuntimeSnapshot: typeof import("./runtime.js").clearSecretsRuntimeSnapshot;
let getActiveRuntimeWebToolsMetadata: typeof import("./runtime.js").getActiveRuntimeWebToolsMetadata;
let prepareSecretsRuntimeSnapshot: typeof import("./runtime.js").prepareSecretsRuntimeSnapshot;
function createOpenAiFileModelsConfig(): NonNullable<OpenClawConfig["models"]> {
@ -120,7 +119,6 @@ describe("secrets runtime snapshot", () => {
({
activateSecretsRuntimeSnapshot,
clearSecretsRuntimeSnapshot,
getActiveRuntimeWebToolsMetadata,
prepareSecretsRuntimeSnapshot,
} = await import("./runtime.js"));
});
@ -739,239 +737,6 @@ describe("secrets runtime snapshot", () => {
expect(profile.key).toBe("primary-key-value");
});
it("treats non-selected web search provider refs as inactive", async () => {
const snapshot = await prepareSecretsRuntimeSnapshot({
config: asConfig({
tools: {
web: {
search: {
enabled: true,
provider: "brave",
apiKey: { source: "env", provider: "default", id: "WEB_SEARCH_API_KEY" },
},
},
},
plugins: {
entries: {
xai: {
config: {
webSearch: {
apiKey: { source: "env", provider: "default", id: "MISSING_GROK_API_KEY" },
},
},
},
},
},
}),
env: {
WEB_SEARCH_API_KEY: "web-search-ref", // pragma: allowlist secret
},
agentDirs: ["/tmp/openclaw-agent-main"],
loadAuthStore: () => ({ version: 1, profiles: {} }),
});
expect(snapshot.config.tools?.web?.search?.apiKey).toBe("web-search-ref");
const xaiWebSearchConfig = snapshot.config.plugins?.entries?.xai?.config as
| { webSearch?: { apiKey?: unknown } }
| undefined;
expect(xaiWebSearchConfig?.webSearch?.apiKey).toEqual({
source: "env",
provider: "default",
id: "MISSING_GROK_API_KEY",
});
expect(snapshot.warnings).toEqual(
expect.arrayContaining([
expect.objectContaining({
code: "SECRETS_REF_IGNORED_INACTIVE_SURFACE",
path: "plugins.entries.xai.config.webSearch.apiKey",
}),
]),
);
});
it("keeps non-selected provider refs inactive in web search auto mode", async () => {
const snapshot = await prepareSecretsRuntimeSnapshot({
config: asConfig({
tools: {
web: {
search: {
enabled: true,
apiKey: { source: "env", provider: "default", id: "WEB_SEARCH_API_KEY" },
},
},
},
plugins: {
entries: {
google: {
config: {
webSearch: {
apiKey: {
source: "env",
provider: "default",
id: "WEB_SEARCH_GEMINI_API_KEY",
},
},
},
},
},
},
}),
env: {
WEB_SEARCH_API_KEY: "web-search-ref", // pragma: allowlist secret
WEB_SEARCH_GEMINI_API_KEY: "web-search-gemini-ref", // pragma: allowlist secret
},
agentDirs: ["/tmp/openclaw-agent-main"],
loadAuthStore: () => ({ version: 1, profiles: {} }),
});
expect(snapshot.config.tools?.web?.search?.apiKey).toBe("web-search-ref");
const googleWebSearchConfig = snapshot.config.plugins?.entries?.google?.config as
| { webSearch?: { apiKey?: unknown } }
| undefined;
expect(googleWebSearchConfig?.webSearch?.apiKey).toEqual({
source: "env",
provider: "default",
id: "WEB_SEARCH_GEMINI_API_KEY",
});
expect(snapshot.webTools.search.selectedProvider).toBe("brave");
expect(snapshot.warnings).toEqual(
expect.arrayContaining([
expect.objectContaining({
code: "SECRETS_REF_IGNORED_INACTIVE_SURFACE",
path: "plugins.entries.google.config.webSearch.apiKey",
}),
]),
);
});
it("resolves selected web search provider ref even when provider config is disabled", async () => {
const snapshot = await prepareSecretsRuntimeSnapshot({
config: asConfig({
tools: {
web: {
search: {
enabled: true,
provider: "gemini",
},
},
},
plugins: {
entries: {
google: {
config: {
webSearch: {
enabled: false,
apiKey: {
source: "env",
provider: "default",
id: "WEB_SEARCH_GEMINI_API_KEY",
},
},
},
},
},
},
}),
env: {
WEB_SEARCH_GEMINI_API_KEY: "web-search-gemini-ref", // pragma: allowlist secret
},
agentDirs: ["/tmp/openclaw-agent-main"],
loadAuthStore: () => ({ version: 1, profiles: {} }),
});
const resolvedGoogleWebSearchConfig = snapshot.config.plugins?.entries?.google?.config as
| { webSearch?: { apiKey?: unknown } }
| undefined;
expect(resolvedGoogleWebSearchConfig?.webSearch?.apiKey).toBe("web-search-gemini-ref");
expect(snapshot.warnings.map((warning) => warning.path)).not.toContain(
"plugins.entries.google.config.webSearch.apiKey",
);
});
it("fails fast at startup when selected web search provider ref is unresolved", async () => {
await expect(
prepareSecretsRuntimeSnapshot({
config: asConfig({
tools: {
web: {
search: {
enabled: true,
provider: "gemini",
},
},
},
plugins: {
entries: {
google: {
config: {
webSearch: {
apiKey: {
source: "env",
provider: "default",
id: "MISSING_WEB_SEARCH_GEMINI_API_KEY",
},
},
},
},
},
},
}),
env: {},
agentDirs: ["/tmp/openclaw-agent-main"],
loadAuthStore: () => ({ version: 1, profiles: {} }),
}),
).rejects.toThrow("[WEB_SEARCH_KEY_UNRESOLVED_NO_FALLBACK]");
});
it("exposes active runtime web tool metadata as a defensive clone", async () => {
const snapshot = await prepareSecretsRuntimeSnapshot({
config: asConfig({
tools: {
web: {
search: {
provider: "gemini",
},
},
},
plugins: {
entries: {
google: {
config: {
webSearch: {
apiKey: {
source: "env",
provider: "default",
id: "WEB_SEARCH_GEMINI_API_KEY",
},
},
},
},
},
},
}),
env: {
WEB_SEARCH_GEMINI_API_KEY: "web-search-gemini-ref", // pragma: allowlist secret
},
agentDirs: ["/tmp/openclaw-agent-main"],
loadAuthStore: () => ({ version: 1, profiles: {} }),
});
activateSecretsRuntimeSnapshot(snapshot);
const first = getActiveRuntimeWebToolsMetadata();
expect(first?.search.providerConfigured).toBe("gemini");
expect(first?.search.selectedProvider).toBe("gemini");
expect(first?.search.selectedProviderKeySource).toBe("secretRef");
if (!first) {
throw new Error("missing runtime web tools metadata");
}
first.search.providerConfigured = "brave";
first.search.selectedProvider = "brave";
const second = getActiveRuntimeWebToolsMetadata();
expect(second?.search.providerConfigured).toBe("gemini");
expect(second?.search.selectedProvider).toBe("gemini");
});
it("resolves model provider request secret refs for headers, auth, and tls material", async () => {
const config = asConfig({
models: {

View File

@ -17,27 +17,19 @@ import {
setRuntimeConfigSnapshot,
type OpenClawConfig,
} from "../config/config.js";
import { loadPluginManifestRegistry } from "../plugins/manifest-registry.js";
import type { PluginOrigin } from "../plugins/types.js";
import { resolveUserPath } from "../utils.js";
import {
collectCommandSecretAssignmentsFromSnapshot,
type CommandSecretAssignment,
} from "./command-config.js";
import { resolveSecretRefValues } from "./resolve.js";
import { collectAuthStoreAssignments } from "./runtime-auth-collectors.js";
import { collectConfigAssignments } from "./runtime-config-collectors.js";
import {
applyResolvedAssignments,
createResolverContext,
type SecretResolverWarning,
} from "./runtime-shared.js";
import { type SecretResolverWarning } from "./runtime-shared.js";
import {
clearActiveRuntimeWebToolsMetadata,
getActiveRuntimeWebToolsMetadata as getActiveRuntimeWebToolsMetadataFromState,
setActiveRuntimeWebToolsMetadata,
} from "./runtime-web-tools-state.js";
import { resolveRuntimeWebTools, type RuntimeWebToolsMetadata } from "./runtime-web-tools.js";
import type { RuntimeWebToolsMetadata } from "./runtime-web-tools.js";
export type { SecretResolverWarning } from "./runtime-shared.js";
@ -75,6 +67,18 @@ const preparedSnapshotRefreshContext = new WeakMap<
PreparedSecretsRuntimeSnapshot,
SecretsRuntimeRefreshContext
>();
let runtimeManifestPromise: Promise<typeof import("./runtime-manifest.runtime.js")> | null = null;
let runtimePreparePromise: Promise<typeof import("./runtime-prepare.runtime.js")> | null = null;
function loadRuntimeManifestHelpers() {
runtimeManifestPromise ??= import("./runtime-manifest.runtime.js");
return runtimeManifestPromise;
}
function loadRuntimePrepareHelpers() {
runtimePreparePromise ??= import("./runtime-prepare.runtime.js");
return runtimePreparePromise;
}
function cloneSnapshot(snapshot: PreparedSecretsRuntimeSnapshot): PreparedSecretsRuntimeSnapshot {
return {
@ -130,14 +134,15 @@ function resolveRefreshAgentDirs(
return [...new Set([...context.explicitAgentDirs, ...configDerived])];
}
function resolveLoadablePluginOrigins(params: {
async function resolveLoadablePluginOrigins(params: {
config: OpenClawConfig;
env: NodeJS.ProcessEnv;
}): ReadonlyMap<string, PluginOrigin> {
}): Promise<ReadonlyMap<string, PluginOrigin>> {
const workspaceDir = resolveAgentWorkspaceDir(
params.config,
resolveDefaultAgentId(params.config),
);
const { loadPluginManifestRegistry } = await loadRuntimeManifestHelpers();
const manifestRegistry = loadPluginManifestRegistry({
config: params.config,
workspaceDir,
@ -172,12 +177,20 @@ export async function prepareSecretsRuntimeSnapshot(params: {
/** Test override for discovered loadable plugins and their origins. */
loadablePluginOrigins?: ReadonlyMap<string, PluginOrigin>;
}): Promise<PreparedSecretsRuntimeSnapshot> {
const {
applyResolvedAssignments,
collectAuthStoreAssignments,
collectConfigAssignments,
createResolverContext,
resolveRuntimeWebTools,
resolveSecretRefValues,
} = await loadRuntimePrepareHelpers();
const runtimeEnv = mergeSecretsRuntimeEnv(params.env);
const sourceConfig = structuredClone(params.config);
const resolvedConfig = structuredClone(params.config);
const loadablePluginOrigins =
params.loadablePluginOrigins ??
resolveLoadablePluginOrigins({ config: sourceConfig, env: runtimeEnv });
(await resolveLoadablePluginOrigins({ config: sourceConfig, env: runtimeEnv }));
const context = createResolverContext({
sourceConfig,
env: runtimeEnv,
@ -249,10 +262,7 @@ export function activateSecretsRuntimeSnapshot(snapshot: PreparedSecretsRuntimeS
env: { ...process.env } as Record<string, string | undefined>,
explicitAgentDirs: null,
loadAuthStore: loadAuthProfileStoreForSecretsRuntime,
loadablePluginOrigins: resolveLoadablePluginOrigins({
config: next.sourceConfig,
env: process.env,
}),
loadablePluginOrigins: new Map<string, PluginOrigin>(),
} satisfies SecretsRuntimeRefreshContext);
setRuntimeConfigSnapshot(next.config, next.sourceConfig);
replaceRuntimeAuthProfileStoreSnapshots(next.authStores);