88} from "./agent-fleet.js" ;
99import { createSubAgentSessionStore } from "./session-store.js" ;
1010import { createPermissionGate } from "../permission/gate.js" ;
11- import type { RunSubAgentParams } from "./types.js" ;
11+ import type { RunSubAgentParams , RunSubAgentResult } from "./types.js" ;
1212
1313const testPermissionGate = createPermissionGate ( {
1414 approvals : [ ] ,
@@ -37,7 +37,7 @@ function deferred<T>(): {
3737}
3838
3939function makeDeps (
40- run : ( params : RunSubAgentParams ) => Promise < string > ,
40+ run : ( params : RunSubAgentParams ) => Promise < RunSubAgentResult > ,
4141 opts : { cwd ?: string } = { } ,
4242) : AgentFleetDeps {
4343 return {
@@ -75,7 +75,7 @@ async function callTool(
7575
7676describe ( "spawn_agent" , ( ) => {
7777 test ( "returns immediately with a running agent_id without waiting for the worker" , async ( ) => {
78- const gate = deferred < string > ( ) ;
78+ const gate = deferred < RunSubAgentResult > ( ) ;
7979 const deps = makeDeps ( async ( ) => gate . promise ) ;
8080 const spawn = createSpawnAgentTool ( deps ) ;
8181
@@ -94,13 +94,17 @@ describe("spawn_agent", () => {
9494 // Worker is still pending; store confirms it has not finished.
9595 expect ( deps . sessions . get ( result . agent_id as string ) ?. status ) . toBe ( "running" ) ;
9696
97- gate . resolve ( "done" ) ;
97+ gate . resolve ( { report : "done" } ) ;
9898 } ) ;
9999} ) ;
100100
101101describe ( "spawn_agent + wait_agents" , ( ) => {
102102 test ( "wait_agents on one target returns once it completes while siblings keep running" , async ( ) => {
103- const gates = [ deferred < string > ( ) , deferred < string > ( ) , deferred < string > ( ) ] ;
103+ const gates = [
104+ deferred < RunSubAgentResult > ( ) ,
105+ deferred < RunSubAgentResult > ( ) ,
106+ deferred < RunSubAgentResult > ( ) ,
107+ ] ;
104108 let callIndex = 0 ;
105109 const deps = makeDeps ( async ( ) => {
106110 const i = callIndex ++ ;
@@ -116,7 +120,7 @@ describe("spawn_agent + wait_agents", () => {
116120 ) ;
117121 const ids = spawned . map ( ( s ) => s . agent_id as string ) ;
118122
119- gates [ 0 ] ! . resolve ( "first report" ) ;
123+ gates [ 0 ] ! . resolve ( { report : "first report" } ) ;
120124
121125 const waited = await callTool ( wait , { targets : [ ids [ 0 ] ] , timeout_ms : 5000 } ) ;
122126 expect ( waited . timed_out ) . toBe ( false ) ;
@@ -129,12 +133,12 @@ describe("spawn_agent + wait_agents", () => {
129133 expect ( deps . sessions . get ( ids [ 1 ] ! ) ?. status ) . toBe ( "running" ) ;
130134 expect ( deps . sessions . get ( ids [ 2 ] ! ) ?. status ) . toBe ( "running" ) ;
131135
132- gates [ 1 ] ! . resolve ( "second" ) ;
133- gates [ 2 ] ! . resolve ( "third" ) ;
136+ gates [ 1 ] ! . resolve ( { report : "second" } ) ;
137+ gates [ 2 ] ! . resolve ( { report : "third" } ) ;
134138 } ) ;
135139
136140 test ( "wait_agents times out on a still-running agent without cancelling it, and can be called again" , async ( ) => {
137- const gate = deferred < string > ( ) ;
141+ const gate = deferred < RunSubAgentResult > ( ) ;
138142 const deps = makeDeps ( async ( ) => gate . promise ) ;
139143 const spawn = createSpawnAgentTool ( deps ) ;
140144 const wait = createWaitAgentsTool ( { sessions : deps . sessions , fleetRecords : deps . fleetRecords } ) ;
@@ -155,7 +159,7 @@ describe("spawn_agent + wait_agents", () => {
155159 expect ( deps . sessions . get ( id ) ?. status ) . toBe ( "running" ) ;
156160
157161 // A second wait still works cleanly (either another timeout, or completion).
158- gate . resolve ( "finished" ) ;
162+ gate . resolve ( { report : "finished" } ) ;
159163 const second = await callTool ( wait , { targets : [ id ] , timeout_ms : 5000 } ) ;
160164 expect ( second . timed_out ) . toBe ( false ) ;
161165 const secondResults = second . results as {
@@ -168,7 +172,7 @@ describe("spawn_agent + wait_agents", () => {
168172 } ) ;
169173
170174 test ( "wait_agents with no targets waits on all currently running spawned agents" , async ( ) => {
171- const gates = [ deferred < string > ( ) , deferred < string > ( ) ] ;
175+ const gates = [ deferred < RunSubAgentResult > ( ) , deferred < RunSubAgentResult > ( ) ] ;
172176 let callIndex = 0 ;
173177 const deps = makeDeps ( async ( ) => gates [ callIndex ++ ] ! . promise ) ;
174178 const spawn = createSpawnAgentTool ( deps ) ;
@@ -177,14 +181,14 @@ describe("spawn_agent + wait_agents", () => {
177181 await callTool ( spawn , { description : "a" , prompt : "do it" , intent : "explore" } ) ;
178182 await callTool ( spawn , { description : "b" , prompt : "do it" , intent : "explore" } ) ;
179183
180- gates [ 0 ] ! . resolve ( "a done" ) ;
184+ gates [ 0 ] ! . resolve ( { report : "a done" } ) ;
181185 const result = await callTool ( wait , { timeout_ms : 5000 } ) ;
182186 expect ( result . timed_out ) . toBe ( false ) ;
183187 const results = result . results as { status : string } [ ] ;
184188 expect ( results ) . toHaveLength ( 2 ) ;
185189 expect ( results . some ( ( r ) => r . status === "done" ) ) . toBe ( true ) ;
186190
187- gates [ 1 ] ! . resolve ( "b done" ) ;
191+ gates [ 1 ] ! . resolve ( { report : "b done" } ) ;
188192 } ) ;
189193
190194 test ( "reports survive well past the session store's display cap (20) until wait_agents collects them" , async ( ) => {
@@ -193,7 +197,7 @@ describe("spawn_agent + wait_agents", () => {
193197 // them is collected, proving fleetRecords — not the store — is what
194198 // wait_agents actually reads from.
195199 const COUNT = 25 ;
196- const deps = makeDeps ( async ( ) => "irrelevant" ) ;
200+ const deps = makeDeps ( async ( ) => ( { report : "irrelevant" } ) ) ;
197201 const spawn = createSpawnAgentTool ( deps ) ;
198202 const wait = createWaitAgentsTool ( { sessions : deps . sessions , fleetRecords : deps . fleetRecords } ) ;
199203
@@ -226,7 +230,7 @@ describe("spawn_agent + wait_agents", () => {
226230
227231describe ( "spawn_agent write-lane isolation" , ( ) => {
228232 test ( "refuses a second concurrent implement-intent spawn against the same cwd" , async ( ) => {
229- const gate = deferred < string > ( ) ;
233+ const gate = deferred < RunSubAgentResult > ( ) ;
230234 const deps = makeDeps ( async ( ) => gate . promise , { cwd : "/repo" } ) ;
231235 const spawn = createSpawnAgentTool ( deps ) ;
232236
@@ -246,11 +250,11 @@ describe("spawn_agent write-lane isolation", () => {
246250 expect ( second . content ) . toContain ( "Error:" ) ;
247251 expect ( second . content ) . toContain ( first . agent_id as string ) ;
248252
249- gate . resolve ( "done" ) ;
253+ gate . resolve ( { report : "done" } ) ;
250254 } ) ;
251255
252256 test ( "does not refuse a second concurrent explore-intent spawn against the same cwd" , async ( ) => {
253- const deps = makeDeps ( async ( ) => "explored" , { cwd : "/repo" } ) ;
257+ const deps = makeDeps ( async ( ) => ( { report : "explored" } ) , { cwd : "/repo" } ) ;
254258 const spawn = createSpawnAgentTool ( deps ) ;
255259
256260 const first = await callTool ( spawn , {
@@ -269,7 +273,7 @@ describe("spawn_agent write-lane isolation", () => {
269273 } ) ;
270274
271275 test ( "releases the write lane once the implement worker finishes, allowing another" , async ( ) => {
272- const deps = makeDeps ( async ( ) => "built" , { cwd : "/repo" } ) ;
276+ const deps = makeDeps ( async ( ) => ( { report : "built" } ) , { cwd : "/repo" } ) ;
273277 const spawn = createSpawnAgentTool ( deps ) ;
274278 const wait = createWaitAgentsTool ( { sessions : deps . sessions , fleetRecords : deps . fleetRecords } ) ;
275279
0 commit comments