Skip to content

fix(tui): show spinner while a continued subagent runs - #59950

Merged
rekram1-node merged 2 commits into
devfrom
subagent-continue-spinner
Oct 28, 2026
Merged

rekram1-node merged 2 commits into
devfrom
subagent-continue-spinner

Conversation

@rekram1-node

@rekram1-node rekram1-node commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Problem

When the agent continues an existing subagent, its row shows a static ↳ icon even while the subagent is still working. Nothing tells you it is busy. A fresh subagent row already shows a spinner in the same situation.

Change

A continued subagent row now spins while the subagent is running, the same way a fresh one does, and goes back to ↳ once it stops.

  ↳ Continue subagent — MiniMax base64 default  Background     (idle)
- ↳ Continue subagent — MiniMax base64 default  Background     (running)
+ ⠋ Continue subagent — MiniMax base64 default  Background     (running)

Whether the subagent is running is read from the child session's status. For continuations the child session ID falls back to input.sessionID when the tool metadata doesn't have one yet. That keeps background continuations spinning after the tool call itself returns, and makes the row clickable earlier. The fallback is skipped when the call failed: a bad continuation can name an unrelated session (like the parent itself, which is always running during the turn), and following it would make the errored row spin, hide its error, and open the wrong session on click.

Visual

<svg xmlns="http://www.w3.org/2000/svg" width="240" height="72" viewBox="0 0 240 72" fill="none">
  <style>
    .s{transform-origin:24px 36px;animation:r 1s linear infinite}
    @keyframes r{to{transform:rotate(360deg)}}
    @media (prefers-reduced-motion:reduce){.s{animation:none}}
  </style>
  <circle cx="24" cy="36" r="7" stroke="currentColor" stroke-opacity=".2" stroke-width="2"/>
  <path class="s" d="M24 29a7 7 0 0 1 7 7" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
  <rect x="42" y="31" width="110" height="10" rx="5" fill="currentColor" fill-opacity=".55"/>
  <rect x="164" y="29" width="56" height="14" rx="4" fill="currentColor" fill-opacity=".15"/>
</svg>

Out of scope

This PR only changes the TUI row. It doesn't touch the desktop or web apps.

Verification

  • bun typecheck in packages/tui: passes
  • There is no render harness for session tool rows, so I didn't add a render test or check the change in a live TUI.

@opencodejr opencodejr Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good: a continued background subagent row now spins while the child session runs and goes back to ↳ when it finishes. I checked this with an opencode-drive script using the simulated model, comparing the base and this PR side by side (screenshots below). The packages/tui tests near the change have the same results as on the base (two shell-output timeout failures on both).

Public API: unchanged (TUI rendering only).

One edge case is noted inline: the input.sessionID fallback also applies when the continuation was rejected. That can make a failed row spin and hide its error.

Before

After

const { navigate } = useRoute()
const data = useData()
const sessionID = createMemo(() => stringValue(props.metadata.sessionID) ?? stringValue(props.metadata.sessionId))
const sessionID = createMemo(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The input.sessionID fallback also applies when the tool call failed. For example, the model passes its own or another session's ID and gets Session … is not a child of the current session or Subagent session not found. If that session is running (the parent's own ID always is during the turn), isRunning() is true, so the errored row spins. InlineTool hides the error while running is set, so the failure isn't visible until that session goes idle, and clicking the row opens the unrelated session. Skipping the fallback when props.part.state.status === "error" would avoid this.

@opencodejr opencodejr Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new commit addresses my earlier point: the row now ignores the continuation's input.sessionID when the tool call failed, so a rejected continuation doesn't spin, hide its error, or open an unrelated session. I re-ran the opencode-drive check with the simulated model, and a continued background subagent still spins while its child runs. The failed-call case I only checked by reading the code. Public API: unchanged. No new concerns.

Before

After

@rekram1-node
rekram1-node merged commit 71d3556 into dev Oct 28, 2026
15 checks passed
@rekram1-node
rekram1-node deleted the subagent-continue-spinner branch October 28, 2026 18:21
@amrkmn amrkmn mentioned this pull request Oct 29, 2026
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant