Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 19 additions & 12 deletions src-node/claude-code-agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 " +
Expand Down Expand Up @@ -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
Expand Down
10 changes: 6 additions & 4 deletions src/nls/root/strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -2660,9 +2660,9 @@ define({
"AI_CHAT_FILE_NOT_FOUND_MSG": "Could not open <span class=\"dialog-filename\">{0}</span>. 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.<br><br>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.<br><br>Only enable Full Auto in projects you trust. You can switch back to Edit Mode at any time using <kbd>Shift+Tab</kbd> 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.<br><br>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.<br><br>Only enable Allow Everything in projects you trust. You can switch back to Edit Mode at any time using <kbd>Shift+Tab</kbd> 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",
Expand Down Expand Up @@ -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.",
Expand Down
10 changes: 10 additions & 0 deletions src/styles/Extn-AIChatPanel.less
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -2726,6 +2732,10 @@
&.mode-plan {
background-color: #3498db;
}

&.mode-classifier {
background-color: #9b59b6;
}
}

.ai-permission-label {
Expand Down
2 changes: 1 addition & 1 deletion tracking-repos.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"phoenixPro": {
"commitID": "4c5eea43d26daf438d288eb12ff968d1a9780b38"
"commitID": "ab180272ae33a5abbd53dcdc60eddb0c4d035a6c"
}
}
Loading