ai-chat: validate persisted messages, fix metadata on broadcast/resume, document advanced patterns#910
Conversation
…st/resume path. **Structural message validation:** Messages loaded from SQLite are now validated for required structure (non-empty `id` string, valid `role`, `parts` is an array). Malformed rows — from corruption, manual tampering, or schema drift — are logged with a warning and silently skipped instead of crashing the agent. This is intentionally lenient: empty `parts` arrays are allowed (streams that errored mid-flight), and no tool/data schema validation is performed at load time (that remains a userland concern via `safeValidateUIMessages` from the AI SDK). **Message metadata on broadcast/resume path:** The server already captures `messageMetadata` from `start`, `finish`, and `message-metadata` stream chunks and persists it on `message.metadata`. However, the client-side broadcast path (multi-tab sync) and stream resume path (reconnection) did not propagate metadata — the `activeStreamRef` only tracked `parts`. Now it also tracks `metadata`, and `flushActiveStreamToMessages` includes it in the partial message flushed to React state. This means cross-tab clients and reconnecting clients see metadata (model info, token usage, timestamps) during streaming, not just after the final `CF_AGENT_CHAT_MESSAGES` broadcast.
🦋 Changeset detectedLatest commit: 58924ab The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
|
/bonk review this pr |
|
Now I have a thorough understanding of all the changes. Let me compile the review. PR Review: ai-chat: validate persisted messages, fix metadata on broadcast/resume, document advanced patternsOverall AssessmentClean, well-structured PR. The three concerns (validation, metadata propagation, docs) are logically distinct but small enough to ship together. The code is defensive, well-commented, and thoroughly tested. 1. Message Validation (
|
| Area | Verdict |
|---|---|
| Validation logic | Clean, correct, well-placed |
| Metadata propagation | Correct across all paths (broadcast, resume, continuation) |
| Tests | Thorough — 13 new tests covering all branches |
| Docs | Clear, practical, well-scoped |
| Changeset | Good |
Suggestions (non-blocking):
- Consider adding a test for the JSON parse failure path in
_loadMessagesFromDb(completely unparseable data) to make that coverage explicit. - Verify that
LanguageModelV3Middlewareis the current type name in the AI SDK version the project depends on.
Looks good to ship.
Add a unit test that ensures completely unparseable JSON messages are discarded by message validation. The test sets up an agent, persists a valid message, inserts a broken JSON raw message via agentStub.insertRawMessage, and asserts that getValidatedMessages returns only the valid message.
Summary
id,role,parts). Malformed rows from corruption, tampering, or schema drift are logged and silently skipped instead of crashing the agent.messageMetadatafromstart/finish/message-metadatastream chunks. Previously, cross-tab clients and reconnecting clients only received metadata after the finalCF_AGENT_CHAT_MESSAGESbroadcast — now they see it during streaming. Also fixes metadata loss during tool continuations.docs/chat-agents.mddocumenting AI SDK features that work out of the box inonChatMessage:prepareStep(dynamic model/tool control),wrapLanguageModel(middleware for guardrails, RAG, caching),generateObject(structured output in tools),ToolLoopAgent(reusable subagents), andasync function*(preliminary tool results for streaming progress).Changes
packages/ai-chat/src/index.tsisValidMessageStructure()validation in_loadMessagesFromDb()packages/ai-chat/src/react.tsxactiveStreamRefnow tracksmetadata; chunk handler captures metadata from stream events;flushActiveStreamToMessagesincludes metadata; continuation path carries over existing metadatapackages/ai-chat/src/tests/validate-messages.test.tspackages/ai-chat/src/tests/message-builder.test.tsapplyChunkToPartsreturnsfalsefor metadata-level chunks (start,finish,message-metadata,finish-step)packages/ai-chat/src/tests/worker.tsinsertRawMessage()helper for injecting malformed rows in testsdocs/chat-agents.mdprepareStep, middleware,generateObject,ToolLoopAgent, and preliminary results.changeset/validate-messages-and-metadata.md@cloudflare/ai-chatTest plan
npm run checkpasses (typecheck, oxlint, oxfmt, sherif, export checks)