@@ -39,6 +39,17 @@ import {
3939 type SubAgentProvider ,
4040 type SubAgentSessionStore ,
4141} from "../subagent/index.js" ;
42+ import {
43+ createFleetRecords ,
44+ createSpawnAgentTool ,
45+ createWaitAgentsTool ,
46+ } from "../subagent/agent-fleet.js" ;
47+ import {
48+ createCloseAgentTool ,
49+ createResumeAgentTool ,
50+ createInterruptAgentTool ,
51+ createFollowupTaskTool ,
52+ } from "../subagent/lifecycle-tools.js" ;
4253import { parseManageTasksArgs } from "./tasks.js" ;
4354import { createListDirTool } from "../util/list-dir.js" ;
4455import { createWebFetchTool } from "../tools/web-fetch.js" ;
@@ -263,6 +274,84 @@ export async function createAgentToolset(args: AgentToolsetArgs): Promise<AgentT
263274
264275 // Align the advertised run_shell timeout with shell-guard (no built-in default;
265276 // advertise settings.shell.timeoutMs when set).
277+ // Orchestrator tools (task / search / trace / fleet) are assembled once so the
278+ // fleet verbs can reuse the same sessions store the task tool already holds —
279+ // never a private mailbox allocated only for spawn_agent/wait_agents.
280+ const orchestratorTools : AgentTool [ ] = [ ] ;
281+ if ( subAgentsEnabled && args . subAgent !== undefined ) {
282+ const sa = args . subAgent ;
283+ orchestratorTools . push (
284+ createTaskTool ( {
285+ cwd,
286+ getWorkdirBase : sa . getWorkdirBase ,
287+ provider : sa . provider ,
288+ permissionGate,
289+ inheritMcpTools : ( ) => inheritedMcpTools ,
290+ run : runSubAgent ,
291+ ...( shellTimeout !== undefined ? { shellTimeout } : { } ) ,
292+ ...( shellEnv !== undefined ? { shellEnv } : { } ) ,
293+ ...( extraToolPlugins . length > 0 ? { extraToolPlugins } : { } ) ,
294+ ...( sa . onEvent !== undefined ? { onEvent : sa . onEvent } : { } ) ,
295+ ...( sa . onProgress !== undefined ? { onProgress : sa . onProgress } : { } ) ,
296+ ...( sa . sessions !== undefined ? { sessions : sa . sessions } : { } ) ,
297+ ...( sa . settings !== undefined ? { settings : sa . settings } : { } ) ,
298+ ...( sa . catalog !== undefined ? { catalog : sa . catalog } : { } ) ,
299+ ...( sa . profiles !== undefined ? { profiles : sa . profiles } : { } ) ,
300+ ...( args . getBlobReader !== undefined ? { getBlobReader : args . getBlobReader } : { } ) ,
301+ ...( sa . useWorktree !== undefined ? { useWorktree : sa . useWorktree } : { } ) ,
302+ ...( args . telemetry !== undefined ? { telemetry : args . telemetry } : { } ) ,
303+ } ) ,
304+ ) ;
305+ if ( sa . profiles !== undefined ) {
306+ orchestratorTools . push (
307+ createSearchAgentsTool ( ( ) => {
308+ const profiles = sa . profiles ;
309+ return typeof profiles === "function" ? profiles ( ) : ( profiles ?? [ ] ) ;
310+ } ) ,
311+ ) ;
312+ }
313+ // Tier 1: the primary session is always an orchestrator and may
314+ // target any worker (assertCanTargetAgent's rule), so no authority
315+ // context is passed here — omitting it is treated as unrestricted,
316+ // matching Tier 1's actual authority.
317+ orchestratorTools . push ( createReadAgentTraceTool ( sa . getWorkdirBase ) ) ;
318+
319+ // Mirror nested runSubAgent's orchestrator fleet mount (run.ts), but
320+ // reuse the existing TUI/exec session store — do not allocate a private
321+ // store only for these verbs. spawnAllowlist stays unwired on primary.
322+ if ( sa . sessions !== undefined ) {
323+ const fleetSessions = sa . sessions ;
324+ const fleetRecords = createFleetRecords ( ) ;
325+ const fleetDeps = {
326+ permissionGate,
327+ inheritMcpTools : ( ) => inheritedMcpTools ,
328+ ...( shellTimeout !== undefined ? { shellTimeout } : { } ) ,
329+ ...( shellEnv !== undefined ? { shellEnv } : { } ) ,
330+ ...( extraToolPlugins . length > 0 ? { extraToolPlugins } : { } ) ,
331+ cwd,
332+ getWorkdirBase : sa . getWorkdirBase ,
333+ provider : sa . provider ,
334+ ...( args . getBlobReader !== undefined ? { getBlobReader : args . getBlobReader } : { } ) ,
335+ run : runSubAgent ,
336+ sessions : fleetSessions ,
337+ fleetRecords,
338+ ...( sa . onEvent !== undefined ? { onEvent : sa . onEvent } : { } ) ,
339+ ...( sa . onProgress !== undefined ? { onProgress : sa . onProgress } : { } ) ,
340+ ...( sa . settings !== undefined ? { settings : sa . settings } : { } ) ,
341+ ...( sa . catalog !== undefined ? { catalog : sa . catalog } : { } ) ,
342+ ...( args . telemetry !== undefined ? { telemetry : args . telemetry } : { } ) ,
343+ } ;
344+ orchestratorTools . push (
345+ createSpawnAgentTool ( fleetDeps ) ,
346+ createWaitAgentsTool ( { sessions : fleetSessions , fleetRecords } ) ,
347+ createCloseAgentTool ( { sessions : fleetSessions } ) ,
348+ createResumeAgentTool ( { sessions : fleetSessions } ) ,
349+ createInterruptAgentTool ( { sessions : fleetSessions } ) ,
350+ createFollowupTaskTool ( { sessions : fleetSessions } ) ,
351+ ) ;
352+ }
353+ }
354+
266355 const baseTools : AgentTool [ ] = [
267356 ...fromToolRunner ( posixTools ) . map ( ( tool ) => ( {
268357 ...tool ,
@@ -276,47 +365,7 @@ export async function createAgentToolset(args: AgentToolsetArgs): Promise<AgentT
276365 createUseSkillTool ( cwd , skillDirs , args . telemetry ) ,
277366 createWebFetchTool ( ) ,
278367 createWebSearchTool ( ) ,
279- ...( subAgentsEnabled && args . subAgent !== undefined
280- ? [
281- createTaskTool ( {
282- cwd,
283- getWorkdirBase : args . subAgent . getWorkdirBase ,
284- provider : args . subAgent . provider ,
285- permissionGate,
286- inheritMcpTools : ( ) => inheritedMcpTools ,
287- run : runSubAgent ,
288- ...( shellTimeout !== undefined ? { shellTimeout } : { } ) ,
289- ...( shellEnv !== undefined ? { shellEnv } : { } ) ,
290- ...( extraToolPlugins . length > 0 ? { extraToolPlugins } : { } ) ,
291- ...( args . subAgent . onEvent !== undefined ? { onEvent : args . subAgent . onEvent } : { } ) ,
292- ...( args . subAgent . onProgress !== undefined
293- ? { onProgress : args . subAgent . onProgress }
294- : { } ) ,
295- ...( args . subAgent . sessions !== undefined ? { sessions : args . subAgent . sessions } : { } ) ,
296- ...( args . subAgent . settings !== undefined ? { settings : args . subAgent . settings } : { } ) ,
297- ...( args . subAgent . catalog !== undefined ? { catalog : args . subAgent . catalog } : { } ) ,
298- ...( args . subAgent . profiles !== undefined ? { profiles : args . subAgent . profiles } : { } ) ,
299- ...( args . getBlobReader !== undefined ? { getBlobReader : args . getBlobReader } : { } ) ,
300- ...( args . subAgent . useWorktree !== undefined
301- ? { useWorktree : args . subAgent . useWorktree }
302- : { } ) ,
303- ...( args . telemetry !== undefined ? { telemetry : args . telemetry } : { } ) ,
304- } ) ,
305- ...( args . subAgent . profiles !== undefined
306- ? [
307- createSearchAgentsTool ( ( ) => {
308- const profiles = args . subAgent ! . profiles ;
309- return typeof profiles === "function" ? profiles ( ) : ( profiles ?? [ ] ) ;
310- } ) ,
311- ]
312- : [ ] ) ,
313- // Tier 1: the primary session is always an orchestrator and may
314- // target any worker (assertCanTargetAgent's rule), so no authority
315- // context is passed here — omitting it is treated as unrestricted,
316- // matching Tier 1's actual authority.
317- createReadAgentTraceTool ( args . subAgent . getWorkdirBase ) ,
318- ]
319- : [ ] ) ,
368+ ...orchestratorTools ,
320369 stringTool ( {
321370 definition : manageTasksDefinition ,
322371 handler : async ( rawArgs : Record < string , unknown > ) : Promise < string > => {
0 commit comments