@@ -376,12 +376,49 @@ export function useRealtimeChatHistory({
376376 }
377377 }
378378
379+ // Capture the just-completed assistant message from the realtime
380+ // buffer BEFORE clearing it. After compaction the refetched history
381+ // may be shorter and miss this message entirely. Fixes #505.
382+ const completedAssistant =
383+ realtimeMessages . length > 0
384+ ? ( ( ) => {
385+ const last = realtimeMessages [ realtimeMessages . length - 1 ] as
386+ | Record < string , unknown >
387+ | undefined
388+ return last ?. role === 'assistant' ? last : null
389+ } ) ( )
390+ : null
391+
379392 // Clear realtime buffer immediately — no more stale data in render
380393 store . clearRealtimeBuffer ( effectiveSessionKey )
381394 clearCompletedStreaming ( )
382395
383396 // Background refetch for long-term consistency — doesn't block render
384- queryClient . invalidateQueries ( { queryKey : key , refetchType : 'all' } )
397+ queryClient . invalidateQueries ( { queryKey : key , refetchType : 'all' } ) . then ( ( ) => {
398+ // Re-inject the completed assistant message if compaction dropped it
399+ if ( completedAssistant ) {
400+ const refetchData =
401+ queryClient . getQueryData < Record < string , unknown > > ( key )
402+ const refetchedMessages =
403+ ( refetchData ?. messages as Array < Record < string , unknown > > ) ?? [ ]
404+ const assistantTail = ( completedAssistant . content ?? completedAssistant . text ?? '' )
405+ . toString ( )
406+ . slice ( - 64 )
407+ const alreadyPresent = refetchedMessages . some (
408+ ( m ) =>
409+ m . role === 'assistant' &&
410+ ( ( m . content ?? m . text ?? '' ) as string ) . toString ( ) . slice ( - 64 ) === assistantTail ,
411+ )
412+ if ( ! alreadyPresent ) {
413+ appendHistoryMessage (
414+ queryClient ,
415+ effectiveFriendlyId ,
416+ effectiveSessionKey ,
417+ completedAssistant as unknown as import ( '@/types/chat' ) . ChatMessage ,
418+ )
419+ }
420+ }
421+ } )
385422
386423 // Check for compaction — significant message count drop
387424 const newData =
0 commit comments