From dbf90e440ac93a642fee5cb87f30af602fcbad4c Mon Sep 17 00:00:00 2001 From: chunxiaox Date: Fri, 31 Jul 2026 10:26:53 -0400 Subject: [PATCH] feat(tui): include terminal width in status_line.command payload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The JSON snapshot piped to status_line.command had no width, and the command is spawned with piped stdio so process.stdout.columns is unavailable — a status line script cannot right-align or lay out full-width content. Pass FooterComponent.render(width) through in the payload so commands can build left/right-justified HUD layouts. Refs #2477 --- .../src/tui/components/chrome/footer.ts | 5 +++-- .../src/tui/utils/status-line-command.ts | 6 ++++++ .../components/chrome/footer-status-line.test.ts | 16 ++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/apps/kimi-code/src/tui/components/chrome/footer.ts b/apps/kimi-code/src/tui/components/chrome/footer.ts index 4bb8a75f9b..2dd18e8905 100644 --- a/apps/kimi-code/src/tui/components/chrome/footer.ts +++ b/apps/kimi-code/src/tui/components/chrome/footer.ts @@ -278,7 +278,7 @@ export class FooterComponent implements Component { let line1: string; let customLine: string | null = null; if (this.statusLineRunner !== null) { - this.statusLineRunner.maybeRefresh(this.statusLinePayload()); + this.statusLineRunner.maybeRefresh(this.statusLinePayload(width)); customLine = this.statusLineRunner.current(); } @@ -435,7 +435,7 @@ export class FooterComponent implements Component { return slots; } - private statusLinePayload(): StatusLinePayload { + private statusLinePayload(width: number): StatusLinePayload { const state = this.state; return { model: modelDisplayName(state), @@ -448,6 +448,7 @@ export class FooterComponent implements Component { maxContextTokens: state.maxContextTokens, sessionId: state.sessionId, version: state.version, + width, }; } diff --git a/apps/kimi-code/src/tui/utils/status-line-command.ts b/apps/kimi-code/src/tui/utils/status-line-command.ts index 6482a4ac7c..1918e41cf0 100644 --- a/apps/kimi-code/src/tui/utils/status-line-command.ts +++ b/apps/kimi-code/src/tui/utils/status-line-command.ts @@ -25,6 +25,12 @@ export interface StatusLinePayload { maxContextTokens: number; sessionId: string; version: string; + /** + * Terminal width in columns, so the command can lay out full-width + * (left/right-justified) status lines. Piped stdio has no TTY, so + * `process.stdout.columns` is unavailable to the command. + */ + width: number; } export function runStatusLineCommand( diff --git a/apps/kimi-code/test/tui/components/chrome/footer-status-line.test.ts b/apps/kimi-code/test/tui/components/chrome/footer-status-line.test.ts index a6be39adfb..e2233b71f4 100644 --- a/apps/kimi-code/test/tui/components/chrome/footer-status-line.test.ts +++ b/apps/kimi-code/test/tui/components/chrome/footer-status-line.test.ts @@ -52,6 +52,7 @@ const payload: StatusLinePayload = { maxContextTokens: 8192, sessionId: 'ses-1', version: '1.2.3', + width: 120, }; function plain(text: string): string { @@ -142,6 +143,7 @@ describe('runStatusLineCommand', () => { expect(parsed.model).toBe('kimi-k2'); expect(parsed.gitBranch).toBe('main'); expect(parsed.cwd).toBe('/tmp/project'); + expect(parsed.width).toBe(120); }); it('returns null on a nonzero exit', async () => { @@ -201,6 +203,20 @@ describe('FooterComponent status_line command', () => { expect(plain(footer.render(120)[0]!)).toContain('kimi-k2'); }); + + it('sends the terminal width from render() in the payload', async () => { + const state: AppState = { + ...baseState, + statusLine: { items: null, command: 'cat' }, + }; + const footer = new FooterComponent(state); + + // Wide render so the echoed payload JSON (width field last) is not truncated. + footer.render(500); // kicks the first run with width 500 + await new Promise((resolve) => setTimeout(resolve, 300)); + + expect(plain(footer.render(500)[0]!)).toContain('"width":500'); + }); }); describe('StatusLineCommandRunner', () => {