mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-08-31 10:37:12 +00:00
fix(tui): dismiss /btw panel before cancelling compaction on Esc and Ctrl+C (#1811)
This commit is contained in:
parent
31449728b7
commit
cec15e2188
3 changed files with 110 additions and 15 deletions
5
.changeset/btw-panel-compaction-priority.md
Normal file
5
.changeset/btw-panel-compaction-priority.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@moonshot-ai/kimi-code": patch
|
||||
---
|
||||
|
||||
Fix Esc and Ctrl+C cancelling compaction instead of closing an open /btw panel.
|
||||
|
|
@ -129,15 +129,8 @@ export class EditorKeyboardController {
|
|||
return;
|
||||
}
|
||||
|
||||
if (host.state.appState.isCompacting) {
|
||||
this.clearPendingExit();
|
||||
|
||||
if (this.clearEditorTextIfPresent()) return;
|
||||
|
||||
this.cancelCurrentCompaction();
|
||||
return;
|
||||
}
|
||||
|
||||
// The btw panel stacks above the transcript, so Ctrl+C cancels/closes it
|
||||
// before touching an in-flight compaction or stream.
|
||||
if (host.btwPanelController.cancelRunning()) {
|
||||
this.clearPendingExit();
|
||||
return;
|
||||
|
|
@ -147,6 +140,15 @@ export class EditorKeyboardController {
|
|||
return;
|
||||
}
|
||||
|
||||
if (host.state.appState.isCompacting) {
|
||||
this.clearPendingExit();
|
||||
|
||||
if (this.clearEditorTextIfPresent()) return;
|
||||
|
||||
this.cancelCurrentCompaction();
|
||||
return;
|
||||
}
|
||||
|
||||
if (host.state.appState.streamingPhase !== 'idle') {
|
||||
this.clearPendingExit();
|
||||
|
||||
|
|
@ -184,12 +186,14 @@ export class EditorKeyboardController {
|
|||
this.clearPendingUndoEsc();
|
||||
return;
|
||||
}
|
||||
if (host.state.appState.isCompacting) {
|
||||
this.cancelCurrentCompaction();
|
||||
// The btw panel stacks above the transcript, so Esc dismisses it before
|
||||
// touching an in-flight compaction or stream.
|
||||
if (host.btwPanelController.closeOrCancel()) {
|
||||
this.clearPendingUndoEsc();
|
||||
return;
|
||||
}
|
||||
if (host.btwPanelController.closeOrCancel()) {
|
||||
if (host.state.appState.isCompacting) {
|
||||
this.cancelCurrentCompaction();
|
||||
this.clearPendingUndoEsc();
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,16 +12,24 @@ interface Harness {
|
|||
readonly editor: Record<string, ((...args: never[]) => unknown) | undefined>;
|
||||
readonly openUndoSelector: ReturnType<typeof vi.fn>;
|
||||
readonly cancelRunningShellCommand: ReturnType<typeof vi.fn>;
|
||||
readonly cancelCompaction: ReturnType<typeof vi.fn>;
|
||||
readonly btwCancelRunning: ReturnType<typeof vi.fn>;
|
||||
readonly btwCloseOrCancel: ReturnType<typeof vi.fn>;
|
||||
}
|
||||
|
||||
function createHarness(options: { streamingPhase?: string; isCompacting?: boolean } = {}): Harness {
|
||||
const editor: Record<string, ((...args: never[]) => unknown) | undefined> = {
|
||||
setHistoryFilter: vi.fn() as unknown as (...args: never[]) => unknown,
|
||||
setInputMode: vi.fn() as unknown as (...args: never[]) => unknown,
|
||||
getText: vi.fn(() => '') as unknown as (...args: never[]) => unknown,
|
||||
setText: vi.fn() as unknown as (...args: never[]) => unknown,
|
||||
};
|
||||
const openUndoSelector = vi.fn();
|
||||
const cancelRunningShellCommand = vi.fn();
|
||||
const session = { cancel: vi.fn(async () => {}) };
|
||||
const cancelCompaction = vi.fn(async () => {});
|
||||
const btwCancelRunning = vi.fn(() => false);
|
||||
const btwCloseOrCancel = vi.fn(() => false);
|
||||
const session = { cancel: vi.fn(async () => {}), cancelCompaction };
|
||||
|
||||
const host = {
|
||||
state: {
|
||||
|
|
@ -35,7 +43,7 @@ function createHarness(options: { streamingPhase?: string; isCompacting?: boolea
|
|||
ui: { requestRender: vi.fn() },
|
||||
},
|
||||
session,
|
||||
btwPanelController: { closeOrCancel: vi.fn(() => false) },
|
||||
btwPanelController: { cancelRunning: btwCancelRunning, closeOrCancel: btwCloseOrCancel },
|
||||
openUndoSelector,
|
||||
cancelRunningShellCommand,
|
||||
} as unknown as EditorKeyboardHost;
|
||||
|
|
@ -46,7 +54,15 @@ function createHarness(options: { streamingPhase?: string; isCompacting?: boolea
|
|||
);
|
||||
controller.install();
|
||||
|
||||
return { host, editor, openUndoSelector, cancelRunningShellCommand };
|
||||
return {
|
||||
host,
|
||||
editor,
|
||||
openUndoSelector,
|
||||
cancelRunningShellCommand,
|
||||
cancelCompaction,
|
||||
btwCancelRunning,
|
||||
btwCloseOrCancel,
|
||||
};
|
||||
}
|
||||
|
||||
function pressEscape(editor: Harness['editor']): void {
|
||||
|
|
@ -55,6 +71,12 @@ function pressEscape(editor: Harness['editor']): void {
|
|||
(handler as () => void)();
|
||||
}
|
||||
|
||||
function pressCtrlC(editor: Harness['editor']): void {
|
||||
const handler = editor['onCtrlC'];
|
||||
if (handler === undefined) throw new Error('onCtrlC handler not installed');
|
||||
(handler as () => void)();
|
||||
}
|
||||
|
||||
function pressNonEscape(editor: Harness['editor']): void {
|
||||
const handler = editor['onNonEscapeInput'];
|
||||
if (handler === undefined) throw new Error('onNonEscapeInput handler not installed');
|
||||
|
|
@ -123,6 +145,70 @@ describe('EditorKeyboardController double-Esc undo', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('EditorKeyboardController btw panel priority', () => {
|
||||
it('Esc closes the btw panel first while compacting, without cancelling compaction', () => {
|
||||
const { editor, btwCloseOrCancel, cancelCompaction } = createHarness({ isCompacting: true });
|
||||
btwCloseOrCancel.mockReturnValue(true);
|
||||
|
||||
pressEscape(editor);
|
||||
|
||||
expect(btwCloseOrCancel).toHaveBeenCalledOnce();
|
||||
expect(cancelCompaction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Esc cancels compaction on the next press once the btw panel is gone', () => {
|
||||
const { editor, btwCloseOrCancel, cancelCompaction } = createHarness({ isCompacting: true });
|
||||
btwCloseOrCancel.mockReturnValueOnce(true);
|
||||
|
||||
pressEscape(editor);
|
||||
expect(cancelCompaction).not.toHaveBeenCalled();
|
||||
|
||||
pressEscape(editor);
|
||||
expect(cancelCompaction).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('Esc cancels compaction directly when no btw panel is open', () => {
|
||||
const { editor, btwCloseOrCancel, cancelCompaction } = createHarness({ isCompacting: true });
|
||||
|
||||
pressEscape(editor);
|
||||
|
||||
expect(btwCloseOrCancel).toHaveBeenCalledOnce();
|
||||
expect(cancelCompaction).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('Ctrl+C cancels a running btw question first while compacting', () => {
|
||||
const { editor, btwCancelRunning, cancelCompaction } = createHarness({ isCompacting: true });
|
||||
btwCancelRunning.mockReturnValue(true);
|
||||
|
||||
pressCtrlC(editor);
|
||||
|
||||
expect(btwCancelRunning).toHaveBeenCalledOnce();
|
||||
expect(cancelCompaction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Ctrl+C closes an idle btw panel while compacting, without cancelling compaction', () => {
|
||||
const { editor, btwCloseOrCancel, cancelCompaction } = createHarness({ isCompacting: true });
|
||||
btwCloseOrCancel.mockReturnValue(true);
|
||||
|
||||
pressCtrlC(editor);
|
||||
|
||||
expect(btwCloseOrCancel).toHaveBeenCalledOnce();
|
||||
expect(cancelCompaction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Ctrl+C cancels compaction when no btw panel is open', () => {
|
||||
const { editor, btwCancelRunning, btwCloseOrCancel, cancelCompaction } = createHarness({
|
||||
isCompacting: true,
|
||||
});
|
||||
|
||||
pressCtrlC(editor);
|
||||
|
||||
expect(btwCancelRunning).toHaveBeenCalledOnce();
|
||||
expect(btwCloseOrCancel).toHaveBeenCalledOnce();
|
||||
expect(cancelCompaction).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
|
||||
describe('EditorKeyboardController shell history recall', () => {
|
||||
type Recall = (entry: string, direction: 1 | -1) => string | undefined;
|
||||
type Mock = ReturnType<typeof vi.fn>;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue