@@ -394,6 +394,66 @@ describe("tui-event-handlers: handleAgentEvent", () => {
394394 expect ( tui . requestRender ) . not . toHaveBeenCalled ( ) ;
395395 } ) ;
396396
397+ it ( "clears orphaned streaming when final arrives inactive but no runs remain in flight" , ( ) => {
398+ const { state, chatLog, setActivityStatus, handleChatEvent } = createHandlersHarness ( {
399+ state : { activeChatRunId : null } ,
400+ } ) ;
401+
402+ handleChatEvent ( {
403+ runId : "run-orphan" ,
404+ sessionKey : state . currentSessionKey ,
405+ state : "delta" ,
406+ message : { content : "partial" } ,
407+ } ) ;
408+ expect ( state . activeChatRunId ) . toBe ( "run-orphan" ) ;
409+ setActivityStatus . mockClear ( ) ;
410+
411+ // Simulate active pointer lost while the same run still completes (failover / gateway race).
412+ state . activeChatRunId = null ;
413+
414+ handleChatEvent ( {
415+ runId : "run-orphan" ,
416+ sessionKey : state . currentSessionKey ,
417+ state : "final" ,
418+ message : { content : [ { type : "text" , text : "done" } ] } ,
419+ } ) ;
420+
421+ expect ( chatLog . finalizeAssistant ) . toHaveBeenCalled ( ) ;
422+ expect ( setActivityStatus ) . toHaveBeenCalledWith ( "idle" ) ;
423+ } ) ;
424+
425+ it ( "does not clear activity on inactive final when another run is still in flight" , ( ) => {
426+ const { state, chatLog, setActivityStatus, handleChatEvent } = createHandlersHarness ( {
427+ state : { activeChatRunId : null } ,
428+ } ) ;
429+
430+ handleChatEvent ( {
431+ runId : "run-a" ,
432+ sessionKey : state . currentSessionKey ,
433+ state : "delta" ,
434+ message : { content : "a" } ,
435+ } ) ;
436+ handleChatEvent ( {
437+ runId : "run-b" ,
438+ sessionKey : state . currentSessionKey ,
439+ state : "delta" ,
440+ message : { content : "b" } ,
441+ } ) ;
442+ expect ( state . activeChatRunId ) . toBe ( "run-a" ) ;
443+ state . activeChatRunId = "run-b" ;
444+ setActivityStatus . mockClear ( ) ;
445+
446+ handleChatEvent ( {
447+ runId : "run-a" ,
448+ sessionKey : state . currentSessionKey ,
449+ state : "final" ,
450+ message : { content : [ { type : "text" , text : "done a" } ] } ,
451+ } ) ;
452+
453+ expect ( chatLog . finalizeAssistant ) . toHaveBeenCalled ( ) ;
454+ expect ( setActivityStatus ) . not . toHaveBeenCalled ( ) ;
455+ } ) ;
456+
397457 it ( "suppresses tool events when verbose is off" , ( ) => {
398458 const { chatLog, tui, handleAgentEvent } = createHandlersHarness ( {
399459 state : {
0 commit comments