Skip to content

feat(console): single Terminal Host — one PTY terminal per agent, re-parented between surfaces (#2378) - #2399

Merged
kevinthelago merged 4 commits into
developfrom
2378-terminal-host
Jul 6, 2026
Merged

feat(console): single Terminal Host — one PTY terminal per agent, re-parented between surfaces (#2378)#2399
kevinthelago merged 4 commits into
developfrom
2378-terminal-host

Conversation

@kevinthelago

Copy link
Copy Markdown
Owner

Slice 3 of the console-retire epic (#2372). Extracts terminal hosting out of the console page into an app-level TerminalHost so the console grid cell and the Glance dock are equal peers over one terminal per agent — eliminating the pre-#2378 double-mount (two <TerminalView>s for one paneId coordinating by hand so they wouldn't fight over PTY sizing).

How

  • TerminalHost (mounted once per window in App.tsx + DetachedWindow.tsx) owns a single <TerminalView> per paneId, portaled into a stable per-pane container.
  • Surfaces drop a <TerminalSlot paneId> placeholder; the host re-parents the container (plain appendChild move, not a remount) into whichever slot currently owns it — console cell or Glance dock — parking it in a hidden holding node otherwise, so the xterm/PTY + scrollback survive the hand-off.
  • PaneAt → primary slot (supplies launch/cwd/status props); Glance dock → viewer slot (visibility only). Host composes: launch props from the primary, visibility/focus from the current owner.

Notes

  • Also fixes a latent double-count of live agents (one mount, not two).
  • Tear-off window gets its own host (it's a separate React root reconnecting to the same PTYs).

Verification

  • npm run typecheck clean · npm run lint 0 errors.
  • Tests: new TerminalHost suite (one mount per paneId, re-parent-not-remount on hand-off, teardown on last-slot-unmount); consoleCrossTabMount guardrail kept green; the console + Glance dock suites re-pointed to the slot.
  • Not yet exercised in the running app (GUI hand-off / tear-off).

Advances #2372. Closes #2378.

🤖 Generated with Claude Code

kevinthelago and others added 3 commits July 5, 2026 15:47
…parented between surfaces (#2378)

Extract terminal HOSTING out of the console page into an app-level TerminalHost
so the console grid cell and the Glance dock are equal peers over ONE terminal
per agent (no double-mount). TerminalHost owns a single <TerminalView> per paneId
(portaled into a stable per-pane container); a <TerminalSlot paneId> placeholder
re-parents that container into whichever surface currently shows it (console cell
OR glance dock), parking it in a hidden holding node otherwise so the xterm/PTY +
scrollback survive the hand-off intact.

Replaces the pre-#2378 double-mount: two <TerminalView>s for one paneId that
coordinated by hand ("only one is visible") to avoid fighting over PTY sizing.
One host = one terminal = no coordination hack, no doubled renderer memory, no
doubled reconnect side-effects, no double-counted live-agent tally.

- PaneAt drops a primary TerminalSlot (supplies launch/cwd/status props); the
  Glance dock drops a viewer slot (supplies visibility). Host composes: launch
  props from the primary, visibility/focus from the current owner.
- DetachedWindow (tear-off) gets its own TerminalHost — it's a separate window
  reconnecting to the same PTYs, so its console cells' slots need a host ancestor.
- Guardrail preserved: consoleCrossTabMount (every tab's panes stay warm across
  switches). New TerminalHost suite proves one mount per paneId + re-parent (not
  remount) on hand-off + teardown only when the last slot unmounts.

Advances #2372 (retire the console page — Glance becomes the sole surface).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kevinthelago
kevinthelago merged commit 49c6828 into develop Jul 6, 2026
7 checks passed
kevinthelago added a commit that referenced this pull request Jul 6, 2026
…point terminal mock

- glance.css: the drill transition moved to the shared .graph-drill-anim
  (shared/ui/layouts/graphCanvas.css, #2418) and GlanceWorkspace already
  uses it — dropped this file's now-dead .glance-drill-anim copy; kept
  the #2401 morph CSS.
- GlanceStreamMorph.test.tsx: the dock renders TerminalSlot since the
  single Terminal Host landed (#2378/#2399), so the old TerminalView
  mock intercepted nothing — mock the slot, mirroring the dock's test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kevinthelago
kevinthelago deleted the 2378-terminal-host branch July 6, 2026 19:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant