From 93753843715a50c41ae36f2525b51479f14c8e25 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Fri, 5 Dec 2025 12:13:33 +0100 Subject: [PATCH] fix: strip remaining escape sequences from bash output stripAnsi misses some escape sequences like standalone ESC \ (String Terminator) which caused rendering issues when displaying captured TUI output. Now also removes any remaining ESC+char sequences and control characters after stripAnsi processing. --- packages/coding-agent/CHANGELOG.md | 1 + packages/coding-agent/src/tui/tool-execution.ts | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 1a5a7f2b..0c1efed1 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -10,6 +10,7 @@ - **Print mode error handling**: `-p` flag now outputs error messages and exits with code 1 when requests fail, instead of silently producing no output. - **Branch selector crash**: Fixed TUI crash when user messages contained Unicode characters (like `✔` or `›`) that caused line width to exceed terminal width. Now uses proper `truncateToWidth` instead of `substring`. +- **Bash output escape sequences**: Fixed incomplete stripping of terminal escape sequences in bash tool output. `stripAnsi` misses some sequences like standalone String Terminator (`ESC \`), which could cause rendering issues when displaying captured TUI output. ### Added diff --git a/packages/coding-agent/src/tui/tool-execution.ts b/packages/coding-agent/src/tui/tool-execution.ts index cca9ac07..8f7c66d6 100644 --- a/packages/coding-agent/src/tui/tool-execution.ts +++ b/packages/coding-agent/src/tui/tool-execution.ts @@ -85,7 +85,17 @@ export class ToolExecutionComponent extends Container { // Strip ANSI codes and carriage returns from raw output // (bash may emit colors/formatting, and Windows may include \r) - let output = textBlocks.map((c: any) => stripAnsi(c.text || "").replace(/\r/g, "")).join("\n"); + let output = textBlocks + .map((c: any) => { + let text = stripAnsi(c.text || "").replace(/\r/g, ""); + // stripAnsi misses some escape sequences like standalone ESC \ (String Terminator) + // and leaves orphaned fragments from malformed sequences (e.g. TUI output captured to file) + // Clean up: remove ESC + any following char, and control chars except newline/tab + text = text.replace(/\x1b./g, ""); + text = text.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/g, ""); + return text; + }) + .join("\n"); // Add indicator for images if (imageBlocks.length > 0) {