From 2284ba6219f7f73ed92a654c540ef1091c16a9da Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 24 Jun 2026 20:21:25 +0800 Subject: [PATCH] fix(tui): clear editor draft on Ctrl-C during compaction When compaction is in progress and the editor has a draft, Ctrl-C now clears the draft first instead of cancelling compaction, matching the streaming behavior. The clear-text logic is shared between the compaction and streaming branches. --- .changeset/fix-ctrl-c-compaction.md | 5 ++++ .../src/tui/controllers/editor-keyboard.ts | 15 ++++++++---- .../test/tui/kimi-tui-message-flow.test.ts | 24 +++++++++++++++++++ 3 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 .changeset/fix-ctrl-c-compaction.md diff --git a/.changeset/fix-ctrl-c-compaction.md b/.changeset/fix-ctrl-c-compaction.md new file mode 100644 index 0000000000..58fd932505 --- /dev/null +++ b/.changeset/fix-ctrl-c-compaction.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +Fix Ctrl-C during compaction so it clears a pending editor draft first instead of cancelling immediately. diff --git a/apps/kimi-code/src/tui/controllers/editor-keyboard.ts b/apps/kimi-code/src/tui/controllers/editor-keyboard.ts index bc5b922b0e..42871d5dce 100644 --- a/apps/kimi-code/src/tui/controllers/editor-keyboard.ts +++ b/apps/kimi-code/src/tui/controllers/editor-keyboard.ts @@ -72,6 +72,9 @@ export class EditorKeyboardController { if (host.state.appState.isCompacting) { this.clearPendingExit(); + + if (this.clearEditorTextIfPresent()) return; + this.cancelCurrentCompaction(); return; } @@ -88,10 +91,7 @@ export class EditorKeyboardController { if (host.state.appState.streamingPhase !== 'idle') { this.clearPendingExit(); - if (editor.getText().length > 0) { - editor.setText(''); - return; - } + if (this.clearEditorTextIfPresent()) return; this.cancelCurrentStream(); return; @@ -254,6 +254,13 @@ export class EditorKeyboardController { this.host.state.ui.requestRender(); } + private clearEditorTextIfPresent(): boolean { + const editor = this.host.state.editor; + if (editor.getText().length === 0) return false; + editor.setText(''); + return true; + } + private cancelCurrentStream(): void { void this.host.session?.cancel(); } diff --git a/apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts b/apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts index 0d6c498dc5..621f11653e 100644 --- a/apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts +++ b/apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts @@ -1423,6 +1423,30 @@ command = "vim" expect(session.cancelCompaction).toHaveBeenCalledTimes(1); }); + it('clears editor text before cancelling compaction on Ctrl-C', async () => { + const { driver, session } = await makeDriver(); + driver.sessionEventHandler.handleEvent( + { + type: 'compaction.started', + agentId: 'main', + sessionId: 'ses-1', + trigger: 'manual', + } as Event, + vi.fn(), + ); + driver.state.editor.setText('draft while compacting'); + + driver.state.editor.onCtrlC?.(); + + expect(driver.state.editor.getText()).toBe(''); + expect(session.cancelCompaction).not.toHaveBeenCalled(); + expect(driver.state.appState.isCompacting).toBe(true); + + driver.state.editor.onCtrlC?.(); + + expect(session.cancelCompaction).toHaveBeenCalledTimes(1); + }); + it('dispatches the next queued message after compaction is cancelled', async () => { vi.useFakeTimers(); try {