@@ -358,50 +358,79 @@ const handleToolCall = (state: EventHandlerState, event: PrintModeToolCall) => {
358358/**
359359 * Recursively finds and updates agent blocks that match a spawn_agents tool call.
360360 */
361- const updateSpawnAgentBlocks = (
362- blocks : ContentBlock [ ] ,
361+ const updateSpawnAgentBlock = (
362+ block : ContentBlock ,
363363 toolCallId : string ,
364364 results : any [ ] ,
365- ) : ContentBlock [ ] => {
366- return blocks . map ( ( block ) => {
367- if ( block . type !== 'agent' ) {
368- return block
369- }
365+ ) : ContentBlock | null => {
366+ if ( block . type !== 'agent' ) {
367+ return block
368+ }
370369
371- if ( block . spawnToolCallId === toolCallId && block . spawnIndex !== undefined && block . blocks ) {
372- const result = results [ block . spawnIndex ]
373-
374- if ( result ?. value ) {
375- const { content, hasError } = extractSpawnAgentResultContent ( result . value )
376- // Check if the agent already streamed text content (e.g., basher).
377- // Agents like thinker return all output at the end via lastMessage,
378- // so we should add final content even if they have tool blocks.
379- const hasStreamedTextContent = block . blocks . some (
380- ( b ) => b . type === 'text' && b . textType === 'text'
381- )
382- const finalBlocks = content && ! hasStreamedTextContent
383- ? [ ...block . blocks , { type : 'text' , content } as ContentBlock ]
384- : block . blocks
385- if ( hasError || finalBlocks . length > 0 ) {
386- return {
387- ...block ,
388- blocks : finalBlocks ,
389- status : hasError ? ( 'failed' as const ) : ( 'complete' as const ) ,
390- }
370+ const spawnIndex = block . spawnIndex
371+ const childBlocks = block . blocks
372+ const isSpawnResultTarget =
373+ block . spawnToolCallId === toolCallId &&
374+ spawnIndex !== undefined &&
375+ childBlocks
376+
377+ if ( isSpawnResultTarget ) {
378+ const result = results [ spawnIndex ]
379+ if ( result ?. value ) {
380+ const { content, hasError } = extractSpawnAgentResultContent ( result . value )
381+
382+ if ( hasError ) {
383+ if ( childBlocks . length === 0 ) {
384+ return null
385+ }
386+
387+ return {
388+ ...block ,
389+ blocks : content
390+ ? [ ...childBlocks , { type : 'text' , content } as ContentBlock ]
391+ : childBlocks ,
392+ status : 'complete' as const ,
391393 }
392394 }
393- }
394395
395- // Recursively process nested agent blocks
396- if ( block . blocks ?. length ) {
397- const updatedNestedBlocks = updateSpawnAgentBlocks ( block . blocks , toolCallId , results )
398- if ( updatedNestedBlocks !== block . blocks ) {
399- return { ...block , blocks : updatedNestedBlocks }
396+ // Agents like thinker return all output at the end via lastMessage,
397+ // while agents like basher may have already streamed their text.
398+ const hasStreamedTextContent = childBlocks . some (
399+ ( b ) => b . type === 'text' && b . textType === 'text' ,
400+ )
401+ const finalBlocks =
402+ content && ! hasStreamedTextContent
403+ ? [ ...childBlocks , { type : 'text' , content } as ContentBlock ]
404+ : childBlocks
405+
406+ if ( finalBlocks . length > 0 ) {
407+ return {
408+ ...block ,
409+ blocks : finalBlocks ,
410+ status : 'complete' as const ,
411+ }
400412 }
401413 }
414+ }
402415
416+ if ( ! childBlocks ?. length ) {
403417 return block
404- } )
418+ }
419+
420+ return {
421+ ...block ,
422+ blocks : updateSpawnAgentBlocks ( childBlocks , toolCallId , results ) ,
423+ }
424+ }
425+
426+ const updateSpawnAgentBlocks = (
427+ blocks : ContentBlock [ ] ,
428+ toolCallId : string ,
429+ results : any [ ] ,
430+ ) : ContentBlock [ ] => {
431+ return blocks
432+ . map ( ( block ) => updateSpawnAgentBlock ( block , toolCallId , results ) )
433+ . filter ( ( block ) : block is ContentBlock => block !== null )
405434}
406435
407436const handleSpawnAgentsResult = (
@@ -433,7 +462,8 @@ const handleToolResult = (
433462 )
434463
435464 const firstOutput = event . output ?. [ 0 ]
436- const firstOutputValue = firstOutput && 'value' in firstOutput ? firstOutput . value : undefined
465+ const firstOutputValue =
466+ firstOutput && 'value' in firstOutput ? firstOutput . value : undefined
437467 const isSpawnAgentsResult =
438468 Array . isArray ( firstOutputValue ) &&
439469 firstOutputValue . some ( ( v : any ) => v ?. agentName || v ?. agentType )
0 commit comments