44import { describe , expect , it } from 'vitest'
55import type { ContentBlock } from '../../types'
66import {
7- assistantMessageHasRunningWork ,
7+ assistantMessageHasVisibleExecutingTool ,
88 parseBlocks ,
99 shouldShowTrailingThinking ,
1010 shouldSmoothTextSegment ,
@@ -14,10 +14,6 @@ function subagentStart(name: string, spanId: string, parentSpanId: string): Cont
1414 return { type : 'subagent' , content : name , spanId, parentSpanId, timestamp : 1 }
1515}
1616
17- function subagentEnd ( spanId : string ) : ContentBlock {
18- return { type : 'subagent_end' , spanId, timestamp : 2 }
19- }
20-
2117function subagentToolCall (
2218 id : string ,
2319 name : string ,
@@ -489,41 +485,46 @@ describe('parseBlocks legacy — thinking between top-level tools', () => {
489485 } )
490486} )
491487
492- describe ( 'assistantMessageHasRunningWork' , ( ) => {
493- it ( 'reads an open subagent lane as running work' , ( ) => {
494- expect ( assistantMessageHasRunningWork ( [ subagentStart ( 'workflow' , 'S1' , 'main' ) ] ) ) . toBe ( true )
495- } )
496-
497- it ( 'reads a lane closed by its paired subagent_end (live path) as settled' , ( ) => {
498- const blocks : ContentBlock [ ] = [ subagentStart ( 'workflow' , 'S1' , 'main' ) , subagentEnd ( 'S1' ) ]
499- expect ( assistantMessageHasRunningWork ( blocks ) ) . toBe ( false )
500- } )
501-
502- it ( 'reads a lane closed by a stamped endedAt (persisted path) as settled' , ( ) => {
503- const closed : ContentBlock = { ...subagentStart ( 'workflow' , 'S1' , 'main' ) , endedAt : 5 }
504- expect ( assistantMessageHasRunningWork ( [ closed ] ) ) . toBe ( false )
488+ describe ( 'assistantMessageHasVisibleExecutingTool' , ( ) => {
489+ it ( 'does not treat an open subagent lane as an executing tool row' , ( ) => {
490+ expect ( assistantMessageHasVisibleExecutingTool ( [ subagentStart ( 'workflow' , 'S1' , 'main' ) ] ) ) . toBe (
491+ false
492+ )
505493 } )
506494
507- it ( 'keeps an executing tool as running work after every lane closed ' , ( ) => {
495+ it ( 'keeps a visible executing tool as active work' , ( ) => {
508496 const blocks : ContentBlock [ ] = [
509497 subagentStart ( 'workflow' , 'S1' , 'main' ) ,
510- subagentEnd ( 'S1' ) ,
511498 {
512499 type : 'tool_call' ,
513- toolCall : { id : 't1' , name : 'grep' , status : 'executing' } ,
500+ toolCall : { id : 't1' , name : 'grep' , status : 'executing' , calledBy : 'workflow' } ,
501+ spanId : 'S1' ,
514502 timestamp : 3 ,
515503 } ,
516504 ]
517- expect ( assistantMessageHasRunningWork ( blocks ) ) . toBe ( true )
505+ expect ( assistantMessageHasVisibleExecutingTool ( blocks ) ) . toBe ( true )
518506 } )
519507
520- it ( 'tracks parallel lanes independently — one still- open lane keeps the turn running ' , ( ) => {
508+ it ( 'does not let open parallel lanes suppress the single turn-level indicator ' , ( ) => {
521509 const blocks : ContentBlock [ ] = [
522510 subagentStart ( 'workflow' , 'S1' , 'main' ) ,
523511 subagentStart ( 'search' , 'S2' , 'main' ) ,
524- subagentEnd ( 'S1' ) ,
525512 ]
526- expect ( assistantMessageHasRunningWork ( blocks ) ) . toBe ( true )
527- expect ( assistantMessageHasRunningWork ( [ ...blocks , subagentEnd ( 'S2' ) ] ) ) . toBe ( false )
513+ expect ( assistantMessageHasVisibleExecutingTool ( blocks ) ) . toBe ( false )
514+ } )
515+
516+ it ( 'ignores the executing dispatch tool represented by its subagent lane' , ( ) => {
517+ const blocks : ContentBlock [ ] = [
518+ {
519+ type : 'tool_call' ,
520+ toolCall : { id : 'dispatch-1' , name : 'workspace_file' , status : 'executing' } ,
521+ timestamp : 1 ,
522+ } ,
523+ {
524+ ...subagentStart ( 'file' , 'S1' , 'main' ) ,
525+ parentToolCallId : 'dispatch-1' ,
526+ } ,
527+ ]
528+ expect ( assistantMessageHasVisibleExecutingTool ( blocks ) ) . toBe ( false )
528529 } )
529530} )
0 commit comments