feat(brain): wire STREAM_BROWSER real-time modes into the reply engine (browser + Gemini)

Completes the two info modes in the Python brain:

- config.py: read STREAM_BROWSER / GEMINI_API_KEY / GEMINI_MODEL from env into
  Settings (stream_browser, gemini_api_key, gemini_model). Verified load_settings
  reads both modes.
- realtime_search.py: two fail-open backends returning the same fenced
  UNTRUSTED-WEB-EXTRACT envelope: browser_search() shells the Node CDP helper to
  drive the on-screen Chrome (visible on the broadcast); gemini_search() calls
  the Gemini REST API with google_search grounding.
- web_search.run(): routes by mode before the DDG cascade (true->browser,
  false->Gemini), falling through to DDG/Brave/Wikipedia on any miss.
- browse_and_play tool: plays a YouTube video on the shared screen (true mode
  only); registered in the tool registry.
- specs + docs/llm_contexts.md updated (new Gemini LLM context); CLAUDE.md spec
  registry updated.

Verified live against the running Chrome: true-mode webSearch returned real
Google results for "오늘 서울 날씨", browseAndPlay played the IU 밤편지 MV, and
false-mode degrades gracefully on a bad/absent key. A valid GEMINI_API_KEY is
still needed to confirm the real Gemini grounding output.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
javis-bot
2026-06-10 16:46:58 +09:00
parent c420d5da53
commit 702fe8017e
9 changed files with 257 additions and 1 deletions

View File

@@ -239,6 +239,12 @@ class Settings:
# Empty string means "not configured" — the tool then falls through to
# the always-on Wikipedia fallback. Free tier is 2,000 queries/month.
brave_search_api_key: str
# Real-time info routing (mirrors the bot's STREAM_BROWSER, read from env).
# True -> browser tools drive the on-screen Chrome (visible on the broadcast).
# False -> geminiSearch uses the Gemini API (gemini_api_key / gemini_model).
stream_browser: bool
gemini_api_key: str
gemini_model: str
# Zero-config Wikipedia fallback toggle. When True (default), the tool
# queries Wikipedia's REST summary API as a last resort before giving up
# with the honest "blocked" envelope. Privacy-light (public API, no key,
@@ -580,6 +586,10 @@ def load_settings() -> Settings:
# Build Settings. Some fields support env var overrides.
# Env overrides: JARVIS_VOICE_DEBUG, JARVIS_WHISPER_BACKEND
voice_debug = os.environ.get("JARVIS_VOICE_DEBUG", "0") == "1"
# Real-time info mode + Gemini account (shared with the bot's .env).
stream_browser = os.environ.get("STREAM_BROWSER", "true").strip().lower() not in ("0", "false", "no")
gemini_api_key = os.environ.get("GEMINI_API_KEY", "").strip()
gemini_model = os.environ.get("GEMINI_MODEL", "").strip() or "gemini-2.0-flash"
# Normalize/convert fields
db_path = str(merged.get("db_path") or _default_db_path())
@@ -855,6 +865,9 @@ def load_settings() -> Settings:
# Web Search
web_search_enabled=web_search_enabled,
brave_search_api_key=brave_search_api_key,
stream_browser=stream_browser,
gemini_api_key=gemini_api_key,
gemini_model=gemini_model,
wikipedia_fallback_enabled=wikipedia_fallback_enabled,
# Dictation