Skip to content
This repository was archived by the owner on Sep 2, 2026. It is now read-only.

feat(tabs): add Reload command to tab context menus - #167

Merged
64ix merged 3 commits into
fork-mainfrom
add-a-reload-button-on-tabs-for-tui-refresh
Aug 24, 2026
Merged

feat(tabs): add Reload command to tab context menus#167
64ix merged 3 commits into
fork-mainfrom
add-a-reload-button-on-tabs-for-tui-refresh

Conversation

@64ix

@64ix 64ix commented Aug 24, 2026

Copy link
Copy Markdown
Owner

Description

Right-clicking a TUI conversation tab (e.g. an opencode agent) or a terminal tab now offers a Reload command. It kills the session's PTY and starts a fresh one — a recovery hatch for glitched display state (broken scroll regions, garbled redraws, broken scrollback) that scrolling or redrawing cannot fix.

Implementation, renderer-only (reuses existing RPC surface):

  • Conversation tabs (ConversationManagerStore.restartConversation): dehydrate kills the backend process without respawn tracking, then hydrate respawns it with resume flags so the agent session continues where it left off. The renderer-side PtySession is replaced with a fresh instance so the new process replays into a clean xterm (the PTY registry resets its ring buffer per incarnation).
  • Terminal tabs (TerminalManagerStore.restartTerminal): pty.stopSession tears the shell down without deleting the terminal record, then the terminal is re-hydrated; same fresh-session swap.
  • Failures surface a destructive toast; even when the respawn fails, the session object is still replaced so the tab recovers to an empty terminal instead of staying dead.
  • Works for local and SSH-backed sessions alike (both go through the same provider interface). In tmux mode, reload detaches and reattaches, which repaints cleanly.

Out of scope: ACP chat tabs — those sessions are not PTYs and would need their own restart mechanism.

Related issues

None filed yet.

Testing

  • pnpm run format
  • pnpm exec oxlint . (app)
  • pnpm typecheck (tsgo)
  • pnpm exec vitest run --project node --project main-db --project migrations --project scripts — all green locally, including PTY integration tests
  • New unit tests: restart swaps in a fresh session + ordering of stop→respawn; recovery when the respawn rejects
Checklist
  • I kept this PR small and focused
  • I ran a self-review before opening this PR
  • I ran the relevant local checks or explained why not
  • I updated docs when behavior or setup changed
  • I added or updated tests when behavior changed, or explained why not
  • I only added comments where the logic is not obvious
  • I used Conventional Commits for commit
    messages and, when possible, the PR title

64ix added 3 commits August 24, 2026 11:45
…xt menus

Right-clicking a TUI conversation tab (e.g. an opencode agent) or a plain
terminal tab now offers Reload: it kills the session's PTY and starts a
fresh one, as a recovery hatch for glitched display state (broken scroll
regions, garbled redraws) that scrolling cannot fix.

- conversations: dehydrate (kills the process without respawn tracking)
  then hydrate (respawns with resume flags), replacing the renderer-side
  PtySession so the new process replays into a clean xterm
- terminals: pty.stopSession (keeps the terminal record) then re-hydrate,
  same fresh-session swap
- failures surface a destructive toast; the session is still replaced so
  the tab recovers instead of staying dead
…state

- destroy whatever session re-populated the slot while the restart
  round-trips were in flight (list-data reaction / conversation-created
  event) instead of overwriting it and leaking its ptyStartedChannel
  subscription
- do not create the replacement session when the store was disposed
  mid-restart (task view unmounted during the reload)
- clear working/awaiting-input status when the conversation process is
  killed: deliberate kills are classified as "stopped" by the supervisor,
  so agentSessionExited never fires and the resumed TUI starts idle
A teardown requested while a restart round-trip was in flight (the tab
reconciler dehydrating after the last tab closed) could land between the
reload's kill and respawn: it killed nothing and orphaned the freshly
spawned agent with no tab attached. The store's hydrate/dehydrate — the
same methods the reconciler drives — now queue behind a per-conversation
gate held for the duration of restartConversation, so ordering is always
kill -> respawn -> queued changes. The reconciler's own intent-flip
handling then converges (teardown kills the respawn, or rehydrates if
the tab reopened).
@64ix
64ix merged commit 03667bc into fork-main Aug 24, 2026
1 check passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant