Skip to content

feat(app): pick Auto or Manual permission mode per session - #319

Merged
quickbeard merged 2 commits into
mainfrom
feat/permission-mode-select
Aug 25, 2026
Merged

quickbeard merged 2 commits into
mainfrom
feat/permission-mode-select

Conversation

@quickbeard

Copy link
Copy Markdown
Owner

Adds a permission-mode select to the prompt bar, immediately right of the model select.

[+]  [MiniMax/MiniMax-M3 ▾]  [Manual ▾]                         [Send]
  • Auto — every request the config does not explicitly deny is approved.
  • Manual — the agent stops and asks.
  • Defaults: Code → Manual, Work → Auto.

It drives the same client-side auto-accept state as the permissions.autoaccept command (Cmd/Ctrl+Shift+A) and the Settings → General switch, so all three stay in step instead of becoming a third source of truth. In a session it writes a session-level override, so that session stops following its directory default. On a draft it steers the directory default — what that command already does there, and what the new session inherits when it is sent.

Work needed the mode to become real

The sandbox guest config shipped permission: "allow". A server told to allow everything resolves every action to allow and never emits permission.asked (packages/core/src/permission.ts:160), so Manual would have had nothing to gate — the control would have been decorative on the Work side.

That line is gone. The guest asks like any other server now, and the walk-away default moved host-side: enableConfiguredDirectory gained an autoByDefault parameter, passed as sideForServerKey(activeServer()) === "work". Net default behaviour on Work is unchanged; the difference is that Manual is enforceable.

Two consequences:

  • Existing sandboxes keep the old guest config until their next start. Until then their select renders a non-interactive Auto with a tooltip saying why — the same fallback a project whose own config says permission: "allow" gets.
  • A Work agent left on Manual will wait for approval instead of running unattended. That is the point of the option, but it is a behaviour that did not exist before.

Files

packages/app/src/components/prompt-input-v2.tsx PromptInputV2PermissionControl, passed through the existing modelControl slot as a fragment — no new slot in session-ui, one fewer upstream file touched
packages/app/src/components/prompt-input/permission-mode.ts (+ test) the session-vs-directory write decision, with the no-op guard that stops re-picking the current mode from flipping the directory toggle
packages/app/src/context/permission.tsx autoByDefault for the Work default
packages/desktop/src/main/sandbox/egress.ts guest config no longer approves everything
packages/app/src/i18n/{en,es,vi}.ts prompt.permission.*
DIVERGENCES.md, CHANGELOG.md one row, one Unreleased entry

The TUI's own shift+tab manual/auto cycle is untouched.

Testing

bun typecheck and the suites are clean in both packages — app 703 unit + 130 browser, desktop 136.

Driven in the running dev app over CDP: on a Code session the select renders right of the model select showing Manual, opening it lists Auto=false | Manual=true, picking Auto flips the trigger and the menu state, and picking Manual returns it.

Not verified against a real sandbox. The dev machine has no sandboxes and no built codev-vmm helper, so the Work auto default, the guest-config change, and the locked fallback are covered by reasoning and unit tests only. Worth a manual pass on a machine with a sandbox before release.

🤖 Generated with Claude Code

quickbeard and others added 2 commits August 25, 2026 09:13
Adds a permission-mode select to the prompt bar, immediately right of the
model select. Code sessions default to Manual, Work sessions to Auto — which
is what each side already did; the change is that the choice is now visible
and per-session. It drives the same client-side auto-accept state as the
`permissions.autoaccept` command and the Settings switch, so all three agree.
A session takes an explicit override; a draft steers the directory default,
matching what that command already does there.

Work needed the mode to become real. Its sandbox guest config shipped
`permission: "allow"`, and a server told to allow everything never emits
`permission.asked`, so Manual would have had nothing to gate. The guest now
asks like any other server and the walk-away default moved host-side, where
`enableConfiguredDirectory` seeds Work directories to auto-accept. Existing
sandboxes pick this up on their next start; until then their select renders a
non-interactive Auto explaining why it is fixed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Matches the TUI's consent gate. The first Code-side enable in an app run
raises a confirm dialog — "permission requests that are not explicitly denied
will be approved automatically", and that this is dangerous — focused on
Cancel so a stray Enter declines, followed by a warning toast. Later enables
in the same run are silent, and turning it off never asks.

All three doors go through one gate: the prompt's mode select, the
`permissions.autoaccept` command, and the Settings switch. A warning one of
them skips is theatre.

Work never asks. Auto is the default there, which nobody chose, and the
sandbox confines the agent to the VM and one mounted folder — so a dialog
would greet every new Work session with a question about a decision it did
not make.

The dialog claims focus twice, on mount and on the next frame: the prompt
input restores focus to its editor a frame after its menu closes, and without
the second claim Enter would send the prompt out from under an open dialog.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@quickbeard

Copy link
Copy Markdown
Owner Author

Added: consent gate for Code-side auto-approve (541ea30)

Matches the TUI's enableAutoApprove. The first Code-side enable in an app run raises a confirm dialog — "Permission requests that are not explicitly denied will be approved automatically" / "This is dangerous: CoDev Code can run commands and edit files without asking" — focused on Cancel so a stray Enter declines, followed by a warning toast. Later enables in the same run are silent; turning auto-approve off never asks.

All three doors go through one gate — the prompt's mode select, the permissions.autoaccept command, and the Settings switch — via useAutoAcceptConsent() in the new fork-only src/components/dialog-auto-accept.tsx. A warning one of three doors skips is theatre.

Work never asks. Auto is the default there, which nobody chose, and the sandbox confines the agent to the VM and one mounted folder — a dialog would greet every new Work session with a question about a decision it did not make. The rule lives in autoAcceptNeedsConsent, unit-tested.

One thing worth a reviewer's eye: the dialog claims focus twice, on mount and on the next animation frame. The prompt input restores focus to its editor a frame after its menu closes (restoreFocus in session-ui's interaction.ts), and without the second claim focus sat in the editor with a modal open — Enter would have sent the prompt rather than answering the dialog. Verified fixed.

Verified in the running app

Manual → Auto (Code) dialog appears, mode stays Manual while open
Cancel dialog closes, mode stays Manual
Focus on open document.activeElement is the Cancel button
Enable auto-approve mode becomes Auto, one warning toast
Second enable, same run no dialog
Auto → Manual no dialog, ever
Settings switch, on consent dialog stacks on top of the Settings dialog (push, not show); cancelling leaves the switch off and Settings open

Still unverified against a real sandbox — no sandboxes and no built codev-vmm on this machine — so the Work exemption is covered by the unit test and reasoning only.

bun typecheck clean; app 705 unit (+2) and 130 browser tests pass.

@quickbeard
quickbeard merged commit d0585f6 into main Aug 25, 2026
0 of 5 checks passed
@quickbeard
quickbeard deleted the feat/permission-mode-select branch August 25, 2026 02:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant