From 1500764b46cd24c60d42c96fb45e282626f1a0f5 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Thu, 20 Feb 2025 21:21:18 +0100 Subject: [PATCH] fix(react): handle non-concatenable messages --- libs/sdk-js/package.json | 2 +- libs/sdk-js/src/react/stream.tsx | 35 +++++++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/libs/sdk-js/package.json b/libs/sdk-js/package.json index 7cbae0cae..6b3f3733a 100644 --- a/libs/sdk-js/package.json +++ b/libs/sdk-js/package.json @@ -1,6 +1,6 @@ { "name": "@langchain/langgraph-sdk", - "version": "0.0.44", + "version": "0.0.45", "description": "Client library for interacting with the LangGraph API", "type": "module", "packageManager": "yarn@1.22.19", diff --git a/libs/sdk-js/src/react/stream.tsx b/libs/sdk-js/src/react/stream.tsx index a8685a19a..044e5fa4a 100644 --- a/libs/sdk-js/src/react/stream.tsx +++ b/libs/sdk-js/src/react/stream.tsx @@ -43,6 +43,7 @@ import { type BaseMessage, coerceMessageLikeToMessage, convertToChunk, + isBaseMessageChunk, } from "@langchain/core/messages"; class StreamError extends Error { @@ -60,8 +61,19 @@ class StreamError extends Error { } } +function tryConvertToChunk(message: BaseMessage): BaseMessageChunk | null { + try { + return convertToChunk(message); + } catch { + return null; + } +} + class MessageTupleManager { - chunks: Record = {}; + chunks: Record< + string, + { chunk?: BaseMessageChunk | BaseMessage; index?: number } + > = {}; constructor() { this.chunks = {}; @@ -76,13 +88,26 @@ class MessageTupleManager { .toLowerCase() as Message["type"]; } - const chunk = convertToChunk(coerceMessageLikeToMessage(serialized)); + const message = coerceMessageLikeToMessage(serialized); + const chunk = tryConvertToChunk(message); - const id = chunk.id; - if (!id) return null; + const id = (chunk ?? message).id; + if (!id) { + console.warn( + "No message ID found for chunk, ignoring in state", + serialized, + ); + return null; + } this.chunks[id] ??= {}; - this.chunks[id].chunk = this.chunks[id]?.chunk?.concat(chunk) ?? chunk; + if (chunk) { + const prev = this.chunks[id].chunk; + this.chunks[id].chunk = + (isBaseMessageChunk(prev) ? prev : null)?.concat(chunk) ?? chunk; + } else { + this.chunks[id].chunk = message; + } return id; }