cmux-next agent pane: split an agent reply at its tool calls

Merged
TE
1mo ago
+73-11

Part of the cmux-next parity work listed in #16174 (comment). One of the four agent pane bugs from the real-agent clip in #16231 (comment).

Problem

The direct client streamed every agent message chunk of a turn into one assistant row. Text before and after a tool call ran together ("...in path.rg is unavailable"), and the tool calls showed below all of it, out of order. A user message did not end the streaming row either, so the next reply could join the previous one.

Change

  • A new tool call ends the assistant row being streamed, so the text after it starts a new row below the tool activity. An update to a call already seen stays in that call's row.
  • A user message ends the streaming row too.
  • A row keeps its first timestamp while chunks append to it, so the rows stay in event order.

Verification

  • Red first: commit 1 adds the two tests in direct.test.ts, which fail before the fix.
  • bun test src/agent-session/acpmux (91 pass), typecheck, lint:ci, build-agent-pane-web.sh --check.

Screenshots

A real-agent clip from one fleet build with all four transcript fixes (feat-cmux-next-transcript-fixes-demo) will be added here. The mock transport writes rows directly and skips the client reducer, so a mock capture cannot show this fix.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Fixes the cmux-next agent pane so agent text before and after a tool call is split into separate rows instead of being streamed into one continuous reply. Tool calls now render in event order under the text they belong to.

  • A new tool call or thought ends the streamed assistant row; the text after it starts a new row below the tool activity.
  • Updates to a tool call already shown stay in that call's fold, so late status changes land where the call began.
  • A user message ends the streamed reply, so the next reply starts on its own row.
  • Rows keep the timestamp they began with, preserving event order as chunks append.
  • When a message is superseded, all the assistant rows it split into are dropped.