From e3a2728fa3cf331b6d075dbfd6543990083c72eb Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Tue, 11 Nov 2025 22:03:54 -0500 Subject: [PATCH] tui: add double-esc interrupt mechanism for long-running operations Users can now press escape twice within 5 seconds to interrupt long-running operations in the TUI. The first press shows a visual hint, and the second press aborts the current session. --- .../cli/cmd/tui/component/prompt/index.tsx | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx index 408c62cde..a7f248758 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx @@ -228,11 +228,21 @@ export function Prompt(props: PromptProps) { if (!props.sessionID) return if (autocomplete.visible) return if (!input.focused) return - sdk.client.session.abort({ - path: { - id: props.sessionID, - }, - }) + + setStore("interrupt", store.interrupt + 1) + + setTimeout(() => { + setStore("interrupt", 0) + }, 5000) + + if (store.interrupt >= 2) { + sdk.client.session.abort({ + path: { + id: props.sessionID, + }, + }) + setStore("interrupt", 0) + } dialog.clear() }, }, @@ -252,6 +262,7 @@ export function Prompt(props: PromptProps) { prompt: PromptInfo mode: "normal" | "shell" extmarkToPartIndex: Map + interrupt: number }>({ prompt: { input: "", @@ -259,6 +270,7 @@ export function Prompt(props: PromptProps) { }, mode: "normal", extmarkToPartIndex: new Map(), + interrupt: 0, }) createEffect(() => { @@ -746,8 +758,11 @@ export function Prompt(props: PromptProps) { - - esc interrupt + 0 ? theme.primary : theme.text}> + esc{" "} + 0 ? theme.primary : theme.textMuted }}> + {store.interrupt > 0 ? "again to interrupt" : "interrupt"} +