diff --git a/src/permission/gate.ts b/src/permission/gate.ts index 29e3725fc..13016d3c0 100644 --- a/src/permission/gate.ts +++ b/src/permission/gate.ts @@ -331,6 +331,12 @@ const AUTO_ALLOWED_TOOLS = new Set([ "search_agents", "spawn_agent", "wait_agents", + "list_agents", + "send_input", + "interrupt_agent", + "close_agent", + "resume_agent", + "read_agent_trace", ]); export interface PermissionGateOptions { diff --git a/src/permission/permission.test.ts b/src/permission/permission.test.ts index 5fb6b946c..92b69f259 100644 --- a/src/permission/permission.test.ts +++ b/src/permission/permission.test.ts @@ -1553,6 +1553,12 @@ describe("createPermissionGate", () => { "search_agents", "spawn_agent", "wait_agents", + "list_agents", + "send_input", + "interrupt_agent", + "close_agent", + "resume_agent", + "read_agent_trace", ]) { const verdict = await gate.evaluate({ id: "c", name, arguments: {} }); expect(verdict.allowed).toBe(true); @@ -1560,6 +1566,36 @@ describe("createPermissionGate", () => { expect(asked).toBe(0); }); + test("ask mode prompts for fleet continuation tools", async () => { + let asked = 0; + let approval = false; + const gate = createPermissionGate({ + approvals: [], + requestApproval: async () => { + asked++; + return { allow: approval }; + }, + interactive: true, + skipPermissions: false, + reactorGated: false, + auto: false, + }); + const tools = [ + "list_agents", + "send_input", + "interrupt_agent", + "close_agent", + "resume_agent", + "read_agent_trace", + ]; + for (const [index, name] of tools.entries()) { + approval = index % 2 === 0; + const verdict = await gate.evaluate({ id: "c", name, arguments: {} }); + expect(verdict.allowed).toBe(approval); + } + expect(asked).toBe(tools.length); + }); + // manage_tasks's handler has no side effect — the task list is mutated // earlier by the director, before this tool ever executes — so denying it // cannot undo anything. It auto-allows unconditionally, not just in auto