Adds a full, non-capped agent terminal reachable from a new expand trigger on the embedded AgentTermPreview (the detail-panel preview on AgentsPage stays as-is, just gains the trigger). Opens /agents/:name/terminal in a new dynamic tab in Shell's header, next to the static nav row — tabs persist across a reload via useDynamicTabs, a small localStorage-backed hook built on @hive/shared's existing settings-storage primitive. AgentTermPreview gains two new props to support both mounts from one component: fullHeight (drops the 12em preview cap, fills its page) and showHeaderBadges (default true — lets a future caller that already shows turn_state/model/ctx/cost elsewhere suppress this cluster; AgentsPage doesn't use it, see below). Deviation from the originally posted plan (issue comment 80596): that plan proposed AgentsPage's embedded preview pass showHeaderBadges as false, reasoning the detail panel already duplicates that info. Checked the actual code before implementing — it doesn't; AgentRow/ AgentTypes.ts carry none of turn_state/model/ctx/cost, and AgentTermPreview's own floating badges are the only place swarm-ui shows them. Left the badges visible there instead of shipping a regression the plan's own stated justification didn't hold up to. Also fixed a same-tab pub/sub race found by actually rendering a cold load of /agents/:name/terminal (headless chromium, not just reasoning about the code): useLocalSetting subscribes inside a useEffect, and mount effects fire children-before-parents, so a descendant's mount-time write (AgentTerminalPage registering its own tab) can beat an ancestor's (Shell's) subscription into existence, leaving Shell's tab row silently empty on a direct/reload load. Fixed by having useDynamicTabs re-sync from storage on every location change, not just on notify() — the fix lives in the new hook itself, not in the shared settings-storage primitive theme/motion overrides also use.
107 lines
4.7 KiB
CSS
107 lines
4.7 KiB
CSS
/* <AgentTermPreview> — a *preview*, not the full terminal: a much
|
|
shorter cap than @hive/shared/terminal.css's own 32em default so it
|
|
reads as "peek at what's happening" inside the detail panel rather
|
|
than competing with the panel's own fields for vertical space. */
|
|
@import "@hive/shared/terminal.css";
|
|
|
|
.ui-agent-term-preview {
|
|
margin-block-start: 1rem;
|
|
}
|
|
|
|
/* Holds the connection-status badge + (unless `fullHeight`) the
|
|
expand-to-fullscreen trigger — `margin-left: auto` targets the expand
|
|
trigger by its OWN class, not `:last-child` (tried that first; it
|
|
silently broke when `fullHeight` hides the expand trigger, since the
|
|
status badge then becomes the `:last-child` too and gets pushed to
|
|
the right edge instead of staying flush left — caught by actually
|
|
rendering the `fullHeight` case, not just reasoning about the CSS).
|
|
Same split-row intent `Shell.css`'s `.shell-header-actions` already
|
|
uses for its own pair of triggers, just addressed directly instead of
|
|
positionally. */
|
|
.ui-agent-term-preview-toolbar {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-block-end: 0.5rem;
|
|
}
|
|
.ui-agent-term-preview-expand {
|
|
margin-left: auto;
|
|
}
|
|
|
|
.ui-agent-term-preview-wrap.terminal-wrap {
|
|
max-height: 12em;
|
|
}
|
|
|
|
/* `AgentTerminalPage`'s full-tab mount (`fullHeight` prop → the
|
|
`-full` modifier on the OUTER `.ui-agent-term-preview` root, not the
|
|
wrap) — self-contained flex chain, not dependent on the page around
|
|
it doing anything beyond giving this root a real height to fill (see
|
|
AgentTerminalPage.css). Column flex so the toolbar keeps its natural
|
|
height and the terminal-wrap below it takes the rest; `flex: 1` +
|
|
`min-height: 0` on the wrap (not `height: 100%`) is deliberate — a
|
|
flex item's `height` percentage doesn't account for a sibling
|
|
(the toolbar) already consuming space the way `flex: 1` does, and
|
|
`min-height: 0` is what actually lets the item shrink below its
|
|
content's natural height so `.live.terminal`'s own `overflow-y: auto`
|
|
(terminal.css) scrolls instead of the whole column growing past its
|
|
container. `!important`-free, but the `max-height: none` overrides
|
|
below rely on source order (equal specificity to the un-modified
|
|
rules above — same class count on both sides), not on being "more
|
|
specific" — keep this block after the un-modified one if this file
|
|
is ever reordered. */
|
|
.ui-agent-term-preview-full {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
.ui-agent-term-preview-full .ui-agent-term-preview-wrap.terminal-wrap {
|
|
max-height: none;
|
|
flex: 1;
|
|
min-height: 0;
|
|
}
|
|
.ui-agent-term-preview-full .ui-agent-term-preview-wrap .live.terminal {
|
|
max-height: none;
|
|
height: 100%;
|
|
}
|
|
|
|
/* `box-sizing: border-box`, not the browser's default `content-box` —
|
|
`.live.terminal`'s own `padding: 0.8em 1em 0.4em` (terminal.css) is
|
|
otherwise added ON TOP of this `max-height`, so the box renders
|
|
~1.2em taller than intended and spills past `.terminal-wrap`'s own
|
|
`max-height` above (which has no padding of its own to inflate it)
|
|
since `.terminal-wrap` has no `overflow: hidden` to catch the excess
|
|
— mara: "the terminal text bleeds out at the bottom of the terminal".
|
|
Confirmed via measured `clientHeight` (194px vs the wrap's 177px, a
|
|
~17px gap matching 1.2em at this font size) before this fix, not
|
|
just reasoning about the CSS. */
|
|
.ui-agent-term-preview-wrap .live.terminal {
|
|
max-height: 12em;
|
|
box-sizing: border-box;
|
|
/* Extra top padding (base `.live.terminal` rule: `0.8em 1em 0.4em`) so
|
|
the floating badge cluster below has room to sit above the first
|
|
row's text instead of overlapping it — found by actually rendering
|
|
this: with the base padding, "thinking"/"model sonnet" sat directly
|
|
on top of the terminal's first line whenever content started right
|
|
at the top (a running preview scrolled to the newest rows almost
|
|
always does). */
|
|
padding-block-start: 2.4em;
|
|
}
|
|
|
|
/* Floating turn_state/agent_state/model/ctx/cost badge cluster —
|
|
positioned by `.terminal-wrap`'s own `position: relative`, same
|
|
anchor `@hive/shared/terminal.css`'s `.tail-pill` already uses, rather
|
|
than a second positioned ancestor of our own. Top-right corner: the
|
|
scroll-to-bottom `.tail-pill` (that same stylesheet) anchors
|
|
bottom-right, so the two overlays never compete for the same corner.
|
|
`flex-wrap` rather than a fixed width — a badge cluster this narrow
|
|
can still overflow the box at small viewport widths, and wrapping
|
|
beats clipping or shrinking the terminal underneath. */
|
|
.ui-agent-term-preview-header-badges {
|
|
position: absolute;
|
|
top: 0.4em;
|
|
right: 0.4em;
|
|
z-index: 1;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
justify-content: flex-end;
|
|
gap: 0.25em;
|
|
max-width: calc(100% - 0.8em);
|
|
}
|