diff --git a/tests/test_cogitate_coder.py b/tests/test_cogitate_coder.py index 906247cbd..33552f1ef 100644 --- a/tests/test_cogitate_coder.py +++ b/tests/test_cogitate_coder.py @@ -141,14 +141,14 @@ class TestOpenAIWriteFlag: class TestGoogleWriteFlag: - """Verify --allowed-tools is controlled by config write flag.""" + """Verify --approval-mode is controlled by config write flag.""" def _provider(self): return importlib.import_module("think.providers.google") @patch("think.providers.google.CLIRunner") - def test_no_write_restricts_tools(self, mock_runner_cls): - """Without write flag, --allowed-tools restricts to sol.""" + def test_no_write_uses_plan_mode(self, mock_runner_cls): + """Without write flag, approval-mode is plan (read-only).""" provider = self._provider() mock_instance = AsyncMock() mock_instance.run = AsyncMock(return_value="result") @@ -159,12 +159,12 @@ class TestGoogleWriteFlag: asyncio.run(provider.run_cogitate(config)) cmd = mock_runner_cls.call_args.kwargs["cmd"] - assert "--allowed-tools" in cmd - assert "run_shell_command(sol)" in cmd + idx = cmd.index("--approval-mode") + assert cmd[idx + 1] == "plan" @patch("think.providers.google.CLIRunner") - def test_write_true_grants_full_access(self, mock_runner_cls): - """With write=True, --allowed-tools is omitted.""" + def test_write_true_uses_yolo_mode(self, mock_runner_cls): + """With write=True, approval-mode is yolo (full access).""" provider = self._provider() mock_instance = AsyncMock() mock_instance.run = AsyncMock(return_value="result") @@ -175,7 +175,8 @@ class TestGoogleWriteFlag: asyncio.run(provider.run_cogitate(config)) cmd = mock_runner_cls.call_args.kwargs["cmd"] - assert "--allowed-tools" not in cmd + idx = cmd.index("--approval-mode") + assert cmd[idx + 1] == "yolo" # --------------------------------------------------------------------------- diff --git a/tests/test_google_cli.py b/tests/test_google_cli.py index a654aa1f5..3306b1b6e 100644 --- a/tests/test_google_cli.py +++ b/tests/test_google_cli.py @@ -16,7 +16,7 @@ def _google_provider(): return importlib.reload(importlib.import_module("think.providers.google")) -def _assert_write_mode_removes_allowed_tools(make_runner): +def _assert_write_mode_uses_yolo_approval(make_runner): provider = _google_provider() MockCLIRunner = make_runner() with patch("think.providers.google.CLIRunner", MockCLIRunner): @@ -27,8 +27,8 @@ def _assert_write_mode_removes_allowed_tools(make_runner): ) ) cmd = MockCLIRunner.last_instance.cmd - assert "--yolo" in cmd - assert "--allowed-tools" not in cmd + idx = cmd.index("--approval-mode") + assert cmd[idx + 1] == "yolo" class TestTranslateGemini: @@ -339,11 +339,11 @@ class TestRunCogitateCommand: ) ) cmd = MockCLIRunner.last_instance.cmd - assert "--yolo" in cmd - assert cmd[cmd.index("--allowed-tools") + 1] == "run_shell_command(sol)" + idx = cmd.index("--approval-mode") + assert cmd[idx + 1] == "plan" - def test_write_mode_removes_allowed_tools(self): - _assert_write_mode_removes_allowed_tools(self._mock_runner) + def test_write_mode_uses_yolo_approval(self): + _assert_write_mode_uses_yolo_approval(self._mock_runner) def test_sandbox_none(self): provider = _google_provider() diff --git a/think/providers/google.py b/think/providers/google.py index 4609f36a3..0375de2aa 100644 --- a/think/providers/google.py +++ b/think/providers/google.py @@ -693,24 +693,27 @@ async def run_cogitate( if system_instruction: prompt_body = system_instruction + "\n\n" + prompt_body - # Build CLI command — yolo mode auto-approves all tool calls - # (required for headless subprocess use). + # Build CLI command. approval-mode controls tool access: + # "yolo" — auto-approve all tools (write-enabled agents only) + # "plan" — read-only mode (no file writes, no destructive tools) + # The deprecated --allowed-tools flag did NOT restrict tool + # availability, only auto-approval — combined with --yolo it + # provided zero protection. --approval-mode plan is the + # replacement that actually enforces read-only. + approval = "yolo" if config.get("write") else "plan" cmd = [ "gemini", "-p", "-", "-o", "stream-json", - "--yolo", + "--approval-mode", + approval, "-m", model, "--sandbox=none", ] - # Restrict tool access unless write mode is enabled - if not config.get("write"): - cmd.extend(["--allowed-tools", "run_shell_command(sol)"]) - # Resume from previous session if continuing if session_id: cmd.extend(["--resume", session_id])