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"; const { resolvePluginWebSearchProvidersMock } = vi.hoisted(() => ({ resolvePluginWebSearchProvidersMock: vi.fn(() => buildTestWebSearchProviders()), })); vi.mock("../plugins/web-search-providers.runtime.js", () => ({ resolvePluginWebSearchProviders: resolvePluginWebSearchProvidersMock, })); vi.mock("../plugins/installed-plugin-index-records.js", () => ({ loadInstalledPluginIndexInstallRecordsSync: () => ({}), })); 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" ? 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 }), ]; } export function resetPluginWebSearchProvidersMock() { resolvePluginWebSearchProvidersMock.mockReset(); resolvePluginWebSearchProvidersMock.mockReturnValue(buildTestWebSearchProviders()); } export function getResolvePluginWebSearchProvidersMock() { return resolvePluginWebSearchProvidersMock; } 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, }; }