Read back only the turns that parse, and say how many did not (#207)
Restoring a thread ended `stored as Message[]` — a cast, not a check — so whatever
the history store held reached `setMessages` and then every projection that draws
a transcript. A turn in another shape took the conversation down rather than
itself: a tool call written `{id, name, args}` instead of AG-UI's
`{id, type: "function", function: …}` reached a renderer that dereferenced
`toolCall.function.arguments`, and one bad turn made a thread unopenable.
Each turn is now parsed with `MessageSchema` from `@ag-ui/core` and one that does
not parse is left out. Checked where history enters the app rather than in a
projection, because there are several projections and one history.
A dropped turn is counted and shown. `readThreadMessages` returns the count
beside the messages and the conversation draws a line naming it, because a turn
that quietly disappears from a record people read back is worse than a visible
failure — it reads as a message nobody sent. That was the objection that closed
the earlier attempt at this, and it is the part worth getting right.
The original object is returned rather than `parsed.data`. Zod strips keys a
schema does not name, so handing back the parsed copy would turn a validation
step into a silent rewrite of every message that passed. The parse decides
whether a turn is well formed, not what it contains.
Failing closed to an open composer is unchanged: an unreadable history still lets
somebody type. Dropping the bad turns and keeping the good ones is strictly more
than casting everything was.
This is the browser half of what #199 reports as its third problem. The other
half — server-side run validation rejecting a whole run with `400 invalid_literal,
expected "function"`, which makes the thread unusable — is a separate change and
is not addressed here.
Diagnosis and the original test cases are Arpan Sarkar's, from #43; the shapes
asserted here are the ones that file found.
Closes #44 H
Hotragn Pettugani committed
342a292e681dab3fd081ed6faf42ebb42f9f6311
Parent: 434902f
Committed by GitHub <noreply@github.com>
on 8/24/2026, 4:06:18 PM