From 1f842fa654c0e106331fe95957072fd569ca5b81 Mon Sep 17 00:00:00 2001 From: Shoubhit Dash Date: Tue, 7 Jul 2026 17:57:17 +0530 Subject: [PATCH] fix(tui): stabilize websearch labels --- packages/tui/src/routes/session/index.tsx | 13 +++++++++++-- packages/tui/src/util/tool-display.ts | 8 ++++++++ packages/tui/test/util/tool-display.test.ts | 21 ++++++++++++++++++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/packages/tui/src/routes/session/index.tsx b/packages/tui/src/routes/session/index.tsx index d1ea5e1272..5ce997182c 100644 --- a/packages/tui/src/routes/session/index.tsx +++ b/packages/tui/src/routes/session/index.tsx @@ -37,7 +37,7 @@ import type { } from "@opencode-ai/sdk/v2" import { useLocal } from "../../context/local" import { Locale } from "../../util/locale" -import { webSearchProviderLabel } from "../../util/tool-display" +import { selectedWebSearchProvider, webSearchProviderLabel } from "../../util/tool-display" import { useRenderer, useTerminalDimensions, type JSX } from "@opentui/solid" import { useSDK } from "../../context/sdk" import { useEditorContext } from "../../context/editor" @@ -2345,9 +2345,18 @@ function WebFetch(props: ToolProps) { } function WebSearch(props: ToolProps) { + const data = useData() + const [provider, setProvider] = createSignal( + selectedWebSearchProvider(data.location.integration.list() ?? []) ?? stringValue(props.metadata.provider), + ) + createEffect(() => { + if (provider()) return + const next = selectedWebSearchProvider(data.location.integration.list() ?? []) + if (next) setProvider(next) + }) return ( - {webSearchProviderLabel(props.metadata.provider)} "{stringValue(props.input.query)}"{" "} + {webSearchProviderLabel(provider())} "{stringValue(props.input.query)}"{" "} ({numberValue(props.metadata.numResults)} results) ) diff --git a/packages/tui/src/util/tool-display.ts b/packages/tui/src/util/tool-display.ts index 18e256bd34..c8c5fca873 100644 --- a/packages/tui/src/util/tool-display.ts +++ b/packages/tui/src/util/tool-display.ts @@ -1,9 +1,17 @@ +import type { IntegrationInfo } from "@opencode-ai/sdk/v2" + export function webSearchProviderLabel(provider: unknown) { if (provider === "parallel") return "Parallel Web Search" if (provider === "exa") return "Exa Web Search" return "Web Search" } +export function selectedWebSearchProvider(integrations: readonly Pick[]) { + return integrations.find((integration) => + integration.capabilities.some((capability) => capability.type === "search" && capability.selected), + )?.id +} + export function toolDisplayMetadata(state: unknown): Record { if (!state || typeof state !== "object" || Array.isArray(state)) return {} if (!("status" in state) || state.status === "pending") return {} diff --git a/packages/tui/test/util/tool-display.test.ts b/packages/tui/test/util/tool-display.test.ts index f77f54cbab..0ee2fd3b2a 100644 --- a/packages/tui/test/util/tool-display.test.ts +++ b/packages/tui/test/util/tool-display.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test" -import { toolDisplayMetadata, webSearchProviderLabel } from "../../src/util/tool-display" +import { selectedWebSearchProvider, toolDisplayMetadata, webSearchProviderLabel } from "../../src/util/tool-display" describe("webSearchProviderLabel", () => { test("labels known providers", () => { @@ -21,6 +21,25 @@ describe("webSearchProviderLabel", () => { } }) +describe("selectedWebSearchProvider", () => { + test("returns the selected search integration", () => { + expect( + selectedWebSearchProvider([ + { id: "exa", capabilities: [{ type: "search", connection: "optional", selected: false }] }, + { id: "parallel", capabilities: [{ type: "search", connection: "optional", selected: true }] }, + ]), + ).toBe("parallel") + }) + + test("ignores unselected and unrelated capabilities", () => { + expect( + selectedWebSearchProvider([ + { id: "exa", capabilities: [{ type: "search", connection: "optional", selected: false }] }, + ]), + ).toBeUndefined() + }) +}) + describe("toolDisplayMetadata", () => { test("returns structured metadata for non-pending states", () => { const structured = { provider: "parallel", numResults: 3 }