91 lines
3.2 KiB
TypeScript
91 lines
3.2 KiB
TypeScript
import { describe, expect, test } from "bun:test"
|
|
import { Effect } from "effect"
|
|
import { parseResponse } from "../../src/tool/mcp-websearch"
|
|
import { selectWebSearchProvider, webSearchModelName, webSearchProviderLabel } from "../../src/tool/websearch"
|
|
import { ProviderID } from "../../src/provider/schema"
|
|
import { webSearchEnabled } from "../../src/tool/registry"
|
|
|
|
const SESSION_ID = "ses_0196aabbccddeeff001122334455"
|
|
|
|
describe("websearch provider", () => {
|
|
test("selects a stable provider per session", () => {
|
|
expect(selectWebSearchProvider(SESSION_ID)).toBe(selectWebSearchProvider(SESSION_ID))
|
|
})
|
|
|
|
test("supports an operational override", () => {
|
|
const original = process.env.OPENCODE_WEBSEARCH_PROVIDER
|
|
|
|
try {
|
|
process.env.OPENCODE_WEBSEARCH_PROVIDER = "parallel"
|
|
expect(selectWebSearchProvider(SESSION_ID)).toBe("parallel")
|
|
|
|
process.env.OPENCODE_WEBSEARCH_PROVIDER = "exa"
|
|
expect(selectWebSearchProvider(SESSION_ID)).toBe("exa")
|
|
} finally {
|
|
if (original === undefined) delete process.env.OPENCODE_WEBSEARCH_PROVIDER
|
|
else process.env.OPENCODE_WEBSEARCH_PROVIDER = original
|
|
}
|
|
})
|
|
|
|
test("routes to Exa when the Exa flag is enabled", () => {
|
|
expect(selectWebSearchProvider(SESSION_ID, { exa: true, parallel: false })).toBe("exa")
|
|
})
|
|
|
|
test("routes to Parallel when the Parallel flag is enabled", () => {
|
|
expect(selectWebSearchProvider(SESSION_ID, { exa: false, parallel: true })).toBe("parallel")
|
|
})
|
|
|
|
test("is only enabled for opencode or explicit websearch provider flags", () => {
|
|
expect(webSearchEnabled(ProviderID.opencode, { exa: false, parallel: false })).toBe(true)
|
|
expect(webSearchEnabled(ProviderID.openai, { exa: false, parallel: false })).toBe(false)
|
|
expect(webSearchEnabled(ProviderID.openai, { exa: true, parallel: false })).toBe(true)
|
|
expect(webSearchEnabled(ProviderID.openai, { exa: false, parallel: true })).toBe(true)
|
|
})
|
|
|
|
test("uses branded labels", () => {
|
|
expect(webSearchProviderLabel("parallel")).toBe("Parallel Web Search")
|
|
expect(webSearchProviderLabel("exa")).toBe("Exa Web Search")
|
|
expect(webSearchProviderLabel(undefined)).toBe("Web Search")
|
|
})
|
|
|
|
test("uses the provider API model id for Parallel analytics", () => {
|
|
expect(
|
|
webSearchModelName({
|
|
model: {
|
|
id: "claude-opus-4-7",
|
|
api: { id: "claude-opus-4.7" },
|
|
},
|
|
}),
|
|
).toBe("claude-opus-4.7")
|
|
})
|
|
})
|
|
|
|
describe("websearch MCP response parser", () => {
|
|
const payload = JSON.stringify({
|
|
jsonrpc: "2.0",
|
|
id: 1,
|
|
result: {
|
|
content: [
|
|
{
|
|
type: "text",
|
|
text: "search results",
|
|
},
|
|
],
|
|
},
|
|
})
|
|
|
|
test("parses plain JSON-RPC responses", async () => {
|
|
await expect(Effect.runPromise(parseResponse(payload))).resolves.toBe("search results")
|
|
})
|
|
|
|
test("parses SSE JSON-RPC responses", async () => {
|
|
await expect(Effect.runPromise(parseResponse(`event: message\ndata: ${payload}\n\n`))).resolves.toBe(
|
|
"search results",
|
|
)
|
|
})
|
|
|
|
test("ignores non-JSON SSE data frames", async () => {
|
|
await expect(Effect.runPromise(parseResponse(`data: [DONE]\ndata: ${payload}\n\n`))).resolves.toBe("search results")
|
|
})
|
|
})
|