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();