diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/BashOutputTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/BashOutputTool.tsx
index f2dc8f143a..8c4402436c 100644
--- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/BashOutputTool.tsx
+++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/BashOutputTool.tsx
@@ -1,4 +1,4 @@
-import { AccordionItem, Card, CardBody, Chip, Code } from '@heroui/react'
+import { AccordionItem, Chip, Code } from '@heroui/react'
import { CheckCircle, Terminal, XCircle } from 'lucide-react'
import { useMemo } from 'react'
@@ -132,57 +132,43 @@ export function BashOutputTool({ input, output }: { input: BashOutputToolInput;
{/* Standard Output */}
{parsedOutput.stdout && (
-
-
- stdout:
-
- {parsedOutput.stdout}
-
-
-
+
+
stdout:
+
+ {parsedOutput.stdout}
+
+
)}
{/* Standard Error */}
{parsedOutput.stderr && (
-
-
- stderr:
-
- {parsedOutput.stderr}
-
-
-
+
+
stderr:
+
+ {parsedOutput.stderr}
+
+
)}
{/* Tool Use Error */}
{parsedOutput.tool_use_error && (
-
-
-
-
- Error:
-
-
- {parsedOutput.tool_use_error}
-
-
-
+
+
+
+ Error:
+
+
+ {parsedOutput.tool_use_error}
+
+
)}
>
) : (
// 原始输出(如果解析失败或非 XML 格式)
output && (
-
-
-
- {output}
-
-
-
+
)
)}
diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/UnknownToolRenderer.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/UnknownToolRenderer.tsx
new file mode 100644
index 0000000000..ad26caa549
--- /dev/null
+++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/UnknownToolRenderer.tsx
@@ -0,0 +1,88 @@
+import { AccordionItem } from '@heroui/react'
+import { useCodeStyle } from '@renderer/context/CodeStyleProvider'
+import { Wrench } from 'lucide-react'
+import { useEffect, useState } from 'react'
+
+import { ToolTitle } from './GenericTools'
+
+interface UnknownToolProps {
+ toolName: string
+ input?: unknown
+ output?: unknown
+}
+
+export function UnknownToolRenderer({ toolName = '', input, output }: UnknownToolProps) {
+ const { highlightCode } = useCodeStyle()
+ const [inputHtml, setInputHtml] = useState('')
+ const [outputHtml, setOutputHtml] = useState('')
+
+ useEffect(() => {
+ if (input !== undefined) {
+ const inputStr = JSON.stringify(input, null, 2)
+ highlightCode(inputStr, 'json').then(setInputHtml)
+ }
+ }, [input, highlightCode])
+
+ useEffect(() => {
+ if (output !== undefined) {
+ const outputStr = JSON.stringify(output, null, 2)
+ highlightCode(outputStr, 'json').then(setOutputHtml)
+ }
+ }, [output, highlightCode])
+
+ const getToolDisplayName = (name: string) => {
+ if (name.startsWith('mcp__')) {
+ const parts = name.substring(5).split('__')
+ if (parts.length >= 2) {
+ return `${parts[0]}:${parts.slice(1).join(':')}`
+ }
+ }
+ return name
+ }
+
+ const getToolDescription = () => {
+ if (toolName.startsWith('mcp__')) {
+ return 'MCP Server Tool'
+ }
+ return 'Tool'
+ }
+
+ return (
+ }
+ label={getToolDisplayName(toolName)}
+ params={getToolDescription()}
+ />
+ }>
+
+ {input !== undefined && (
+
+ )}
+
+ {output !== undefined && (
+
+ )}
+
+ {input === undefined && output === undefined && (
+
No data available for this tool
+ )}
+
+
+ )
+}
diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/index.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/index.tsx
index 7d33a756d5..e32e4d6fd6 100644
--- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/index.tsx
+++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/index.tsx
@@ -19,10 +19,10 @@ import { SearchTool } from './SearchTool'
import { TaskTool } from './TaskTool'
import { TodoWriteTool } from './TodoWriteTool'
import { AgentToolsType, ToolInput, ToolOutput } from './types'
+import { UnknownToolRenderer } from './UnknownToolRenderer'
import { WebFetchTool } from './WebFetchTool'
import { WebSearchTool } from './WebSearchTool'
import { WriteTool } from './WriteTool'
-
const logger = loggerService.withContext('MessageAgentTools')
// 创建工具渲染器映射,这样就实现了完全的类型安全
@@ -54,20 +54,24 @@ function renderToolContent(toolName: AgentToolsType, input: ToolInput, output?:
const Renderer = toolRenderers[toolName]
return (
- div:first-child]:!flex-none [&>div:first-child]:flex [&>div:first-child]:flex-col [&>div:first-child]:text-start [&>div:first-child]:max-w-full',
- indicator: 'flex-shrink-0',
- subtitle: 'text-xs',
- content:
- 'rounded-md bg-foreground-50 p-2 text-foreground-900 dark:bg-foreground-100 max-h-96 p-2 overflow-scroll'
- }}
- defaultExpandedKeys={toolName === AgentToolsType.TodoWrite ? [AgentToolsType.TodoWrite] : []}>
- {/* */}
- {Renderer({ input: input as any, output: output as any })}
-
+
+
div:first-child]:!flex-none [&>div:first-child]:flex [&>div:first-child]:flex-col [&>div:first-child]:text-start [&>div:first-child]:max-w-full',
+ indicator: 'flex-shrink-0',
+ subtitle: 'text-xs',
+ content:
+ 'rounded-md bg-foreground-50 p-2 text-foreground-900 dark:bg-foreground-100 max-h-96 p-2 overflow-scroll',
+ base: 'space-y-1'
+ }}
+ defaultExpandedKeys={toolName === AgentToolsType.TodoWrite ? [AgentToolsType.TodoWrite] : []}>
+ {Renderer
+ ? Renderer({ input: input as any, output: output as any })
+ : UnknownToolRenderer({ input: input as any, output: output as any, toolName })}
+
+
)
}
@@ -80,17 +84,5 @@ export function MessageAgentTools({ toolResponse }: { toolResponse: NormalToolRe
response
})
- // 使用类型守卫确保类型安全
- if (!isValidAgentToolsType(tool?.name)) {
- logger.warn('Invalid tool name received', { toolName: tool?.name })
- return (
-
-
Invalid tool name: {tool?.name}
-
- )
- }
-
- const toolName = tool.name
-
- return renderToolContent(toolName, args as ToolInput, response as ToolOutput)
+ return renderToolContent(tool.name as AgentToolsType, args as ToolInput, response as ToolOutput)
}
diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageTool.tsx
index 29b25e9a55..1b68bf7066 100644
--- a/src/renderer/src/pages/home/Messages/Tools/MessageTool.tsx
+++ b/src/renderer/src/pages/home/Messages/Tools/MessageTool.tsx
@@ -10,39 +10,48 @@ interface Props {
block: ToolMessageBlock
}
const prefix = 'builtin_'
+const agentPrefix = 'mcp__'
+const agentTools = [
+ 'Read',
+ 'Task',
+ 'Bash',
+ 'Search',
+ 'Glob',
+ 'TodoWrite',
+ 'WebSearch',
+ 'Grep',
+ 'Write',
+ 'WebFetch',
+ 'Edit',
+ 'MultiEdit',
+ 'BashOutput',
+ 'NotebookEdit',
+ 'ExitPlanMode'
+]
+const isAgentTool = (toolName: string) => {
+ if (agentTools.includes(toolName) || toolName.startsWith(agentPrefix)) {
+ return true
+ }
+ return false
+}
const ChooseTool = (toolResponse: NormalToolResponse): React.ReactNode | null => {
let toolName = toolResponse.tool.name
if (toolName.startsWith(prefix)) {
toolName = toolName.slice(prefix.length)
- }
-
- switch (toolName) {
- case 'web_search':
- case 'web_search_preview':
- return
- case 'knowledge_search':
- return
- case 'memory_search':
- return
- case 'Read':
- case 'Task':
- case 'Bash':
- case 'Search':
- case 'Glob':
- case 'TodoWrite':
- case 'WebSearch':
- case 'Grep':
- case 'Write':
- case 'WebFetch':
- case 'Edit':
- case 'MultiEdit':
- case 'BashOutput':
- case 'NotebookEdit':
- case 'ExitPlanMode':
- return
- default:
- return null
+ switch (toolName) {
+ case 'web_search':
+ case 'web_search_preview':
+ return
+ case 'knowledge_search':
+ return
+ case 'memory_search':
+ return
+ default:
+ return null
+ }
+ } else if (isAgentTool(toolName)) {
+ return
}
}