@@ -396,11 +396,128 @@ describe('useSSE', () => {
396396 title : 'Error' ,
397397 message : 'Queued send failed' ,
398398 failedPrompt : 'queued message' ,
399+ kind : 'session' ,
399400 } )
400401
401402 unmount ( )
402403 } )
403404
405+ it ( 'retracts a network send error when the server confirms session activity' , async ( ) => {
406+ const queryClient = new QueryClient ( { defaultOptions : { queries : { retry : false } } } )
407+ const wrapper = ( { children } : { children : ReactNode } ) => (
408+ < QueryClientProvider client = { queryClient } > { children } </ QueryClientProvider >
409+ )
410+
411+ useSendErrorStore . getState ( ) . setError ( {
412+ sessionID : 'session-1' ,
413+ title : 'Connection Failed' ,
414+ message : 'Could not connect to the server.' ,
415+ failedPrompt : 'in-flight prompt' ,
416+ kind : 'network' ,
417+ } )
418+
419+ const { result, unmount } = renderHook (
420+ ( ) => useSSE ( 'http://localhost:5551' , '/repo' , 'session-1' ) ,
421+ { wrapper } ,
422+ )
423+
424+ await waitFor ( ( ) => expect ( MockEventSource . instances ) . toHaveLength ( 1 ) )
425+ act ( ( ) => {
426+ MockEventSource . instances [ 0 ] . emit ( 'connected' , { clientId : 'client-1' } )
427+ } )
428+ await waitFor ( ( ) => expect ( result . current . isConnected ) . toBe ( true ) )
429+
430+ act ( ( ) => {
431+ MockEventSource . instances [ 0 ] . emit ( 'message' , {
432+ type : 'message.updated' ,
433+ properties : {
434+ info : { id : 'assistant-1' , role : 'assistant' , sessionID : 'session-1' , time : { created : 1 } } ,
435+ } ,
436+ } )
437+ } )
438+
439+ expect ( useSendErrorStore . getState ( ) . getError ( 'session-1' ) ) . toBeNull ( )
440+
441+ unmount ( )
442+ } )
443+
444+ it ( 'retracts a network send error when the session goes idle' , async ( ) => {
445+ const queryClient = new QueryClient ( { defaultOptions : { queries : { retry : false } } } )
446+ const wrapper = ( { children } : { children : ReactNode } ) => (
447+ < QueryClientProvider client = { queryClient } > { children } </ QueryClientProvider >
448+ )
449+
450+ useSendErrorStore . getState ( ) . setError ( {
451+ sessionID : 'session-1' ,
452+ title : 'Request Timeout' ,
453+ message : 'The request took too long.' ,
454+ kind : 'network' ,
455+ } )
456+
457+ const { result, unmount } = renderHook (
458+ ( ) => useSSE ( 'http://localhost:5551' , '/repo' , 'session-1' ) ,
459+ { wrapper } ,
460+ )
461+
462+ await waitFor ( ( ) => expect ( MockEventSource . instances ) . toHaveLength ( 1 ) )
463+ act ( ( ) => {
464+ MockEventSource . instances [ 0 ] . emit ( 'connected' , { clientId : 'client-1' } )
465+ } )
466+ await waitFor ( ( ) => expect ( result . current . isConnected ) . toBe ( true ) )
467+
468+ act ( ( ) => {
469+ MockEventSource . instances [ 0 ] . emit ( 'message' , {
470+ type : 'session.idle' ,
471+ properties : { sessionID : 'session-1' } ,
472+ } )
473+ } )
474+
475+ expect ( useSendErrorStore . getState ( ) . getError ( 'session-1' ) ) . toBeNull ( )
476+
477+ unmount ( )
478+ } )
479+
480+ it ( 'preserves a server-reported session error when the session later goes idle' , async ( ) => {
481+ const queryClient = new QueryClient ( { defaultOptions : { queries : { retry : false } } } )
482+ const wrapper = ( { children } : { children : ReactNode } ) => (
483+ < QueryClientProvider client = { queryClient } > { children } </ QueryClientProvider >
484+ )
485+
486+ useSendErrorStore . getState ( ) . setQueuedPrompt ( 'session-1' , 'queued message' )
487+
488+ const { result, unmount } = renderHook (
489+ ( ) => useSSE ( 'http://localhost:5551' , '/repo' , 'session-1' ) ,
490+ { wrapper } ,
491+ )
492+
493+ await waitFor ( ( ) => expect ( MockEventSource . instances ) . toHaveLength ( 1 ) )
494+ act ( ( ) => {
495+ MockEventSource . instances [ 0 ] . emit ( 'connected' , { clientId : 'client-1' } )
496+ } )
497+ await waitFor ( ( ) => expect ( result . current . isConnected ) . toBe ( true ) )
498+
499+ act ( ( ) => {
500+ MockEventSource . instances [ 0 ] . emit ( 'message' , {
501+ type : 'session.error' ,
502+ properties : {
503+ sessionID : 'session-1' ,
504+ error : { name : 'UnknownError' , data : { message : 'Queued send failed' } } ,
505+ } ,
506+ } )
507+ } )
508+
509+ act ( ( ) => {
510+ MockEventSource . instances [ 0 ] . emit ( 'message' , {
511+ type : 'session.idle' ,
512+ properties : { sessionID : 'session-1' } ,
513+ } )
514+ } )
515+
516+ expect ( useSendErrorStore . getState ( ) . getError ( 'session-1' ) ) . not . toBeNull ( )
517+
518+ unmount ( )
519+ } )
520+
404521 it ( 'does not create a send error banner once the queued prompt has been cleared' , async ( ) => {
405522 const queryClient = new QueryClient ( {
406523 defaultOptions : {
0 commit comments