import { Box } from "ink"; import { memo } from "react"; import { INTERRUPTED_BY_USER } from "../../constants"; import { clipToolReturn } from "../../tools/manager"; import type { StreamingState } from "../helpers/accumulator"; import { useTerminalWidth } from "../hooks/useTerminalWidth"; import { BlinkDot } from "./BlinkDot.js"; import { CollapsedOutputDisplay } from "./CollapsedOutputDisplay"; import { colors } from "./colors.js"; import { MarkdownDisplay } from "./MarkdownDisplay.js"; import { StreamingOutputDisplay } from "./StreamingOutputDisplay"; import { Text } from "./Text"; type BashCommandLine = { kind: "bash_command"; id: string; input: string; output: string; phase?: "running" | "finished"; success?: boolean; streaming?: StreamingState; }; /** * BashCommandMessage - Renders bash mode command output * Similar to CommandMessage but with red ! indicator instead of dot * * Features: * - Two-column layout with left gutter (2 chars) and right content area * - Red ! indicator (blinking when running) * - Proper terminal width calculation and wrapping * - Markdown rendering for output */ export const BashCommandMessage = memo( ({ line }: { line: BashCommandLine }) => { const columns = useTerminalWidth(); const rightWidth = Math.max(0, columns - 2); // gutter is 2 cols // Determine indicator state based on phase and success const getIndicatorElement = () => { if (!line.phase || line.phase === "finished") { // Show red ! for both success and failure (it's user-run, not agent-run) return !; } if (line.phase === "running") { return ; } return !; }; return ( {/* Command input */} {getIndicatorElement()} {line.input} {/* Streaming output during execution */} {line.phase === "running" && line.streaming && ( )} {/* Full output after completion (no collapse for bash mode) */} {line.phase === "finished" && line.output && (line.output === INTERRUPTED_BY_USER ? ( // Red styling for interrupted commands (LET-7199) {" ⎿ "} {INTERRUPTED_BY_USER} ) : ( ))} {/* Fallback: show output when phase is undefined (legacy bash commands before streaming) */} {!line.phase && line.output && ( {" ⎿ "} )} ); }, ); BashCommandMessage.displayName = "BashCommandMessage";