import test from "node:test"; import assert from "node:assert/strict"; import { mkdtemp, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { loadWebSearchConfig, WebSearchConfigError } from "./config.ts"; async function writeTempConfig(contents: unknown) { const dir = await mkdtemp(join(tmpdir(), "pi-web-search-config-")); const file = join(dir, "web-search.json"); const body = typeof contents === "string" ? contents : JSON.stringify(contents, null, 2); await writeFile(file, body, "utf8"); return file; } test("loadWebSearchConfig returns a normalized default provider and provider lookup", async () => { const file = await writeTempConfig({ defaultProvider: "exa-main", providers: [ { name: "exa-main", type: "exa", apiKey: "exa-test-key", options: { defaultSearchLimit: 7, defaultFetchTextMaxCharacters: 9000, }, }, ], }); const config = await loadWebSearchConfig(file); assert.equal(config.defaultProviderName, "exa-main"); assert.equal(config.defaultProvider.name, "exa-main"); assert.equal(config.providersByName.get("exa-main")?.apiKey, "exa-test-key"); assert.equal(config.providers[0]?.options?.defaultSearchLimit, 7); }); test("loadWebSearchConfig normalizes a Tavily default with Exa fallback", async () => { const file = await writeTempConfig({ defaultProvider: "tavily-main", providers: [ { name: "tavily-main", type: "tavily", apiKey: "tvly-test-key", }, { name: "exa-fallback", type: "exa", apiKey: "exa-test-key", }, ], }); const config = await loadWebSearchConfig(file); assert.equal(config.defaultProviderName, "tavily-main"); assert.equal(config.defaultProvider.type, "tavily"); assert.equal(config.providersByName.get("exa-fallback")?.type, "exa"); }); test("loadWebSearchConfig rejects a missing default provider target", async () => { const file = await writeTempConfig({ defaultProvider: "missing", providers: [ { name: "exa-main", type: "exa", apiKey: "exa-test-key", }, ], }); await assert.rejects( () => loadWebSearchConfig(file), (error) => error instanceof WebSearchConfigError && /defaultProvider \"missing\"/.test(error.message), ); }); test("loadWebSearchConfig rejects a missing file with a helpful example message", async () => { const file = join(tmpdir(), "pi-web-search-does-not-exist.json"); await assert.rejects( () => loadWebSearchConfig(file), (error) => error instanceof WebSearchConfigError && error.message.includes(file) && error.message.includes('"defaultProvider"') && error.message.includes('"providers"'), ); });