personal memory agent
0
fork

Configure Feed

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

Merge branch 'hopper-paqcwqdy-vertex-settings-override'

+126
+111
tests/test_cli_provider.py
··· 4 4 """Tests for think.providers.cli — CLI subprocess runner infrastructure.""" 5 5 6 6 import asyncio 7 + import json 7 8 import os 9 + from pathlib import Path 8 10 from unittest.mock import AsyncMock, mock_open, patch 9 11 10 12 import pytest ··· 833 835 env = build_cogitate_env("GOOGLE_API_KEY") 834 836 assert "GOOGLE_CLOUD_PROJECT" not in env 835 837 assert "GOOGLE_CLOUD_LOCATION" not in env 838 + 839 + def test_vertex_backend_sets_system_settings_path(self): 840 + """Vertex backend exposes the Gemini CLI system settings path.""" 841 + config = { 842 + "providers": { 843 + "google_backend": "vertex", 844 + "auth": {"google": "platform"}, 845 + } 846 + } 847 + with ( 848 + patch.dict(os.environ, {"GOOGLE_API_KEY": "gk-test"}, clear=True), 849 + patch("think.utils.get_config", return_value=config), 850 + patch("think.utils.get_journal", return_value="/fake/journal"), 851 + patch.object(Path, "exists", return_value=True), 852 + ): 853 + env = build_cogitate_env("GOOGLE_API_KEY") 854 + assert ( 855 + env["GEMINI_CLI_SYSTEM_SETTINGS_PATH"] 856 + == "/fake/journal/.config/gemini-vertex-settings.json" 857 + ) 858 + 859 + def test_aistudio_backend_no_system_settings_path(self): 860 + """AI Studio backend does not set Gemini CLI system settings.""" 861 + config = { 862 + "providers": { 863 + "google_backend": "aistudio", 864 + "auth": {"google": "api_key"}, 865 + } 866 + } 867 + with ( 868 + patch.dict(os.environ, {"GOOGLE_API_KEY": "gk-test"}, clear=True), 869 + patch("think.utils.get_config", return_value=config), 870 + ): 871 + env = build_cogitate_env("GOOGLE_API_KEY") 872 + assert "GEMINI_CLI_SYSTEM_SETTINGS_PATH" not in env 873 + 874 + def test_aistudio_clears_inherited_system_settings_path(self): 875 + """AI Studio clears inherited Gemini CLI system settings.""" 876 + config = { 877 + "providers": { 878 + "google_backend": "aistudio", 879 + "auth": {"google": "api_key"}, 880 + } 881 + } 882 + with ( 883 + patch.dict( 884 + os.environ, 885 + { 886 + "GOOGLE_API_KEY": "gk-test", 887 + "GEMINI_CLI_SYSTEM_SETTINGS_PATH": "/old/settings.json", 888 + }, 889 + clear=True, 890 + ), 891 + patch("think.utils.get_config", return_value=config), 892 + ): 893 + env = build_cogitate_env("GOOGLE_API_KEY") 894 + assert "GEMINI_CLI_SYSTEM_SETTINGS_PATH" not in env 895 + 896 + def test_vertex_writes_settings_file_when_absent(self): 897 + """Vertex backend creates Gemini CLI system settings when missing.""" 898 + config = { 899 + "providers": { 900 + "google_backend": "vertex", 901 + "auth": {"google": "platform"}, 902 + } 903 + } 904 + with ( 905 + patch.dict(os.environ, {"GOOGLE_API_KEY": "gk-test"}, clear=True), 906 + patch("think.utils.get_config", return_value=config), 907 + patch("think.utils.get_journal", return_value="/fake/journal"), 908 + patch.object(Path, "exists", return_value=False), 909 + patch("os.makedirs") as mock_mkdirs, 910 + patch("builtins.open", mock_open()) as mock_file, 911 + patch("os.chmod") as mock_chmod, 912 + ): 913 + env = build_cogitate_env("GOOGLE_API_KEY") 914 + written = "".join(call.args[0] for call in mock_file().write.call_args_list) 915 + assert env["GEMINI_CLI_SYSTEM_SETTINGS_PATH"] == ( 916 + "/fake/journal/.config/gemini-vertex-settings.json" 917 + ) 918 + assert mock_mkdirs.called 919 + assert mock_file.called 920 + assert json.loads(written) == { 921 + "security": {"auth": {"selectedType": "vertex-ai"}} 922 + } 923 + mock_chmod.assert_called_once_with( 924 + "/fake/journal/.config/gemini-vertex-settings.json", 0o600 925 + ) 926 + 927 + def test_vertex_skips_settings_write_when_exists(self): 928 + """Vertex backend does not rewrite existing Gemini CLI settings.""" 929 + config = { 930 + "providers": { 931 + "google_backend": "vertex", 932 + "auth": {"google": "platform"}, 933 + } 934 + } 935 + with ( 936 + patch.dict(os.environ, {"GOOGLE_API_KEY": "gk-test"}, clear=True), 937 + patch("think.utils.get_config", return_value=config), 938 + patch("think.utils.get_journal", return_value="/fake/journal"), 939 + patch.object(Path, "exists", return_value=True), 940 + patch("builtins.open", mock_open()) as mock_file, 941 + ): 942 + env = build_cogitate_env("GOOGLE_API_KEY") 943 + assert env["GEMINI_CLI_SYSTEM_SETTINGS_PATH"] == ( 944 + "/fake/journal/.config/gemini-vertex-settings.json" 945 + ) 946 + mock_file.assert_not_called()
+15
think/providers/cli.py
··· 487 487 ) 488 488 # else: GOOGLE_APPLICATION_CREDENTIALS may be inherited from env 489 489 env["GOOGLE_CLOUD_LOCATION"] = "global" 490 + from think.utils import get_journal 491 + 492 + settings_path = ( 493 + Path(get_journal()) / ".config" / "gemini-vertex-settings.json" 494 + ) 495 + if not settings_path.exists(): 496 + os.makedirs(settings_path.parent, exist_ok=True) 497 + with open(settings_path, "w", encoding="utf-8") as settings_file: 498 + json.dump( 499 + {"security": {"auth": {"selectedType": "vertex-ai"}}}, 500 + settings_file, 501 + ) 502 + os.chmod(str(settings_path), 0o600) 503 + env["GEMINI_CLI_SYSTEM_SETTINGS_PATH"] = str(settings_path) 490 504 else: 491 505 # AI Studio: clear any inherited Vertex env vars so the CLI 492 506 # doesn't accidentally run in Vertex mode. 493 507 for vkey in ( 508 + "GEMINI_CLI_SYSTEM_SETTINGS_PATH", 494 509 "GOOGLE_APPLICATION_CREDENTIALS", 495 510 "GOOGLE_CLOUD_LOCATION", 496 511 "GOOGLE_CLOUD_PROJECT",