@@ -3022,6 +3022,160 @@ describe("agent event handler", () => {
30223022 ) ;
30233023 } ) ;
30243024
3025+ it ( "mirrors commentary-phase assistant events only to exact session message subscribers" , ( ) => {
3026+ const {
3027+ broadcast,
3028+ broadcastToConnIds,
3029+ nodeSendToSession,
3030+ sessionMessageSubscribers,
3031+ handler,
3032+ nowSpy,
3033+ } = createHarness ( {
3034+ now : 1_000 ,
3035+ resolveSessionKeyForRun : ( ) => "session-hidden" ,
3036+ } ) ;
3037+ sessionMessageSubscribers . subscribe ( "conn-selected" , "session-hidden" ) ;
3038+ sessionMessageSubscribers . subscribe ( "conn-other" , "session-other" ) ;
3039+ registerAgentRunContext ( "run-hidden-commentary" , {
3040+ sessionKey : "session-hidden" ,
3041+ isControlUiVisible : false ,
3042+ verboseLevel : "off" ,
3043+ } ) ;
3044+
3045+ handler ( {
3046+ runId : "run-hidden-commentary" ,
3047+ seq : 1 ,
3048+ stream : "assistant" ,
3049+ ts : Date . now ( ) ,
3050+ data : {
3051+ text : "I will inspect the files first." ,
3052+ delta : "I will inspect the files first." ,
3053+ phase : "commentary" ,
3054+ } ,
3055+ } ) ;
3056+ handler ( {
3057+ runId : "run-hidden-commentary" ,
3058+ seq : 2 ,
3059+ stream : "assistant" ,
3060+ ts : Date . now ( ) ,
3061+ data : {
3062+ text : "Untagged text frame must not mirror." ,
3063+ delta : "Untagged text frame must not mirror." ,
3064+ } ,
3065+ } ) ;
3066+ handler ( {
3067+ runId : "run-hidden-commentary" ,
3068+ seq : 3 ,
3069+ stream : "assistant" ,
3070+ ts : Date . now ( ) ,
3071+ data : {
3072+ delta : "Untagged delta-only stream must not mirror." ,
3073+ } ,
3074+ } ) ;
3075+ handler ( {
3076+ runId : "run-hidden-commentary" ,
3077+ seq : 4 ,
3078+ stream : "assistant" ,
3079+ ts : Date . now ( ) ,
3080+ data : { text : "Terminal echo without delta" } ,
3081+ } ) ;
3082+ handler ( {
3083+ runId : "run-hidden-commentary" ,
3084+ seq : 5 ,
3085+ stream : "assistant" ,
3086+ ts : Date . now ( ) ,
3087+ data : { text : "Final answer" , delta : "Final answer" , phase : "final_answer" } ,
3088+ } ) ;
3089+ handler ( {
3090+ runId : "run-hidden-commentary" ,
3091+ seq : 6 ,
3092+ stream : "assistant" ,
3093+ ts : Date . now ( ) ,
3094+ data : {
3095+ delta : "Streaming commentary delta." ,
3096+ phase : "commentary" ,
3097+ } ,
3098+ } ) ;
3099+
3100+ expect ( chatBroadcastCalls ( broadcast ) ) . toHaveLength ( 0 ) ;
3101+ expect ( agentBroadcastCalls ( broadcast ) ) . toHaveLength ( 0 ) ;
3102+ expect ( nodeSendToSession ) . not . toHaveBeenCalled ( ) ;
3103+
3104+ const agentCalls = broadcastToConnIds . mock . calls . filter ( ( [ event ] ) => event === "agent" ) ;
3105+ expect ( agentCalls ) . toHaveLength ( 2 ) ;
3106+ expect ( agentCalls [ 0 ] ?. [ 2 ] ) . toEqual ( new Set ( [ "conn-selected" ] ) ) ;
3107+ expect ( agentCalls [ 1 ] ?. [ 2 ] ) . toEqual ( new Set ( [ "conn-selected" ] ) ) ;
3108+ expectPayloadFields ( agentCalls [ 0 ] ?. [ 1 ] , {
3109+ runId : "run-hidden-commentary" ,
3110+ sessionKey : "session-hidden" ,
3111+ stream : "assistant" ,
3112+ } ) ;
3113+ expectPayloadFields ( agentCalls [ 1 ] ?. [ 1 ] , {
3114+ runId : "run-hidden-commentary" ,
3115+ sessionKey : "session-hidden" ,
3116+ stream : "assistant" ,
3117+ } ) ;
3118+ expectPayloadDataFields ( agentCalls [ 0 ] ?. [ 1 ] , {
3119+ text : "I will inspect the files first." ,
3120+ delta : "I will inspect the files first." ,
3121+ phase : "commentary" ,
3122+ } ) ;
3123+ expectPayloadDataFields ( agentCalls [ 1 ] ?. [ 1 ] , {
3124+ delta : "Streaming commentary delta." ,
3125+ phase : "commentary" ,
3126+ } ) ;
3127+
3128+ const chatCalls = broadcastToConnIds . mock . calls . filter ( ( [ event ] ) => event === "chat" ) ;
3129+ expect ( chatCalls ) . toHaveLength ( 1 ) ;
3130+ expect ( chatCalls [ 0 ] ?. [ 2 ] ) . toEqual ( new Set ( [ "conn-selected" ] ) ) ;
3131+ expectPayloadFields ( chatCalls [ 0 ] ?. [ 1 ] , {
3132+ runId : "run-hidden-commentary" ,
3133+ sessionKey : "session-hidden" ,
3134+ state : "delta" ,
3135+ } ) ;
3136+ nowSpy ?. mockRestore ( ) ;
3137+ } ) ;
3138+
3139+ it ( "does not mirror aborted non-control-UI-visible assistant commentary" , ( ) => {
3140+ const {
3141+ broadcast,
3142+ broadcastToConnIds,
3143+ chatRunState,
3144+ nodeSendToSession,
3145+ sessionMessageSubscribers,
3146+ handler,
3147+ nowSpy,
3148+ } = createHarness ( {
3149+ now : 1_000 ,
3150+ resolveSessionKeyForRun : ( ) => "session-hidden-aborted" ,
3151+ } ) ;
3152+ sessionMessageSubscribers . subscribe ( "conn-selected" , "session-hidden-aborted" ) ;
3153+ registerAgentRunContext ( "run-hidden-commentary-aborted" , {
3154+ sessionKey : "session-hidden-aborted" ,
3155+ isControlUiVisible : false ,
3156+ verboseLevel : "off" ,
3157+ } ) ;
3158+ chatRunState . abortedRuns . set ( "run-hidden-commentary-aborted" , 1_000 ) ;
3159+
3160+ handler ( {
3161+ runId : "run-hidden-commentary-aborted" ,
3162+ seq : 1 ,
3163+ stream : "assistant" ,
3164+ ts : Date . now ( ) ,
3165+ data : {
3166+ text : "This aborted commentary must not be mirrored." ,
3167+ delta : "This aborted commentary must not be mirrored." ,
3168+ phase : "commentary" ,
3169+ } ,
3170+ } ) ;
3171+
3172+ expect ( chatBroadcastCalls ( broadcast ) ) . toHaveLength ( 0 ) ;
3173+ expect ( agentBroadcastCalls ( broadcast ) ) . toHaveLength ( 0 ) ;
3174+ expect ( broadcastToConnIds ) . not . toHaveBeenCalled ( ) ;
3175+ expect ( nodeSendToSession ) . not . toHaveBeenCalled ( ) ;
3176+ nowSpy ?. mockRestore ( ) ;
3177+ } ) ;
3178+
30253179 it ( "uses agent event sessionKey when run-context lookup cannot resolve" , ( ) => {
30263180 const { broadcast, handler } = createHarness ( {
30273181 resolveSessionKeyForRun : ( ) => undefined ,
0 commit comments