From 685736667eead5df868328b56155b1bcc0c9ef57 Mon Sep 17 00:00:00 2001 From: can1357 Date: Fri, 6 Feb 2026 07:10:33 +0100 Subject: [PATCH] fix(coding-agent): fixed tab character rendering causing UI holes by converting tabs to spaces - Fixed tab character rendering in tool output previews and code cell displays by converting tabs to spaces for consistent terminal display. - Applied replaceTabs() function across patch rendering, write tool output, and code cell output to ensure uniform tab handling. --- packages/coding-agent/CHANGELOG.md | 2 ++ packages/coding-agent/src/patch/shared.ts | 5 +++-- packages/coding-agent/src/tools/write.ts | 5 +++-- packages/coding-agent/src/tui/code-cell.ts | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 5eeb27f7c..341ed41b5 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -1,8 +1,10 @@ # Changelog ## [Unreleased] + ### Fixed +- Fixed tab character rendering in tool output previews and code cell displays, ensuring tabs are properly converted to spaces for consistent terminal display - Fixed `newSession()` to properly await session manager operations, ensuring new session is fully initialized before returning - Fixed session formatting to use XML structure for tools and tool invocations instead of YAML, improving compatibility with structured output parsing diff --git a/packages/coding-agent/src/patch/shared.ts b/packages/coding-agent/src/patch/shared.ts index f2a14d185..cd206d318 100644 --- a/packages/coding-agent/src/patch/shared.ts +++ b/packages/coding-agent/src/patch/shared.ts @@ -14,6 +14,7 @@ import { formatStatusIcon, getDiffStats, PREVIEW_LIMITS, + replaceTabs, shortenPath, ToolUIKit, truncateDiffByHunk, @@ -181,7 +182,7 @@ export const editToolRenderer = { const maxLines = 6; text += "\n\n"; for (const line of previewLines.slice(0, maxLines)) { - text += `${uiTheme.fg("toolOutput", ui.truncate(line, 80))}\n`; + text += `${uiTheme.fg("toolOutput", ui.truncate(replaceTabs(line), 80))}\n`; } if (previewLines.length > maxLines) { text += uiTheme.fg("dim", `… ${previewLines.length - maxLines} more lines`); @@ -191,7 +192,7 @@ export const editToolRenderer = { const maxLines = 6; text += "\n\n"; for (const line of previewLines.slice(0, maxLines)) { - text += `${uiTheme.fg("toolOutput", ui.truncate(line, 80))}\n`; + text += `${uiTheme.fg("toolOutput", ui.truncate(replaceTabs(line), 80))}\n`; } if (previewLines.length > maxLines) { text += uiTheme.fg("dim", `… ${previewLines.length - maxLines} more lines`); diff --git a/packages/coding-agent/src/tools/write.ts b/packages/coding-agent/src/tools/write.ts index 19d338eb3..4259a2cfb 100644 --- a/packages/coding-agent/src/tools/write.ts +++ b/packages/coding-agent/src/tools/write.ts @@ -23,6 +23,7 @@ import { formatExpandHint, formatMoreItems, formatStatusIcon, + replaceTabs, shortenPath, ToolUIKit, } from "./render-utils"; @@ -160,7 +161,7 @@ function formatStreamingContent(content: string, uiTheme: Theme, ui: ToolUIKit): text += uiTheme.fg("dim", `… (${hidden} earlier lines)\n`); } for (const line of displayLines) { - text += `${uiTheme.fg("toolOutput", ui.truncate(line, 80))}\n`; + text += `${uiTheme.fg("toolOutput", ui.truncate(replaceTabs(line), 80))}\n`; } text += uiTheme.fg("dim", `… (streaming)`); return text; @@ -175,7 +176,7 @@ function renderContentPreview(content: string, expanded: boolean, uiTheme: Theme let text = "\n\n"; for (const line of displayLines) { - text += `${uiTheme.fg("toolOutput", ui.truncate(line, 80))}\n`; + text += `${uiTheme.fg("toolOutput", ui.truncate(replaceTabs(line), 80))}\n`; } if (!expanded && hidden > 0) { const hint = formatExpandHint(uiTheme, expanded, hidden > 0); diff --git a/packages/coding-agent/src/tui/code-cell.ts b/packages/coding-agent/src/tui/code-cell.ts index 7d589736f..7105e4f65 100644 --- a/packages/coding-agent/src/tui/code-cell.ts +++ b/packages/coding-agent/src/tui/code-cell.ts @@ -90,7 +90,7 @@ export function renderCodeCell(options: CodeCellOptions, theme: Theme): string[] const maxLines = expanded ? rawLines.length : Math.min(rawLines.length, outputMaxLines); const displayLines = rawLines .slice(0, maxLines) - .map(line => (line.includes("\x1b[") ? line : theme.fg("toolOutput", line))); + .map(line => (line.includes("\x1b[") ? replaceTabs(line) : theme.fg("toolOutput", replaceTabs(line)))); outputLines.push(...displayLines); const remaining = rawLines.length - maxLines; if (remaining > 0) {