@@ -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,14 @@ export function useChat(
511521 return b
512522 }
513523
524+ const isStale = ( ) => expectedGen !== undefined && streamGenRef . current !== expectedGen
525+
514526 const flush = ( ) => {
527+ if ( isStale ( ) ) return
515528 streamingBlocksRef . current = [ ...blocks ]
516529 const snapshot = { content : runningText , contentBlocks : [ ...blocks ] }
517530 setMessages ( ( prev ) => {
531+ if ( expectedGen !== undefined && streamGenRef . current !== expectedGen ) return prev
518532 const idx = prev . findIndex ( ( m ) => m . id === assistantId )
519533 if ( idx >= 0 ) {
520534 return prev . map ( ( m ) => ( m . id === assistantId ? { ...m , ...snapshot } : m ) )
@@ -524,6 +538,10 @@ export function useChat(
524538 }
525539
526540 while ( true ) {
541+ if ( isStale ( ) ) {
542+ reader . cancel ( ) . catch ( ( ) => { } )
543+ break
544+ }
527545 const { done, value } = await reader . read ( )
528546 if ( done ) break
529547
@@ -975,15 +993,15 @@ export function useChat(
975993 content : message ,
976994 ...( storedAttachments && { fileAttachments : storedAttachments } ) ,
977995 }
978- queryClient . setQueryData < TaskChatHistory > ( taskKeys . detail ( chatIdRef . current ) , ( old ) =>
979- old
996+ queryClient . setQueryData < TaskChatHistory > ( taskKeys . detail ( chatIdRef . current ) , ( old ) => {
997+ return old
980998 ? {
981999 ...old ,
9821000 messages : [ ...old . messages , cachedUserMsg ] ,
9831001 activeStreamId : userMessageId ,
9841002 }
9851003 : undefined
986- )
1004+ } )
9871005 }
9881006
9891007 const userAttachments = storedAttachments ?. map ( toDisplayAttachment )
@@ -1049,7 +1067,7 @@ export function useChat(
10491067
10501068 if ( ! response . body ) throw new Error ( 'No response body' )
10511069
1052- await processSSEStream ( response . body . getReader ( ) , assistantId )
1070+ await processSSEStream ( response . body . getReader ( ) , assistantId , gen )
10531071 } catch ( err ) {
10541072 if ( err instanceof Error && err . name === 'AbortError' ) return
10551073 setError ( err instanceof Error ? err . message : 'Failed to send message' )
@@ -1180,6 +1198,8 @@ export function useChat(
11801198
11811199 useEffect ( ( ) => {
11821200 return ( ) => {
1201+ abortControllerRef . current ?. abort ( )
1202+ abortControllerRef . current = null
11831203 streamGenRef . current ++
11841204 sendingRef . current = false
11851205 }
0 commit comments