personal memory agent
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix(cogitate): mirror GOOGLE_API_KEY → GEMINI_API_KEY for AI Studio CLI subprocess

gemini-cli's getAuthTypeFromEnv() honors GEMINI_API_KEY for gemini-api-key
auto-mode; GOOGLE_API_KEY is recognized only for vertex-ai mode. Without
GEMINI_API_KEY, non-interactive `-p -` invocations fall through to
~/.gemini/settings.json's selectedType, which throws FatalAuthenticationError
(exit 41) on fresh installs that lack a cached oauth-personal session.

In build_cogitate_env's AI Studio branch, mirror the canonical key into the
child env when GOOGLE_API_KEY is set and GEMINI_API_KEY is not, so the CLI
auto-detects api-key auth the same way the Vertex branch asserts vertex-ai
via GEMINI_CLI_SYSTEM_SETTINGS_PATH.

Eliminates the hand-edit-journal.json workaround for new installs whose
wizard config sets only GOOGLE_API_KEY (the default).

Decision record: extro/records/decisions/260505-vpe-cogitate-google-api-key-mirror-shipped.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

+83
+77
tests/test_cli_provider.py
··· 1515 1515 env = build_cogitate_env("google") 1516 1516 assert "GEMINI_CLI_SYSTEM_SETTINGS_PATH" not in env 1517 1517 1518 + def test_aistudio_mirrors_google_api_key_to_gemini_api_key(self): 1519 + """AI Studio mirrors GOOGLE_API_KEY → GEMINI_API_KEY for gemini-cli auth auto-detect.""" 1520 + config = { 1521 + "providers": { 1522 + "google_backend": "aistudio", 1523 + "auth": {"google": "api_key"}, 1524 + } 1525 + } 1526 + with ( 1527 + patch.dict(os.environ, {"GOOGLE_API_KEY": "gk-test"}, clear=True), 1528 + patch("think.utils.get_config", return_value=config), 1529 + ): 1530 + env = build_cogitate_env("google") 1531 + assert env["GOOGLE_API_KEY"] == "gk-test" 1532 + assert env["GEMINI_API_KEY"] == "gk-test" 1533 + 1534 + def test_aistudio_preserves_explicit_gemini_api_key(self): 1535 + """If GEMINI_API_KEY is already set, mirror does not overwrite it.""" 1536 + config = { 1537 + "providers": { 1538 + "google_backend": "aistudio", 1539 + "auth": {"google": "api_key"}, 1540 + } 1541 + } 1542 + with ( 1543 + patch.dict( 1544 + os.environ, 1545 + {"GOOGLE_API_KEY": "gk-test", "GEMINI_API_KEY": "gemini-explicit"}, 1546 + clear=True, 1547 + ), 1548 + patch("think.utils.get_config", return_value=config), 1549 + ): 1550 + env = build_cogitate_env("google") 1551 + assert env["GOOGLE_API_KEY"] == "gk-test" 1552 + assert env["GEMINI_API_KEY"] == "gemini-explicit" 1553 + 1554 + def test_aistudio_no_mirror_when_google_key_absent(self): 1555 + """Platform-mode strips GOOGLE_API_KEY; mirror does not synthesize GEMINI_API_KEY.""" 1556 + config = { 1557 + "providers": { 1558 + "google_backend": "aistudio", 1559 + "auth": {"google": "platform"}, 1560 + } 1561 + } 1562 + with ( 1563 + patch.dict(os.environ, {"GOOGLE_API_KEY": "gk-test"}, clear=True), 1564 + patch("think.utils.get_config", return_value=config), 1565 + ): 1566 + env = build_cogitate_env("google") 1567 + assert "GOOGLE_API_KEY" not in env 1568 + assert "GEMINI_API_KEY" not in env 1569 + 1570 + def test_vertex_does_not_mirror_to_gemini_api_key(self): 1571 + """Vertex backend strips GOOGLE_API_KEY; no GEMINI_API_KEY mirror happens.""" 1572 + config = { 1573 + "providers": { 1574 + "google_backend": "vertex", 1575 + "vertex_credentials": "/tmp/fake-sa.json", 1576 + "auth": {"google": "platform"}, 1577 + } 1578 + } 1579 + with ( 1580 + patch.dict(os.environ, {"GOOGLE_API_KEY": "gk-test"}, clear=True), 1581 + patch("think.utils.get_config", return_value=config), 1582 + patch("os.path.exists", return_value=True), 1583 + patch( 1584 + "builtins.open", 1585 + mock_open( 1586 + read_data='{"type": "service_account", "project_id": "my-gcp-project"}' 1587 + ), 1588 + ), 1589 + patch.object(Path, "exists", return_value=True), 1590 + ): 1591 + env = build_cogitate_env("google") 1592 + assert "GOOGLE_API_KEY" not in env 1593 + assert "GEMINI_API_KEY" not in env 1594 + 1518 1595 def test_vertex_writes_settings_file_when_absent(self, tmp_path): 1519 1596 """Vertex backend creates Gemini CLI system settings when missing.""" 1520 1597 creds_path = tmp_path / "fake-sa.json"
+6
think/providers/cli.py
··· 801 801 "GOOGLE_GENAI_USE_VERTEXAI", 802 802 ): 803 803 env.pop(vkey, None) 804 + # Gemini CLI's auth auto-detection only honors GEMINI_API_KEY for 805 + # api-key mode; GOOGLE_API_KEY is recognized only for vertex-ai mode. 806 + # Mirror the canonical key so non-interactive `-p -` invocations 807 + # don't fall through to oauth-personal and FatalAuthenticationError. 808 + if "GOOGLE_API_KEY" in env and "GEMINI_API_KEY" not in env: 809 + env["GEMINI_API_KEY"] = env["GOOGLE_API_KEY"] 804 810 return env 805 811 806 812