From cbe4bd9adfb94a00d02b7546bde553e64a344453 Mon Sep 17 00:00:00 2001 From: simosmik Date: Mon, 9 Feb 2026 10:22:36 +0000 Subject: [PATCH] fix: remove one-line logic from messagecomponent --- .../chat/messages/MessageComponent.tsx | 207 ++---------------- src/components/chat/tools/ToolRenderer.tsx | 29 +-- .../tools/components/CollapsibleDisplay.tsx | 114 ++++++---- .../chat/tools/components/OneLineDisplay.tsx | 76 ++++--- 4 files changed, 154 insertions(+), 272 deletions(-) diff --git a/src/components/chat/messages/MessageComponent.tsx b/src/components/chat/messages/MessageComponent.tsx index 4161adf..294fdff 100644 --- a/src/components/chat/messages/MessageComponent.tsx +++ b/src/components/chat/messages/MessageComponent.tsx @@ -145,112 +145,31 @@ const MessageComponent = memo(({ message, index, prevMessage, createDiff, onFile )}
- - {message.isToolUse && !['Read', 'TodoWrite', 'TodoRead'].includes(message.toolName) ? ( - (() => { - // Minimize Grep and Glob tools since they happen frequently - const isSearchTool = ['Grep', 'Glob'].includes(message.toolName); - if (isSearchTool) { - return ( - <> -
-
-
- - - - {message.toolName} - - {message.toolInput && (() => { - try { - const input = JSON.parse(message.toolInput); - return ( - - {input.pattern && {t('search.pattern')} {input.pattern}} - {input.path && {t('search.in')} {input.path}} - - ); - } catch (e) { - return null; - } - })()} -
- {message.toolResult && ( - - {t('tools.searchResults')} - - - - - )} -
-
- - ); - } - - // Full display for other tools - return ( -
- {/* Decorative gradient overlay */} -
- -
-
-
- - - - - {/* Subtle pulse animation */} -
-
-
- - {message.toolName} - - - {message.toolId} - -
+ {message.isToolUse ? ( + <> +
+
+ {message.displayText}
- {onShowSettings && ( - - )}
- {/* All tool input rendering now handled by ToolRenderer */} - {message.toolInput && (() => { - // Use new ToolRenderer for all tools (config-driven) - return ( - - ); - })()} + + {message.toolInput && ( + + )} {/* Tool Result Section */} {message.toolResult && (() => { @@ -714,9 +633,7 @@ const MessageComponent = memo(({ message, index, prevMessage, createDiff, onFile
); })()} -
- ); - })() + ) : message.isInteractivePrompt ? ( // Special handling for interactive prompts
@@ -800,84 +717,6 @@ const MessageComponent = memo(({ message, index, prevMessage, createDiff, onFile
- ) : message.isToolUse && message.toolName === 'Read' ? ( - // Simple Read tool indicator - (() => { - try { - const input = JSON.parse(message.toolInput); - if (input.file_path) { - const filename = input.file_path.split('/').pop(); - return ( -
-
- - - - Read - -
-
- ); - } - } catch (e) { - return ( -
-
- - - - Read file -
-
- ); - } - })() - ) : message.isToolUse && message.toolName === 'TodoWrite' ? ( - // Simple TodoWrite tool indicator with tasks - (() => { - try { - const input = JSON.parse(message.toolInput); - if (input.todos && Array.isArray(input.todos)) { - return ( -
-
- - - - Update todo list -
- -
- ); - } - } catch (e) { - return ( -
-
- - - - Update todo list -
-
- ); - } - })() - ) : message.isToolUse && message.toolName === 'TodoRead' ? ( - // Simple TodoRead tool indicator -
-
- - - - Read todo list -
-
) : message.isThinking ? ( /* Thinking messages - collapsible by default */
diff --git a/src/components/chat/tools/ToolRenderer.tsx b/src/components/chat/tools/ToolRenderer.tsx index 9dfe54e..8d80117 100644 --- a/src/components/chat/tools/ToolRenderer.tsx +++ b/src/components/chat/tools/ToolRenderer.tsx @@ -13,12 +13,12 @@ interface ToolRendererProps { toolName: string; toolInput: any; toolResult?: any; + toolId?: string; mode: 'input' | 'result'; - // Callbacks and helpers onFileOpen?: (filePath: string, diffInfo?: any) => void; createDiff?: (oldStr: string, newStr: string) => DiffLine[]; selectedProject?: Project | null; - // Display options + onShowSettings?: () => void; autoExpandTools?: boolean; showRawParameters?: boolean; rawToolInput?: string; @@ -32,10 +32,12 @@ export const ToolRenderer: React.FC = ({ toolName, toolInput, toolResult, + toolId, mode, onFileOpen, createDiff, selectedProject, + onShowSettings, autoExpandTools = false, showRawParameters = false, rawToolInput @@ -45,7 +47,6 @@ export const ToolRenderer: React.FC = ({ if (!displayConfig) return null; - // Parse tool input/result let parsedData: any; try { const rawData = mode === 'input' ? toolInput : toolResult; @@ -54,9 +55,6 @@ export const ToolRenderer: React.FC = ({ parsedData = mode === 'input' ? toolInput : toolResult; } - // ============================================================================ - // ONE-LINE DISPLAY - // ============================================================================ if (displayConfig.type === 'one-line') { const value = displayConfig.getValue?.(parsedData) || ''; const secondary = displayConfig.getSecondary?.(parsedData); @@ -69,6 +67,9 @@ export const ToolRenderer: React.FC = ({ return ( = ({ action={displayConfig.action} onAction={handleAction} colorScheme={displayConfig.colorScheme} - resultId={mode === 'input' ? `tool-result-${toolName}` : undefined} + resultId={mode === 'input' ? `tool-result-${toolId}` : undefined} /> ); } - // ============================================================================ - // COLLAPSIBLE DISPLAY - // ============================================================================ if (displayConfig.type === 'collapsible') { const title = typeof displayConfig.title === 'function' ? displayConfig.title(parsedData) @@ -93,14 +91,12 @@ export const ToolRenderer: React.FC = ({ ? displayConfig.defaultOpen : autoExpandTools; - // Get content props from config const contentProps = displayConfig.getContentProps?.(parsedData, { selectedProject, createDiff, onFileOpen }) || {}; - // Render content based on contentType let contentComponent = null; switch (displayConfig.contentType) { @@ -169,7 +165,6 @@ export const ToolRenderer: React.FC = ({ ); } - // Action button for file operations let actionButton = null; if (displayConfig.actionButton === 'file-button' && contentProps.filePath) { const handleFileClick = async (e: React.MouseEvent) => { @@ -177,7 +172,6 @@ export const ToolRenderer: React.FC = ({ e.stopPropagation(); if (!onFileOpen) return; - // For Edit/ApplyPatch tools, fetch current file and reverse-apply the edit if (toolName === 'Edit' || toolName === 'ApplyPatch') { try { const { api } = await import('../../../utils/api'); @@ -202,7 +196,6 @@ export const ToolRenderer: React.FC = ({ onFileOpen(contentProps.filePath); } } - // For Write tool, fetch written file else if (toolName === 'Write') { try { const { api } = await import('../../../utils/api'); @@ -235,6 +228,8 @@ export const ToolRenderer: React.FC = ({ return ( = ({ }} showRawParameters={mode === 'input' && showRawParameters} rawContent={rawToolInput} + onShowSettings={onShowSettings} /> ); } - // ============================================================================ - // SPECIAL / HIDDEN - // ============================================================================ return null; }; diff --git a/src/components/chat/tools/components/CollapsibleDisplay.tsx b/src/components/chat/tools/components/CollapsibleDisplay.tsx index b4692e3..a92dffe 100644 --- a/src/components/chat/tools/components/CollapsibleDisplay.tsx +++ b/src/components/chat/tools/components/CollapsibleDisplay.tsx @@ -4,6 +4,8 @@ import { CollapsibleSection } from './CollapsibleSection'; type ContentType = 'diff' | 'markdown' | 'file-list' | 'todo-list' | 'text'; interface CollapsibleDisplayProps { + toolName: string; + toolId?: string; title: string; defaultOpen?: boolean; action?: React.ReactNode; @@ -12,15 +14,12 @@ interface CollapsibleDisplayProps { showRawParameters?: boolean; rawContent?: string; className?: string; + onShowSettings?: () => void; } -/** - * Unified collapsible display for complex tool inputs and results - * Used by: Edit, Write, Plan, TodoWrite, Grep/Glob (results), etc. - * - * Content is rendered by specialized components based on contentType - */ export const CollapsibleDisplay: React.FC = ({ + toolName, + toolId, title, defaultOpen = false, action, @@ -28,65 +27,98 @@ export const CollapsibleDisplay: React.FC = ({ contentProps, showRawParameters = false, rawContent, - className = '' + className = '', + onShowSettings }) => { - // Import content renderers dynamically based on type const renderContent = () => { switch (contentType) { case 'diff': - // DiffViewer already exists - will be imported by ToolRenderer return contentProps.DiffViewer; case 'markdown': - // Markdown component already exists - will be imported by ToolRenderer return contentProps.MarkdownComponent; case 'file-list': - // FileListContent will be created return contentProps.FileListComponent; case 'todo-list': - // TodoListContent will be created return contentProps.TodoListComponent; case 'text': - // TextContent will be created return contentProps.TextComponent; default: return
Unknown content type: {contentType}
; } }; - return ( - - {/* Main content */} - {renderContent()} +
+
- {/* Optional raw parameters viewer */} - {showRawParameters && rawContent && ( -
- - - +
+
+
+ + + - View raw parameters -
-
-            {rawContent}
-          
-
- )} - +
+
+
+ + {toolName} + + {toolId && ( + + {toolId} + + )} +
+
+ {onShowSettings && ( + + )} + + + + {renderContent()} + + {showRawParameters && rawContent && ( +
+ + + + + View raw parameters + +
+              {rawContent}
+            
+
+ )} +
+ ); }; diff --git a/src/components/chat/tools/components/OneLineDisplay.tsx b/src/components/chat/tools/components/OneLineDisplay.tsx index 8db63d4..8aa17e2 100644 --- a/src/components/chat/tools/components/OneLineDisplay.tsx +++ b/src/components/chat/tools/components/OneLineDisplay.tsx @@ -3,6 +3,7 @@ import React, { useState } from 'react'; type ActionType = 'copy' | 'open-file' | 'jump-to-results' | 'none'; interface OneLineDisplayProps { + toolName: string; icon?: string; label?: string; value: string; @@ -14,6 +15,8 @@ interface OneLineDisplayProps { secondary?: string; }; resultId?: string; // For jump-to-results + toolResult?: any; // For showing result link + toolId?: string; } /** @@ -21,6 +24,7 @@ interface OneLineDisplayProps { * Used by: Bash, Read, Grep/Glob (minimized), TodoRead, etc. */ export const OneLineDisplay: React.FC = ({ + toolName, icon, label, value, @@ -31,7 +35,9 @@ export const OneLineDisplay: React.FC = ({ primary: 'text-gray-700 dark:text-gray-300', secondary: 'text-gray-500 dark:text-gray-400' }, - resultId + resultId, + toolResult, + toolId }) => { const [copied, setCopied] = useState(false); @@ -96,39 +102,51 @@ export const OneLineDisplay: React.FC = ({ return null; }; - return ( -
- {/* Icon */} - {icon && ( - - {icon} - - )} +
+
+
+ {icon ? ( + + {icon} + + ) : label ? ( + {label} + ) : ( + {toolName} + )} - {/* Label */} - {label && ( - {label} - )} + - {/* Value - different rendering based on action type */} - {action === 'open-file' ? ( - renderActionButton() - ) : ( - - {value} - - )} + {action === 'open-file' ? ( + renderActionButton() + ) : ( + + {value} + + )} - {/* Secondary text (e.g., description) */} - {secondary && ( - - ({secondary}) - - )} + {secondary && ( + + ({secondary}) + + )} - {/* Action button (copy, jump) */} - {action !== 'open-file' && renderActionButton()} + {action === 'copy' && renderActionButton()} +
+ + {action === 'jump-to-results' && toolResult && ( + + Search results + + + + + )} +
); };