From 041eeeef67b61b359f7799fff528a75282d98220 Mon Sep 17 00:00:00 2001 From: "posthog[bot]" <206114724+posthog[bot]@users.noreply.github.com> Date: Mon, 29 Jun 2026 05:52:17 +0000 Subject: [PATCH] fix(agent): make Auto Mode auto-approve edits and shell commands Auto Mode advertised hands-off, classifier-based approval but its allow-set (`AUTO_ALLOWED_TOOLS.auto`) only contained the base read/search/web/agent tools. Bash, BashOutput, KillShell, Edit, Write, and NotebookEdit fell through `canUseTool` to a manual permission prompt on every call, so users on Auto Mode were still asked to approve each edit and command. Add WRITE_TOOLS and BASH_TOOLS to the auto allow-set so the mode runs hands-off as advertised. MCP tools stay gated separately (do_not_use is denied, needs_approval still prompts), so auto remains narrower than bypassPermissions. The "model classifier" wording in the mode description is also corrected to describe the actual behavior, since the SDK's canUseTool arbiter can't re-defer to the classifier for these tools. Generated-By: PostHog Code Task-Id: 0add1c68-e7b5-4ef4-9221-508ff13108e0 --- .../permissions/permission-handlers.test.ts | 47 +++++++++++++++++++ packages/agent/src/adapters/claude/tools.ts | 8 +++- packages/agent/src/execution-mode.ts | 2 +- packages/core/src/sessions/executionModes.ts | 2 +- 4 files changed, 56 insertions(+), 3 deletions(-) diff --git a/packages/agent/src/adapters/claude/permissions/permission-handlers.test.ts b/packages/agent/src/adapters/claude/permissions/permission-handlers.test.ts index 528a219e18..3137059271 100644 --- a/packages/agent/src/adapters/claude/permissions/permission-handlers.test.ts +++ b/packages/agent/src/adapters/claude/permissions/permission-handlers.test.ts @@ -345,3 +345,50 @@ describe("canUseTool MCP approval enforcement", () => { ); }); }); + +describe("canUseTool auto mode hands-off approval", () => { + beforeEach(() => { + clearMcpToolMetadataCache(); + }); + + // Auto mode advertises hands-off approval; it must not prompt for the write + // and shell tools that drive every real task. + it.each(["Bash", "BashOutput", "KillShell", "Edit", "Write", "NotebookEdit"])( + "auto-allows %s in auto mode without prompting", + async (toolName) => { + const context = createContext(toolName, { + session: { + permissionMode: "auto", + settingsManager: { + getRepoRoot: vi.fn().mockReturnValue("/repo"), + }, + }, + }); + + const result = await canUseTool(context); + + expect(result.behavior).toBe("allow"); + expect(context.client.requestPermission).not.toHaveBeenCalled(); + }, + ); + + // Guard against the fix leaking into default mode, where these tools should + // still go through the manual permission prompt. + it.each(["Bash", "Edit", "Write"])( + "still prompts for %s in default mode", + async (toolName) => { + const context = createContext(toolName, { + session: { + permissionMode: "default", + settingsManager: { + getRepoRoot: vi.fn().mockReturnValue("/repo"), + }, + }, + }); + + await canUseTool(context); + + expect(context.client.requestPermission).toHaveBeenCalled(); + }, + ); +}); diff --git a/packages/agent/src/adapters/claude/tools.ts b/packages/agent/src/adapters/claude/tools.ts index 9074737ae1..eaccc7d218 100644 --- a/packages/agent/src/adapters/claude/tools.ts +++ b/packages/agent/src/adapters/claude/tools.ts @@ -43,7 +43,13 @@ const BASE_ALLOWED_TOOLS = [ ]; const AUTO_ALLOWED_TOOLS: Record> = { - auto: new Set(BASE_ALLOWED_TOOLS), + // Auto mode is hands-off: it auto-approves file edits and shell commands on + // top of the base read/search/web/agent tools. Without WRITE_TOOLS and + // BASH_TOOLS here, Edit/Write/Bash fall through to a manual prompt on every + // call, which contradicts what the mode advertises. MCP tools are still gated + // separately (do_not_use is denied, needs_approval still prompts) in + // canUseTool, so auto stays narrower than bypassPermissions. + auto: new Set([...BASE_ALLOWED_TOOLS, ...WRITE_TOOLS, ...BASH_TOOLS]), default: new Set(BASE_ALLOWED_TOOLS), acceptEdits: new Set([...BASE_ALLOWED_TOOLS, ...WRITE_TOOLS]), plan: new Set(BASE_ALLOWED_TOOLS), diff --git a/packages/agent/src/execution-mode.ts b/packages/agent/src/execution-mode.ts index 99f6799183..f19e85e589 100644 --- a/packages/agent/src/execution-mode.ts +++ b/packages/agent/src/execution-mode.ts @@ -34,7 +34,7 @@ if (ALLOW_BYPASS) { { id: "auto", name: "Auto Mode", - description: "Use a model classifier to approve/deny permission prompts", + description: "Auto-approve file edits and shell commands", }, ); } diff --git a/packages/core/src/sessions/executionModes.ts b/packages/core/src/sessions/executionModes.ts index 8d471d44f1..2c716ced6d 100644 --- a/packages/core/src/sessions/executionModes.ts +++ b/packages/core/src/sessions/executionModes.ts @@ -28,7 +28,7 @@ const availableModes: ModeInfo[] = [ { id: "auto", name: "Auto Mode", - description: "Use a model classifier to approve/deny permission prompts", + description: "Auto-approve file edits and shell commands", }, ];