import { parseApplyPatch } from "../../parse-apply-patch"; import { shortenPath } from "../../utils/short-path"; import chalk from "chalk"; import { Text } from "ink"; import React from "react"; export function TerminalChatToolCallCommand({ commandForDisplay, explanation, }: { commandForDisplay: string; explanation?: string; }): React.ReactElement { // ------------------------------------------------------------------------- // Colorize diff output inside the command preview: we detect individual // lines that begin with '+' or '-' (excluding the typical diff headers like // '+++', '---', '++', '--') and apply green/red coloring. This mirrors // how Git shows diffs and makes the patch easier to review. // ------------------------------------------------------------------------- const colorizedCommand = commandForDisplay .split("\n") .map((line) => { if (line.startsWith("+") && !line.startsWith("++")) { return chalk.green(line); } if (line.startsWith("-") && !line.startsWith("--")) { return chalk.red(line); } return line; }) .join("\n"); return ( <> Shell Command $ {colorizedCommand} {explanation && ( <> Explanation {explanation.split("\n").map((line, i) => { // Apply different styling to headings (numbered items) if (line.match(/^\d+\.\s+/)) { return ( {line} ); } else if (line.match(/^\s*\*\s+/)) { // Style bullet points return ( {line} ); } else if (line.match(/^(WARNING|CAUTION|NOTE):/i)) { // Style warnings return ( {line} ); } else { return {line}; } })} )} ); } export function TerminalChatToolCallApplyPatch({ commandForDisplay, patch, }: { commandForDisplay: string; patch: string; }): React.ReactElement { const ops = React.useMemo(() => parseApplyPatch(patch), [patch]); const firstOp = ops?.[0]; const title = React.useMemo(() => { if (!firstOp) { return ""; } return capitalize(firstOp.type); }, [firstOp]); const filePath = React.useMemo(() => { if (!firstOp) { return ""; } return shortenPath(firstOp.path || "."); }, [firstOp]); if (ops == null) { return ( <> Invalid Patch The provided patch command is invalid. {commandForDisplay} ); } if (!firstOp) { return ( <> Empty Patch No operations found in the patch command. {commandForDisplay} ); } return ( <> {title} {filePath} $ {commandForDisplay} ); } const capitalize = (s: string) => s.charAt(0).toUpperCase() + s.slice(1);