From 3fc24326840e76faa1681cece61d4d653ce5d073 Mon Sep 17 00:00:00 2001 From: Neha Prasad Date: Fri, 30 Jan 2026 00:14:34 +0530 Subject: [PATCH] fix: prevent Citations UI glitching during streaming chats (#4897) * fix: prevent Citations UI glitching during streaming chats * replaced random keys with stable keys * simplify citation glitch fix * Remove unneeded memo() * Simplify key logic * Replace Boolean(source) with !!source * change cohere to behave with citations like other models --------- Co-authored-by: shatfield4 Co-authored-by: Timothy Carambat Co-authored-by: Marcello Fitton --- .../ChatHistory/Citation/index.jsx | 19 +++++++++---------- frontend/src/utils/chat/index.js | 2 +- server/utils/AiProviders/cohere/index.js | 2 +- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/Citation/index.jsx b/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/Citation/index.jsx index 91e283ca..9d29b8bf 100644 --- a/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/Citation/index.jsx +++ b/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/Citation/index.jsx @@ -1,5 +1,4 @@ -import { memo, useState } from "react"; -import { v4 } from "uuid"; +import { Fragment, useState } from "react"; import { decode as HTMLDecode } from "he"; import truncate from "truncate"; import ModalWrapper from "@/components/ModalWrapper"; @@ -70,9 +69,9 @@ export default function Citations({ sources = [] }) { {open && (
- {combineLikeSources(sources).map((source) => ( + {combineLikeSources(sources).map((source, idx) => ( setSelectedSource(source)} textSizeClass={textSizeClass} @@ -90,7 +89,7 @@ export default function Citations({ sources = [] }) { ); } -const Citation = memo(({ source, onClick, textSizeClass }) => { +const Citation = ({ source, onClick, textSizeClass }) => { const { title, references = 1 } = source; if (!title) return null; const chunkSourceInfo = parseChunkSource(source); @@ -120,7 +119,7 @@ const Citation = memo(({ source, onClick, textSizeClass }) => {
); -}); +}; function omitChunkHeader(text) { if (!text.includes("")) return text; @@ -132,7 +131,7 @@ function CitationDetailModal({ source, onClose }) { const { isUrl, text: webpageUrl, href: linkTo } = parseChunkSource(source); return ( - +
@@ -175,8 +174,8 @@ function CitationDetailModal({ source, onClose }) { >
{chunks.map(({ text, score }, idx) => ( - <> -
+ +

{HTMLDecode(omitChunkHeader(text))} @@ -199,7 +198,7 @@ function CitationDetailModal({ source, onClose }) { {idx !== chunks.length - 1 && (


)} - + ))}
diff --git a/frontend/src/utils/chat/index.js b/frontend/src/utils/chat/index.js index def11bd6..f7672436 100644 --- a/frontend/src/utils/chat/index.js +++ b/frontend/src/utils/chat/index.js @@ -112,7 +112,7 @@ export default function handleChat( updatedHistory = { ...existingHistory, content: existingHistory.content + textResponse, - sources, + ...(sources && sources.length > 0 ? { sources } : {}), error, closed: close, animate: !close, diff --git a/server/utils/AiProviders/cohere/index.js b/server/utils/AiProviders/cohere/index.js index 18ac025a..aaf7a258 100644 --- a/server/utils/AiProviders/cohere/index.js +++ b/server/utils/AiProviders/cohere/index.js @@ -193,7 +193,7 @@ class CohereLLM { writeResponseChunk(response, { uuid, - sources, + sources: [], type: "textResponseChunk", textResponse: text, close: false,