From bf17f52f04776eec629e5f5d3423e3e4be804388 Mon Sep 17 00:00:00 2001 From: zbl1998-sdjn <1051061805@qq.com> Date: Sun, 12 Jul 2026 04:38:38 +1000 Subject: [PATCH] fix(web): don't interrupt the running prompt when Escape closes a dialog ConversationPane's document-level Escape handler interrupts the running prompt, but didn't check whether a modal dialog owns Escape. App.vue's capture-phase handler deliberately leaves Escape for an open dialog to close itself, so with the session-search popup (or any Dialog) open, one Escape both closed the dialog AND interrupted the task. Guard onKeyDown with openDialogCount, mirroring App.vue's anyOverlayOpen check. Closes #1538 --- .changeset/web-escape-dialog-no-interrupt.md | 5 +++++ apps/kimi-web/src/components/chat/ConversationPane.vue | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 .changeset/web-escape-dialog-no-interrupt.md diff --git a/.changeset/web-escape-dialog-no-interrupt.md b/.changeset/web-escape-dialog-no-interrupt.md new file mode 100644 index 000000000..64c1ca23d --- /dev/null +++ b/.changeset/web-escape-dialog-no-interrupt.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +web: Don't interrupt the running prompt when Escape closes an open dialog (such as the session search popup). diff --git a/apps/kimi-web/src/components/chat/ConversationPane.vue b/apps/kimi-web/src/components/chat/ConversationPane.vue index 7c7f47511..0f3fe0a2d 100644 --- a/apps/kimi-web/src/components/chat/ConversationPane.vue +++ b/apps/kimi-web/src/components/chat/ConversationPane.vue @@ -16,6 +16,7 @@ import Spinner from '../ui/Spinner.vue'; import Tooltip from '../ui/Tooltip.vue'; import { getVisibleWorkspaces } from '../../lib/workspacePicker'; import { safeRemove, STORAGE_KEYS } from '../../lib/storage'; +import { openDialogCount } from '../../composables/dialogStack'; const { t, locale } = useI18n(); @@ -1026,6 +1027,10 @@ function handleInterrupt(): void { } function onKeyDown(event: KeyboardEvent): void { + // A modal dialog open on top of the conversation owns Escape (it closes + // itself); don't also interrupt the running prompt underneath. Mirrors the + // `anyOverlayOpen` guard in App.vue's global capture-phase Escape handler (#1538). + if (openDialogCount.value > 0) return; if (event.key === 'Escape' && (props.running || props.sending)) { event.preventDefault(); handleInterrupt();