import React, { useState } from 'react'; import { Terminal, CheckCircle, AlertTriangle, CircleDashed, Code, Clock, ArrowRight, TerminalIcon, } from 'lucide-react'; import { ToolViewProps } from '../types'; import { formatTimestamp, getToolTitle } from '../utils'; import { cn } from '@/lib/utils'; import { useTheme } from 'next-themes'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { ScrollArea } from "@/components/ui/scroll-area"; import { LoadingState } from '../shared/LoadingState'; import { extractCommandData } from './_utils'; export function CommandToolView({ name = 'execute-command', assistantContent, toolContent, assistantTimestamp, toolTimestamp, isSuccess = true, isStreaming = false, }: ToolViewProps) { const { resolvedTheme } = useTheme(); const isDarkTheme = resolvedTheme === 'dark'; const [showFullOutput, setShowFullOutput] = useState(true); const { command, output, exitCode, sessionName, cwd, completed, actualIsSuccess, actualToolTimestamp, actualAssistantTimestamp } = extractCommandData( assistantContent, toolContent, isSuccess, toolTimestamp, assistantTimestamp ); const displayText = name === 'check-command-output' ? sessionName : command; const displayLabel = name === 'check-command-output' ? 'Session' : 'Command'; const displayPrefix = name === 'check-command-output' ? 'tmux:' : '$'; const toolTitle = getToolTitle(name); const formattedOutput = React.useMemo(() => { if (!output) return []; let processedOutput = output; try { if (typeof output === 'string' && (output.trim().startsWith('{') || output.trim().startsWith('{'))) { const parsed = JSON.parse(output); if (parsed && typeof parsed === 'object' && parsed.output) { processedOutput = parsed.output; } } } catch (e) { } processedOutput = String(processedOutput); processedOutput = processedOutput.replace(/\\\\/g, '\\'); processedOutput = processedOutput .replace(/\\n/g, '\n') .replace(/\\t/g, '\t') .replace(/\\"/g, '"') .replace(/\\'/g, "'"); processedOutput = processedOutput.replace(/\\u([0-9a-fA-F]{4})/g, (_match, group) => { return String.fromCharCode(parseInt(group, 16)); }); return processedOutput.split('\n'); }, [output]); const hasMoreLines = formattedOutput.length > 10; const previewLines = formattedOutput.slice(0, 10); const linesToShow = showFullOutput ? formattedOutput : previewLines; return (
{toolTitle}
{!isStreaming && ( {actualIsSuccess ? ( ) : ( )} {actualIsSuccess ? (name === 'check-command-output' ? 'Output retrieved successfully' : 'Command executed successfully') : (name === 'check-command-output' ? 'Failed to retrieve output' : 'Command failed') } )}
{isStreaming ? ( ) : displayText ? (
{output && (
Terminal output
{exitCode !== null && exitCode !== 0 && ( Error )}
                        {linesToShow.map((line, index) => (
                          
{line || ' '}
))} {!showFullOutput && hasMoreLines && (
+ {formattedOutput.length - 10} more lines
)}
)} {!output && !isStreaming && (

No output received

)}
) : (

{name === 'check-command-output' ? 'No Session Found' : 'No Command Found'}

{name === 'check-command-output' ? 'No session name was detected. Please provide a valid session name to check.' : 'No command was detected. Please provide a valid command to execute.' }

)}
{!isStreaming && displayText && ( {displayLabel} )}
{actualToolTimestamp && !isStreaming ? formatTimestamp(actualToolTimestamp) : actualAssistantTimestamp ? formatTimestamp(actualAssistantTimestamp) : ''}
); }