Hey! Just so you know this was written by Claude, but it's a super simple 2-line change, and it fixed some rendering of messages for me when I initiated a retry.
Thanks for the great package! Just thought I would let you all know.
---- Claude Notes ----
Bug
useUIMessages shows duplicate message content during streaming. For example, when an agent counts to 10 with tool calls between each number, the UI briefly shows entries like 7, 8, 7 + RunCode, 8 + RunCode — the text appears once without its tool call, then again with it.
The duplicates disappear once the stream finishes and only persisted messages remain.
Root cause
In useUIMessages, combineUIMessages runs before dedupeMessages:
const combined = combineUIMessages(sorted(paginated.results));
return { ...paginated, results: dedupeMessages(combined, streamMessages ?? []) };
combineUIMessages merges all adjacent assistant messages at the same order into a single UIMessage, collapsing its stepOrder to the first message's value (e.g. stepOrder: 1). When dedupeMessages then tries to match a streaming message at stepOrder: 13 against the combined message at stepOrder: 1, they don't match — so both are kept.
Fix
Swap the order — dedup first (while each persisted message still has its original stepOrder), then combine:
const deduped = dedupeMessages(sorted(paginated.results), streamMessages ?? []);
return { ...paginated, results: combineUIMessages(deduped) };
This is a two-line change in src/react/useUIMessages.ts.
Reproduction
Any multi-step agent generation with saveStreamDeltas: true where the LLM produces text + tool calls in each step. The duplicates appear transiently during streaming as each step transitions from streaming to persisted.
Easiest repro: prompt the agent to "count to 10, saying each number then calling a tool to sleep for 1 second before the next."
Hey! Just so you know this was written by Claude, but it's a super simple 2-line change, and it fixed some rendering of messages for me when I initiated a retry.
Thanks for the great package! Just thought I would let you all know.
---- Claude Notes ----
Bug
useUIMessagesshows duplicate message content during streaming. For example, when an agent counts to 10 with tool calls between each number, the UI briefly shows entries like7, 8, 7 + RunCode, 8 + RunCode— the text appears once without its tool call, then again with it.The duplicates disappear once the stream finishes and only persisted messages remain.
Root cause
In
useUIMessages,combineUIMessagesruns beforededupeMessages:combineUIMessagesmerges all adjacent assistant messages at the sameorderinto a single UIMessage, collapsing itsstepOrderto the first message's value (e.g.stepOrder: 1). WhendedupeMessagesthen tries to match a streaming message atstepOrder: 13against the combined message atstepOrder: 1, they don't match — so both are kept.Fix
Swap the order — dedup first (while each persisted message still has its original
stepOrder), then combine:This is a two-line change in
src/react/useUIMessages.ts.Reproduction
Any multi-step agent generation with
saveStreamDeltas: truewhere the LLM produces text + tool calls in each step. The duplicates appear transiently during streaming as each step transitions from streaming to persisted.Easiest repro: prompt the agent to "count to 10, saying each number then calling a tool to sleep for 1 second before the next."