feat(desktop): Shift+click the status-bar zap to toggle YOLO globally (#41666)
The status-bar zap currently toggles per-session approval bypass (the same scope as the TUI's Shift+Tab). This adds a global escape hatch: Shift+clicking the zap flips the persistent approvals.mode in config.yaml between "off" (bypass on) and "manual" (bypass off), affecting every session, the CLI, the TUI, and cron — and it survives restarts. - statusbar-controls: thread the click's shiftKey through onSelect via a new StatusbarSelectModifiers arg. - yolo-session: add setGlobalYolo() that calls config.set with scope="global". - use-statusbar-items: branch toggleYolo on modifiers.shiftKey; plain click stays per-session, Shift+click goes global. - tui_gateway config.set "yolo" key: add scope="global" that reads/writes approvals.mode through the gateway's own (mtime-cached) config view, honors an explicit value, and re-emits session.info to every live session so each window's zap reflects the flip immediately. - i18n: tooltip copy in en/ja/zh/zh-hant notes Shift+click toggles globally. Tests: two new tui_gateway tests cover the global toggle and explicit-value paths; existing session/process-scope yolo tests still pass.
This commit is contained in:
@@ -1454,6 +1454,66 @@ def test_config_set_yolo_toggles_session_scope():
|
||||
server._sessions.clear()
|
||||
|
||||
|
||||
def test_config_set_yolo_global_scope_writes_approvals_mode(tmp_path, monkeypatch):
|
||||
"""Shift+click the desktop zap -> scope="global" flips persistent approvals.mode."""
|
||||
import yaml
|
||||
|
||||
cfg_path = tmp_path / "config.yaml"
|
||||
cfg_path.write_text(yaml.safe_dump({"approvals": {"mode": "manual"}}))
|
||||
monkeypatch.setattr(server, "_hermes_home", tmp_path)
|
||||
|
||||
resp_on = server.handle_request(
|
||||
{
|
||||
"id": "1",
|
||||
"method": "config.set",
|
||||
"params": {"key": "yolo", "scope": "global"},
|
||||
}
|
||||
)
|
||||
assert resp_on["result"]["value"] == "1"
|
||||
assert resp_on["result"]["scope"] == "global"
|
||||
assert yaml.safe_load(cfg_path.read_text())["approvals"]["mode"] == "off"
|
||||
|
||||
resp_off = server.handle_request(
|
||||
{
|
||||
"id": "2",
|
||||
"method": "config.set",
|
||||
"params": {"key": "yolo", "scope": "global"},
|
||||
}
|
||||
)
|
||||
assert resp_off["result"]["value"] == "0"
|
||||
assert yaml.safe_load(cfg_path.read_text())["approvals"]["mode"] == "manual"
|
||||
|
||||
|
||||
def test_config_set_yolo_global_scope_honors_explicit_value(tmp_path, monkeypatch):
|
||||
"""An explicit value pins global approvals.mode regardless of prior state."""
|
||||
import yaml
|
||||
|
||||
cfg_path = tmp_path / "config.yaml"
|
||||
cfg_path.write_text(yaml.safe_dump({"approvals": {"mode": "manual"}}))
|
||||
monkeypatch.setattr(server, "_hermes_home", tmp_path)
|
||||
|
||||
resp = server.handle_request(
|
||||
{
|
||||
"id": "1",
|
||||
"method": "config.set",
|
||||
"params": {"key": "yolo", "scope": "global", "value": "1"},
|
||||
}
|
||||
)
|
||||
assert resp["result"]["value"] == "1"
|
||||
assert yaml.safe_load(cfg_path.read_text())["approvals"]["mode"] == "off"
|
||||
|
||||
# Setting it on again is idempotent — stays off.
|
||||
resp_again = server.handle_request(
|
||||
{
|
||||
"id": "2",
|
||||
"method": "config.set",
|
||||
"params": {"key": "yolo", "scope": "global", "value": "1"},
|
||||
}
|
||||
)
|
||||
assert resp_again["result"]["value"] == "1"
|
||||
assert yaml.safe_load(cfg_path.read_text())["approvals"]["mode"] == "off"
|
||||
|
||||
|
||||
def test_config_set_fast_updates_live_agent_and_config(monkeypatch):
|
||||
writes = []
|
||||
emits = []
|
||||
|
||||
Reference in New Issue
Block a user