diff --git a/src/web/chat/components/ToolRendering/ToolCollapse.tsx b/src/web/chat/components/ToolRendering/ToolCollapse.tsx new file mode 100644 index 00000000..1a57c37f --- /dev/null +++ b/src/web/chat/components/ToolRendering/ToolCollapse.tsx @@ -0,0 +1,42 @@ +import React, { useState } from 'react'; +import { CornerDownRight } from 'lucide-react'; +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/web/chat/components/ui/collapsible'; + +interface ToolCollapseProps { + summaryText: string; + defaultExpanded?: boolean; + children: React.ReactNode; + ariaLabel?: string; +} + +export function ToolCollapse({ + summaryText, + defaultExpanded = false, + children, + ariaLabel +}: ToolCollapseProps) { + const [isExpanded, setIsExpanded] = useState(defaultExpanded); + + return ( +
+ + +
+ + {summaryText} +
+
+ + + {children} + +
+
+ ); +} \ No newline at end of file diff --git a/src/web/chat/components/ToolRendering/tools/BashTool.tsx b/src/web/chat/components/ToolRendering/tools/BashTool.tsx index 260fca4d..8b1a4032 100644 --- a/src/web/chat/components/ToolRendering/tools/BashTool.tsx +++ b/src/web/chat/components/ToolRendering/tools/BashTool.tsx @@ -1,5 +1,6 @@ import React from 'react'; import { CodeHighlight } from '../../CodeHighlight'; +import { ToolCollapse } from '../ToolCollapse'; interface BashToolProps { input: any; @@ -9,13 +10,17 @@ interface BashToolProps { export function BashTool({ input, result }: BashToolProps) { return ( -
+ -
+ ); } \ No newline at end of file diff --git a/src/web/chat/components/ToolRendering/tools/EditTool.tsx b/src/web/chat/components/ToolRendering/tools/EditTool.tsx index 9c180c79..0ee5ceeb 100644 --- a/src/web/chat/components/ToolRendering/tools/EditTool.tsx +++ b/src/web/chat/components/ToolRendering/tools/EditTool.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { detectLanguageFromPath } from '../../../utils/language-detection'; import { CodeHighlight } from '../../CodeHighlight'; import { DiffViewer } from './DiffViewer'; +import { ToolCollapse } from '../ToolCollapse'; interface EditToolProps { input: any; @@ -14,54 +15,60 @@ export function EditTool({ input, result, isMultiEdit = false, workingDirectory // 从文件路径检测语言 const filePath = input?.file_path || ''; const language = detectLanguageFromPath(filePath); - // For MultiEdit, process all edits - if (isMultiEdit && input.edits && Array.isArray(input.edits)) { - return ( -
- {input.edits.map((edit: any, index: number) => ( -
- - {index < input.edits.length - 1 && ( -
- )} -
- ))} -
- ); - } + + const renderContent = () => { + // For MultiEdit, process all edits + if (isMultiEdit && input.edits && Array.isArray(input.edits)) { + return ( +
+ {input.edits.map((edit: any, index: number) => ( +
+ + {index < input.edits.length - 1 && ( +
+ )} +
+ ))} +
+ ); + } - // For regular Edit, process single edit - if (input.old_string !== undefined && input.new_string !== undefined) { - return ( -
+ // For regular Edit, process single edit + if (input.old_string !== undefined && input.new_string !== undefined) { + return ( + ); + } + + // Fallback if we can't parse the edit + return result ? ( + + ) : ( +
+
Edit completed successfully
); - } + }; - // Fallback if we can't parse the edit - return ( -
- {result ? ( - - ) : ( -
-
Edit completed successfully
-
- )} -
+ + {renderContent()} + ); } \ No newline at end of file diff --git a/src/web/chat/components/ToolRendering/tools/FallbackTool.tsx b/src/web/chat/components/ToolRendering/tools/FallbackTool.tsx index 65e61450..34ed5613 100644 --- a/src/web/chat/components/ToolRendering/tools/FallbackTool.tsx +++ b/src/web/chat/components/ToolRendering/tools/FallbackTool.tsx @@ -1,6 +1,5 @@ -import React, { useState } from 'react'; -import { CornerDownRight } from 'lucide-react'; -import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/web/chat/components/ui/collapsible'; +import React from 'react'; +import { ToolCollapse } from '../ToolCollapse'; interface FallbackToolProps { toolName: string; @@ -9,8 +8,6 @@ interface FallbackToolProps { } export function FallbackTool({ toolName, input, result }: FallbackToolProps) { - const [isExpanded, setIsExpanded] = useState(false); - const formatContent = (content: string): string => { try { // Try to parse and format as JSON if possible @@ -23,41 +20,30 @@ export function FallbackTool({ toolName, input, result }: FallbackToolProps) { }; return ( -
- - -
- - {toolName} completed + +
+ {result && ( +
+
+              {formatContent(result || 'No result')}
+            
- + )} - - {result && ( -
-
-                {formatContent(result || 'No result')}
-              
-
- )} - - {/* Always show input in expanded state for debugging */} - {input && ( -
- Input: -
-                {JSON.stringify(input, null, 2)}
-              
-
- )} -
- -
+ {/* Always show input in expanded state for debugging */} + {input && ( +
+ Input: +
+              {JSON.stringify(input, null, 2)}
+            
+
+ )} +
+ ); } \ No newline at end of file diff --git a/src/web/chat/components/ToolRendering/tools/PlanTool.tsx b/src/web/chat/components/ToolRendering/tools/PlanTool.tsx index 8b50ab45..6088649e 100644 --- a/src/web/chat/components/ToolRendering/tools/PlanTool.tsx +++ b/src/web/chat/components/ToolRendering/tools/PlanTool.tsx @@ -1,5 +1,6 @@ import React from 'react'; import ReactMarkdown from 'react-markdown'; +import { ToolCollapse } from '../ToolCollapse'; interface PlanToolProps { input: any; @@ -11,7 +12,11 @@ export function PlanTool({ input, result }: PlanToolProps) { const planContent = input.plan || result || 'No plan provided'; return ( -
+
-
+ ); } \ No newline at end of file diff --git a/src/web/chat/components/ToolRendering/tools/ReadTool.tsx b/src/web/chat/components/ToolRendering/tools/ReadTool.tsx index 243e6380..bf15f58f 100644 --- a/src/web/chat/components/ToolRendering/tools/ReadTool.tsx +++ b/src/web/chat/components/ToolRendering/tools/ReadTool.tsx @@ -1,9 +1,8 @@ -import React, { useState } from 'react'; -import { CornerDownRight } from 'lucide-react'; +import React from 'react'; import { countLines } from '../../../utils/tool-utils'; import { detectLanguageFromPath } from '../../../utils/language-detection'; import { CodeHighlight } from '../../CodeHighlight'; -import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/web/chat/components/ui/collapsible'; +import { ToolCollapse } from '../ToolCollapse'; interface ReadToolProps { input: any; @@ -27,35 +26,25 @@ export function ReadTool({ input, result, workingDirectory }: ReadToolProps) { return
; } - const [isExpanded, setIsExpanded] = useState(false); - const cleanedContent = cleanFileContent(result); const lineCount = countLines(cleanedContent); const filePath = input?.file_path || ''; const language = detectLanguageFromPath(filePath); return ( -
- - - - Read {lineCount} line{lineCount !== 1 ? 's' : ''} - - - - {cleanedContent && ( - - )} - - -
+ + {cleanedContent && ( + + )} + ); } \ No newline at end of file diff --git a/src/web/chat/components/ToolRendering/tools/SearchTool.tsx b/src/web/chat/components/ToolRendering/tools/SearchTool.tsx index 2bebb205..5dff5fde 100644 --- a/src/web/chat/components/ToolRendering/tools/SearchTool.tsx +++ b/src/web/chat/components/ToolRendering/tools/SearchTool.tsx @@ -1,7 +1,6 @@ -import React, { useState } from 'react'; -import { CornerDownRight } from 'lucide-react'; +import React from 'react'; import { countLines, extractFileCount } from '../../../utils/tool-utils'; -import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/web/chat/components/ui/collapsible'; +import { ToolCollapse } from '../ToolCollapse'; interface SearchToolProps { input: any; @@ -10,8 +9,6 @@ interface SearchToolProps { } export function SearchTool({ input, result, toolType }: SearchToolProps) { - const [isExpanded, setIsExpanded] = useState(false); - const getSummaryText = (): string => { switch (toolType) { case 'Grep': @@ -32,29 +29,16 @@ export function SearchTool({ input, result, toolType }: SearchToolProps) { }; return ( -
- - -
- - {getSummaryText()} -
-
- - - {result && ( -
-
{result}
-
- )} -
-
-
+ + {result && ( +
+
{result}
+
+ )} +
); } \ No newline at end of file diff --git a/src/web/chat/components/ToolRendering/tools/WebTool.tsx b/src/web/chat/components/ToolRendering/tools/WebTool.tsx index 78fa63de..4890baf6 100644 --- a/src/web/chat/components/ToolRendering/tools/WebTool.tsx +++ b/src/web/chat/components/ToolRendering/tools/WebTool.tsx @@ -1,7 +1,7 @@ -import React, { useState } from 'react'; -import { CornerDownRight, Globe } from 'lucide-react'; +import React from 'react'; +import { Globe } from 'lucide-react'; import { extractDomain } from '../../../utils/tool-utils'; -import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/web/chat/components/ui/collapsible'; +import { ToolCollapse } from '../ToolCollapse'; interface WebToolProps { input: any; @@ -10,8 +10,6 @@ interface WebToolProps { } export function WebTool({ input, result, toolType }: WebToolProps) { - const [isExpanded, setIsExpanded] = useState(false); - const getSummaryText = (): string => { if (toolType === 'WebSearch') { // Could potentially extract timing information from result if available @@ -52,30 +50,18 @@ export function WebTool({ input, result, toolType }: WebToolProps) { return (
- - -
- - {getSummaryText()} + + {result && ( +
+
{result}
- - - {getDomainPills()} - - - {result && ( -
-
{result}
-
- )} -
- + )} +
+ {getDomainPills()}
); } \ No newline at end of file diff --git a/src/web/chat/components/ToolRendering/tools/WriteTool.tsx b/src/web/chat/components/ToolRendering/tools/WriteTool.tsx index b02b14c8..c0887333 100644 --- a/src/web/chat/components/ToolRendering/tools/WriteTool.tsx +++ b/src/web/chat/components/ToolRendering/tools/WriteTool.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { detectLanguageFromPath } from '../../../utils/language-detection'; import { DiffViewer } from './DiffViewer'; +import { ToolCollapse } from '../ToolCollapse'; interface WriteToolProps { input: any; @@ -14,12 +15,16 @@ export function WriteTool({ input, result, workingDirectory }: WriteToolProps) { const language = detectLanguageFromPath(filePath); return ( -
+ -
+ ); } \ No newline at end of file