Skip to content

Commit b6624d7

Browse files
committed
feat(ai-chat): apply mid-stream permission-mode cycles to bash hook
The Bash PreToolUse hook closed over the permissionMode argument set once at _runQuery start. Cycling the panel's permission bar from Edit Mode to Full Auto mid-stream had no effect on bash calls already queued in the same turn — they kept hitting the confirm prompt even though the user had already opted out of confirmation. Add a module-level _runtimePermissionMode that hooks read at decision time and a setPermissionMode peer the browser calls on every cycle. _runQuery still seeds it from the params at start; setPermissionMode overrides it for the rest of the turn. The Bash hook now reads from this mutable instead of the closure parameter. Other hooks (Edit/Write plan-mode confirm, plan-file branches) keep using the closure parameter intentionally — flipping into/out of plan mode mid-stream can't undo what the SDK already permitted at query start, so the runtime override would only confuse those paths.
1 parent dc4fc9e commit b6624d7

1 file changed

Lines changed: 33 additions & 1 deletion

File tree

src-node/claude-code-agent.js

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ let _planApproved = false;
8181
// Shape: { text: string, images: [{mediaType, base64Data}] } or null
8282
let _queuedClarification = null;
8383

84+
// Module-level "runtime" permission mode that hooks read at decision time.
85+
// Updated on every sendPrompt and via the setPermissionMode peer when the
86+
// user cycles the panel's permission bar mid-stream — without this, the
87+
// Bash hook would close over the value at query start and continue
88+
// prompting for confirmation even after the user has flipped to Full Auto.
89+
let _runtimePermissionMode = "acceptEdits";
90+
8491
const nodeConnector = global.createNodeConnector(CONNECTOR_ID, exports);
8592

8693
/**
@@ -360,6 +367,22 @@ exports.answerPlanModeWriteConfirm = async function (params) {
360367
return { success: true };
361368
};
362369

370+
/**
371+
* Apply a mid-stream permission-mode change so hooks running for the rest
372+
* of the turn use the new value. Called from the browser when the user
373+
* cycles the permission bar (so e.g. Bash stops prompting immediately
374+
* after switching from Edit Mode to Full Auto). The next sendPrompt also
375+
* passes permissionMode in params, so this peer is only strictly required
376+
* during streaming — but calling it on every cycle keeps the agent's
377+
* tracker authoritative.
378+
*/
379+
exports.setPermissionMode = async function (params) {
380+
if (params && typeof params.mode === "string") {
381+
_runtimePermissionMode = params.mode;
382+
}
383+
return { success: true };
384+
};
385+
363386
/**
364387
* Resume a previous session by setting the session ID.
365388
* The next sendPrompt call will use queryOptions.resume with this session ID.
@@ -430,6 +453,10 @@ exports.clearClarification = async function () {
430453
* Internal: run a Claude SDK query and stream results back to the browser.
431454
*/
432455
async function _runQuery(requestId, prompt, projectPath, model, signal, locale, images, envOverrides, permissionMode) {
456+
// Sync the runtime mutable that hooks read for permission decisions —
457+
// setPermissionMode (peer) updates this same variable when the user
458+
// cycles modes mid-stream.
459+
_runtimePermissionMode = permissionMode || "acceptEdits";
433460
let editCount = 0;
434461
let toolCounter = 0;
435462
// SDK tool_use id (e.g. "toolu_01...") → our sequential toolCounter so a
@@ -863,7 +890,12 @@ async function _runQuery(requestId, prompt, projectPath, model, signal, locale,
863890
matcher: "Bash",
864891
hooks: [
865892
async (input) => {
866-
if (permissionMode !== "acceptEdits") {
893+
// Read from the runtime mutable so mid-stream
894+
// permission-mode flips (e.g. user switches Edit
895+
// Mode → Full Auto while bash is in flight) take
896+
// effect on the NEXT bash call without waiting
897+
// for the next prompt.
898+
if (_runtimePermissionMode !== "acceptEdits") {
867899
// Plan mode: SDK handles. Full Auto: allow freely.
868900
return {};
869901
}

0 commit comments

Comments
 (0)