Skip to content

Commit 520e435

Browse files
committed
fix(tui): refine subagent interrupt flow and footer feedback
1 parent 983a34d commit 520e435

2 files changed

Lines changed: 31 additions & 11 deletions

File tree

packages/tui/src/routes/session/index.tsx

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ export function Session() {
199199
return current ? { directory: current.directory, workspaceID: current.workspaceID } : undefined
200200
})
201201
const sessionStatus = createMemo(() => sync.data.session_status[route.sessionID]?.type ?? "idle")
202+
const sessionBusy = createMemo(() => sessionStatus() !== "idle")
202203

203204
createEffect(() => {
204205
const title = Locale.truncate(session()?.title ?? "", 50)
@@ -293,13 +294,15 @@ export function Session() {
293294
(isIdle) => {
294295
if (isIdle) resetInterrupt()
295296
},
297+
{ defer: true },
296298
),
297299
)
298300

299301
createEffect(
300302
on(
301303
() => route.sessionID,
302304
() => resetInterrupt(),
305+
{ defer: true },
303306
),
304307
)
305308

@@ -1159,21 +1162,26 @@ export function Session() {
11591162
run: () => {
11601163
dialog.clear()
11611164
const next = interruptCount() + 1
1162-
setInterruptCount(next)
1163-
if (interruptTimer) clearTimeout(interruptTimer)
1164-
interruptTimer = setTimeout(resetInterrupt, 5000)
11651165
if (next >= 2) {
11661166
resetInterrupt()
1167-
sync.set("permission", route.sessionID, [])
1168-
sync.set("question", route.sessionID, [])
11691167
void sdk.client.session
11701168
.abort({ sessionID: route.sessionID })
1169+
.then(() => {
1170+
// Server cancels the runner but does not emit session-wide
1171+
// permission/question cleanup events; clear stale local state
1172+
sync.set("permission", route.sessionID, [])
1173+
sync.set("question", route.sessionID, [])
1174+
})
11711175
.catch((error: unknown) => {
11721176
toast.show({
11731177
message: errorMessage(error),
11741178
variant: "error",
11751179
})
11761180
})
1181+
} else {
1182+
setInterruptCount(next)
1183+
if (interruptTimer) clearTimeout(interruptTimer)
1184+
interruptTimer = setTimeout(resetInterrupt, 5000)
11771185
}
11781186
},
11791187
},
@@ -1366,7 +1374,7 @@ export function Session() {
13661374
<Show when={session()?.parentID}>
13671375
<SubagentFooter
13681376
interruptCount={interruptCount}
1369-
sessionBusy={() => sessionStatus() !== "idle"}
1377+
sessionBusy={sessionBusy}
13701378
/>
13711379
</Show>
13721380
<Show when={visible()}>

packages/tui/src/routes/session/subagent-footer.tsx

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export function SubagentFooter(props: {
6464
const previousShortcut = useCommandShortcut("session.child.previous")
6565
const nextShortcut = useCommandShortcut("session.child.next")
6666
const interruptShortcut = useCommandShortcut("session.child.interrupt")
67+
const armed = createMemo(() => props.interruptCount() > 0)
6768
const [hover, setHover] = createSignal<"parent" | "prev" | "next" | null>(null)
6869
useTerminalDimensions()
6970

@@ -100,11 +101,22 @@ export function SubagentFooter(props: {
100101
</box>
101102
<box flexDirection="row" gap={2}>
102103
<Show when={props.sessionBusy()}>
103-
<text fg={props.interruptCount() > 0 ? theme.primary : theme.text}>
104-
{interruptShortcut() || "esc"}{" "}
105-
<span style={{ fg: props.interruptCount() > 0 ? theme.primary : theme.textMuted }}>
106-
{props.interruptCount() > 0 ? "again to interrupt" : "interrupt"}
107-
</span>
104+
<text fg={armed() ? theme.primary : theme.text}>
105+
{armed() ? (
106+
<>
107+
<span style={{ fg: armed() ? theme.primary : theme.textMuted }}>
108+
{interruptShortcut()}
109+
</span>{" "}
110+
again to interrupt
111+
</>
112+
) : (
113+
<>
114+
Interrupt{" "}
115+
<span style={{ fg: armed() ? theme.primary : theme.textMuted }}>
116+
{interruptShortcut()}
117+
</span>
118+
</>
119+
)}
108120
</text>
109121
</Show>
110122
<box

0 commit comments

Comments
 (0)