Explorar el Código

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.
Dax Raad hace 3 meses
padre
commit
e3a2728fa3
Se han modificado 1 ficheros con 22 adiciones y 7 borrados
  1. 22 7
      packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx

+ 22 - 7
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<number, number>
+    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) {
             </Match>
             <Match when={status() === "working"}>
               <box flexDirection="row" gap={1}>
-                <text fg={theme.text}>
-                  esc <span style={{ fg: theme.textMuted }}>interrupt</span>
+                <text fg={store.interrupt > 0 ? theme.primary : theme.text}>
+                  esc{" "}
+                  <span style={{ fg: store.interrupt > 0 ? theme.primary : theme.textMuted }}>
+                    {store.interrupt > 0 ? "again to interrupt" : "interrupt"}
+                  </span>
                 </text>
               </box>
             </Match>