Skip to content

Commit 6fbf999

Browse files
author
Theodore Li
committed
Fix task switch causing duplicate text renderings
1 parent b930ee3 commit 6fbf999

1 file changed

Lines changed: 28 additions & 7 deletions

File tree

  • apps/sim/app/workspace/[workspaceId]/home/hooks

apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,11 @@ export function useChat(
279279

280280
const sendMessageRef = useRef<UseChatReturn['sendMessage']>(async () => {})
281281
const processSSEStreamRef = useRef<
282-
(reader: ReadableStreamDefaultReader<Uint8Array>, assistantId: string) => Promise<void>
282+
(
283+
reader: ReadableStreamDefaultReader<Uint8Array>,
284+
assistantId: string,
285+
expectedGen?: number
286+
) => Promise<void>
283287
>(async () => {})
284288
const finalizeRef = useRef<(options?: { error?: boolean }) => void>(() => {})
285289

@@ -379,7 +383,8 @@ export function useChat(
379383
}
380384

381385
appliedChatIdRef.current = chatHistory.id
382-
setMessages(chatHistory.messages.map(mapStoredMessage))
386+
const mappedMessages = chatHistory.messages.map(mapStoredMessage)
387+
setMessages(mappedMessages)
383388

384389
if (chatHistory.resources.length > 0) {
385390
setResources(chatHistory.resources)
@@ -392,6 +397,7 @@ export function useChat(
392397
}
393398

394399
if (activeStreamId && !sendingRef.current) {
400+
abortControllerRef.current?.abort()
395401
const gen = ++streamGenRef.current
396402
const abortController = new AbortController()
397403
abortControllerRef.current = abortController
@@ -461,7 +467,7 @@ export function useChat(
461467
},
462468
})
463469

464-
await processSSEStreamRef.current(combinedStream.getReader(), assistantId)
470+
await processSSEStreamRef.current(combinedStream.getReader(), assistantId, gen)
465471
} catch (err) {
466472
if (err instanceof Error && err.name === 'AbortError') return
467473
} finally {
@@ -489,7 +495,11 @@ export function useChat(
489495
}, [activeResourceId, resources])
490496

491497
const processSSEStream = useCallback(
492-
async (reader: ReadableStreamDefaultReader<Uint8Array>, assistantId: string) => {
498+
async (
499+
reader: ReadableStreamDefaultReader<Uint8Array>,
500+
assistantId: string,
501+
expectedGen?: number
502+
) => {
493503
const decoder = new TextDecoder()
494504
let buffer = ''
495505
const blocks: ContentBlock[] = []
@@ -511,10 +521,15 @@ export function useChat(
511521
return b
512522
}
513523

524+
const isStale = () =>
525+
expectedGen !== undefined && streamGenRef.current !== expectedGen
526+
514527
const flush = () => {
528+
if (isStale()) return
515529
streamingBlocksRef.current = [...blocks]
516530
const snapshot = { content: runningText, contentBlocks: [...blocks] }
517531
setMessages((prev) => {
532+
if (expectedGen !== undefined && streamGenRef.current !== expectedGen) return prev
518533
const idx = prev.findIndex((m) => m.id === assistantId)
519534
if (idx >= 0) {
520535
return prev.map((m) => (m.id === assistantId ? { ...m, ...snapshot } : m))
@@ -524,6 +539,10 @@ export function useChat(
524539
}
525540

526541
while (true) {
542+
if (isStale()) {
543+
reader.cancel().catch(() => {})
544+
break
545+
}
527546
const { done, value } = await reader.read()
528547
if (done) break
529548

@@ -975,15 +994,15 @@ export function useChat(
975994
content: message,
976995
...(storedAttachments && { fileAttachments: storedAttachments }),
977996
}
978-
queryClient.setQueryData<TaskChatHistory>(taskKeys.detail(chatIdRef.current), (old) =>
979-
old
997+
queryClient.setQueryData<TaskChatHistory>(taskKeys.detail(chatIdRef.current), (old) => {
998+
return old
980999
? {
9811000
...old,
9821001
messages: [...old.messages, cachedUserMsg],
9831002
activeStreamId: userMessageId,
9841003
}
9851004
: undefined
986-
)
1005+
})
9871006
}
9881007

9891008
const userAttachments = storedAttachments?.map(toDisplayAttachment)
@@ -1180,6 +1199,8 @@ export function useChat(
11801199

11811200
useEffect(() => {
11821201
return () => {
1202+
abortControllerRef.current?.abort()
1203+
abortControllerRef.current = null
11831204
streamGenRef.current++
11841205
sendingRef.current = false
11851206
}

0 commit comments

Comments
 (0)