From 230fcff1fe039171d2499aae2511f7a7f6902356 Mon Sep 17 00:00:00 2001 From: PaiduiXiaowangzi Date: Fri, 14 Aug 2026 01:17:36 +0800 Subject: [PATCH] fix(tui): sanitize background task output --- .changeset/fix-windows-task-output-frames.md | 5 +++++ .../src/tui/components/dialogs/task-output-viewer.ts | 3 ++- .../src/tui/components/dialogs/tasks-browser.ts | 3 ++- apps/kimi-code/test/tui/task-output-viewer.test.ts | 8 ++++++++ apps/kimi-code/test/tui/tasks-browser.test.ts | 10 ++++++++++ 5 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 .changeset/fix-windows-task-output-frames.md diff --git a/.changeset/fix-windows-task-output-frames.md b/.changeset/fix-windows-task-output-frames.md new file mode 100644 index 0000000000..3565fbfa22 --- /dev/null +++ b/.changeset/fix-windows-task-output-frames.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +Fix task browser frames becoming misaligned when Windows background task output contains terminal control characters. diff --git a/apps/kimi-code/src/tui/components/dialogs/task-output-viewer.ts b/apps/kimi-code/src/tui/components/dialogs/task-output-viewer.ts index 4a463671cb..fe9def13fd 100644 --- a/apps/kimi-code/src/tui/components/dialogs/task-output-viewer.ts +++ b/apps/kimi-code/src/tui/components/dialogs/task-output-viewer.ts @@ -22,6 +22,7 @@ import type { BackgroundTaskInfo, BackgroundTaskStatus } from '@moonshot-ai/kimi import { currentTheme } from '#/tui/theme'; import { printableChar } from '@/tui/utils/printable-key'; +import { sanitizeShellOutput } from '@/tui/utils/shell-output'; const ELLIPSIS = '…'; @@ -104,7 +105,7 @@ export class TaskOutputViewer extends Container implements Focusable { } private splitOutput(output: string): string[] { - return (output.length > 0 ? output : '[no output captured]').split('\n'); + return sanitizeShellOutput(output.length > 0 ? output : '[no output captured]').split('\n'); } // ── input ────────────────────────────────────────────────────────── diff --git a/apps/kimi-code/src/tui/components/dialogs/tasks-browser.ts b/apps/kimi-code/src/tui/components/dialogs/tasks-browser.ts index 1874d0e7a0..aadcc601e7 100644 --- a/apps/kimi-code/src/tui/components/dialogs/tasks-browser.ts +++ b/apps/kimi-code/src/tui/components/dialogs/tasks-browser.ts @@ -27,6 +27,7 @@ import type { BackgroundTaskInfo, BackgroundTaskStatus } from '@moonshot-ai/kimi import { SELECT_POINTER } from '@/tui/constant/symbols'; import { currentTheme } from '#/tui/theme'; import { printableChar } from '@/tui/utils/printable-key'; +import { sanitizeShellOutput } from '@/tui/utils/shell-output'; const ELLIPSIS = '…'; @@ -605,7 +606,7 @@ export class TasksBrowserApp extends Container implements Focusable { body = '[no output captured]'; else body = this.props.tailOutput; - const rawLines = body.split('\n'); + const rawLines = sanitizeShellOutput(body).split('\n'); const tailLines = rawLines.slice(-innerHeight); const styled = tailLines.map((line) => currentTheme.fg('textDim', line)); while (styled.length < innerHeight) styled.push(''); diff --git a/apps/kimi-code/test/tui/task-output-viewer.test.ts b/apps/kimi-code/test/tui/task-output-viewer.test.ts index 5948ec6c84..08c4023d06 100644 --- a/apps/kimi-code/test/tui/task-output-viewer.test.ts +++ b/apps/kimi-code/test/tui/task-output-viewer.test.ts @@ -75,6 +75,14 @@ describe('TaskOutputViewer — rendering', () => { expect(lines.length).toBe(24); }); + it('removes carriage returns from Windows task output so frames stay aligned', () => { + const lines = makeViewer({ + output: 'Reply from 127.0.0.1: time<1ms TTL=128\r\nReply from 127.0.0.1: time<1ms TTL=128\r\n', + }).render(120); + + expect(lines.every((line) => !line.includes('\r'))).toBe(true); + }); + it('shows the task header (id + status + description)', () => { const out = strip( makeViewer({ diff --git a/apps/kimi-code/test/tui/tasks-browser.test.ts b/apps/kimi-code/test/tui/tasks-browser.test.ts index 7d5a54c3bf..a127c086bf 100644 --- a/apps/kimi-code/test/tui/tasks-browser.test.ts +++ b/apps/kimi-code/test/tui/tasks-browser.test.ts @@ -243,6 +243,16 @@ describe('TasksBrowserApp — full-screen rendering', () => { expect(out).toContain('listening on :3000'); }); + it('removes carriage returns from Windows task output so frames stay aligned', () => { + const lines = makeApp({ + tasks: [task({ taskId: 'bash-aaaaaaaa' })], + selectedTaskId: 'bash-aaaaaaaa', + tailOutput: 'Reply from 127.0.0.1: time<1ms TTL=128\r\nReply from 127.0.0.1: time<1ms TTL=128\r\n', + }).render(120); + + expect(lines.every((line) => !line.includes('\r'))).toBe(true); + }); + it('shows a loading state when tail is loading', () => { const out = strip( makeApp({