diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/BashTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/BashTool.tsx index 6e7826b298..9ea04b2dfc 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/BashTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/BashTool.tsx @@ -16,15 +16,16 @@ export function BashTool({ input, output }: { input: BashToolInputType; output?: } label="Bash" - params={ - - {input.command} - - } + params={input.description} stats={output ? `${outputLines} ${outputLines === 1 ? 'line' : 'lines'}` : undefined} /> + } + subtitle={ + + {input.command} + }> -
{output}
+
{output}
) } diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/GenericTools.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/GenericTools.tsx index e4f033dc14..11314e984f 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/GenericTools.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/GenericTools.tsx @@ -19,9 +19,9 @@ export function ToolTitle({ return (
{icon} - {label && {label}} - {params && {params}} - {stats && {stats}} + {label && {label}} + {params && {params}} + {stats && {stats}}
) } diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/ReadTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/ReadTool.tsx index beba2f2164..078c9e4dfa 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/ReadTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/ReadTool.tsx @@ -1,7 +1,9 @@ -import { AccordionItem } from '@heroui/react' +import { AccordionItem, ScrollShadow } from '@heroui/react' import { FileText } from 'lucide-react' -import { SimpleFieldInputTool, StringOutputTool, ToolTitle } from './GenericTools' +import { ToolTitle } from './GenericTools' +import { AgentToolsType } from './types' +import ReactMarkdown from 'react-markdown' import type { ReadToolInput as ReadToolInputType, ReadToolOutput as ReadToolOutputType } from './types' export function ReadTool({ input, output }: { input: ReadToolInputType; output?: ReadToolOutputType }) { @@ -20,7 +22,7 @@ export function ReadTool({ input, output }: { input: ReadToolInputType; output?: return ( }> -
- - {output && ( -
- -
- )} -
+ {output ? ( + //
+ {output} + //
+ ) : null}
) } diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/TaskTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/TaskTool.tsx index 0b8d4495ed..2007a141ee 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/TaskTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/TaskTool.tsx @@ -2,6 +2,8 @@ import { AccordionItem } from '@heroui/react' import { Bot } from 'lucide-react' import { ToolTitle } from './GenericTools' +import Markdown from 'react-markdown' + import type { TaskToolInput as TaskToolInputType, TaskToolOutput as TaskToolOutputType } from './types' export function TaskTool({ input, output }: { input: TaskToolInputType; output?: TaskToolOutputType }) { @@ -12,8 +14,7 @@ export function TaskTool({ input, output }: { input: TaskToolInputType; output?: title={} label="Task" params={input.description} />}> {output?.map((item) => (
-
Type: {item.type}
-
{item.text}
+
{item.type === 'text' ? {item.text} : item.text}
))} diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/TodoWriteTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/TodoWriteTool.tsx index 988b86fefc..b844de1771 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/TodoWriteTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/TodoWriteTool.tsx @@ -1,16 +1,47 @@ -import { AccordionItem } from '@heroui/react' -import { ListTodo } from 'lucide-react' +import { AccordionItem, Chip, Card, CardBody } from '@heroui/react' +import { ListTodo, CheckCircle, Clock, Circle } from 'lucide-react' import { ToolTitle } from './GenericTools' import type { TodoWriteToolInput as TodoWriteToolInputType, - TodoWriteToolOutput as TodoWriteToolOutputType + TodoWriteToolOutput as TodoWriteToolOutputType, + TodoItem } from './types' +import { AgentToolsType } from './types' + +const getStatusConfig = (status: TodoItem['status']) => { + switch (status) { + case 'completed': + return { + color: 'success' as const, + icon: , + label: '已完成' + } + case 'in_progress': + return { + color: 'primary' as const, + icon: , + label: '进行中' + } + case 'pending': + return { + color: 'default' as const, + icon: , + label: '待处理' + } + default: + return { + color: 'default' as const, + icon: , + label: '待处理' + } + } +} export function TodoWriteTool({ input, output }: { input: TodoWriteToolInputType; output?: TodoWriteToolOutputType }) { return ( }> -
- {input.todos.map((todo, index) => ( -
-
- {todo.status} - {todo.activeForm && {todo.activeForm}} -
-
{todo.content}
-
- ))} +
+ {input.todos.map((todo, index) => { + const statusConfig = getStatusConfig(todo.status) + return ( + + +
+ + {statusConfig.label} + +
+
+ {todo.status === 'completed' ? {todo.content} : todo.content} +
+ {todo.status === 'in_progress' && ( +
{todo.activeForm}
+ )} +
+
+
+
+ ) + })}
{output} diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WebFetchTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WebFetchTool.tsx new file mode 100644 index 0000000000..329be3d373 --- /dev/null +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WebFetchTool.tsx @@ -0,0 +1,17 @@ +import { AccordionItem } from '@heroui/react' +import { Globe } from 'lucide-react' + +import { ToolTitle } from './GenericTools' +import type { WebFetchToolInput, WebFetchToolOutput } from './types' + +export function WebFetchTool({ input, output }: { input: WebFetchToolInput; output?: WebFetchToolOutput }) { + return ( + } label="Web Fetch" params={input.url} />} + subtitle={input.prompt}> + {output} + + ) +} diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WebSearchTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WebSearchTool.tsx index 0aaafcd394..7e9d85c5cc 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WebSearchTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WebSearchTool.tsx @@ -20,10 +20,7 @@ export function WebSearchTool({ input, output }: { input: WebSearchToolInput; ou stats={output ? `${resultCount} ${resultCount === 1 ? 'result' : 'results'}` : undefined} /> }> -
- - {output} -
+ {output} ) } 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 9eae101020..f2605a1cca 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/index.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/index.tsx @@ -16,6 +16,7 @@ import { TodoWriteTool } from './TodoWriteTool' import { AgentToolsType, ToolInput, ToolOutput } from './types' import { WebSearchTool } from './WebSearchTool' import { WriteTool } from './WriteTool' +import { WebFetchTool } from './WebFetchTool' const logger = loggerService.withContext('MessageAgentTools') @@ -29,7 +30,8 @@ export const toolRenderers = { [AgentToolsType.TodoWrite]: TodoWriteTool, [AgentToolsType.WebSearch]: WebSearchTool, [AgentToolsType.Grep]: GrepTool, - [AgentToolsType.Write]: WriteTool + [AgentToolsType.Write]: WriteTool, + [AgentToolsType.WebFetch]: WebFetchTool } as const // 类型守卫函数 @@ -40,18 +42,18 @@ export function isValidAgentToolsType(toolName: unknown): toolName is AgentTools // 统一的渲染函数 function renderToolContent(toolName: AgentToolsType, input: ToolInput, output?: ToolOutput) { const Renderer = toolRenderers[toolName] - if (!Renderer) { - logger.error('Unknown tool type', { toolName }) - return
Unknown tool type: {toolName}
- } return ( div:first-child]:!flex-none [&>div:first-child]:flex [&>div:first-child]:flex-col [&>div:first-child]:text-start' - }}> + 'p-0 [&>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 h-fit max-h-96 scroll-auto' + }} + defaultExpandedKeys={toolName === AgentToolsType.TodoWrite ? [AgentToolsType.TodoWrite] : []}> {/* */} {Renderer({ input: input as any, output: output as any })} diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/types.ts b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/types.ts index 019e8a737b..0e483688a6 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/types.ts +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/types.ts @@ -7,7 +7,8 @@ export enum AgentToolsType { TodoWrite = 'TodoWrite', WebSearch = 'WebSearch', Grep = 'Grep', - Write = 'Write' + Write = 'Write', + WebFetch = 'WebFetch' } // Read 工具的类型定义 @@ -52,7 +53,7 @@ export type GlobToolOutput = string // TodoWrite 工具的类型定义 export interface TodoItem { content: string - status: string + status: 'completed' | 'in_progress' | 'pending' activeForm?: string } @@ -66,9 +67,15 @@ export type TodoWriteToolOutput = string export interface WebSearchToolInput { query: string } - export type WebSearchToolOutput = string +// WebFetch 工具的类型定义 +export type WebFetchToolInput = { + prompt: string + url: string +} +export type WebFetchToolOutput = string + // Grep 工具的类型定义 export interface GrepToolInput { pattern: string @@ -93,6 +100,7 @@ export type ToolInput = | GlobToolInput | TodoWriteToolInput | WebSearchToolInput + | WebFetchToolInput | GrepToolInput | WriteToolInput export type ToolOutput = @@ -104,6 +112,7 @@ export type ToolOutput = | TodoWriteToolOutput | WebSearchToolOutput | GrepToolOutput + | WebFetchToolOutput | WriteToolOutput // 工具渲染器接口 export interface ToolRenderer { diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageTool.tsx index 07b97976c3..77f61e1442 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageTool.tsx @@ -34,6 +34,7 @@ const ChooseTool = (toolResponse: NormalToolResponse): React.ReactNode | null => case 'WebSearch': case 'Grep': case 'Write': + case 'WebFetch': return default: return null