@@ -315,6 +315,86 @@ describe("CodexAppServerAgent", () => {
315315 ) . toHaveLength ( 1 ) ;
316316 } ) ;
317317
318+ it . each ( [ "resumeAgent" , "sendInput" ] ) (
319+ "attaches child activity to the current %s call" ,
320+ async ( collaborationTool ) => {
321+ let turnNumber = 0 ;
322+ const stub = makeStubRpc ( {
323+ initialize : { } ,
324+ "thread/start" : { thread : { id : "thr_1" } } ,
325+ "turn/start" : ( ) => ( {
326+ turn : {
327+ id : `turn_${ ++ turnNumber } ` ,
328+ status : "inProgress" ,
329+ } ,
330+ } ) ,
331+ } ) ;
332+ const { client, sessionUpdates } = makeFakeClient ( ) ;
333+ const agent = new CodexAppServerAgent ( client , {
334+ processOptions : { binaryPath : "/bundle/codex" } ,
335+ model : "gpt-5.5" ,
336+ rpcFactory : stub . factory ,
337+ } ) ;
338+
339+ await agent . initialize ( init ) ;
340+ await agent . newSession ( { cwd : "/repo" } as unknown as NewSessionRequest ) ;
341+
342+ const firstPrompt = agent . prompt ( {
343+ sessionId : "thr_1" ,
344+ prompt : [ { type : "text" , text : "spawn" } ] ,
345+ } as unknown as PromptRequest ) ;
346+ stub . emit ( "item/started" , {
347+ threadId : "thr_1" ,
348+ turnId : "turn_1" ,
349+ item : {
350+ type : "collabAgentToolCall" ,
351+ id : "spawn_1" ,
352+ tool : "spawnAgent" ,
353+ receiverThreadIds : [ "subagent_1" ] ,
354+ status : "inProgress" ,
355+ } ,
356+ } ) ;
357+ stub . emit ( "turn/completed" , {
358+ threadId : "thr_1" ,
359+ turn : { id : "turn_1" , status : "completed" } ,
360+ } ) ;
361+ await firstPrompt ;
362+
363+ const secondPrompt = agent . prompt ( {
364+ sessionId : "thr_1" ,
365+ prompt : [ { type : "text" , text : "continue" } ] ,
366+ } as unknown as PromptRequest ) ;
367+ const currentCallId = `${ collaborationTool } _1` ;
368+ stub . emit ( "item/started" , {
369+ threadId : "thr_1" ,
370+ turnId : "turn_2" ,
371+ item : {
372+ type : "collabAgentToolCall" ,
373+ id : currentCallId ,
374+ tool : collaborationTool ,
375+ receiverThreadIds : [ "subagent_1" ] ,
376+ status : "inProgress" ,
377+ } ,
378+ } ) ;
379+ stub . emit ( "item/agentMessage/delta" , {
380+ threadId : "subagent_1" ,
381+ turnId : "subagent_turn_2" ,
382+ itemId : "message_2" ,
383+ delta : "continued work" ,
384+ } ) ;
385+
386+ expect ( JSON . stringify ( sessionUpdates ) ) . toContain (
387+ `"parentToolCallId":"${ currentCallId } "` ,
388+ ) ;
389+
390+ stub . emit ( "turn/completed" , {
391+ threadId : "thr_1" ,
392+ turn : { id : "turn_2" , status : "completed" } ,
393+ } ) ;
394+ await secondPrompt ;
395+ } ,
396+ ) ;
397+
318398 it . each ( [
319399 {
320400 label : "reads an empty goal" ,
@@ -2477,6 +2557,53 @@ describe("CodexAppServerAgent", () => {
24772557 } ) ;
24782558 } ) ;
24792559
2560+ it ( "restores subagent relationships from resumed thread history" , async ( ) => {
2561+ const stub = makeStubRpc ( {
2562+ initialize : { } ,
2563+ "thread/resume" : {
2564+ thread : {
2565+ id : "t1" ,
2566+ turns : [
2567+ {
2568+ items : [
2569+ {
2570+ type : "collabAgentToolCall" ,
2571+ id : "spawn_1" ,
2572+ tool : "spawnAgent" ,
2573+ receiverThreadIds : [ "subagent_1" ] ,
2574+ status : "completed" ,
2575+ } ,
2576+ ] ,
2577+ } ,
2578+ ] ,
2579+ } ,
2580+ } ,
2581+ } ) ;
2582+ const { client, sessionUpdates } = makeFakeClient ( ) ;
2583+ const agent = new CodexAppServerAgent ( client , {
2584+ processOptions : { binaryPath : "/x/codex" } ,
2585+ model : "gpt-5.5" ,
2586+ rpcFactory : stub . factory ,
2587+ } ) ;
2588+ await agent . initialize ( init ) ;
2589+ await agent . resumeSession ( {
2590+ sessionId : "t1" ,
2591+ cwd : "/r" ,
2592+ mcpServers : [ ] ,
2593+ } as unknown as Parameters < typeof agent . resumeSession > [ 0 ] ) ;
2594+
2595+ stub . emit ( "item/agentMessage/delta" , {
2596+ threadId : "subagent_1" ,
2597+ turnId : "subagent_turn_1" ,
2598+ itemId : "message_1" ,
2599+ delta : "still working" ,
2600+ } ) ;
2601+
2602+ expect ( JSON . stringify ( sessionUpdates ) ) . toContain (
2603+ '"parentToolCallId":"spawn_1"' ,
2604+ ) ;
2605+ } ) ;
2606+
24802607 it ( "forwards additionalDirectories to thread/start as writable_roots" , async ( ) => {
24812608 const stub = makeStubRpc ( { "thread/start" : { thread : { id : "t" } } } ) ;
24822609 const { client } = makeFakeClient ( ) ;
0 commit comments