diff --git a/frontendbasejump/src/components/tools/tool-components.tsx b/frontendbasejump/src/components/tools/tool-components.tsx index 9f35f4c6..d1933281 100644 --- a/frontendbasejump/src/components/tools/tool-components.tsx +++ b/frontendbasejump/src/components/tools/tool-components.tsx @@ -1,54 +1,31 @@ 'use client'; import React from 'react'; -import { ParsedTag, ToolComponentProps, ToolDisplayMode, ToolStatusLabels } from '@/lib/types/tool-calls'; +import { ParsedTag, ToolComponentProps } from '@/lib/types/tool-calls'; import { File, FileText, Terminal, FolderPlus, Folder, Code, Search as SearchIcon, - Bell, Replace, ChevronDown, ChevronRight, Plus, Minus + Bell, Replace, Plus, Minus } from 'lucide-react'; import { cn } from '@/lib/utils'; import { diffLines } from 'diff'; -import { useTheme } from 'next-themes'; -interface BaseToolProps { - tag: ParsedTag; - mode: ToolDisplayMode; - title: string; - children: React.ReactNode; - icon?: React.ReactNode; -} - -/** - * Base Tool Component - */ -export const BaseTool: React.FC = ({ tag, mode, title, children, icon }) => { - // Determine if we should use dark mode based on the display mode - const isDark = mode === 'detailed'; - const isRunning = tag.status === 'running'; - +// Shared compact mode component +const CompactToolDisplay: React.FC<{ + icon: React.ReactNode, + name: string, + input: string, + isRunning?: boolean +}> = ({ icon, name, input, isRunning }) => { return ( -
-
- {icon} -
{title}
- {isRunning && ( -
- Running -
-
- )} -
-
- {children} -
+
+ {icon} + {name}: {input} + {isRunning && ( +
+ Running +
+
+ )}
); }; @@ -59,56 +36,89 @@ export const BaseTool: React.FC = ({ tag, mode, title, children, export const CreateFileTool: React.FC = ({ tag, mode }) => { const filePath = tag.attributes.file_path || ''; const fileContent = tag.content || ''; + const isRunning = tag.status === 'running'; + if (mode === 'compact') { + return ( + } + name={isRunning ? "Creating file" : "Created file"} + input={filePath} + isRunning={isRunning} + /> + ); + } + return ( - } - > -
-
- - {filePath} -
-
-          {fileContent}
-        
+
+
+ +
{isRunning ? "Creating file" : "Created file"}: {filePath}
+ {isRunning && ( +
+ Running +
+
+ )}
- +
+
+
+ + {filePath} +
+
+            {fileContent}
+          
+
+
+
); }; /** * Full File Rewrite Tool Component */ - export const FullFileRewriteTool: React.FC = ({ tag, mode }) => { const filePath = tag.attributes.file_path || ''; const fileContent = tag.content || ''; + const isRunning = tag.status === 'running'; - return ( - } - > -
-
- - {filePath} -
-
-          {fileContent}
-        
-
-
- ); -}; + if (mode === 'compact') { + return ( + } + name={isRunning ? "Rewriting file" : "Rewrote file"} + input={filePath} + isRunning={isRunning} + /> + ); + } -/** + return ( +
+
+ +
{isRunning ? "Rewriting file" : "Rewrote file"}: {filePath}
+ {isRunning && ( +
+ Running +
+
+ )} +
+
+
+
+ + {filePath} +
+
+            {fileContent}
+          
+
+
+
); }; @@ -118,24 +128,43 @@ export const FullFileRewriteTool: React.FC = ({ tag, mode }) export const ReadFileTool: React.FC = ({ tag, mode }) => { const filePath = tag.attributes.file_path || ''; const fileContent = tag.content || ''; + const isRunning = tag.status === 'running'; + if (mode === 'compact') { + return ( + } + name={isRunning ? "Reading file" : "Read file"} + input={filePath} + isRunning={isRunning} + /> + ); + } + return ( - } - > -
-
- - {filePath} -
-
-          {fileContent}
-        
+
+
+ +
{isRunning ? "Reading file" : "Read file"}: {filePath}
+ {isRunning && ( +
+ Running +
+
+ )}
- +
+
+
+ + {filePath} +
+
+            {fileContent}
+          
+
+
+
); }; @@ -143,60 +172,77 @@ export const ReadFileTool: React.FC = ({ tag, mode }) => { * Execute Command Tool Component */ export const ExecuteCommandTool: React.FC = ({ tag, mode }) => { - const command = tag.attributes.command || ''; const output = tag.content || ''; - const resultOutput = tag.resultTag?.content || ''; - - // Only show paired view if explicitly paired - const showPairedView = tag.isPaired && tag.resultTag?.content; - - // Check status + const command = tag.resultTag?.content || ''; const isRunning = tag.status === 'running'; - + + if (mode === 'compact') { + return ( + } + name={isRunning ? "Executing" : "Executed"} + input={tag.content} // in compact mode, the command is in the content + isRunning={isRunning} + /> + ); + } + return ( - } - > -
-
- $ - {command} -
- - {showPairedView ? ( -
- {output && ( -
-
Command Output
-
-
{output}
-
-
- )} -
-
Result
-
-
{resultOutput}
-
-
-
- ) : ( -
-
{output}
+
+
+ +
{isRunning ? `Executing: ${command}` : `Executed: ${command}`}
+ {isRunning && ( +
+ Running +
)}
- +
+
+
+
+
+
+
Terminal
+
+ +
+
+ user@localhost + : + ~ + $ + {command} +
+ + {output && ( +
{output}
+ )} + + {!isRunning && ( +
+ user@localhost + : + ~ + $ + +
+ )} +
+
+
+
); }; + /** * String Replace Tool Component */ export const StringReplaceTool: React.FC = ({ tag, mode }) => { const content = tag.content || ''; + const isRunning = tag.status === 'running'; // Parse the old and new strings from the content const oldStrMatch = content.match(/([\s\S]*?)<\/old_str>/); @@ -213,37 +259,55 @@ export const StringReplaceTool: React.FC = ({ tag, mode }) = removed?: boolean; value: string; } + + if (mode === 'compact') { + return ( + } + name={isRunning ? "Updating file" : "Updated file"} + input="" + isRunning={isRunning} + /> + ); + } return ( - } - > -
-
- {diff.map((part: DiffPart, index: number) => ( -
- - {part.added ? : - part.removed ? : - } - -
{part.value}
-
- ))} +
+
+ +
{isRunning ? "Updating file" : "Updated file"}
+ {isRunning && ( +
+ Running +
+
+ )} +
+
+
+
+ {diff.map((part: DiffPart, index: number) => ( +
+ + {part.added ? : + part.removed ? : + } + +
{part.value}
+
+ ))} +
- +
); }; @@ -253,24 +317,43 @@ export const StringReplaceTool: React.FC = ({ tag, mode }) = export const NotifyTool: React.FC = ({ tag, mode }) => { const message = tag.attributes.message || ''; const type = tag.attributes.type || 'info'; + const isRunning = tag.status === 'running'; + if (mode === 'compact') { + return ( + } + name={isRunning ? "Sending notification" : "Sent notification"} + input={message.substring(0, 30) + (message.length > 30 ? '...' : '')} + isRunning={isRunning} + /> + ); + } + return ( - 30 ? '...' : ''}`} - icon={} - > -
- {message} +
+
+ +
{isRunning ? "Sending notification" : "Sent notification"}: {message.substring(0, 30)}{message.length > 30 ? '...' : ''}
+ {isRunning && ( +
+ Running +
+
+ )}
- +
+
+ {message} +
+
+
); }; @@ -281,26 +364,51 @@ export const DirectoryTool: React.FC = ({ tag, mode }) => { const path = tag.attributes.path || ''; const content = tag.content || ''; const isListDirectory = tag.tagName === 'list-directory'; + const isRunning = tag.status === 'running'; + if (mode === 'compact') { + return ( + : } + name={isListDirectory ? + (isRunning ? "Listing directory" : "Listed directory") : + (isRunning ? "Creating directory" : "Created directory")} + input={path} + isRunning={isRunning} + /> + ); + } + return ( - : } - > -
-
- - {path} +
+
+ {isListDirectory ? : } +
+ {isListDirectory ? + (isRunning ? `Listing directory: ${path}` : `Listed directory: ${path}`) : + (isRunning ? `Creating directory: ${path}` : `Created directory: ${path}`)}
- {isListDirectory && content && ( -
-            {content}
-          
+ {isRunning && ( +
+ Running +
+
)}
- +
+
+
+ + {path} +
+ {isListDirectory && content && ( +
+              {content}
+            
+ )} +
+
+
); }; @@ -310,24 +418,43 @@ export const DirectoryTool: React.FC = ({ tag, mode }) => { export const SearchCodeTool: React.FC = ({ tag, mode }) => { const query = tag.attributes.query || ''; const content = tag.content || ''; + const isRunning = tag.status === 'running'; + if (mode === 'compact') { + return ( + } + name={isRunning ? "Searching code" : "Searched code"} + input={query} + isRunning={isRunning} + /> + ); + } + return ( - } - > -
-
- - {query} -
-
-          {content}
-        
+
+
+ +
{isRunning ? "Searching code" : "Searched code"}: {query}
+ {isRunning && ( +
+ Running +
+
+ )}
- +
+
+
+ + {query} +
+
+            {content}
+          
+
+
+
); }; @@ -355,15 +482,35 @@ export function getComponentForTag(tag: ParsedTag): React.FC // Fallback component for unknown tag types (({tag, mode}) => { console.log(`Rendering fallback component for tag: ${tag.tagName}`, tag); + const isRunning = tag.status === 'running'; + + if (mode === 'compact') { + return ( + } + name={isRunning ? `${tag.tagName} operation running` : `${tag.tagName} operation complete`} + input="" + isRunning={isRunning} + /> + ); + } + return ( - } - > -
{tag.content || ''}
-
+
+
+ +
{isRunning ? `${tag.tagName} operation running` : `${tag.tagName} operation complete`}
+ {isRunning && ( +
+ Running +
+
+ )} +
+
+
{tag.content || ''}
+
+
); }); -} \ No newline at end of file +} \ No newline at end of file