From 998ca72c274898f32363f4141b7ebb6de889e8de Mon Sep 17 00:00:00 2001 From: Charles Howard <96023061+charlesrhoward@users.noreply.github.com> Date: Sat, 21 Feb 2026 16:24:44 -0500 Subject: [PATCH 1/2] perf: use incremental chat message fingerprinting --- components/ai-chat-panel.tsx | 38 ++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/components/ai-chat-panel.tsx b/components/ai-chat-panel.tsx index 0d8510d..a123c67 100644 --- a/components/ai-chat-panel.tsx +++ b/components/ai-chat-panel.tsx @@ -436,12 +436,38 @@ export function AIChatPanel({ canvasDimensions }: AIChatPanelProps) { }, []) const getMessagesFingerprint = useCallback((msgs: UIMessage[]) => { - return JSON.stringify( - msgs.map((msg) => ({ - id: msg.id, - ...chatService.convertToDbMessage(msg), - })), - ) + if (msgs.length === 0) return "empty" + + const last = msgs[msgs.length - 1] + const lastWithMeta = last as UIMessage & { content?: string; createdAt?: Date | string } + + let textPartLength = 0 + let filePartCount = 0 + let reasoningPartCount = 0 + for (const part of last.parts || []) { + if (part.type === "text") { + textPartLength += part.text.length + } else if (part.type === "file") { + filePartCount += 1 + } else if (part.type === "reasoning") { + reasoningPartCount += 1 + } + } + + const createdAt = + lastWithMeta.createdAt instanceof Date ? lastWithMeta.createdAt.toISOString() : (lastWithMeta.createdAt ?? "") + + return [ + msgs.length, + last.id, + last.role, + createdAt, + lastWithMeta.content?.length ?? 0, + last.parts?.length ?? 0, + textPartLength, + filePartCount, + reasoningPartCount, + ].join("|") }, []) useLoadChatHistory({ From f72af4c87edafe6068d585cfd1c21c06b992fbc6 Mon Sep 17 00:00:00 2001 From: Charles Howard <96023061+charlesrhoward@users.noreply.github.com> Date: Sat, 21 Feb 2026 16:54:39 -0500 Subject: [PATCH 2/2] chore: retrigger checks for PR #40