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);