diff --git a/src/secrets/runtime-matrix-shadowing.test.ts b/src/secrets/runtime-matrix-shadowing.test.ts index e830b63e1a7..b1944a69649 100644 --- a/src/secrets/runtime-matrix-shadowing.test.ts +++ b/src/secrets/runtime-matrix-shadowing.test.ts @@ -1,143 +1,14 @@ -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import type { AuthProfileStore } from "../agents/auth-profiles.js"; -import type { OpenClawConfig } from "../config/config.js"; -import { createEmptyPluginRegistry } from "../plugins/registry.js"; -import { setActivePluginRegistry } from "../plugins/runtime.js"; -import type { PluginWebSearchProviderEntry } from "../plugins/types.js"; -import { loadBundledChannelSecretContractApi } from "./channel-contract-api.js"; +import { describe, expect, it } from "vitest"; +import "./runtime-matrix.test-support.ts"; +import { + asConfig, + loadAuthStoreWithProfiles, + setupSecretsRuntimeSnapshotTestHooks, +} from "./runtime.test-support.ts"; -const matrixSecrets = loadBundledChannelSecretContractApi("matrix"); -if (!matrixSecrets?.collectRuntimeConfigAssignments) { - throw new Error("Missing Matrix secret contract api"); -} - -type WebProviderUnderTest = "brave" | "gemini" | "grok" | "kimi" | "perplexity" | "firecrawl"; - -const { resolvePluginWebSearchProvidersMock } = vi.hoisted(() => ({ - resolvePluginWebSearchProvidersMock: vi.fn(() => buildTestWebSearchProviders()), -})); - -vi.mock("../plugins/web-search-providers.runtime.js", () => ({ - resolvePluginWebSearchProviders: resolvePluginWebSearchProvidersMock, -})); - -vi.mock("../channels/plugins/bootstrap-registry.js", () => { - return { - getBootstrapChannelPlugin: (id: string) => - id === "matrix" - ? { - secrets: { - collectRuntimeConfigAssignments: matrixSecrets.collectRuntimeConfigAssignments, - }, - } - : undefined, - getBootstrapChannelSecrets: (id: string) => - id === "matrix" - ? { - collectRuntimeConfigAssignments: matrixSecrets.collectRuntimeConfigAssignments, - } - : undefined, - }; -}); - -function asConfig(value: unknown): OpenClawConfig { - return value as OpenClawConfig; -} - -function createTestProvider(params: { - id: WebProviderUnderTest; - pluginId: string; - order: number; -}): PluginWebSearchProviderEntry { - const credentialPath = `plugins.entries.${params.pluginId}.config.webSearch.apiKey`; - const readSearchConfigKey = (searchConfig?: Record): unknown => { - const providerConfig = - searchConfig?.[params.id] && typeof searchConfig[params.id] === "object" - ? (searchConfig[params.id] as { apiKey?: unknown }) - : undefined; - return providerConfig?.apiKey ?? searchConfig?.apiKey; - }; - return { - pluginId: params.pluginId, - id: params.id, - label: params.id, - hint: `${params.id} test provider`, - envVars: [`${params.id.toUpperCase()}_API_KEY`], - placeholder: `${params.id}-...`, - signupUrl: `https://example.com/${params.id}`, - autoDetectOrder: params.order, - credentialPath, - inactiveSecretPaths: [credentialPath], - getCredentialValue: readSearchConfigKey, - setCredentialValue: (searchConfigTarget, value) => { - const providerConfig = - params.id === "brave" || params.id === "firecrawl" - ? searchConfigTarget - : ((searchConfigTarget[params.id] ??= {}) as { apiKey?: unknown }); - providerConfig.apiKey = value; - }, - getConfiguredCredentialValue: (config) => - (config?.plugins?.entries?.[params.pluginId]?.config as { webSearch?: { apiKey?: unknown } }) - ?.webSearch?.apiKey, - setConfiguredCredentialValue: (configTarget, value) => { - const plugins = (configTarget.plugins ??= {}) as { entries?: Record }; - const entries = (plugins.entries ??= {}); - const entry = (entries[params.pluginId] ??= {}) as { config?: Record }; - const config = (entry.config ??= {}); - const webSearch = (config.webSearch ??= {}) as { apiKey?: unknown }; - webSearch.apiKey = value; - }, - resolveRuntimeMetadata: - params.id === "perplexity" - ? () => ({ - perplexityTransport: "search_api" as const, - }) - : undefined, - createTool: () => null, - }; -} - -function buildTestWebSearchProviders(): PluginWebSearchProviderEntry[] { - return [ - createTestProvider({ id: "brave", pluginId: "brave", order: 10 }), - createTestProvider({ id: "gemini", pluginId: "google", order: 20 }), - createTestProvider({ id: "grok", pluginId: "xai", order: 30 }), - createTestProvider({ id: "kimi", pluginId: "moonshot", order: 40 }), - createTestProvider({ id: "perplexity", pluginId: "perplexity", order: 50 }), - createTestProvider({ id: "firecrawl", pluginId: "firecrawl", order: 60 }), - ]; -} - -let clearConfigCache: typeof import("../config/config.js").clearConfigCache; -let clearRuntimeConfigSnapshot: typeof import("../config/config.js").clearRuntimeConfigSnapshot; -let clearSecretsRuntimeSnapshot: typeof import("./runtime.js").clearSecretsRuntimeSnapshot; -let prepareSecretsRuntimeSnapshot: typeof import("./runtime.js").prepareSecretsRuntimeSnapshot; - -function loadAuthStoreWithProfiles(profiles: AuthProfileStore["profiles"]): AuthProfileStore { - return { - version: 1, - profiles, - }; -} +const { prepareSecretsRuntimeSnapshot } = setupSecretsRuntimeSnapshotTestHooks(); describe("secrets runtime snapshot matrix shadowing", () => { - beforeAll(async () => { - ({ clearConfigCache, clearRuntimeConfigSnapshot } = await import("../config/config.js")); - ({ clearSecretsRuntimeSnapshot, prepareSecretsRuntimeSnapshot } = await import("./runtime.js")); - }); - - beforeEach(() => { - resolvePluginWebSearchProvidersMock.mockReset(); - resolvePluginWebSearchProvidersMock.mockReturnValue(buildTestWebSearchProviders()); - }); - - afterEach(() => { - setActivePluginRegistry(createEmptyPluginRegistry()); - clearSecretsRuntimeSnapshot(); - clearRuntimeConfigSnapshot(); - clearConfigCache(); - }); - it("ignores Matrix password refs that are shadowed by scoped env access tokens", async () => { const snapshot = await prepareSecretsRuntimeSnapshot({ config: asConfig({ diff --git a/src/secrets/runtime-matrix-top-level.test.ts b/src/secrets/runtime-matrix-top-level.test.ts index 32301adc94b..a76be13513e 100644 --- a/src/secrets/runtime-matrix-top-level.test.ts +++ b/src/secrets/runtime-matrix-top-level.test.ts @@ -1,135 +1,10 @@ -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import type { OpenClawConfig } from "../config/config.js"; -import { createEmptyPluginRegistry } from "../plugins/registry.js"; -import { setActivePluginRegistry } from "../plugins/runtime.js"; -import type { PluginWebSearchProviderEntry } from "../plugins/types.js"; -import { loadBundledChannelSecretContractApi } from "./channel-contract-api.js"; +import { describe, expect, it } from "vitest"; +import "./runtime-matrix.test-support.ts"; +import { asConfig, setupSecretsRuntimeSnapshotTestHooks } from "./runtime.test-support.ts"; -const matrixSecrets = loadBundledChannelSecretContractApi("matrix"); -if (!matrixSecrets?.collectRuntimeConfigAssignments) { - throw new Error("Missing Matrix secret contract api"); -} - -type WebProviderUnderTest = "brave" | "gemini" | "grok" | "kimi" | "perplexity" | "firecrawl"; - -const { resolvePluginWebSearchProvidersMock } = vi.hoisted(() => ({ - resolvePluginWebSearchProvidersMock: vi.fn(() => buildTestWebSearchProviders()), -})); - -vi.mock("../plugins/web-search-providers.runtime.js", () => ({ - resolvePluginWebSearchProviders: resolvePluginWebSearchProvidersMock, -})); - -vi.mock("../channels/plugins/bootstrap-registry.js", () => { - return { - getBootstrapChannelPlugin: (id: string) => - id === "matrix" - ? { - secrets: { - collectRuntimeConfigAssignments: matrixSecrets.collectRuntimeConfigAssignments, - }, - } - : undefined, - getBootstrapChannelSecrets: (id: string) => - id === "matrix" - ? { - collectRuntimeConfigAssignments: matrixSecrets.collectRuntimeConfigAssignments, - } - : undefined, - }; -}); - -function asConfig(value: unknown): OpenClawConfig { - return value as OpenClawConfig; -} - -function createTestProvider(params: { - id: WebProviderUnderTest; - pluginId: string; - order: number; -}): PluginWebSearchProviderEntry { - const credentialPath = `plugins.entries.${params.pluginId}.config.webSearch.apiKey`; - const readSearchConfigKey = (searchConfig?: Record): unknown => { - const providerConfig = - searchConfig?.[params.id] && typeof searchConfig[params.id] === "object" - ? (searchConfig[params.id] as { apiKey?: unknown }) - : undefined; - return providerConfig?.apiKey ?? searchConfig?.apiKey; - }; - return { - pluginId: params.pluginId, - id: params.id, - label: params.id, - hint: `${params.id} test provider`, - envVars: [`${params.id.toUpperCase()}_API_KEY`], - placeholder: `${params.id}-...`, - signupUrl: `https://example.com/${params.id}`, - autoDetectOrder: params.order, - credentialPath, - inactiveSecretPaths: [credentialPath], - getCredentialValue: readSearchConfigKey, - setCredentialValue: (searchConfigTarget, value) => { - const providerConfig = - params.id === "brave" || params.id === "firecrawl" - ? searchConfigTarget - : ((searchConfigTarget[params.id] ??= {}) as { apiKey?: unknown }); - providerConfig.apiKey = value; - }, - getConfiguredCredentialValue: (config) => - (config?.plugins?.entries?.[params.pluginId]?.config as { webSearch?: { apiKey?: unknown } }) - ?.webSearch?.apiKey, - setConfiguredCredentialValue: (configTarget, value) => { - const plugins = (configTarget.plugins ??= {}) as { entries?: Record }; - const entries = (plugins.entries ??= {}); - const entry = (entries[params.pluginId] ??= {}) as { config?: Record }; - const config = (entry.config ??= {}); - const webSearch = (config.webSearch ??= {}) as { apiKey?: unknown }; - webSearch.apiKey = value; - }, - resolveRuntimeMetadata: - params.id === "perplexity" - ? () => ({ - perplexityTransport: "search_api" as const, - }) - : undefined, - createTool: () => null, - }; -} - -function buildTestWebSearchProviders(): PluginWebSearchProviderEntry[] { - return [ - createTestProvider({ id: "brave", pluginId: "brave", order: 10 }), - createTestProvider({ id: "gemini", pluginId: "google", order: 20 }), - createTestProvider({ id: "grok", pluginId: "xai", order: 30 }), - createTestProvider({ id: "kimi", pluginId: "moonshot", order: 40 }), - createTestProvider({ id: "perplexity", pluginId: "perplexity", order: 50 }), - createTestProvider({ id: "firecrawl", pluginId: "firecrawl", order: 60 }), - ]; -} - -let clearConfigCache: typeof import("../config/config.js").clearConfigCache; -let clearRuntimeConfigSnapshot: typeof import("../config/config.js").clearRuntimeConfigSnapshot; -let clearSecretsRuntimeSnapshot: typeof import("./runtime.js").clearSecretsRuntimeSnapshot; -let prepareSecretsRuntimeSnapshot: typeof import("./runtime.js").prepareSecretsRuntimeSnapshot; +const { prepareSecretsRuntimeSnapshot } = setupSecretsRuntimeSnapshotTestHooks(); describe("secrets runtime snapshot matrix access token", () => { - beforeAll(async () => { - ({ clearConfigCache, clearRuntimeConfigSnapshot } = await import("../config/config.js")); - ({ clearSecretsRuntimeSnapshot, prepareSecretsRuntimeSnapshot } = await import("./runtime.js")); - }); - - beforeEach(() => { - resolvePluginWebSearchProvidersMock.mockReset(); - resolvePluginWebSearchProvidersMock.mockReturnValue(buildTestWebSearchProviders()); - }); - - afterEach(() => { - setActivePluginRegistry(createEmptyPluginRegistry()); - clearSecretsRuntimeSnapshot(); - clearRuntimeConfigSnapshot(); - clearConfigCache(); - }); - it("resolves top-level Matrix accessToken refs even when named accounts exist", async () => { const snapshot = await prepareSecretsRuntimeSnapshot({ config: asConfig({ diff --git a/src/secrets/runtime-matrix.test-support.ts b/src/secrets/runtime-matrix.test-support.ts new file mode 100644 index 00000000000..280f8b28344 --- /dev/null +++ b/src/secrets/runtime-matrix.test-support.ts @@ -0,0 +1,24 @@ +import { vi } from "vitest"; +import { loadBundledChannelSecretContractApi } from "./channel-contract-api.js"; + +const matrixSecrets = loadBundledChannelSecretContractApi("matrix"); +if (!matrixSecrets?.collectRuntimeConfigAssignments) { + throw new Error("Missing Matrix secret contract api"); +} + +vi.mock("../channels/plugins/bootstrap-registry.js", () => ({ + getBootstrapChannelPlugin: (id: string) => + id === "matrix" + ? { + secrets: { + collectRuntimeConfigAssignments: matrixSecrets.collectRuntimeConfigAssignments, + }, + } + : undefined, + getBootstrapChannelSecrets: (id: string) => + id === "matrix" + ? { + collectRuntimeConfigAssignments: matrixSecrets.collectRuntimeConfigAssignments, + } + : undefined, +})); diff --git a/src/secrets/runtime-request-secret-refs.test.ts b/src/secrets/runtime-request-secret-refs.test.ts index a64d81e4841..0bd95eba901 100644 --- a/src/secrets/runtime-request-secret-refs.test.ts +++ b/src/secrets/runtime-request-secret-refs.test.ts @@ -1,118 +1,13 @@ -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import type { AuthProfileStore } from "../agents/auth-profiles.js"; -import type { OpenClawConfig } from "../config/config.js"; -import { createEmptyPluginRegistry } from "../plugins/registry.js"; -import { setActivePluginRegistry } from "../plugins/runtime.js"; -import type { PluginWebSearchProviderEntry } from "../plugins/types.js"; +import { describe, expect, it } from "vitest"; +import { + asConfig, + loadAuthStoreWithProfiles, + setupSecretsRuntimeSnapshotTestHooks, +} from "./runtime.test-support.ts"; -type WebProviderUnderTest = "brave" | "gemini" | "grok" | "kimi" | "perplexity" | "firecrawl"; - -const { resolvePluginWebSearchProvidersMock } = vi.hoisted(() => ({ - resolvePluginWebSearchProvidersMock: vi.fn(() => buildTestWebSearchProviders()), -})); - -vi.mock("../plugins/web-search-providers.runtime.js", () => ({ - resolvePluginWebSearchProviders: resolvePluginWebSearchProvidersMock, -})); - -function asConfig(value: unknown): OpenClawConfig { - return value as OpenClawConfig; -} - -function createTestProvider(params: { - id: WebProviderUnderTest; - pluginId: string; - order: number; -}): PluginWebSearchProviderEntry { - const credentialPath = `plugins.entries.${params.pluginId}.config.webSearch.apiKey`; - const readSearchConfigKey = (searchConfig?: Record): unknown => { - const providerConfig = - searchConfig?.[params.id] && typeof searchConfig[params.id] === "object" - ? (searchConfig[params.id] as { apiKey?: unknown }) - : undefined; - return providerConfig?.apiKey ?? searchConfig?.apiKey; - }; - return { - pluginId: params.pluginId, - id: params.id, - label: params.id, - hint: `${params.id} test provider`, - envVars: [`${params.id.toUpperCase()}_API_KEY`], - placeholder: `${params.id}-...`, - signupUrl: `https://example.com/${params.id}`, - autoDetectOrder: params.order, - credentialPath, - inactiveSecretPaths: [credentialPath], - getCredentialValue: readSearchConfigKey, - setCredentialValue: (searchConfigTarget, value) => { - const providerConfig = - params.id === "brave" || params.id === "firecrawl" - ? searchConfigTarget - : ((searchConfigTarget[params.id] ??= {}) as { apiKey?: unknown }); - providerConfig.apiKey = value; - }, - getConfiguredCredentialValue: (config) => - (config?.plugins?.entries?.[params.pluginId]?.config as { webSearch?: { apiKey?: unknown } }) - ?.webSearch?.apiKey, - setConfiguredCredentialValue: (configTarget, value) => { - const plugins = (configTarget.plugins ??= {}) as { entries?: Record }; - const entries = (plugins.entries ??= {}); - const entry = (entries[params.pluginId] ??= {}) as { config?: Record }; - const config = (entry.config ??= {}); - const webSearch = (config.webSearch ??= {}) as { apiKey?: unknown }; - webSearch.apiKey = value; - }, - resolveRuntimeMetadata: - params.id === "perplexity" - ? () => ({ - perplexityTransport: "search_api" as const, - }) - : undefined, - createTool: () => null, - }; -} - -function buildTestWebSearchProviders(): PluginWebSearchProviderEntry[] { - return [ - createTestProvider({ id: "brave", pluginId: "brave", order: 10 }), - createTestProvider({ id: "gemini", pluginId: "google", order: 20 }), - createTestProvider({ id: "grok", pluginId: "xai", order: 30 }), - createTestProvider({ id: "kimi", pluginId: "moonshot", order: 40 }), - createTestProvider({ id: "perplexity", pluginId: "perplexity", order: 50 }), - createTestProvider({ id: "firecrawl", pluginId: "firecrawl", order: 60 }), - ]; -} - -function loadAuthStoreWithProfiles(profiles: AuthProfileStore["profiles"]): AuthProfileStore { - return { - version: 1, - profiles, - }; -} - -let clearConfigCache: typeof import("../config/config.js").clearConfigCache; -let clearRuntimeConfigSnapshot: typeof import("../config/config.js").clearRuntimeConfigSnapshot; -let clearSecretsRuntimeSnapshot: typeof import("./runtime.js").clearSecretsRuntimeSnapshot; -let prepareSecretsRuntimeSnapshot: typeof import("./runtime.js").prepareSecretsRuntimeSnapshot; +const { prepareSecretsRuntimeSnapshot } = setupSecretsRuntimeSnapshotTestHooks(); describe("secrets runtime snapshot request secret refs", () => { - beforeAll(async () => { - ({ clearConfigCache, clearRuntimeConfigSnapshot } = await import("../config/config.js")); - ({ clearSecretsRuntimeSnapshot, prepareSecretsRuntimeSnapshot } = await import("./runtime.js")); - }); - - beforeEach(() => { - resolvePluginWebSearchProvidersMock.mockReset(); - resolvePluginWebSearchProvidersMock.mockReturnValue(buildTestWebSearchProviders()); - }); - - afterEach(() => { - setActivePluginRegistry(createEmptyPluginRegistry()); - clearSecretsRuntimeSnapshot(); - clearRuntimeConfigSnapshot(); - clearConfigCache(); - }); - it("can skip auth-profile SecretRef resolution when includeAuthStoreRefs is false", async () => { const missingEnvVar = `OPENCLAW_MISSING_AUTH_PROFILE_SECRET_${Date.now()}`; delete process.env[missingEnvVar]; diff --git a/src/secrets/runtime.test-support.ts b/src/secrets/runtime.test-support.ts new file mode 100644 index 00000000000..4ac3395a72b --- /dev/null +++ b/src/secrets/runtime.test-support.ts @@ -0,0 +1,132 @@ +import { afterEach, beforeAll, beforeEach, vi } from "vitest"; +import type { AuthProfileStore } from "../agents/auth-profiles.js"; +import type { OpenClawConfig } from "../config/config.js"; +import { createEmptyPluginRegistry } from "../plugins/registry.js"; +import { setActivePluginRegistry } from "../plugins/runtime.js"; +import type { PluginWebSearchProviderEntry } from "../plugins/types.js"; + +type PrepareSecretsRuntimeSnapshot = typeof import("./runtime.js").prepareSecretsRuntimeSnapshot; +type WebProviderUnderTest = "brave" | "gemini" | "grok" | "kimi" | "perplexity" | "firecrawl"; + +const { resolvePluginWebSearchProvidersMock } = vi.hoisted(() => ({ + resolvePluginWebSearchProvidersMock: vi.fn(() => buildTestWebSearchProviders()), +})); + +vi.mock("../plugins/web-search-providers.runtime.js", () => ({ + resolvePluginWebSearchProviders: resolvePluginWebSearchProvidersMock, +})); + +export function asConfig(value: unknown): OpenClawConfig { + return value as OpenClawConfig; +} + +export function loadAuthStoreWithProfiles( + profiles: AuthProfileStore["profiles"], +): AuthProfileStore { + return { + version: 1, + profiles, + }; +} + +function createTestProvider(params: { + id: WebProviderUnderTest; + pluginId: string; + order: number; +}): PluginWebSearchProviderEntry { + const credentialPath = `plugins.entries.${params.pluginId}.config.webSearch.apiKey`; + const readSearchConfigKey = (searchConfig?: Record): unknown => { + const providerConfig = + searchConfig?.[params.id] && typeof searchConfig[params.id] === "object" + ? (searchConfig[params.id] as { apiKey?: unknown }) + : undefined; + return providerConfig?.apiKey ?? searchConfig?.apiKey; + }; + return { + pluginId: params.pluginId, + id: params.id, + label: params.id, + hint: `${params.id} test provider`, + envVars: [`${params.id.toUpperCase()}_API_KEY`], + placeholder: `${params.id}-...`, + signupUrl: `https://example.com/${params.id}`, + autoDetectOrder: params.order, + credentialPath, + inactiveSecretPaths: [credentialPath], + getCredentialValue: readSearchConfigKey, + setCredentialValue: (searchConfigTarget, value) => { + const providerConfig = + params.id === "brave" || params.id === "firecrawl" + ? searchConfigTarget + : ((searchConfigTarget[params.id] ??= {}) as { apiKey?: unknown }); + providerConfig.apiKey = value; + }, + getConfiguredCredentialValue: (config) => + (config?.plugins?.entries?.[params.pluginId]?.config as { webSearch?: { apiKey?: unknown } }) + ?.webSearch?.apiKey, + setConfiguredCredentialValue: (configTarget, value) => { + const plugins = (configTarget.plugins ??= {}) as { entries?: Record }; + const entries = (plugins.entries ??= {}); + const entry = (entries[params.pluginId] ??= {}) as { config?: Record }; + const config = (entry.config ??= {}); + const webSearch = (config.webSearch ??= {}) as { apiKey?: unknown }; + webSearch.apiKey = value; + }, + resolveRuntimeMetadata: + params.id === "perplexity" + ? () => ({ + perplexityTransport: "search_api" as const, + }) + : undefined, + createTool: () => null, + }; +} + +export function buildTestWebSearchProviders(): PluginWebSearchProviderEntry[] { + return [ + createTestProvider({ id: "brave", pluginId: "brave", order: 10 }), + createTestProvider({ id: "gemini", pluginId: "google", order: 20 }), + createTestProvider({ id: "grok", pluginId: "xai", order: 30 }), + createTestProvider({ id: "kimi", pluginId: "moonshot", order: 40 }), + createTestProvider({ id: "perplexity", pluginId: "perplexity", order: 50 }), + createTestProvider({ id: "firecrawl", pluginId: "firecrawl", order: 60 }), + ]; +} + +export function resetPluginWebSearchProvidersMock() { + resolvePluginWebSearchProvidersMock.mockReset(); + resolvePluginWebSearchProvidersMock.mockReturnValue(buildTestWebSearchProviders()); +} + +export function setupSecretsRuntimeSnapshotTestHooks(): { + prepareSecretsRuntimeSnapshot: PrepareSecretsRuntimeSnapshot; +} { + let clearConfigCache: typeof import("../config/config.js").clearConfigCache; + let clearRuntimeConfigSnapshot: typeof import("../config/config.js").clearRuntimeConfigSnapshot; + let clearSecretsRuntimeSnapshot: typeof import("./runtime.js").clearSecretsRuntimeSnapshot; + let prepareSecretsRuntimeSnapshotImpl: PrepareSecretsRuntimeSnapshot; + + beforeAll(async () => { + ({ clearConfigCache, clearRuntimeConfigSnapshot } = await import("../config/config.js")); + ({ + clearSecretsRuntimeSnapshot, + prepareSecretsRuntimeSnapshot: prepareSecretsRuntimeSnapshotImpl, + } = await import("./runtime.js")); + }); + + beforeEach(() => { + resetPluginWebSearchProvidersMock(); + }); + + afterEach(() => { + setActivePluginRegistry(createEmptyPluginRegistry()); + clearSecretsRuntimeSnapshot(); + clearRuntimeConfigSnapshot(); + clearConfigCache(); + }); + + return { + prepareSecretsRuntimeSnapshot: ((...args) => + prepareSecretsRuntimeSnapshotImpl(...args)) as PrepareSecretsRuntimeSnapshot, + }; +}