优化消息的部分call tool显示
This commit is contained in:
@@ -22,6 +22,7 @@ import { useTranslations } from "next-intl"
|
||||
import { isValidElement } from "react"
|
||||
|
||||
import { CodeBlock } from "./code-block"
|
||||
import { MessageResponse } from "./message"
|
||||
|
||||
export type ToolProps = ComponentProps<typeof Collapsible>
|
||||
|
||||
@@ -315,12 +316,34 @@ function isDuplicateErrorOutput(
|
||||
export type ToolOutputProps = ComponentProps<"div"> & {
|
||||
output: ToolPart["output"]
|
||||
errorText: ToolPart["errorText"]
|
||||
renderAsMarkdown?: boolean
|
||||
}
|
||||
|
||||
const MD_INDICATORS = [
|
||||
/^#{1,6}\s/m,
|
||||
/^\s*[-*+]\s/m,
|
||||
/^\s*\d+\.\s/m,
|
||||
/\*\*[^*]+\*\*/,
|
||||
/\[.+\]\(.+\)/,
|
||||
/```[\s\S]*?```/,
|
||||
/^\s*>/m,
|
||||
/^\|.+\|$/m,
|
||||
]
|
||||
|
||||
function looksLikeMarkdown(text: string): boolean {
|
||||
let count = 0
|
||||
for (const re of MD_INDICATORS) {
|
||||
if (re.test(text)) count++
|
||||
if (count >= 2) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export const ToolOutput = ({
|
||||
className,
|
||||
output,
|
||||
errorText,
|
||||
renderAsMarkdown,
|
||||
...props
|
||||
}: ToolOutputProps) => {
|
||||
const t = useTranslations("Folder.chat.tool")
|
||||
@@ -342,8 +365,18 @@ export const ToolOutput = ({
|
||||
<CodeBlock code={JSON.stringify(output, null, 2)} language="json" />
|
||||
)
|
||||
} else if (typeof output === "string") {
|
||||
const language = detectOutputLanguage(output)
|
||||
Output = <CodeBlock code={output} language={language} />
|
||||
const shouldRenderMd =
|
||||
renderAsMarkdown ?? (detectOutputLanguage(output) === "log" && looksLikeMarkdown(output))
|
||||
if (shouldRenderMd) {
|
||||
Output = (
|
||||
<div className="prose prose-sm dark:prose-invert max-w-none p-3 text-sm [&_ul]:list-inside [&_ol]:list-inside">
|
||||
<MessageResponse>{output}</MessageResponse>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
const language = detectOutputLanguage(output)
|
||||
Output = <CodeBlock code={output} language={language} />
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -871,6 +871,7 @@ function getToolIcon(
|
||||
if (name === "task") return getTaskToolIcon(input ?? null)
|
||||
if (name === "taskcreate" || name === "taskupdate" || name === "tasklist")
|
||||
return <ListTodoIcon className={ICON_CLASS} />
|
||||
if (name === "agent") return getTaskToolIcon(input ?? null)
|
||||
if (name === "skill") return <SparklesIcon className={ICON_CLASS} />
|
||||
if (name === "enterplanmode" || name === "exitplanmode")
|
||||
return <BrainIcon className={ICON_CLASS} />
|
||||
@@ -1000,6 +1001,13 @@ function deriveToolTitle(
|
||||
if (desc) return `${prefix}${ellipsis(desc, 60 - prefix.length)}`
|
||||
if (subagent) return subagent
|
||||
}
|
||||
if (name === "agent") {
|
||||
const subagent = getField("subagent_type")
|
||||
const desc = getField("description")
|
||||
const prefix = subagent ? `${subagent}: ` : ""
|
||||
if (desc) return `${prefix}${ellipsis(desc, 60 - prefix.length)}`
|
||||
if (subagent) return subagent
|
||||
}
|
||||
if (name === "taskcreate") {
|
||||
const subj = getField("subject")
|
||||
if (subj) return `TaskCreate: ${ellipsis(subj, 50)}`
|
||||
@@ -2156,7 +2164,8 @@ const ToolCallPart = memo(function ToolCallPart({
|
||||
input={part.input}
|
||||
/>
|
||||
)}
|
||||
{toolNameLower === "task" && part.output ? (
|
||||
{(toolNameLower === "task" || toolNameLower === "agent") &&
|
||||
part.output ? (
|
||||
<div className="text-sm prose prose-sm dark:prose-invert max-w-none [&_ul]:list-inside [&_ol]:list-inside">
|
||||
<MessageResponse>{part.output}</MessageResponse>
|
||||
</div>
|
||||
|
||||
@@ -32,6 +32,29 @@ const EXACT_TOOL_NAME_ALIASES: Record<string, string> = {
|
||||
web_search: "websearch",
|
||||
context7_query_docs: "context7_query-docs",
|
||||
context7_resolve_library_id: "context7_resolve-library-id",
|
||||
agent: "agent",
|
||||
// Gemini CLI
|
||||
searchtext: "grep",
|
||||
search_text: "grep",
|
||||
writefile: "write",
|
||||
editfile: "edit",
|
||||
// Codex
|
||||
update_plan: "task",
|
||||
request_user_input: "question",
|
||||
// OpenCode
|
||||
delegate_task: "task",
|
||||
call_omo_agent: "agent",
|
||||
ast_grep_search: "grep",
|
||||
ast_grep_replace: "edit",
|
||||
background_task: "task",
|
||||
background_cancel: "task",
|
||||
background_output: "task",
|
||||
slashcommand: "skill",
|
||||
question: "question",
|
||||
lsp_diagnostics: "lsp",
|
||||
lsp_document_symbols: "lsp",
|
||||
lsp_goto_definition: "lsp",
|
||||
lsp_servers: "lsp",
|
||||
execute: "bash",
|
||||
search: "grep",
|
||||
fetch: "webfetch",
|
||||
@@ -65,6 +88,10 @@ function inferFromFreeformName(input: string): string | null {
|
||||
if (/^glob(?:\b|[_\s:-])/.test(normalized)) return "glob"
|
||||
if (/^webfetch(?:\b|[_\s:-])/.test(normalized)) return "webfetch"
|
||||
if (/^websearch(?:\b|[_\s:-])/.test(normalized)) return "websearch"
|
||||
if (/\bweb[_\s-]?search\b/.test(normalized)) return "websearch"
|
||||
if (/\bgrep\b/.test(normalized)) return "grep"
|
||||
if (/\bagent\b/.test(normalized)) return "agent"
|
||||
if (/\blsp\b/.test(normalized)) return "lsp"
|
||||
if (/^todowrite(?:\b|[_\s:-])/.test(normalized)) return "todowrite"
|
||||
if (/^taskupdate(?:\b|[_\s:-])/.test(normalized)) return "taskupdate"
|
||||
if (/^taskcreate(?:\b|[_\s:-])/.test(normalized)) return "taskcreate"
|
||||
|
||||
Reference in New Issue
Block a user