From 8800406517e00c096a99595e4a895e03c0c6094d Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 18 Aug 2026 22:28:03 +0530 Subject: [PATCH 1/2] feat(ai-chat): support SDK classifier-driven Auto permission mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Companion to the phoenix-pro change adding a 4th permission mode, 'auto', which routes tool-call approval through the Claude Agent SDK's own model classifier instead of a blanket accept-all. The SDK (pinned ^0.2.126, installed 0.2.141) already supports this — no SDK upgrade needed. - src-node/claude-code-agent.js: default permission mode changed from acceptEdits to auto (matches the browser default); comments updated — no functional hook changes required, since the existing PreToolUse hooks already defer to the SDK for any mode they don't specifically handle. - strings.js: new AI_CHAT_MODE_AUTO / AI_CHAT_MODE_INFO_AUTO strings; renamed 'Full Auto' to 'Allow Everything' throughout (label, consent dialog title/body/button) to stay distinct from the new Auto mode. - Extn-AIChatPanel.less: new mode-classifier dot color for Auto; permission dropdown popup capped against the viewport (90vh) instead of inheriting the shared widget's 160px max-height, which forced an unnecessary scrollbar for 4 two-line items. --- src-node/claude-code-agent.js | 31 +++++++++++++++++++------------ src/nls/root/strings.js | 10 ++++++---- src/styles/Extn-AIChatPanel.less | 10 ++++++++++ 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src-node/claude-code-agent.js b/src-node/claude-code-agent.js index f3f5394037..a25800ab88 100644 --- a/src-node/claude-code-agent.js +++ b/src-node/claude-code-agent.js @@ -103,11 +103,14 @@ let _planApproved = false; let _queuedClarification = null; // Module-level "runtime" permission mode that hooks read at decision time. -// Updated on every sendPrompt and via the setPermissionMode peer when the -// user cycles the panel's permission bar mid-stream — without this, the -// Bash hook would close over the value at query start and continue -// prompting for confirmation even after the user has flipped to Full Auto. -let _runtimePermissionMode = "acceptEdits"; +// One of "plan" | "acceptEdits" | "auto" (SDK classifier-approved) | +// "bypassPermissions" (Allow Everything). Updated on every sendPrompt and +// via the setPermissionMode peer when the user cycles the panel's +// permission bar mid-stream — without this, the Bash hook would close over +// the value at query start and continue prompting for confirmation even +// after the user has flipped to Allow Everything. Defaults to "auto" to +// match the browser's default (see AIChatPanel.js's _permissionMode). +let _runtimePermissionMode = "auto"; const nodeConnector = global.createNodeConnector(CONNECTOR_ID, exports); @@ -661,7 +664,7 @@ exports.answerPlanModeWriteConfirm = async function (params) { * Apply a mid-stream permission-mode change so hooks running for the rest * of the turn use the new value. Called from the browser when the user * cycles the permission bar (so e.g. Bash stops prompting immediately - * after switching from Edit Mode to Full Auto). The next sendPrompt also + * after switching from Edit Mode to Allow Everything). The next sendPrompt also * passes permissionMode in params, so this peer is only strictly required * during streaming — but calling it on every cycle keeps the agent's * tracker authoritative. @@ -758,7 +761,7 @@ async function _runQuery(requestId, prompt, projectPath, model, signal, locale, // Sync the runtime mutable that hooks read for permission decisions — // setPermissionMode (peer) updates this same variable when the user // cycles modes mid-stream. - _runtimePermissionMode = permissionMode || "acceptEdits"; + _runtimePermissionMode = permissionMode || "auto"; let editCount = 0; let toolCounter = 0; // SDK tool_use id (e.g. "toolu_01...") → our sequential toolCounter so a @@ -901,7 +904,7 @@ async function _runQuery(requestId, prompt, projectPath, model, signal, locale, } }, mcpServers: { "phoenix-editor": editorMcpServer }, - permissionMode: permissionMode || "acceptEdits", + permissionMode: permissionMode || "auto", appendSystemPrompt: "When modifying an existing file, always prefer the Edit tool " + "(find-and-replace) instead of the Write tool. The Write tool should ONLY be used " + @@ -1288,11 +1291,15 @@ async function _runQuery(requestId, prompt, projectPath, model, signal, locale, async (input) => { // Read from the runtime mutable so mid-stream // permission-mode flips (e.g. user switches Edit - // Mode → Full Auto while bash is in flight) take - // effect on the NEXT bash call without waiting - // for the next prompt. + // Mode → Allow Everything while bash is in flight) + // take effect on the NEXT bash call without + // waiting for the next prompt. if (_runtimePermissionMode !== "acceptEdits") { - // Plan mode: SDK handles. Full Auto: allow freely. + // Plan mode: SDK handles. Auto: SDK's own + // classifier decides. Allow Everything: allow + // freely. Either way, Phoenix's own + // confirm-dialog/safe-bash-allowlist below is + // only for Edit Mode's manual approval flow. return {}; } // Edit Mode: ask user confirmation before running bash diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index e55042a97a..36a2a2806f 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -2660,9 +2660,9 @@ define({ "AI_CHAT_FILE_NOT_FOUND_MSG": "Could not open {0}. The file may have been moved or deleted.", "AI_CHAT_UNDO_RESTORE_WARNING_TITLE": "AI Undo & Restore", "AI_CHAT_UNDO_RESTORE_WARNING_BODY": "This will only undo changes made by the AI. Changes made outside the AI won’t be restored and may be lost. For full version history, use version control like Git.", - "AI_CHAT_FULL_AUTO_WARNING_TITLE": "Switch to Full Auto Mode?", - "AI_CHAT_FULL_AUTO_WARNING_BODY": "Full Auto mode lets the AI run any tool — Bash commands, file edits, file deletions, web fetches — without asking you first.

This is convenient for trusted scratch projects, but can be risky: a misjudged step could overwrite or delete files, run a destructive shell command, or push unintended changes. Use version control (Git) so you can recover if something goes wrong.

Only enable Full Auto in projects you trust. You can switch back to Edit Mode at any time using Shift+Tab or by clicking the mode bar.", - "AI_CHAT_FULL_AUTO_WARNING_PROCEED": "Enable Full Auto", + "AI_CHAT_FULL_AUTO_WARNING_TITLE": "Switch to Allow Everything Mode?", + "AI_CHAT_FULL_AUTO_WARNING_BODY": "Allow Everything mode lets the AI run any tool — Bash commands, file edits, file deletions, web fetches — without asking you first.

This is convenient for trusted scratch projects, but can be risky: a misjudged step could overwrite or delete files, run a destructive shell command, or push unintended changes. Use version control (Git) so you can recover if something goes wrong.

Only enable Allow Everything in projects you trust. You can switch back to Edit Mode at any time using Shift+Tab or by clicking the mode bar.", + "AI_CHAT_FULL_AUTO_WARNING_PROCEED": "Enable Allow Everything", "AI_CHAT_ONBOARDING_REVIEW_PROMPT": "Ready to build", "AI_CHAT_ONBOARDING_SEND": "Send", "AI_CHAT_SHOW_DIFF": "Show diff", @@ -2699,9 +2699,11 @@ define({ "AI_CHAT_PLAN_REVISE_DEFAULT": "Please revise the plan.", "AI_CHAT_MODE_PLAN": "Plan Mode", "AI_CHAT_MODE_EDIT": "AI Edit Mode", - "AI_CHAT_MODE_FULL_AUTO": "Full Auto", + "AI_CHAT_MODE_AUTO": "Auto", + "AI_CHAT_MODE_FULL_AUTO": "Allow Everything", "AI_CHAT_MODE_INFO_PLAN": "AI will propose a plan before making changes (Click to switch)", "AI_CHAT_MODE_INFO_EDIT": "AI can edit files. Shell commands need approval (Click to switch)", + "AI_CHAT_MODE_INFO_AUTO": "AI uses judgment to auto-approve safe actions and asks about risky ones (Click to switch)", "AI_CHAT_MODE_INFO_FULL_AUTO": "AI can edit files and run commands without approval (Click to switch)", "AI_CHAT_PERMISSION_SELECT_TITLE": "Choose how much the AI can do without approval [or Shift+Tab]", "AI_CHAT_AUTH_ERROR_NOTICE": "Claude Code is signed out or your login has expired.", diff --git a/src/styles/Extn-AIChatPanel.less b/src/styles/Extn-AIChatPanel.less index b4ca306a9d..5c24668bf2 100644 --- a/src/styles/Extn-AIChatPanel.less +++ b/src/styles/Extn-AIChatPanel.less @@ -454,6 +454,12 @@ .dropdownbutton-popup.ai-permission-dropdown-popup { min-width: 220px; max-width: 320px; + // Override the shared .dropdownbutton-popup.dropdown-menu 160px cap + // (brackets_patterns_override.less) — 4 two-line items run ~200px, + // past that cap, which forced a scrollbar for a list that otherwise + // fits easily. Cap against the viewport instead so it only scrolls + // if it would genuinely run past the screen. + max-height: 90vh; li a { white-space: normal; @@ -2726,6 +2732,10 @@ &.mode-plan { background-color: #3498db; } + + &.mode-classifier { + background-color: #9b59b6; + } } .ai-permission-label { From eade916376a7cc89116caf821e7d28482aa8beaf Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 18 Aug 2026 22:35:37 +0530 Subject: [PATCH 2/2] build: update pro deps --- tracking-repos.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracking-repos.json b/tracking-repos.json index 162c990997..a7f78a6f5b 100644 --- a/tracking-repos.json +++ b/tracking-repos.json @@ -1,5 +1,5 @@ { "phoenixPro": { - "commitID": "4c5eea43d26daf438d288eb12ff968d1a9780b38" + "commitID": "ab180272ae33a5abbd53dcdc60eddb0c4d035a6c" } }