@@ -39,11 +39,11 @@ export function createBestOfNEditor(
3939 spawnableAgents : buildArray (
4040 'best-of-n-selector' ,
4141 'best-of-n-selector-opus' ,
42- isDefault && 'best-of-n-selector-gemini' ,
42+ 'best-of-n-selector-gemini' ,
4343 'editor-implementor' ,
4444 'editor-implementor-opus' ,
45- isDefault && 'editor-implementor-gemini' ,
46- isMax && 'editor-implementor-gpt-5' ,
45+ 'editor-implementor-gemini' ,
46+ 'editor-implementor-gpt-5' ,
4747 ) ,
4848
4949 inputSchema : {
@@ -230,6 +230,7 @@ function* handleStepsDefault({
230230}
231231function * handleStepsMax ( {
232232 params,
233+ logger,
233234} : AgentStepContext ) : ReturnType <
234235 NonNullable < SecretAgentDefinition [ 'handleSteps' ] >
235236> {
@@ -269,8 +270,9 @@ function* handleStepsMax({
269270 } satisfies ToolCall < 'spawn_agents' >
270271
271272 // Extract spawn results
272- const spawnedImplementations =
273- extractSpawnResults < { text : string } [ ] > ( implementorResults )
273+ const spawnedImplementations = extractSpawnResults (
274+ implementorResults ,
275+ ) as any [ ]
274276
275277 // Extract all the plans from the structured outputs
276278 const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
@@ -280,9 +282,14 @@ function* handleStepsMax({
280282 content :
281283 'errorMessage' in result
282284 ? `Error: ${ result . errorMessage } `
283- : result [ 0 ] . text ,
285+ : extractLastMessageText ( result ) ,
284286 } ) )
285287
288+ logger . info (
289+ { spawnedImplementations, implementations } ,
290+ 'spawnedImplementations' ,
291+ )
292+
286293 // Spawn selector with implementations as params
287294 const { toolResult : selectorResult } = yield {
288295 toolName : 'spawn_agents' ,
@@ -321,15 +328,9 @@ function* handleStepsMax({
321328 return
322329 }
323330
324- // Apply the chosen implementation using STEP_TEXT (only tool calls, no commentary)
325- const toolCallsOnly = extractToolCallsOnly (
326- typeof chosenImplementation . content === 'string'
327- ? chosenImplementation . content
328- : '' ,
329- )
330331 const { agentState : postEditsAgentState } = yield {
331332 type : 'STEP_TEXT' ,
332- text : toolCallsOnly ,
333+ text : chosenImplementation . content ,
333334 } as StepText
334335 const { messageHistory } = postEditsAgentState
335336 const lastAssistantMessageIndex = messageHistory . findLastIndex (
@@ -352,37 +353,60 @@ function* handleStepsMax({
352353 includeToolCall : false ,
353354 } satisfies ToolCall < 'set_output' >
354355
355- function extractSpawnResults < T > (
356- results : any [ ] | undefined ,
357- ) : ( T | { errorMessage : string } ) [ ] {
358- if ( ! results ) return [ ]
359- const spawnedResults = results
360- . filter ( ( result ) => result . type === 'json' )
361- . map ( ( result ) => result . value )
362- . flat ( ) as {
363- agentType : string
364- value : { value ?: T ; errorMessage ?: string }
365- } [ ]
366- return spawnedResults . map (
367- ( result ) =>
368- result . value . value ?? {
369- errorMessage :
370- result . value . errorMessage ?? 'Error extracting spawn results' ,
371- } ,
372- )
356+ /**
357+ * Extracts the array of subagent results from spawn_agents tool output.
358+ *
359+ * The spawn_agents tool result structure is:
360+ * [{ type: 'json', value: [{ agentName, agentType, value: AgentOutput }] }]
361+ *
362+ * Returns an array of agent outputs, one per spawned agent.
363+ */
364+ function extractSpawnResults < T > ( results : any [ ] | undefined ) : T [ ] {
365+ if ( ! results || results . length === 0 ) return [ ]
366+
367+ // Find the json result containing spawn results
368+ const jsonResult = results . find ( ( r ) => r . type === 'json' )
369+ if ( ! jsonResult ?. value ) return [ ]
370+
371+ // Get the spawned agent results array
372+ const spawnedResults = Array . isArray ( jsonResult . value )
373+ ? jsonResult . value
374+ : [ jsonResult . value ]
375+
376+ // Extract the value (AgentOutput) from each result
377+ return spawnedResults . map ( ( result : any ) => result ?. value ) . filter ( Boolean )
373378 }
374379
375- // Extract only tool calls from text, removing any commentary
376- function extractToolCallsOnly ( text : string ) : string {
377- const toolExtractionPattern =
378- / < c o d e b u f f _ t o o l _ c a l l > \n ( .* ?) \n < \/ c o d e b u f f _ t o o l _ c a l l > / gs
379- const matches : string [ ] = [ ]
380-
381- for ( const match of text . matchAll ( toolExtractionPattern ) ) {
382- matches . push ( match [ 0 ] ) // Include the full tool call with tags
380+ /**
381+ * Extracts the text content from a 'lastMessage' AgentOutput.
382+ *
383+ * For agents with outputMode: 'last_message', the output structure is:
384+ * { type: 'lastMessage', value: [{ role: 'assistant', content: [{ type: 'text', text: '...' }] }] }
385+ *
386+ * Returns the text from the last assistant message, or null if not found.
387+ */
388+ function extractLastMessageText ( agentOutput : any ) : string | null {
389+ if ( ! agentOutput ) return null
390+
391+ // Handle 'lastMessage' output mode - the value contains an array of messages
392+ if (
393+ agentOutput . type === 'lastMessage' &&
394+ Array . isArray ( agentOutput . value )
395+ ) {
396+ // Find the last assistant message with text content
397+ for ( let i = agentOutput . value . length - 1 ; i >= 0 ; i -- ) {
398+ const message = agentOutput . value [ i ]
399+ if ( message . role === 'assistant' && Array . isArray ( message . content ) ) {
400+ // Find text content in the message
401+ for ( const part of message . content ) {
402+ if ( part . type === 'text' && typeof part . text === 'string' ) {
403+ return part . text
404+ }
405+ }
406+ }
407+ }
383408 }
384-
385- return matches . join ( '\n' )
409+ return null
386410 }
387411}
388412
0 commit comments