136 lines
3.7 KiB
TypeScript
136 lines
3.7 KiB
TypeScript
import { Container, Spacer, Text } from "@mariozechner/pi-tui";
|
|
import chalk from "chalk";
|
|
|
|
/**
|
|
* Component that renders a tool call with its result (updateable)
|
|
*/
|
|
export class ToolExecutionComponent extends Container {
|
|
private spacer: Spacer;
|
|
private contentText: Text;
|
|
private toolName: string;
|
|
private args: any;
|
|
private result?: { output: string; isError: boolean };
|
|
|
|
constructor(toolName: string, args: any) {
|
|
super();
|
|
this.toolName = toolName;
|
|
this.args = args;
|
|
// Blank line with no background for spacing
|
|
this.spacer = new Spacer(1);
|
|
this.addChild(this.spacer);
|
|
// Content with colored background and padding
|
|
this.contentText = new Text("", 1, 1, { r: 40, g: 40, b: 50 });
|
|
this.addChild(this.contentText);
|
|
this.updateDisplay();
|
|
}
|
|
|
|
updateResult(result: { output: string; isError: boolean }): void {
|
|
this.result = result;
|
|
this.updateDisplay();
|
|
}
|
|
|
|
private updateDisplay(): void {
|
|
const bgColor = this.result
|
|
? this.result.isError
|
|
? { r: 60, g: 40, b: 40 }
|
|
: { r: 40, g: 50, b: 40 }
|
|
: { r: 40, g: 40, b: 50 };
|
|
|
|
this.contentText.setCustomBgRgb(bgColor);
|
|
this.contentText.setText(this.formatToolExecution());
|
|
}
|
|
|
|
private formatToolExecution(): string {
|
|
let text = "";
|
|
|
|
// Format based on tool type
|
|
if (this.toolName === "bash") {
|
|
const command = this.args.command || "";
|
|
text = chalk.bold(`$ ${command}`);
|
|
if (this.result?.isError) {
|
|
text += " ❌";
|
|
}
|
|
|
|
if (this.result) {
|
|
// Show output without code fences - more minimal
|
|
const output = this.result.output.trim();
|
|
if (output) {
|
|
const lines = output.split("\n");
|
|
const maxLines = 5;
|
|
const displayLines = lines.slice(0, maxLines);
|
|
const remaining = lines.length - maxLines;
|
|
|
|
text += "\n\n" + displayLines.map((line: string) => chalk.dim(line)).join("\n");
|
|
if (remaining > 0) {
|
|
text += chalk.dim(`\n... (${remaining} more lines)`);
|
|
}
|
|
}
|
|
}
|
|
} else if (this.toolName === "read") {
|
|
const path = this.args.path || "";
|
|
text = chalk.bold("read") + " " + chalk.cyan(path);
|
|
if (this.result?.isError) {
|
|
text += " ❌";
|
|
}
|
|
|
|
if (this.result) {
|
|
const lines = this.result.output.split("\n");
|
|
const maxLines = 10;
|
|
const displayLines = lines.slice(0, maxLines);
|
|
const remaining = lines.length - maxLines;
|
|
|
|
text += "\n\n" + displayLines.map((line: string) => chalk.dim(line)).join("\n");
|
|
if (remaining > 0) {
|
|
text += chalk.dim(`\n... (${remaining} more lines)`);
|
|
}
|
|
}
|
|
} else if (this.toolName === "write") {
|
|
const path = this.args.path || "";
|
|
const fileContent = this.args.content || "";
|
|
const lines = fileContent.split("\n");
|
|
const totalLines = lines.length;
|
|
|
|
text = chalk.bold("write") + " " + chalk.cyan(path);
|
|
if (totalLines > 10) {
|
|
text += ` (${totalLines} lines)`;
|
|
}
|
|
|
|
if (this.result) {
|
|
text += this.result.isError ? " ❌" : " ✓";
|
|
}
|
|
|
|
// Show first 10 lines of content
|
|
const maxLines = 10;
|
|
const displayLines = lines.slice(0, maxLines);
|
|
const remaining = lines.length - maxLines;
|
|
|
|
text += "\n\n" + displayLines.map((line: string) => chalk.dim(line)).join("\n");
|
|
if (remaining > 0) {
|
|
text += chalk.dim(`\n... (${remaining} more lines)`);
|
|
}
|
|
} else if (this.toolName === "edit") {
|
|
const path = this.args.path || "";
|
|
text = chalk.bold("edit") + " " + chalk.cyan(path);
|
|
if (this.result) {
|
|
text += this.result.isError ? " ❌" : " ✓";
|
|
}
|
|
} else {
|
|
// Generic tool
|
|
text = chalk.bold(this.toolName);
|
|
if (this.result?.isError) {
|
|
text += " ❌";
|
|
} else if (this.result) {
|
|
text += " ✓";
|
|
}
|
|
|
|
const content = JSON.stringify(this.args, null, 2);
|
|
text += "\n\n" + content;
|
|
if (this.result?.output) {
|
|
text += "\n" + this.result.output;
|
|
}
|
|
}
|
|
|
|
return text;
|
|
}
|
|
}
|