@@ -206,6 +206,15 @@ function parseBlocks(blocks: ContentBlock[]): MessageSegment[] {
206206 }
207207
208208 const flushLanes = ( ) => {
209+ // Finalize state on the already-pushed segments before we drop them from
210+ // the map. Without this, a thinking/main text/options/stopped block landing
211+ // between a subagent's start and its end strands the lane with stale
212+ // isOpen/isDelegating flags — the later subagent_end iterates groupsByKey
213+ // and can't find it to close.
214+ for ( const g of groupsByKey . values ( ) ) {
215+ g . isOpen = false
216+ g . isDelegating = false
217+ }
209218 groupsByKey . clear ( )
210219 activeGroupKey = null
211220 }
@@ -337,17 +346,24 @@ function parseBlocks(blocks: ContentBlock[]): MessageSegment[] {
337346 g . isDelegating = false
338347 }
339348 }
340- }
341- if ( block . parentToolCallId && activeGroupKey ?. endsWith ( `:${ block . parentToolCallId } ` ) ) {
342- activeGroupKey = null
343- } else if ( ! block . parentToolCallId ) {
344- for ( const g of groupsByKey . values ( ) ) {
345- if ( g . agentName !== 'mothership' ) {
346- g . isOpen = false
347- g . isDelegating = false
349+ if ( activeGroupKey ?. endsWith ( `:${ block . parentToolCallId } ` ) ) {
350+ activeGroupKey = null
351+ }
352+ } else {
353+ // Unparented end blocks come from legacy/partial persisted streams
354+ // that predate parentToolCallId. Only collapse a lane this way when
355+ // we have no parented groups, so we don't force-close legitimate
356+ // parallel lanes mid-render.
357+ const hasParentedGroup = [ ...groupsByKey . keys ( ) ] . some ( ( key ) => ! key . endsWith ( ':legacy' ) )
358+ if ( ! hasParentedGroup ) {
359+ for ( const g of groupsByKey . values ( ) ) {
360+ if ( g . agentName !== 'mothership' ) {
361+ g . isOpen = false
362+ g . isDelegating = false
363+ }
348364 }
365+ activeGroupKey = null
349366 }
350- activeGroupKey = null
351367 }
352368 continue
353369 }
0 commit comments