import { ReactNode } from "react"; import { XCircle, CheckCircle, Sparkles, RotateCcw } from "lucide-react"; import { Button } from "../DesignSystem/Button"; import { Link } from "@tanstack/react-router"; import { useOllamaHelp } from "../../features/Terminal/useOllamaHelp"; import { useAppSelector } from "../../app/hooks"; import { ExecutionResult } from "./commandUtils"; import { CommandBlock } from "./CommandBlock"; interface CommandWithAIProps { command: string; title: string; icon?: ReactNode; borderColor?: string; headerButtons?: ReactNode; statusBar?: ReactNode; className?: string; copied: boolean; onCopy?: () => void; result?: ExecutionResult | null; onDismissResult?: () => void; cwd?: string; } export function CommandWithAI({ command, title, icon, borderColor, headerButtons, statusBar, className = "", copied, onCopy, result, onDismissResult, cwd = "", }: CommandWithAIProps) { const { getSuggestion, suggestion, isLoading: isGettingSuggestion, error: suggestionError, clearSuggestion, lastPrompt, } = useOllamaHelp(); const ollamaEnabled = useAppSelector((s) => s.settings.ollama.enabled); const handleAskForHelp = async () => { if (!result || result.exitCode === 0) return; await getSuggestion(command, result.output, result.exitCode, cwd); }; const handleRetryAiHelp = async () => { if (!result || result.exitCode === 0) return; clearSuggestion(); await getSuggestion(command, result.output, result.exitCode, cwd); }; // Determine border color based on result // Format duration for display const formatDuration = (ms: number): string => { if (ms < 1000) { return `${Math.round(ms)}ms`; } else if (ms < 60000) { return `${(ms / 1000).toFixed(1)}s`; } else { const minutes = Math.floor(ms / 60000); const seconds = ((ms % 60000) / 1000).toFixed(1); return `${minutes}m ${seconds}s`; } }; let computedBorderColor = borderColor; if (result) { computedBorderColor = result.exitCode !== -1 ? result.exitCode === 0 ? "border-ctp-green" : "border-ctp-red" : "border-ctp-surface0"; } // Enhanced status bar with result info let enhancedStatusBar = statusBar; // -1 => command still running if (result && result.exitCode !== -1) { const resultStatusBar = (
{result.exitCode === 0 ? ( ) : ( )} Exit: {result.exitCode} at {result.timestamp.toLocaleTimeString()} • took{" "} {formatDuration(result.duration)}
{/* Show Ask for Help button only when Ollama help is enabled, for failed commands, and when no suggestion exists and no suggestion error */} {ollamaEnabled && result.exitCode !== 0 && !suggestion && !suggestionError && ( )} {onDismissResult && ( )}
); enhancedStatusBar = statusBar || resultStatusBar; } return ( <> {/* AI Suggestion */} {suggestion && (
{/* AI icon */}

{suggestion.model}

{/* Show the prompt that was sent to AI as a learning tool */} {lastPrompt && (
View prompt sent to Ollama
                        {lastPrompt.trim()}
                      
)}
{suggestion.suggestion}
Generated at {suggestion.timestamp.toLocaleTimeString()} {suggestion.generationTime && ( • took {formatDuration(suggestion.generationTime)} )}
)} {/* AI Error */} {suggestionError && (

⚠️ AI Assistant Unavailable

{suggestionError.includes("404") ? ( <> The AI model isn't available. You can download it by running{" "} ollama pull qwen3:8b . Check out the{" "} Ollama tutorial {" "} for more information. ) : ( <> Looks like we weren't able to call Ollama. Please make sure Ollama is running. If you haven't already, visit the{" "} Ollama tutorial {" "} for help with installation and setup. )}
)} ); }