diff --git a/apps/cloud-api/tests/test_cloud_planner_config.py b/apps/cloud-api/tests/test_cloud_planner_config.py index 0ddc1ac..d71c13a 100644 --- a/apps/cloud-api/tests/test_cloud_planner_config.py +++ b/apps/cloud-api/tests/test_cloud_planner_config.py @@ -40,6 +40,15 @@ def test_build_cloud_planner_client_uses_managed_anthropic_key() -> None: assert client._api_key == "managed-api-key" +def test_build_cloud_planner_client_uses_anthropic_base_url() -> None: + client = build_cloud_planner_client( + _resolved_profile("anthropic", base_url="https://anthropic-proxy.example") + ) + + assert isinstance(client, AnthropicToolCallingClient) + assert client._base_url == "https://anthropic-proxy.example" + + def test_build_cloud_planner_client_uses_openai_compatible_base_url() -> None: client = build_cloud_planner_client( _resolved_profile("openai-compatible", base_url="https://compat.example/v1") diff --git a/apps/cloud-api/tests/test_llm_provider_management.py b/apps/cloud-api/tests/test_llm_provider_management.py index bd4d126..3054cf7 100644 --- a/apps/cloud-api/tests/test_llm_provider_management.py +++ b/apps/cloud-api/tests/test_llm_provider_management.py @@ -136,6 +136,29 @@ def test_provider_profile_requires_admin_scope(monkeypatch) -> None: ) +def test_anthropic_profile_accepts_custom_base_url(monkeypatch) -> None: + from cryptography.fernet import Fernet + + monkeypatch.setenv( + "CLOUD_LLM_PROVIDER_ENCRYPTION_KEY", Fernet.generate_key().decode() + ) + app = create_app(config=CloudControlConfig(database_url="sqlite:///:memory:")) + with TestClient(app) as client: + _create_admin(client) + response = client.post( + "/v1/planner/providers", + headers=_csrf_headers(client), + json=_profile_payload( + name="Anthropic proxy", + provider_type="anthropic", + base_url="https://anthropic-proxy.example/", + ), + ) + + assert response.status_code == 201, response.text + assert response.json()["base_url"] == "https://anthropic-proxy.example" + + def test_profile_write_requires_encryption_key(monkeypatch) -> None: monkeypatch.delenv("CLOUD_LLM_PROVIDER_ENCRYPTION_KEY", raising=False) app = create_app(config=CloudControlConfig(database_url="sqlite:///:memory:")) diff --git a/cloud-console/src/views/LlmProvidersView.vue b/cloud-console/src/views/LlmProvidersView.vue index 127e299..c7fd25b 100644 --- a/cloud-console/src/views/LlmProvidersView.vue +++ b/cloud-console/src/views/LlmProvidersView.vue @@ -98,7 +98,7 @@ async function saveProfile() { saving.value = true; try { - const baseUrl = form.provider_type === "anthropic" ? null : form.base_url.trim() || null; + const baseUrl = form.base_url.trim() || null; if (editingId.value) { const existing = profiles.value.find((profile) => profile.id === editingId.value); if (!existing) throw new Error("Provider profile no longer exists"); @@ -195,8 +195,8 @@ onMounted(refresh); -