You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Feature: render session transcript as interleaved AI-comment / CLI-action bubbles
Summary
The session transcript view (and session replay) currently groups all
tool calls for a turn into a single assistant bubble (with tool cards
collapsed inside it), with any AI commentary emitted before/during
those tool calls also collapsed into the same bubble. The dash TUI
shows the same data chronologically: each AI text segment and each
tool call as a separate row, in the order they were actually emitted.
I'd like the WebUI to offer the same chronological / interleaved view.
Current behavior
Given a turn where the assistant thinks, calls a tool, thinks again,
calls another tool, and emits final text, the WebUI shows:
💬 user: "fix the bug"
🤖 assistant: "I'll check the file first."
[▸ terminal: cat /path/to/file]
[▸ terminal: patch -p1 < fix.patch]
"Done — here's what changed."
The "I'll check the file first." text, the two terminal tool cards,
and the "Done — here's what changed." text are all rendered inside
one assistant bubble. You have to expand each tool card to see what
it did, and the chronological relationship between the AI commentary
and the tool calls is hard to follow.
Desired behavior
A new view mode that renders the turn chronologically as separate
bubbles, in the order they were actually emitted:
💬 user: "fix the bug"
🤖 ai: "I'll check the file first."
⏵ terminal: cat /path/to/file
(output: …)
🤖 ai: "Now I'll apply the patch."
⏵ terminal: patch -p1 < fix.patch
(output: …)
🤖 ai: "Done — here's what changed."
This matches what the dash TUI already shows and is what most users
expect when they read a "what did the agent actually do" log.
Why it matters
Readability — long turns with many tool calls are hard to scan
when everything is collapsed into one bubble.
Debugging — when something goes wrong mid-turn, the user has
to expand each tool card to find which step failed and what the
assistant was thinking at the time.
Audit / log review — the chronological view IS the source of
truth (it's how the data is stored in the journal); the current
view is a derived layout that drops temporal information.
Parity with dash TUI — users switching between the two UIs
shouldn't have to mentally re-arrange the same data.
Proposed approach
The session message data already preserves the ordering (assistant
message has content[] with text and tool_use parts in sequence;
separate role: 'tool' messages have tool_call_id linking back).
The render layer just needs to walk those parts in order and emit
one row per part instead of merging them into a single assistant
row.
Sketch of the change, roughly localized to static/ui.js's renderMessages function (line 6453 in current master):
// Where today (line ~475) the code does:// (m.tool_calls||[]).forEach(tc => { … render tool card … });// inside an outer "render one assistant row" loop, change to:function*walkMessageParts(m){// For each assistant message, yield interleaved// {kind:'text', text} and {kind:'tool', toolCall} in order.for(constpartof(m.content||[])){if(part?.type==='text'&&part.text)yield{kind:'text',text: part.text};elseif(part?.type==='tool_use')yield{kind:'tool',toolCall: part};}// Then any top-level tool_calls array entries.for(consttcof(m.tool_calls||[]))yield{kind:'tool',toolCall: tc};}
Then in the render loop, instead of "one row per message", walk
each emitted part and render text parts as assistant text bubbles
and tool parts as their own tool cards. role: 'tool' result
messages stay as separate bubbles, already keyed by tool_call_id so they can be inserted adjacent to their parent
tool card (or remain grouped, depending on view mode).
Scope of change
static/ui.js — the renderMessages function (~700 lines). Most
of the change is in the assistant-message rendering branch.
Possibly static/sessions.js — if a "view mode" toggle is added
(collapsed / interleaved / TUI-mode), state lives here.
Likely a small CSS addition for the new "tui-bubble" row style.
No backend changes — all the needed data is already on each
assistant message.
Open questions for maintainers
Default view? Stay collapsed (current default) and add a
per-session "tui view" toggle, or flip the default? (I'd vote
keep collapsed default to avoid regressing long transcripts;
offer the toggle.)
Reuse / re-derive tool result bubbles? Today role:'tool'
messages are rendered too. In interleaved mode, should the tool
result stay adjacent to the tool card (preferred) or remain a
separate bubble?
Compaction messages? Compressed turns synthesize a single
assistant message with no parts. Should those be skipped in
interleaved mode, or rendered with a "summary" marker?
Feature: render session transcript as interleaved AI-comment / CLI-action bubbles
Summary
The session transcript view (and session replay) currently groups all
tool calls for a turn into a single assistant bubble (with tool cards
collapsed inside it), with any AI commentary emitted before/during
those tool calls also collapsed into the same bubble. The dash TUI
shows the same data chronologically: each AI text segment and each
tool call as a separate row, in the order they were actually emitted.
I'd like the WebUI to offer the same chronological / interleaved view.
Current behavior
Given a turn where the assistant thinks, calls a tool, thinks again,
calls another tool, and emits final text, the WebUI shows:
💬 user: "fix the bug"
🤖 assistant: "I'll check the file first."
[▸ terminal: cat /path/to/file]
[▸ terminal: patch -p1 < fix.patch]
"Done — here's what changed."
The "I'll check the file first." text, the two terminal tool cards,
and the "Done — here's what changed." text are all rendered inside
one assistant bubble. You have to expand each tool card to see what
it did, and the chronological relationship between the AI commentary
and the tool calls is hard to follow.
Desired behavior
A new view mode that renders the turn chronologically as separate
bubbles, in the order they were actually emitted:
💬 user: "fix the bug"
🤖 ai: "I'll check the file first."
⏵ terminal:
cat /path/to/file(output: …)
🤖 ai: "Now I'll apply the patch."
⏵ terminal:
patch -p1 < fix.patch(output: …)
🤖 ai: "Done — here's what changed."
This matches what the dash TUI already shows and is what most users
expect when they read a "what did the agent actually do" log.
Why it matters
when everything is collapsed into one bubble.
to expand each tool card to find which step failed and what the
assistant was thinking at the time.
truth (it's how the data is stored in the journal); the current
view is a derived layout that drops temporal information.
shouldn't have to mentally re-arrange the same data.
Proposed approach
The session message data already preserves the ordering (assistant
message has
content[]with text andtool_useparts in sequence;separate
role: 'tool'messages havetool_call_idlinking back).The render layer just needs to walk those parts in order and emit
one row per part instead of merging them into a single assistant
row.
Sketch of the change, roughly localized to
static/ui.js'srenderMessagesfunction (line 6453 in current master):Then in the render loop, instead of "one row per message", walk
each emitted part and render text parts as assistant text bubbles
and tool parts as their own tool cards.
role: 'tool'resultmessages stay as separate bubbles, already keyed by
tool_call_idso they can be inserted adjacent to their parenttool card (or remain grouped, depending on view mode).
Scope of change
static/ui.js— therenderMessagesfunction (~700 lines). Mostof the change is in the assistant-message rendering branch.
static/sessions.js— if a "view mode" toggle is added(collapsed / interleaved / TUI-mode), state lives here.
assistant message.
Open questions for maintainers
per-session "tui view" toggle, or flip the default? (I'd vote
keep collapsed default to avoid regressing long transcripts;
offer the toggle.)
role:'tool'messages are rendered too. In interleaved mode, should the tool
result stay adjacent to the tool card (preferred) or remain a
separate bubble?
being filled — render it in collapsed mode until streaming ends,
then "promote" to interleaved on settle? (See fix: reattach SSE on session-switch return and preserve live progress (closes #2924) #3005 for related
live-stream work.)
assistant message with no parts. Should those be skipped in
interleaved mode, or rendered with a "summary" marker?
Related
progress; related to streaming half of this feature)
alternative: compact mode groups all tool activity, opposite
direction)
Implementation offer
Happy to send a PR for this. Suggest splitting into two:
walkMessagePartshelper + unit testagainst a few representative session transcripts.
renderMessageswith a view-mode toggle,default off, behind a per-session preference.
Reference: dash TUI's transcript renderer (in
hermes-agentdashcode) is the inspiration and the reference for ordering.