From 03f7643ee1772d89c419e9a3e0491d49fc372cfb Mon Sep 17 00:00:00 2001 From: sjawhar Date: Tue, 17 Feb 2026 01:02:04 +0000 Subject: [PATCH 1/2] fix(background-agent): respect agent tool restrictions in background task launch Reorder tool permission spread so getAgentToolRestrictions() comes last, allowing agent-specific restrictions to override defaults. Fixes all 3 sites: task-starter.ts (startTask), manager.ts (startTask and resume paths). Previously, defaults like call_omo_agent:true would stomp agent restrictions (e.g., explore's call_omo_agent:false) due to JS spread semantics. --- src/features/background-agent/manager.test.ts | 93 +++++++++++++++++++ src/features/background-agent/manager.ts | 4 +- 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/src/features/background-agent/manager.test.ts b/src/features/background-agent/manager.test.ts index d031ff1ed..dcb85bcf9 100644 --- a/src/features/background-agent/manager.test.ts +++ b/src/features/background-agent/manager.test.ts @@ -3941,3 +3941,96 @@ describe("BackgroundManager regression fixes - resume and aborted notification", manager.shutdown() }) }) + +describe("BackgroundManager - tool permission spread order", () => { + test("startTask respects explore agent restrictions", async () => { + //#given + let capturedTools: Record | undefined + const client = { + session: { + get: async () => ({ data: { directory: "/test/dir" } }), + create: async () => ({ data: { id: "session-1" } }), + promptAsync: async (args: { path: { id: string }; body: Record }) => { + capturedTools = args.body.tools as Record + return {} + }, + }, + } + const manager = new BackgroundManager({ client, directory: tmpdir() } as unknown as PluginInput) + const task: BackgroundTask = { + id: "task-1", + status: "pending", + queuedAt: new Date(), + description: "test task", + prompt: "test prompt", + agent: "explore", + parentSessionID: "parent-session", + parentMessageID: "parent-message", + } + const input: import("./types").LaunchInput = { + description: task.description, + prompt: task.prompt, + agent: task.agent, + parentSessionID: task.parentSessionID, + parentMessageID: task.parentMessageID, + } + + //#when + await (manager as unknown as { startTask: (item: { task: BackgroundTask; input: import("./types").LaunchInput }) => Promise }) + .startTask({ task, input }) + + //#then + expect(capturedTools).toBeDefined() + expect(capturedTools?.call_omo_agent).toBe(false) + expect(capturedTools?.task).toBe(false) + expect(capturedTools?.write).toBe(false) + expect(capturedTools?.edit).toBe(false) + + manager.shutdown() + }) + + test("resume respects explore agent restrictions", async () => { + //#given + let capturedTools: Record | undefined + const client = { + session: { + promptAsync: async (args: { path: { id: string }; body: Record }) => { + capturedTools = args.body.tools as Record + return {} + }, + abort: async () => ({}), + }, + } + const manager = new BackgroundManager({ client, directory: tmpdir() } as unknown as PluginInput) + const task: BackgroundTask = { + id: "task-2", + sessionID: "session-2", + parentSessionID: "parent-session", + parentMessageID: "parent-message", + description: "resume task", + prompt: "resume prompt", + agent: "explore", + status: "completed", + startedAt: new Date(), + completedAt: new Date(), + } + getTaskMap(manager).set(task.id, task) + + //#when + await manager.resume({ + sessionId: "session-2", + prompt: "continue", + parentSessionID: "parent-session", + parentMessageID: "parent-message", + }) + + //#then + expect(capturedTools).toBeDefined() + expect(capturedTools?.call_omo_agent).toBe(false) + expect(capturedTools?.task).toBe(false) + expect(capturedTools?.write).toBe(false) + expect(capturedTools?.edit).toBe(false) + + manager.shutdown() + }) +}) diff --git a/src/features/background-agent/manager.ts b/src/features/background-agent/manager.ts index 30adadb7c..649460222 100644 --- a/src/features/background-agent/manager.ts +++ b/src/features/background-agent/manager.ts @@ -355,10 +355,10 @@ export class BackgroundManager { system: input.skillContent, tools: (() => { const tools = { - ...getAgentToolRestrictions(input.agent), task: false, call_omo_agent: true, question: false, + ...getAgentToolRestrictions(input.agent), } setSessionTools(sessionID, tools) return tools @@ -628,10 +628,10 @@ export class BackgroundManager { ...(resumeVariant ? { variant: resumeVariant } : {}), tools: (() => { const tools = { - ...getAgentToolRestrictions(existingTask.agent), task: false, call_omo_agent: true, question: false, + ...getAgentToolRestrictions(existingTask.agent), } setSessionTools(existingTask.sessionID!, tools) return tools From 95491675e8232e01d2ca16987728ec5bd04db917 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Sat, 21 Feb 2026 02:26:02 +0900 Subject: [PATCH 2/2] fix: correct spread order in spawner.ts for tool restrictions --- src/features/background-agent/spawner.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/features/background-agent/spawner.ts b/src/features/background-agent/spawner.ts index e9256eca4..d51fd2db7 100644 --- a/src/features/background-agent/spawner.ts +++ b/src/features/background-agent/spawner.ts @@ -141,10 +141,10 @@ export async function startTask( ...(launchVariant ? { variant: launchVariant } : {}), system: input.skillContent, tools: { - ...getAgentToolRestrictions(input.agent), task: false, call_omo_agent: true, question: false, + ...getAgentToolRestrictions(input.agent), }, parts: [{ type: "text", text: input.prompt }], }, @@ -225,10 +225,10 @@ export async function resumeTask( ...(resumeModel ? { model: resumeModel } : {}), ...(resumeVariant ? { variant: resumeVariant } : {}), tools: { - ...getAgentToolRestrictions(task.agent), task: false, call_omo_agent: true, question: false, + ...getAgentToolRestrictions(task.agent), }, parts: [{ type: "text", text: input.prompt }], },