mirror of
https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git
synced 2026-04-25 10:04:40 +00:00
fix(app): websearch and codesearch tool rendering
This commit is contained in:
@@ -243,6 +243,18 @@ export function getToolInfo(tool: string, input: any = {}): ToolInfo {
|
||||
title: i18n.t("ui.tool.webfetch"),
|
||||
subtitle: input.url,
|
||||
}
|
||||
case "websearch":
|
||||
return {
|
||||
icon: "window-cursor",
|
||||
title: i18n.t("ui.tool.websearch"),
|
||||
subtitle: input.query,
|
||||
}
|
||||
case "codesearch":
|
||||
return {
|
||||
icon: "code",
|
||||
title: i18n.t("ui.tool.codesearch"),
|
||||
subtitle: input.query,
|
||||
}
|
||||
case "task":
|
||||
return {
|
||||
icon: "task",
|
||||
@@ -303,6 +315,18 @@ export function getToolInfo(tool: string, input: any = {}): ToolInfo {
|
||||
}
|
||||
}
|
||||
|
||||
function urls(text: string | undefined) {
|
||||
if (!text) return []
|
||||
const seen = new Set<string>()
|
||||
return [...text.matchAll(/https?:\/\/[^\s<>"'`)\]]+/g)]
|
||||
.map((item) => item[0].replace(/[),.;:!?]+$/g, ""))
|
||||
.filter((item) => {
|
||||
if (seen.has(item)) return false
|
||||
seen.add(item)
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
const CONTEXT_GROUP_TOOLS = new Set(["read", "glob", "grep", "list"])
|
||||
const HIDDEN_TOOLS = new Set(["todowrite", "todoread"])
|
||||
|
||||
@@ -598,6 +622,32 @@ function contextToolSummary(parts: ToolPart[]) {
|
||||
return { read, search, list }
|
||||
}
|
||||
|
||||
function ExaOutput(props: { output?: string }) {
|
||||
const links = createMemo(() => urls(props.output))
|
||||
|
||||
return (
|
||||
<Show when={links().length > 0}>
|
||||
<div data-component="exa-tool-output">
|
||||
<div data-slot="exa-tool-links">
|
||||
<For each={links()}>
|
||||
{(url) => (
|
||||
<a
|
||||
data-slot="exa-tool-link"
|
||||
href={url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
>
|
||||
{url}
|
||||
</a>
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
)
|
||||
}
|
||||
|
||||
export function registerPartComponent(type: string, component: PartComponent) {
|
||||
PART_MAPPING[type] = component
|
||||
}
|
||||
@@ -1467,6 +1517,58 @@ 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
|
||||
})
|
||||
|
||||
return (
|
||||
<BasicTool
|
||||
{...props}
|
||||
icon="window-cursor"
|
||||
trigger={{
|
||||
title: i18n.t("ui.tool.websearch"),
|
||||
subtitle: query(),
|
||||
subtitleClass: "exa-tool-query",
|
||||
}}
|
||||
>
|
||||
<ExaOutput output={props.output} />
|
||||
</BasicTool>
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
ToolRegistry.register({
|
||||
name: "codesearch",
|
||||
render(props) {
|
||||
const i18n = useI18n()
|
||||
const query = createMemo(() => {
|
||||
const value = props.input.query
|
||||
if (typeof value !== "string") return ""
|
||||
return value
|
||||
})
|
||||
|
||||
return (
|
||||
<BasicTool
|
||||
{...props}
|
||||
icon="code"
|
||||
trigger={{
|
||||
title: i18n.t("ui.tool.codesearch"),
|
||||
subtitle: query(),
|
||||
subtitleClass: "exa-tool-query",
|
||||
}}
|
||||
>
|
||||
<ExaOutput output={props.output} />
|
||||
</BasicTool>
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
ToolRegistry.register({
|
||||
name: "task",
|
||||
render(props) {
|
||||
|
||||
Reference in New Issue
Block a user