Add yolo mode: auto-approve tool-call permission requests - #505
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR adds “yolo mode” for the agent pane, enabling automatic approval of tool-call permission requests at the ACP client layer, with two enable paths (global setting + per-session /yolo) and enforcement via the new AllowYoloMode admin policy (GPO).
Changes:
- Adds a new global setting (
agentPane.yoloMode) and Settings UI toggle to launch helpers with--auto-approve-tools, gated byAllowYoloMode. - Adds a per-session
/yoloslash command and sharedyolo_sessionsstate so auto-approve can be enabled for a single ACP session. - Adds policy plumbing + unit tests, plus localized strings and spec documentation for yolo mode.
Reviewed changes
Copilot reviewed 109 out of 109 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/wta/src/protocol/acp/client.rs | Implements yolo-mode auto-approval selection logic in request_permission and threads yolo state into the ACP client. |
| tools/wta/src/protocol/acp/mock_agent_tests.rs | Adds unit tests covering global/per-session yolo behavior and allow-always preference. |
| tools/wta/src/main.rs | Adds hidden helper flags (--auto-approve-tools, --yolo-command-blocked) and wires shared yolo session state into the app/client. |
| tools/wta/src/commands.rs | Registers /yolo slash command and help summary key. |
| tools/wta/src/app.rs | Stores global/per-session yolo mode state, adds /yolo handler, and clears yolo state on /new + /restart. |
| tools/wta/src/app_events.rs | Adds handling for a new session-scoped system message event type. |
| tools/wta/src/app_tests.rs | Updates test harness app construction for new yolo-related App fields. |
| tools/wta/locales/*.yml | Adds localized strings for yolo mode and /yolo command summary across locales. |
| src/cascadia/inc/AgentPolicy.h | Adds AllowYoloMode policy reading + query helpers. |
| src/cascadia/TerminalSettingsModel/MTSMSettings.h | Adds AgentPaneYoloMode setting definition (agentPane.yoloMode). |
| src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl | Exposes AgentPaneYoloMode, EffectiveAgentPaneYoloMode, and IsYoloModePolicyLocked. |
| src/cascadia/TerminalSettingsModel/GlobalAppSettings.h | Declares new effective accessor + policy lock accessor. |
| src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp | Implements effective yolo-mode gating and lock-state query. |
| src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw | Adds UI strings for the global “Auto-approve tool calls (Yolo mode)” toggle and help text. |
| src/cascadia/TerminalSettingsEditor/AIAgentsViewModel.idl | Adds viewmodel properties for yolo mode and its policy lock indicator. |
| src/cascadia/TerminalSettingsEditor/AIAgentsViewModel.h | Adds corresponding C++/WinRT viewmodel method declarations. |
| src/cascadia/TerminalSettingsEditor/AIAgentsViewModel.cpp | Implements yolo-mode property get/set with policy lock guarding and change notifications. |
| src/cascadia/TerminalSettingsEditor/AIAgents.xaml | Adds the yolo-mode toggle UI and disables it when policy-locked. |
| src/cascadia/TerminalApp/TerminalPage.cpp | Plumbs global yolo setting and policy lock into helper command line (--auto-approve-tools, --yolo-command-blocked). |
| src/cascadia/UnitTests_SettingsModel/CustomAgentAndPolicyTests.cpp | Adds SettingsModel unit tests for yolo-mode roundtripping and policy gating behavior. |
| doc/specs/Multi-window-agent-pane.md | Documents yolo mode behavior, enable paths, policy gating, and lifecycle semantics. |
…en available Verified live against copilot --acp --stdio: session/new advertises a per-session config_options entry (category=permissions, id=allow_all). Setting it via session/set_config_option makes the agent stop sending session/request_permission for that session entirely - zero round-trips observed for a subsequent tool call. Add permission_select module (mirrors model_select's config-option detection pattern) to record this capability from NewSessionResponse and apply it to a session via session/set_config_option. Wire it into every new_session call site so a session already in yolo mode (global toggle or a /yolo that raced ahead) gets it applied at creation time, and add a MasterExtRequest::SetSessionAllowAll round-trip so /yolo on an already-live session retroactively applies it too. Agents that don't advertise the config (Claude/Gemini/Codex adapters today) are unaffected: the existing client-side request_permission auto-approve in client.rs remains as the unconditional fallback. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 111 out of 111 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (4)
tools/wta/src/protocol/acp/client.rs:1621
- In yolo mode the code immediately selects an allow option, but it doesn't emit any user-visible signal (despite adding
AppEvent::SessionSystemMessageand localizedsystem.yolo_auto_approved). This makes the new event variant and locale strings unused and contradicts the documented behavior of posting a passive approval message.
tools/wta/src/app.rs:5918 /yolocurrently enables the session override but stays silent. This leaves the localizedsystem.yolo_enabledstring unused and provides no confirmation to the user that auto-approval is now active for the session.
tools/wta/src/protocol/acp/mock_agent_tests.rs:1893- These yolo-mode tests assert that auto-approval emits no events at all, but the feature adds
AppEvent::SessionSystemMessage+system.yolo_auto_approvedspecifically to inform the user what was auto-approved. Once the client emits that message, these assertions should be updated to expect aSessionSystemMessage(and still ensure noPermissionRequestUI prompt is raised).
tools/wta/src/protocol/acp/mock_agent_tests.rs:1914 - This test also assumes yolo auto-approval produces no events. If yolo mode emits a
SessionSystemMessagefor the auto-approved request, consume/assert that message before continuing to the normal interactive flow for the non-yolo session.
…otification plumbing - permission_select::allow_all_option_id now requires the matched config option to also be SessionConfigKind::Select (mirrors model_select::model_option_from_config's guard), so a same-named/ categorized non-Select entry can no longer shadow a later valid Select. Added a regression test for this shape. - Removed the never-constructed AppEvent::SessionSystemMessage variant and its dispatch arm, plus the never-referenced system.yolo_auto_approved / system.yolo_enabled locale strings (all 85 locales) -- leftover plumbing from an earlier iteration of yolo mode's UX that was intentionally made silent (no chat notification on auto-approve, per product decision) but left the now-dead wiring in place. Client-side auto-approve in request_permission and the /yolo command are otherwise unchanged. - Corrected a stale/misleading comment in cmd_yolo that claimed /yolo would retroactively apply once a session_id exists when typed before one is assigned -- it does not; documented the actual (no-op-until-later) behavior instead. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
f9cc10b to
f1a66c6
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 110 out of 110 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
tools/wta/src/protocol/acp/permission_select.rs:59
- The selector match is too broad:
category == "permissions" || id == "allow_all"can select an unrelated permissions-category Select option (if an agent adds more permission-related config options), and WTA would then callsession/set_config_optionwith the wrongconfig_id. Prefer matching the stableid == "allow_all"(optionally validating the category when present) and requireSelect.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 110 out of 110 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
doc/specs/Multi-window-agent-pane.md:949
- This spec claims yolo-mode auto-approval posts an
AppEvent::SessionSystemMessageso the user can see what was approved, but the current implementation (and tests) intentionally keep yolo auto-approval silent (no extra events/messages). The spec should match the shipped behavior.
skips the blocking `PermissionRequest` UI event entirely, picks the best
"allow" option (`allow_always` preferred over `allow_once` — see
`pick_allow_option`), responds immediately, and posts a passive
`AppEvent::SessionSystemMessage` to that session's tab chat so the user
still sees what was approved.
- doc/specs/Multi-window-agent-pane.md: yolo mode section described a
now-removed AppEvent::SessionSystemMessage notification. Updated to
describe the actual (silent) client-side auto-approve, and added the
missing description of the agent-native allow_all delegation channel
(permission_select.rs) added earlier this session.
- system.yolo_blocked_by_policy carried a {Locked="/yolo"} annotation
in all 90 locale files, but no translation (including en-US) ever
spells out the literal "/yolo" token in this string -- it says
"yolo mode"/localized equivalent instead. Removed the stale
annotation everywhere; pre-existing issue, unrelated to this PR's
other changes but surfaced by this round's review once line numbers
shifted.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
`PermOption.kind` is always the PascalCase `format!("{:?}", …)` rendering
of ACP's PermissionOptionKind (see PermOption::is_allow's docs), so the
"allow_always" (snake_case) branch in pick_allow_option could never match
-- only the "AllowAlways" branch did anything, confirmed by the existing
request_permission_yolo_prefers_allow_always_over_allow_once test. Removed
the dead branch and updated the docstring to say AllowAlways/AllowOnce
instead of the never-matching snake_case forms.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 110 out of 110 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (3)
tools/wta/src/protocol/acp/permission_select.rs:59
allow_all_option_idcurrently matches anySelectoption in categorypermissionseven if its id is notallow_all. If an agent ever advertises multiple permission-related config options, this could toggle the wrong setting when yolo mode is enabled. It’s safer to key detection exclusively off the well-known id (allow_all) and treat category as informational only.
tools/wta/src/protocol/acp/client.rs:1600- This comment refers to
allow_always/allow_once, but the code (andPermOption.kind) uses the ACP enum debug renderings likeAllowAlways/AllowOnce. Updating the comment avoids confusion when reading the selection logic.
tools/wta/src/protocol/acp/permission_select.rs:46 - The doc comment for
allow_all_option_idsays it matches by categorypermissionsOR idallow_all. Since matching on category alone is risky (it may match unrelated permission config options), the comment should align with the safer id-based detection.
This issue also appears on line 55 of the same file.
PR #504 refactored run_acp_app out of main.rs into helper/runtime.rs. Reapply the yolo-mode additions (yolo_sessions set, --auto-approve-tools / --yolo-command-blocked passthrough to run_acp_client_over_pipe and App::new) onto their new location. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 111 out of 111 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
tools/wta/src/protocol/acp/permission_select.rs:59
allow_all_option_idcurrently treats any Select config option in categorypermissionsas the native allow-all toggle. If an agent advertises multiple permission-related config options, this can pick the wrong id and then attempt tosession/set_config_option(..., "on")against an unrelated setting. Since the ACP schema always requires anid, this should primarily key off the id (optionally normalizing it), not the free-form category string.
tools/wta/src/app.rs:2158- This field comment says entries are removed when a session ends or is replaced (including
session/load), but the current implementation only removes on/new(cmd_new) and clears on/restart. TheSessionAttachedhandler overwritestab.session_idwithout removing the previous id fromyolo_sessions(seetools/wta/src/app_events.rsSessionAttached arm), so stale ids can linger and could unexpectedly re-enable yolo if an agent ever reuses asession_id. Consider removing the priorsession_idfromyolo_sessionswhenever a tab is re-bound to a newsession_id(and on session end), or update the comment to match the actual cleanup semantics.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 119 out of 119 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
tools/wta/src/protocol/acp/permission_select.rs:62
allow_all_option_idwill treat anyconfigOptionsentry with categorypermissionsas the allow-all selector, even if itsidis notallow_all. That means a future agent that adds additional permissions-related config options could cause WTA to record the wrong config id and callsession/set_config_optionon an unrelated option.
Summary
Adds "yolo mode" (auto-approve tool-call permission requests) for the agent pane.
Two independent, additive enable paths, both gated by the AllowYoloMode GPO policy:
Two enforcement layers
permission_select.rsdetects whether the connected ACP agent advertises a per-sessionconfig_optionsentry (category: "permissions",id: "allow_all") in itssession/newresponse. Verified live against Copilot CLI (copilot --acp --stdio): callingsession/set_config_option(configId: "allow_all", value: "on")makes the agent stop sendingsession/request_permissionentirely for that session — a real protocol-native, per-session auto-approve, with zero permission round-trips observed. This is applied automatically whenever a session is (or becomes) in yolo mode, at every session-creation call site, plus retroactively via a newMasterExtRequest::SetSessionAllowAllwhen/yolois typed on an already-live session.WtaClient::request_permissionintools/wta/src/protocol/acp/client.rs), so it applies uniformly across Copilot, Claude, Gemini, and Codex regardless of whether the agent supports the native option. When active, it skips the permission UI prompt and picks the best "allow" option (preferringallow_alwaysoverallow_once).Agents that don't advertise the native config (Claude/Gemini/Codex ACP adapters today, as far as tested) transparently fall back to layer 2 — no behavior change for them.
Changes
permission_select.rsmodule for agent-native allow-all detection/application,MasterExtRequest::SetSessionAllowAllround-trip.Testing
cargo test --manifest-path tools/wta/Cargo.toml— 1183 passed, 0 failed.TerminalSettingsModel,TerminalSettingsEditor(and previouslyTerminalApp,UnitTests_SettingsModel) built successfully with 0 errors.copilot --acp --stdioconfirmingsession/set_config_option(allow_all, on)suppressessession/request_permissionfor that session only (fresh sessions default to off, no cross-session leakage).Closes #326