Skip to content

feat(tui): surface sessions awaiting input at the top of the open menu - #53435

Merged
kitlangton merged 3 commits into
v2from
pending-attention
Oct 5, 2026
Merged

kitlangton merged 3 commits into
v2from
pending-attention

Conversation

@kitlangton

@kitlangton kitlangton commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Why

When a background session, independent session (session_create), or subagent blocks on a permission prompt or a question (Form), SessionExecution keeps its drain active and reports "running". In the Ctrl+O Open menu (DialogOpen) and /sessions (DialogSessionList), blocked sessions therefore render a working spinner instead of a "needs input" state, sink chronologically below newer activity, and drop out of Ctrl+O altogether once 8 newer sessions update.

What Changes

Sessions awaiting a permission (!) or question (?) now surface at the top of Sessions in Ctrl+O (DialogOpen) and display ! / ? attention markers in both Ctrl+O and /sessions (DialogSessionList).

1. Opening Ctrl+O while background sessions are blocked on input (Before)
Blocked sessions sit buried by time.updated with a false working spinner (⠋), or fall past the 8-session recent limit completely.

Open                                                          esc

Search sessions and projects…

Sessions
› Verify tarball exports                           opencode · now
  Triage flaky CI checks                           opencode · now
  Optimize token counter                           opencode · now
  Add SQLite WAL tuning                            opencode · now
⠋ Migrate auth session cookies                     opencode · now
  Clean up snapshot fixtures                       opencode · now

2. Opening Ctrl+O while background sessions are blocked on input (After)
Sessions awaiting a question (?) or permission (!)—including root sessions blocked via a child subagent or older than the 8 most recent sessions—sort to the top of Sessions with ? / ! icons so Enter immediately opens the first blocked session.

Open                                                          esc

Search sessions and projects…

Sessions
? Migrate auth session cookies                     opencode · now
! Audit Cloudflare worker bindings                 opencode · now
  Verify tarball exports                           opencode · now
  Triage flaky CI checks                           opencode · now
  Optimize token counter                           opencode · now
  Add SQLite WAL tuning                            opencode · now

Attention Hydration & Lineage Resolution

sequenceDiagram
    participant TUI as DialogOpen (Ctrl+O)
    participant Data as Solid Data Store
    participant Server as OpenCode Server

    TUI->>Data: Sync permissions & forms for active() sessions
    Data->>Server: GET /api/session/:id/permission & /form (cached per session)
    Server-->>Data: Pending permissions & forms
    alt Pending or active sessionID is a child subagent
        TUI->>Data: data.session.sync(root(id))
        Data->>Server: GET /api/session/:id
        Server-->>Data: SessionInfo (parentID -> rootID)
        Data->>Data: Register childID in family[rootID]
    end
    TUI->>TUI: Sort attention(rootID) sessions to top with ! / ?
Loading
  • Per-session active hydration (packages/client/src/solid/data.ts, packages/tui/src/component/dialog-open.tsx): data.ts exposes read-only active(), permission.sessions(), and form.sessions() selectors over existing store records. When DialogOpen mounts, it calls the existing data.session.permission.sync(id) and data.session.form.sync(id) methods on currently running (active()) sessions—sharing the same sync.run cache keys as Session and SessionTabs.
  • Subagent lineage resolution (packages/tui/src/component/dialog-open.tsx, packages/tui/src/context/session-tabs.tsx): When a pending permission, pending form, or active session belongs to a child subagent not in the root session list, DialogOpen syncs data.session.root(id) so sessionTabs.status(rootID).attention reflects the blocked child. family(sessionID) always retains session itself even when a child's SessionInfo arrives before its root's.

Demo

open-attention-demo.mp4

Side-by-side opencode-drive capture (96x26 viewport, simulated LLM). Left: origin/v2 (4ed2978a30). Right: pending-attention. Two background sessions are blocked (Audit Cloudflare worker bindings on a shell permission and Migrate auth session cookies on a question), followed by 8 newer idle sessions. Pressing Ctrl+O and Enter on the left opens an idle session while hiding the older permission-blocked session; on the right, both blocked sessions surface at the top with ? and ! and Enter opens the blocked session directly to its question prompt.

Scope

This PR owns surfacing awaiting-input sessions and their ! / ? indicators in DialogOpen (Ctrl+O) and DialogSessionList (/sessions). Global chrome badges and toast notifications remain separate follow-ups.

Verification

bun test test/cli/tui/dialog-open.test.tsx test/cli/tui/dialog-session-list.test.tsx test/context/session-tabs.test.tsx test/cli/tui/data.test.tsx
bun run check
  • packages/tui: 98 pass, 0 fail across dialog-open.test.tsx, dialog-session-list.test.tsx, session-tabs.test.tsx, and data.test.tsx (including the regression test covering older permission-blocked sessions and child-subagent question prompts).
  • bun run check: 0 errors across all 36 workspace tasks and oxlint.
  • Verified end-to-end in a real TUI via opencode-drive against both origin/v2 and HEAD.

@kitlangton
kitlangton enabled auto-merge (squash) October 5, 2026 21:18
@kitlangton
kitlangton merged commit a2a543c into v2 Oct 5, 2026
10 of 11 checks passed
@kitlangton
kitlangton deleted the pending-attention branch October 5, 2026 21:20
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