From 2422ea39c657b9d81b930b0d4e22b6e22b93940c Mon Sep 17 00:00:00 2001 From: gongzhiyong Date: Mon, 13 Apr 2026 16:38:00 +0800 Subject: [PATCH] fix: prevent duplicate card rendering during streaming Streaming orphan UI cards section was rendering all cards with message_id=NONE as orphans, even when they were already claimed by the message-level orphan matching logic via card_id. Added card_id+tool_call_id check to prevent double rendering. Co-Authored-By: Claude Opus 4.6 (1M context) --- langgraph/src/main.tsx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/langgraph/src/main.tsx b/langgraph/src/main.tsx index 58fe565..348ed19 100644 --- a/langgraph/src/main.tsx +++ b/langgraph/src/main.tsx @@ -1041,10 +1041,21 @@ function App() { {thread.isLoading && deduplicateUiItems( (thread.values?.ui ?? []).filter((ui: UIMsgLocal) => { - const attachedToExisting = activeMessages.some( + // Check if attached by message_id + const attachedByMsgId = activeMessages.some( (m) => m.id === ui.metadata?.message_id, ); - return !attachedToExisting; + if (attachedByMsgId) return false; + // Check if attached by card_id matching any tool_call_id (orphan logic) + const cardId = ui.props?.card_id as string | undefined; + if (cardId) { + const claimedByToolCall = activeMessages.some((m) => { + const tcs: { id?: string }[] = (m as any).tool_calls ?? []; + return tcs.some((tc) => tc.id && cardId.includes(tc.id)); + }); + if (claimedByToolCall) return false; + } + return true; }) ) .map((ui: UIMsgLocal) => (