4643e65ad6
deploy / deploy (push) Has been cancelled
nix-eval / nix-eval (push) Has been cancelled
publish / version (push) Has been cancelled
publish / build-cli (push) Has been cancelled
publish / sign-cli-windows (push) Has been cancelled
publish / build-electron (map[bun_install_flags:--os=darwin --cpu=arm64 host:macos-26 platform_flag:--mac --arm64 target:aarch64-apple-darwin]) (push) Has been cancelled
publish / build-electron (map[bun_install_flags:--os=darwin --cpu=x64 host:macos-26-intel platform_flag:--mac --x64 target:x86_64-apple-darwin]) (push) Has been cancelled
publish / build-electron (map[host:blacksmith-4vcpu-ubuntu-2404 platform_flag:--linux target:x86_64-unknown-linux-gnu]) (push) Has been cancelled
publish / build-electron (map[host:blacksmith-4vcpu-ubuntu-2404-arm platform_flag:--linux --arm64 target:aarch64-unknown-linux-gnu]) (push) Has been cancelled
publish / build-electron (map[host:blacksmith-4vcpu-windows-2025 platform_flag:--win target:x86_64-pc-windows-msvc]) (push) Has been cancelled
publish / build-electron (map[host:windows-2025 platform_flag:--win --arm64 target:aarch64-pc-windows-msvc]) (push) Has been cancelled
publish / publish (push) Has been cancelled
docs-locale-sync / sync-locales (push) Has been cancelled
generate / generate (push) Has been cancelled
typecheck / typecheck (push) Has been cancelled
Co-authored-by: Aiden Cline <rekram1-node@users.noreply.github.com>
101 lines
3.4 KiB
TypeScript
101 lines
3.4 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 { webSearchEnabled } from "../../src/tool/registry"
|
|
import { it } from "../lib/effect"
|
|
import { ProviderV2 } from "@opencode-ai/core/provider"
|
|
|
|
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 enabled for OpenCode providers or explicit websearch provider flags", () => {
|
|
expect(webSearchEnabled(ProviderV2.ID.opencode, { exa: false, parallel: false })).toBe(true)
|
|
expect(webSearchEnabled(ProviderV2.ID.make("opencode-go"), { exa: false, parallel: false })).toBe(true)
|
|
expect(webSearchEnabled(ProviderV2.ID.openai, { exa: false, parallel: false })).toBe(false)
|
|
expect(webSearchEnabled(ProviderV2.ID.openai, { exa: true, parallel: false })).toBe(true)
|
|
expect(webSearchEnabled(ProviderV2.ID.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",
|
|
},
|
|
],
|
|
},
|
|
})
|
|
|
|
it.effect("parses plain JSON-RPC responses", () =>
|
|
Effect.gen(function* () {
|
|
const result = yield* parseResponse(payload)
|
|
expect(result).toBe("search results")
|
|
}),
|
|
)
|
|
|
|
it.effect("parses SSE JSON-RPC responses", () =>
|
|
Effect.gen(function* () {
|
|
const result = yield* parseResponse(`event: message\ndata: ${payload}\n\n`)
|
|
expect(result).toBe("search results")
|
|
}),
|
|
)
|
|
|
|
it.effect("ignores non-JSON SSE data frames", () =>
|
|
Effect.gen(function* () {
|
|
const result = yield* parseResponse(`data: [DONE]\ndata: ${payload}\n\n`)
|
|
expect(result).toBe("search results")
|
|
}),
|
|
)
|
|
})
|