diff --git a/apps/settings/routes.py b/apps/settings/routes.py index b1e9d8da6..6bcbfb4ce 100644 --- a/apps/settings/routes.py +++ b/apps/settings/routes.py @@ -229,6 +229,11 @@ def update_config() -> Any: if old_value != new_value: changed_fields[key] = {"old": old_value, "new": new_value} config[section][key] = new_value + if section == "env": + if new_value: + os.environ[key] = new_value + else: + os.environ.pop(key, None) # Hash password before writing to disk if section == "convey" and "password" in data: diff --git a/tests/test_validate_key.py b/tests/test_validate_key.py index 9986292a9..19de7006e 100644 --- a/tests/test_validate_key.py +++ b/tests/test_validate_key.py @@ -4,6 +4,7 @@ from __future__ import annotations import json +import os from unittest.mock import Mock, patch import pytest @@ -309,6 +310,34 @@ def test_update_config_clears_key_validation(settings_client): assert "google" not in saved["providers"]["key_validation"] +def test_update_config_env_mirrors_os_environ(settings_client, monkeypatch): + """The HTTP env-section save path must mirror into os.environ in-process, + matching the CLI pattern (apps/settings/call.py keys_set/keys_clear). + Without this, /api/providers reports `configured: false` until restart.""" + client, _ = settings_client + monkeypatch.delenv("GOOGLE_API_KEY", raising=False) + + with patch( + "think.providers.validate_key", + return_value={"valid": True}, + ): + response = client.put( + "/app/settings/api/config", + json={"section": "env", "data": {"GOOGLE_API_KEY": "live-key"}}, + ) + + assert response.status_code == 200 + assert os.environ.get("GOOGLE_API_KEY") == "live-key" + + response = client.put( + "/app/settings/api/config", + json={"section": "env", "data": {"GOOGLE_API_KEY": ""}}, + ) + + assert response.status_code == 200 + assert "GOOGLE_API_KEY" not in os.environ + + def test_get_providers_includes_key_validation(settings_client): client, journal = settings_client config_path = journal / "config" / "journal.json"