agent chat: other sessions' messages are one inline line each, whole when opened
Another agent's message in the agent chat is now one quiet disclosure line where it arrived, never a card cut short and never one group at the bottom. Opening the line shows the whole message under it, and the line stays where it was.
Leo, 2026-10-29:
- "why the f*** did you guys ff***ing ellipsis EVERYTHING WITH NO WAY TO EXPAND WHAT WAS SAID TO SEE"
- "AND IT'S SO F***ING AWKWARD TO SEE THEM THERE AT THE BOTTOM SINCE WHEN I EXPAND THEM IT JUMPS ME DOWN AND WHEN I COLLAPSE IT JUMPS ME UP"
- "LOOK AT THESE / LEARN FROM CLAUDE CODE"
- "the "read after this turn" stuff gets a bit redundant and also can't these be batched to you?"
Copied from Claude Code: inline placement, the one-line disclosure, the full text on expand, and quiet gray/white type. Kept: our colours and glass. Message delivery is unchanged.
What changed
- Placement: each message is its own row where it arrived. Delivered messages sit between the replies they came between. A steer the agent hasn't read sits in the running turn. A message queued behind the turn sits after it. The "N messages from M sessions" group card is removed (
WaitingMessagesCard,waitingMessages.ts, theWAITING_MESSAGESrow kind, and Find'smemberpath). - The line: the shared
DisclosureRowfrom #27262 shows the sender's mark, the sender, the message's first line muted, and a chevron. On hover: Open chat (its tooltip names the chat and its machine), Reply, and the existing actions. - Expand: a light panel shows "From: ", then the whole message as Markdown, wrapped and never cut, then images, Details (the envelope) and the reply editor. The eight-line cut, Show more and Minimal Mode's separate card are gone.
- No jumps: the transcript holds the line on its pixel while the panel opens or closes (
useAnchoredCollapse/foldAnchor). The browser test measures 0 px of movement mid-view and at the pinned end. - Queue state: "Read after this turn" shows once, above the first queued message, not on each. A steer keeps its own small "Read after this step" tag, since its state differs.
- State: open/closed is page-lived per chat and row (
incomingOpened.ts, which the row estimate reads), and Details usesuseTranscriptDisclosure, so scrolling a row out of the virtualized transcript keeps both. DisclosureRow: additive, optional props:open/onOpenChange,animates,toggleLabel,actions,className,openTitle,fadeIn. The defaults are unchanged for the sub-session card.
On "can't these be batched": acpmux already delivers messages queued behind a busy turn as one turn (hub/digest.rs take_joined / digest_blocks; test tests/hub_integration/agent_digest.rs, 12/12 at 9d8337eb: https://github.com/manaflow-ai/cmux/actions/runs/40838848815). The redundancy was only in the UI, so there is no daemon change.
Supersedes the received-message parts of #26373 and #25683 (same area, open, owner unreachable; left for their owner to close).
Takes back #26749: Leo asked for messages inline where they arrived ("AND IT'S SO F***ING AWKWARD TO SEE THEM THERE AT THE BOTTOM SINCE WHEN I EXPAND THEM IT JUMPS ME DOWN AND WHEN I COLLAPSE IT JUMPS ME UP"), so the one card for several waiting messages at the bottom is removed.
Takes back #26980: the fold of consecutive received messages is replaced by one disclosure line per message, for the same reason.
DisclosureRow came from #27262, which has now landed, and this branch merges base in. The shared row keeps #27262's state, which lasts across virtualization (useTranscriptDisclosure), and its Find reveal. An incoming message passes open/onOpenChange in place of disclosureKey, because the row estimate reads its state (incomingOpened.ts).
Gallery
agent-pane.incoming-message-disclosure:
- A (ships): the sender, then the first line muted.
- B: Claude Code's "Received a message from" wording.
- C: A plus a line count.
- D: the sender alone.
A also has an opened state. B, C and D are drawn only in the gallery. The before/after stills are in the gallery advisory run's artifact on this PR (the status comment links it). They stay out of the PR text, as the repo does for every gallery run.
Tests
- New:
test/incoming-message-disclosure-browser.test.ts(real pane, Chromium):- (a) no truncation without expand: a 40-paragraph message is one 26 px line; opened, all 40 paragraphs show and nothing is clipped (scrollHeight == clientHeight);
- (b) no scroll jump: the line's top is 363.5 ā 363.5 ā 363.5 mid-view and 535.5 ā 535.5 ā 535.5 when it is the last row and the view is pinned;
- (c) inline placement: three senders give three rows between two replies, and a queued run shows one "Read after this turn".
- Updated: the old-DOM tests across 16 files, now matching the new rows. 31 of them fail on a62e77b8 before the update.
- Before the merge: 220 pass, 0 fail across 17 files: https://github.com/manaflow-ai/cmux/actions/runs/40838311501
- After merging base (736f54c2):
tscpasses;- 165 of 169 tests pass across 19 files, including #27262's sub-session disclosure suites and #27313's reply-action suites: https://github.com/manaflow-ai/cmux/actions/runs/40864274277
- The 4 failures are
transcript-gap-select-browser.test.ts"RTL document gaps and both gutters preserve rtl/ltr line endpoints" (Chromium and WebKit). They fail the same way at base 8b110263, so they are a base red: https://github.com/manaflow-ai/cmux/actions/runs/40867075331
- Deleted, because their subject is gone: the eight-line cut and Show more tests, and the Minimal Mode-specific card tests.
Observed / Not run
- Observed: the runs above. An independent review of the merge resolution (a different model) returned SHIP.
- Not run:
test/gallery-coverage.test.ts, which fails on stale entries for files this PR doesn't touch;- no native build is needed (webview-only).
- Known edge: a scroll made by script within about 150 ms after a fold ends is put back by the hold. A wheel or touch releases the hold at once, so readers don't hit it.
Changelog
Changed: Messages from other agents and sessions show as one line where they arrived and open to the full message without moving the view.
Agent session: agent session
š¤ Generated with Claude Code