feat(websearch): add parallel provider rollout (#26227)

This commit is contained in:
Shoubhit Dash
2026-05-08 14:19:36 +05:30
committed by GitHub
parent ae25278eda
commit a43d3e0e1e
13 changed files with 276 additions and 44 deletions

View File

@@ -317,7 +317,17 @@ function taskAgent(
}
}
export function getToolInfo(tool: string, input: any = {}): ToolInfo {
function webSearchProviderLabel(provider: unknown) {
if (provider === "parallel") return "Parallel Web Search"
if (provider === "exa") return "Exa Web Search"
return "Web Search"
}
export function getToolInfo(
tool: string,
input: any = {},
metadata: Record<string, unknown> | undefined = {},
): ToolInfo {
const i18n = useI18n()
switch (tool) {
case "read":
@@ -353,7 +363,7 @@ export function getToolInfo(tool: string, input: any = {}): ToolInfo {
case "websearch":
return {
icon: "window-cursor",
title: i18n.t("ui.tool.websearch"),
title: webSearchProviderLabel(metadata?.provider),
subtitle: input.query,
}
case "task": {
@@ -692,7 +702,11 @@ function isContextGroupTool(part: PartType): part is ToolPart {
}
function contextToolDetail(part: ToolPart): string | undefined {
const info = getToolInfo(part.tool, part.state.input ?? {})
const info = getToolInfo(
part.tool,
part.state.input ?? {},
"metadata" in part.state ? part.state.metadata : undefined,
)
if (info.subtitle) return info.subtitle
if (part.state.status === "error") return part.state.error
if ((part.state.status === "running" || part.state.status === "completed") && part.state.title)
@@ -744,7 +758,11 @@ function contextToolTrigger(part: ToolPart, i18n: ReturnType<typeof useI18n>) {
}
}
default: {
const info = getToolInfo(part.tool, input)
const info = getToolInfo(
part.tool,
input,
"metadata" in part.state ? part.state.metadata : undefined,
)
return {
title: info.title,
subtitle: info.subtitle || contextToolDetail(part),
@@ -1224,6 +1242,7 @@ export interface ToolProps {
input: Record<string, any>
metadata: Record<string, any>
tool: string
sessionID?: string
output?: string
status?: string
hideDetails?: boolean
@@ -1346,6 +1365,11 @@ PART_MAPPING["tool"] = function ToolPartDisplay(props) {
<ToolErrorCard
tool={part().tool}
error={error()}
title={
part().tool === "websearch"
? webSearchProviderLabel(partMetadata().provider)
: undefined
}
defaultOpen={props.defaultOpen}
subtitle={taskSubtitle()}
href={taskHref()}
@@ -1358,6 +1382,7 @@ PART_MAPPING["tool"] = function ToolPartDisplay(props) {
component={render()}
input={input()}
tool={part().tool}
sessionID={part().sessionID}
metadata={partMetadata()}
// @ts-expect-error
output={part().state.output}
@@ -1681,19 +1706,19 @@ ToolRegistry.register({
ToolRegistry.register({
name: "websearch",
render(props) {
const i18n = useI18n()
const query = createMemo(() => {
const value = props.input.query
if (typeof value !== "string") return ""
return value
})
const title = createMemo(() => webSearchProviderLabel(props.metadata.provider))
return (
<BasicTool
{...props}
icon="window-cursor"
trigger={{
title: i18n.t("ui.tool.websearch"),
title: title(),
subtitle: query(),
subtitleClass: "exa-tool-query",
}}

View File

@@ -10,6 +10,7 @@ import { useI18n } from "../context/i18n"
export interface ToolErrorCardProps extends Omit<ComponentProps<typeof Card>, "children" | "variant"> {
tool: string
error: string
title?: string
defaultOpen?: boolean
subtitle?: string
href?: string
@@ -23,8 +24,9 @@ export function ToolErrorCard(props: ToolErrorCardProps) {
})
const open = () => state.open
const copied = () => state.copied
const [split, rest] = splitProps(props, ["tool", "error", "defaultOpen", "subtitle", "href"])
const [split, rest] = splitProps(props, ["tool", "error", "title", "defaultOpen", "subtitle", "href"])
const name = createMemo(() => {
if (split.title) return split.title
const map: Record<string, string> = {
read: "ui.tool.read",
list: "ui.tool.list",