refactor(coding-agent): Standardized tool output rendering with centralized TUI components

- Output block border color now reflects state (error, success, warning) for visual feedback.
- Tools use renderStatusLine, renderTreeList, renderFileList, renderCodeCell for unified formatting.
- Write tool shows streaming preview of content being written with syntax highlighting.
- Read tool displays resolved path information when reading from URLs or symlinks.
- Calculator shows expression and output (e.g., `2+2 = 4`) instead of just the result.
- Empty and error states render consistently with status headers across Find, Grep, Ls, Notebook, Ask.
This commit is contained in:
can1357
2026-01-23 13:46:06 +01:00
parent 0a1610ce71
commit ab869e7828
20 changed files with 377 additions and 96 deletions
+5 -6
View File
@@ -230,7 +230,7 @@ function renderOutputSection(
maxExpanded = 10,
): string[] {
const lines: string[] = [];
const trimmedOutput = output.trim();
const trimmedOutput = output.trimEnd();
if (!trimmedOutput) return lines;
if (trimmedOutput.startsWith("{") || trimmedOutput.startsWith("[")) {
@@ -262,7 +262,7 @@ function renderOutputSection(
lines.push(`${continuePrefix}${theme.fg("dim", "Output")}`);
const outputLines = output.split("\n").filter((line) => line.trim());
const outputLines = output.trimEnd().split("\n");
const previewCount = expanded ? maxExpanded : maxCollapsed;
for (const line of outputLines.slice(0, previewCount)) {
lines.push(`${continuePrefix} ${theme.fg("dim", truncate(line, 70, theme.format.ellipsis))}`);
@@ -730,13 +730,12 @@ function renderAgentResult(result: SingleResult, isLast: boolean, expanded: bool
if (handler?.renderFinal && (dataArray as unknown[]).length > 0) {
hasCustomRendering = true;
const component = handler.renderFinal(dataArray as unknown[], theme, expanded);
lines.push(`${continuePrefix}${theme.fg("dim", `Tool: ${toolName}`)}`);
if (component instanceof Text) {
// Prefix each line with continuePrefix
const text = component.getText();
for (const line of text.split("\n")) {
if (line.trim()) {
lines.push(`${continuePrefix}${line}`);
}
lines.push(`${continuePrefix}${line}`);
}
} else if (component instanceof Container) {
// For containers, render each child
@@ -841,7 +840,7 @@ export function renderResult(
}
}
const indented = lines.map((line) => (line.trim() ? ` ${line}` : ""));
const indented = lines.map((line) => (line.length > 0 ? ` ${line}` : ""));
return new Text(indented.join("\n"), 0, 0);
}