fix(brain): drop --approval-mode yolo from Gemini CLI search

yolo auto-approves every tool call, so a real-time search query could in
principle trigger write/shell tools. Default approval mode still auto-runs the
CLI's read-only web search in headless mode but never silently approves
destructive tools. Verified end-to-end: a grounded query returns a current
answer in ~23s with the account OAuth login. Test asserts yolo is absent;
specs and docs/llm_contexts.md updated.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
javis-bot
2026-06-11 00:58:46 +09:00
parent b88def6756
commit f54e2a46ae
5 changed files with 14 additions and 5 deletions

View File

@@ -172,7 +172,7 @@ Every distinct LLM call in Jarvis, what feeds it, what consumes it, and how it i
- **Weather** ([src/jarvis/tools/builtin/weather.py](src/jarvis/tools/builtin/weather.py), ~line 60) — `ollama_chat_model`, parses location/time/unit from the query.
- **Nutrition log_meal** ([src/jarvis/tools/builtin/nutrition/log_meal.py](src/jarvis/tools/builtin/nutrition/log_meal.py), lines 48 & 136) — `ollama_chat_model`, extracts nutrients, confirms logging.
- **Gemini real-time search** ([src/jarvis/tools/builtin/realtime_search.py](src/jarvis/tools/builtin/realtime_search.py)) — **external Gemini model**, NOT Ollama. Only on the `webSearch` route when `STREAM_BROWSER=false`; the sub-mode is `cfg.gemini_auth` (env `GEMINI_AUTH`, default `oauth`):
- `oauth` (default) `gemini_cli_search()` — shells out to the Gemini CLI (`gemini -p <query> -o json --skip-trust --approval-mode yolo`) authenticated by the user's Google-account login (`GEMINI_API_KEY`/`GOOGLE_API_KEY` stripped from the child env, `GOOGLE_GENAI_USE_GCA=true` set to select OAuth); model is whatever the CLI/account defaults to. Uses the CLI's built-in web-search grounding. Bounded by a 30s subprocess timeout.
- `oauth` (default) `gemini_cli_search()` — shells out to the Gemini CLI (`gemini -p <query> -o json --skip-trust`, default approval mode) authenticated by the user's Google-account login (`GEMINI_API_KEY`/`GOOGLE_API_KEY` stripped from the child env, `GOOGLE_GENAI_USE_GCA=true` set to select OAuth); model is whatever the CLI/account defaults to. Uses the CLI's built-in web-search grounding. Bounded by a 30s subprocess timeout.
- `apikey` `gemini_search()` — one REST `generateContent` call (`gemini_model`, default `gemini-2.0-flash`) with the `google_search` grounding tool; keyed by `GEMINI_API_KEY`.
Both return the fenced UNTRUSTED-WEB-EXTRACT envelope consumed by the main loop (#1). Fail-open: CLI missing / login expired / quota 429 / timeout / errors / missing key all fall through to the DDG cascade. The `STREAM_BROWSER=true` route (`browser_search()`) makes NO LLM call — it drives Chrome and scrapes Google results.

View File

@@ -33,8 +33,9 @@ info is fetched by a tool the reply engine calls. `STREAM_BROWSER` selects HOW:
`UNTRUSTED WEB EXTRACT` envelope. Keeps the 39k-line Python brain dep-free.
- Gemini has two auth sub-modes (`GEMINI_AUTH`):
- `oauth` (default): shell out to the Gemini CLI (`gemini -p <query> -o json
--skip-trust --approval-mode yolo`) authenticated by the user's Google
account login. `GEMINI_API_KEY`/`GOOGLE_API_KEY` are stripped from the child
--skip-trust`, default approval mode — read-only tools like web search run
headless, but write/shell tools are never auto-approved) authenticated by
the user's Google account login. `GEMINI_API_KEY`/`GOOGLE_API_KEY` are stripped from the child
env, and `GOOGLE_GENAI_USE_GCA=true` is set, so the CLI uses the account
login (not API-key auth) and fails fast when no login exists rather than
erroring on "no auth method". The CLI is resolved from `PATH` or