refactor(websearch): rename search domain

This commit is contained in:
Shoubhit Dash 2026-07-08 17:27:31 +05:30
commit c86f4e9b9b
51 changed files with 478 additions and 462 deletions

View file

@ -259,11 +259,11 @@ function registerIntegration(draft: Integration.Draft, definition: IntegrationDe
}),
)
}
if (!definition.search) return
draft.search.update({
if (!definition.websearch) return
draft.websearch.update({
integrationID,
connection: definition.search.connection,
execute: definition.search.execute,
connection: definition.websearch.connection,
execute: definition.websearch.execute,
})
}

View file

@ -95,19 +95,19 @@ describe("fromPromise", () => {
}),
)
it.effect("adapts promise search capability execution", () =>
it.effect("adapts promise web search capability execution", () =>
Effect.gen(function* () {
const integrations = yield* Integration.Service
const plugin = yield* PluginV2.Service
const host = yield* PluginHost.make(plugin)
const promisePlugin = Plugin.define({
id: "promise-search",
id: "promise-websearch",
setup: async (ctx) => {
await ctx.integration.register({
id: "promise-search",
name: "Promise Search",
methods: [{ type: "env", names: ["PROMISE_SEARCH_KEY"] }],
search: {
id: "promise-websearch",
name: "Promise Web Search",
methods: [{ type: "env", names: ["PROMISE_WEBSEARCH_KEY"] }],
websearch: {
connection: "optional",
execute: async (input) => ({ text: `promise: ${input.query}` }),
},
@ -116,12 +116,12 @@ describe("fromPromise", () => {
})
yield* PluginPromise.fromPromise(promisePlugin).effect(host)
expect(yield* integrations.get(Integration.ID.make("promise-search"))).toMatchObject({
name: "Promise Search",
methods: [{ type: "env", names: ["PROMISE_SEARCH_KEY"] }],
expect(yield* integrations.get(Integration.ID.make("promise-websearch"))).toMatchObject({
name: "Promise Web Search",
methods: [{ type: "env", names: ["PROMISE_WEBSEARCH_KEY"] }],
})
const provider = yield* integrations.search.get(Integration.ID.make("promise-search"))
if (!provider) return yield* Effect.die("Expected promise search provider")
const provider = yield* integrations.websearch.get(Integration.ID.make("promise-websearch"))
if (!provider) return yield* Effect.die("Expected promise web search provider")
expect(yield* provider.execute({ query: "effect" }, {})).toEqual({ text: "promise: effect" })
}),
)

View file

@ -7,16 +7,16 @@ import { EventV2 } from "@opencode-ai/core/event"
import { Integration } from "@opencode-ai/core/integration"
import { testEffect } from "../lib/effect"
export interface SearchRequest {
export interface WebSearchRequest {
readonly url: string
readonly headers: Record<string, string>
readonly body: unknown
}
export const requests: SearchRequest[] = []
export const requests: WebSearchRequest[] = []
export const response = { body: "" }
export function resetSearchFixture(body: string) {
export function resetWebSearchFixture(body: string) {
requests.length = 0
response.body = body
}
@ -36,6 +36,6 @@ const http = Layer.succeed(
),
)
export const searchIntegrationTest = testEffect(
export const webSearchIntegrationTest = testEffect(
Layer.merge(AppNodeBuilder.build(LayerNode.group([Integration.node, Credential.node, EventV2.node])), http),
)

View file

@ -2,13 +2,13 @@ import { beforeEach, describe, expect } from "bun:test"
import { Effect } from "effect"
import { Credential } from "@opencode-ai/core/credential"
import { Integration } from "@opencode-ai/core/integration"
import { SearchExa } from "@opencode-ai/core/plugin/search/exa"
import { SearchParallel } from "@opencode-ai/core/plugin/search/parallel"
import { WebSearchExa } from "@opencode-ai/core/plugin/websearch/exa"
import { WebSearchParallel } from "@opencode-ai/core/plugin/websearch/parallel"
import { host, integrationHost } from "./host"
import { requests, resetSearchFixture, searchIntegrationTest } from "./search-fixture"
import { requests, resetWebSearchFixture, webSearchIntegrationTest } from "./websearch-fixture"
beforeEach(() => {
resetSearchFixture(
resetWebSearchFixture(
`event: message\ndata: ${JSON.stringify({
jsonrpc: "2.0",
id: 1,
@ -17,46 +17,46 @@ beforeEach(() => {
)
})
const it = searchIntegrationTest
const it = webSearchIntegrationTest
describe("built-in search integrations", () => {
it.effect("registers and disposes an atomic search integration", () =>
describe("built-in web search integrations", () => {
it.effect("registers and disposes an atomic web search integration", () =>
Effect.gen(function* () {
const integrations = yield* Integration.Service
const registration = yield* integrationHost(integrations).register({
id: "test-search",
name: "Test Search",
id: "test-websearch",
name: "Test Web Search",
methods: [{ type: "key", label: "API key" }],
search: {
websearch: {
connection: "required",
execute: (input) => Effect.succeed({ text: input.query }),
},
})
expect(yield* integrations.get(Integration.ID.make("test-search"))).toMatchObject({
name: "Test Search",
expect(yield* integrations.get(Integration.ID.make("test-websearch"))).toMatchObject({
name: "Test Web Search",
methods: [{ type: "key", label: "API key" }],
search: { connection: "required" },
websearch: { connection: "required" },
})
yield* registration.dispose
expect(yield* integrations.get(Integration.ID.make("test-search"))).toBeUndefined()
expect(yield* integrations.get(Integration.ID.make("test-websearch"))).toBeUndefined()
}),
)
it.effect("registers Exa with its MCP schema", () =>
Effect.gen(function* () {
const integrations = yield* Integration.Service
yield* SearchExa.Plugin.effect(host({ integration: integrationHost(integrations) }))
yield* WebSearchExa.Plugin.effect(host({ integration: integrationHost(integrations) }))
const info = yield* integrations.get(Integration.ID.make("exa"))
expect(info).toMatchObject({
id: "exa",
name: "Exa",
methods: [{ type: "key" }, { type: "env", names: ["EXA_API_KEY"] }],
search: { connection: "optional" },
websearch: { connection: "optional" },
})
const provider = yield* integrations.search.get(Integration.ID.make("exa"))
if (!provider) return yield* Effect.die("Expected Exa search provider")
const provider = yield* integrations.websearch.get(Integration.ID.make("exa"))
if (!provider) return yield* Effect.die("Expected Exa web search provider")
expect(
yield* provider.execute(
{ query: "effect typescript" },
@ -65,7 +65,7 @@ describe("built-in search integrations", () => {
).toEqual({ text: "search results", metadata: { searchTime: 123 } })
expect(requests).toEqual([
{
url: `${SearchExa.endpoint}?exaApiKey=exa+secret`,
url: `${WebSearchExa.endpoint}?exaApiKey=exa+secret`,
headers: expect.any(Object),
body: {
jsonrpc: "2.0",
@ -73,7 +73,7 @@ describe("built-in search integrations", () => {
method: "tools/call",
params: {
name: "web_search_exa",
arguments: { query: "effect typescript" },
arguments: { query: "effect typescript", numResults: 8 },
},
},
},
@ -83,7 +83,7 @@ describe("built-in search integrations", () => {
it.effect("registers Parallel and keeps its credential in the authorization header", () =>
Effect.gen(function* () {
resetSearchFixture(
resetWebSearchFixture(
JSON.stringify({
jsonrpc: "2.0",
id: 1,
@ -107,9 +107,9 @@ describe("built-in search integrations", () => {
}),
)
const integrations = yield* Integration.Service
yield* SearchParallel.Plugin.effect(host({ integration: integrationHost(integrations) }))
const provider = yield* integrations.search.get(Integration.ID.make("parallel"))
if (!provider) return yield* Effect.die("Expected Parallel search provider")
yield* WebSearchParallel.Plugin.effect(host({ integration: integrationHost(integrations) }))
const provider = yield* integrations.websearch.get(Integration.ID.make("parallel"))
if (!provider) return yield* Effect.die("Expected Parallel web search provider")
const output = yield* provider.execute(
{ query: "effect layers" },
@ -136,7 +136,7 @@ describe("built-in search integrations", () => {
},
})
expect(requests[0]).toMatchObject({
url: SearchParallel.endpoint,
url: WebSearchParallel.endpoint,
headers: { authorization: "Bearer parallel-secret" },
body: {
jsonrpc: "2.0",