release: bump version to 0.50.0
This commit is contained in:
169
backend/tests/test_settings_ai_provider.py
Normal file
169
backend/tests/test_settings_ai_provider.py
Normal file
@@ -0,0 +1,169 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
|
||||
from app.api.v1 import settings as settings_api
|
||||
from app.api.v1.settings import (
|
||||
AIProviderIntegrationUpdate,
|
||||
_build_ai_provider_payload,
|
||||
_mask_secret,
|
||||
_normalize_ai_provider_payload,
|
||||
_resolve_provider_api_key,
|
||||
get_runtime_ai_provider_config,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def isolated_ai_provider_env_file(monkeypatch, tmp_path):
|
||||
env_file = tmp_path / ".env"
|
||||
monkeypatch.setattr(settings_api, "AI_PROVIDER_ENV_FILE", env_file)
|
||||
return env_file
|
||||
|
||||
|
||||
def test_legacy_ai_provider_payload_maps_to_provider_config():
|
||||
payload = _normalize_ai_provider_payload(
|
||||
{
|
||||
"provider": "openai",
|
||||
"provider_api": "openai-completions",
|
||||
"base_url": "https://api.openai.example/v1",
|
||||
"model": "gpt-test",
|
||||
"api_key": "old-openai-key",
|
||||
"max_tokens": 2048,
|
||||
"anthropic_version": "2023-06-01",
|
||||
}
|
||||
)
|
||||
|
||||
assert payload["default_provider"] == "openai"
|
||||
assert payload["providers"]["openai"]["api_key"] == "old-openai-key"
|
||||
assert payload["providers"]["openai"]["model"] == "gpt-test"
|
||||
assert payload["providers"]["openai"]["base_url"] == "https://api.openai.example/v1"
|
||||
|
||||
|
||||
def test_provider_key_prefers_specific_env_file_key(isolated_ai_provider_env_file):
|
||||
isolated_ai_provider_env_file.write_text(
|
||||
"OPENAI_API_KEY=openai-env-file-key\nAI_API_KEY=generic-env-file-key\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
value, source = _resolve_provider_api_key("openai", {"api_key": ""})
|
||||
|
||||
assert value == "openai-env-file-key"
|
||||
assert source == "env_file"
|
||||
|
||||
|
||||
def test_provider_key_falls_back_to_generic_ai_api_key(isolated_ai_provider_env_file):
|
||||
isolated_ai_provider_env_file.write_text(
|
||||
"AI_API_KEY=generic-env-file-key\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
value, source = _resolve_provider_api_key("openai", {"api_key": ""})
|
||||
|
||||
assert value == "generic-env-file-key"
|
||||
assert source == "env_file"
|
||||
|
||||
|
||||
def test_mask_secret_without_prefix_is_fully_masked():
|
||||
assert _mask_secret("plainsecret")["preview"] == "***********"
|
||||
assert _mask_secret("sk-prefixed")["preview"] == "sk-********"
|
||||
|
||||
|
||||
def test_build_payload_updates_only_selected_provider_key():
|
||||
current = {
|
||||
"ai_provider": {
|
||||
"default_provider": "openai",
|
||||
"providers": {
|
||||
"openai": {
|
||||
"provider": "openai",
|
||||
"provider_api": "openai-completions",
|
||||
"base_url": "https://api.openai.com/v1",
|
||||
"model": "gpt-old",
|
||||
"api_key": "openai-old-key",
|
||||
"max_tokens": 4096,
|
||||
"anthropic_version": "2023-06-01",
|
||||
},
|
||||
"minimax": {
|
||||
"provider": "minimax",
|
||||
"api_key": "minimax-old-key",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
update = AIProviderIntegrationUpdate(
|
||||
provider="openai",
|
||||
provider_api="openai-completions",
|
||||
base_url="https://api.openai.com/v1",
|
||||
model="gpt-new",
|
||||
api_key="openai-new-key",
|
||||
max_tokens=8192,
|
||||
)
|
||||
|
||||
payload = _build_ai_provider_payload(current, update)
|
||||
|
||||
assert payload["default_provider"] == "openai"
|
||||
assert payload["providers"]["openai"]["api_key"] == "openai-new-key"
|
||||
assert payload["providers"]["openai"]["model"] == "gpt-new"
|
||||
assert payload["providers"]["minimax"]["api_key"] == "minimax-old-key"
|
||||
|
||||
|
||||
def test_build_payload_keeps_saved_key_when_preview_submitted():
|
||||
current = {
|
||||
"ai_provider": {
|
||||
"providers": {
|
||||
"openai": {
|
||||
"provider": "openai",
|
||||
"api_key": "sk-old-secret",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
update = AIProviderIntegrationUpdate(
|
||||
provider="openai",
|
||||
provider_api="openai-completions",
|
||||
base_url="https://api.openai.com/v1",
|
||||
model="gpt-test",
|
||||
api_key="sk-*********",
|
||||
)
|
||||
|
||||
payload = _build_ai_provider_payload(current, update)
|
||||
|
||||
assert payload["providers"]["openai"]["api_key"] == "sk-old-secret"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_runtime_config_uses_default_provider_specific_key(monkeypatch):
|
||||
record = SimpleNamespace(
|
||||
payload={
|
||||
"ai_provider": {
|
||||
"default_provider": "minimax",
|
||||
"providers": {
|
||||
"openai": {
|
||||
"provider": "openai",
|
||||
"api_key": "openai-key",
|
||||
"provider_api": "openai-completions",
|
||||
"base_url": "https://api.openai.com/v1",
|
||||
"model": "gpt-test",
|
||||
},
|
||||
"minimax": {
|
||||
"provider": "minimax",
|
||||
"api_key": "minimax-key",
|
||||
"provider_api": "anthropic-messages",
|
||||
"base_url": "https://api.minimaxi.com/anthropic",
|
||||
"model": "MiniMax-test",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
async def fake_get_setting_record(_db, category):
|
||||
assert category == "external_integrations"
|
||||
return record
|
||||
|
||||
monkeypatch.setattr(settings_api, "get_setting_record", fake_get_setting_record)
|
||||
|
||||
runtime_config = await get_runtime_ai_provider_config(object())
|
||||
|
||||
assert runtime_config["llm_config"]["provider"] == "minimax"
|
||||
assert runtime_config["llm_config"]["api_key"] == "minimax-key"
|
||||
assert runtime_config["llm_config"]["model"] == "MiniMax-test"
|
||||
Reference in New Issue
Block a user