Skip to content

Commit d5449f3

Browse files
committed
fix: restore JSON.stringify messages memo to fix streaming tool call re-renders
1 parent 5f464e6 commit d5449f3

1 file changed

Lines changed: 21 additions & 9 deletions

File tree

packages/react-core/src/v2/components/chat/CopilotChat.tsx

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -437,24 +437,36 @@ export function CopilotChat({
437437
? "processing"
438438
: transcribeMode;
439439

440-
// Memoize messages array - only create new reference when content actually changes
441-
// (agent.messages is mutated in place, so we need a new reference for React to detect changes)
442-
443-
// Use message id + role + content length as memo key instead of JSON.stringify
444-
// to avoid serializing large base64 content on every render while still detecting
445-
// content changes during streaming
440+
// Memoize messages array only create a new reference when content changes.
441+
// We build a lightweight fingerprint instead of JSON.stringify to avoid
442+
// serializing large base64 attachment data on every render. The key captures:
443+
// - message id, role, content length (text streaming)
444+
// - content part count (multimodal additions)
445+
// - tool call ids + argument lengths (tool call streaming)
446446
const messagesMemoKey = agent.messages
447447
.map((m) => {
448-
const contentLen =
448+
const contentKey =
449449
typeof m.content === "string"
450450
? m.content.length
451451
: Array.isArray(m.content)
452452
? m.content.length
453453
: 0;
454-
return `${m.id}:${m.role}:${contentLen}`;
454+
const toolCallsKey =
455+
"toolCalls" in m && Array.isArray(m.toolCalls)
456+
? m.toolCalls
457+
.map(
458+
(tc: any) => `${tc.id}:${tc.function?.arguments?.length ?? 0}`,
459+
)
460+
.join(";")
461+
: "";
462+
return `${m.id}:${m.role}:${contentKey}:${toolCallsKey}`;
455463
})
456464
.join(",");
457-
const messages = useMemo(() => [...agent.messages], [messagesMemoKey]);
465+
const messages = useMemo(
466+
() => [...agent.messages],
467+
// eslint-disable-next-line react-hooks/exhaustive-deps
468+
[messagesMemoKey],
469+
);
458470

459471
const finalProps = merge(mergedProps, {
460472
messages,

0 commit comments

Comments
 (0)