From bc8e675e2b8284da2bde32c636d2cdddad963e5b Mon Sep 17 00:00:00 2001 From: Amit Saroj Date: Wed, 3 Jun 2026 22:36:46 +0530 Subject: [PATCH 1/2] fix(ai): normalize AG-UI snapshot messages to UIMessage[] in MESSAGES_SNAPSHOT handler --- .../ai/src/activities/chat/stream/processor.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/ai/src/activities/chat/stream/processor.ts b/packages/ai/src/activities/chat/stream/processor.ts index 78c93fdb0..546e2ccd3 100644 --- a/packages/ai/src/activities/chat/stream/processor.ts +++ b/packages/ai/src/activities/chat/stream/processor.ts @@ -17,7 +17,7 @@ * @see docs/chat-architecture.md — Canonical reference for AG-UI chunk ordering, * adapter contract, single-shot flows, and expected UIMessage output. */ -import { generateMessageId, uiMessageToModelMessages } from '../messages.js' +import { generateMessageId, modelMessageToUIMessage, uiMessageToModelMessages } from '../messages.js' import { normalizeToolResult } from '../../../utilities/tool-result' import { defaultJSONParser } from './json-parser' import { @@ -870,8 +870,16 @@ export class StreamProcessor { chunk: Extract, ): void { this.resetStreamState() - // AG-UI Message[] is compatible with UIMessage[] at runtime - this.messages = [...chunk.messages] as Array + // Normalize AG-UI messages to UIMessage[] to ensure each message has + // a `parts` array. AG-UI snapshot messages carry `content` but no + // `parts`, so casting them directly as UIMessage[] is unsafe and causes + // "Cannot read properties of undefined (reading 'find')" when any code + // later accesses message.parts (e.g. onToolCallStateChange devtools handler). + this.messages = chunk.messages.map((msg) => + 'parts' in msg + ? (msg as UIMessage) + : modelMessageToUIMessage(msg as any, generateMessageId()), + ) this.emitMessagesChange() } From b091adc7e871329fdef2ac37443199072c309b6b Mon Sep 17 00:00:00 2001 From: Amit Saroj Date: Wed, 3 Jun 2026 22:52:38 +0530 Subject: [PATCH 2/2] fix(ai): preserve original msg.id in MESSAGES_SNAPSHOT normalization --- packages/ai/src/activities/chat/stream/processor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ai/src/activities/chat/stream/processor.ts b/packages/ai/src/activities/chat/stream/processor.ts index 546e2ccd3..9ec82e2e9 100644 --- a/packages/ai/src/activities/chat/stream/processor.ts +++ b/packages/ai/src/activities/chat/stream/processor.ts @@ -878,7 +878,7 @@ export class StreamProcessor { this.messages = chunk.messages.map((msg) => 'parts' in msg ? (msg as UIMessage) - : modelMessageToUIMessage(msg as any, generateMessageId()), + : modelMessageToUIMessage(msg as any, (msg as { id?: string }).id ?? generateMessageId()), ) this.emitMessagesChange() }