feat(console): single Terminal Host — one PTY terminal per agent, re-parented between surfaces (#2378) - #2399
Merged
Merged
Conversation
…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
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Slice 3 of the console-retire epic (#2372). Extracts terminal hosting out of the console page into an app-level
TerminalHostso 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 inApp.tsx+DetachedWindow.tsx) owns a single<TerminalView>per paneId, portaled into a stable per-pane container.<TerminalSlot paneId>placeholder; the host re-parents the container (plainappendChildmove, 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
Verification
npm run typecheckclean ·npm run lint0 errors.TerminalHostsuite (one mount per paneId, re-parent-not-remount on hand-off, teardown on last-slot-unmount);consoleCrossTabMountguardrail kept green; the console + Glance dock suites re-pointed to the slot.Advances #2372. Closes #2378.
🤖 Generated with Claude Code