Add DeepSeek/xAI/OpenAI-compatible sentiment providers; custom dark dropdown
Providers (admin-switchable, no redeploy): - DeepSeek and any OpenAI-compatible endpoint (OpenRouter, Together, Groq, local Ollama) via a generic Chat Completions adapter + base_url - xAI Grok with Live Search (search_parameters web+X, citations) — grounded tier alongside OpenAI and Gemini - DeepSeek / generic compatible endpoints are ungrounded (no web search); UI shows an amber warning and labels each provider's grounding - Optional env fallbacks DEEPSEEK_API_KEY / XAI_API_KEY UI: replace native <select> (unstyleable white popup on Windows) with a custom dark Dropdown component everywhere — sentiment provider, scanner filters, market sort, indicators, admin universe, user role. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -33,7 +33,8 @@ class TestGetConfig:
|
||||
assert config["model"] == "gpt-4o-mini"
|
||||
assert config["api_key_configured"] is False
|
||||
assert config["api_key_source"] == "none"
|
||||
assert set(config["valid_providers"]) == {"openai", "gemini"}
|
||||
assert config["web_search"] is True
|
||||
assert set(config["valid_providers"]) == {"openai", "gemini", "deepseek", "xai", "openai_compatible"}
|
||||
|
||||
async def test_never_returns_raw_key(self, session: AsyncSession):
|
||||
await sps.update_sentiment_config(session, api_key="sk-secret-123")
|
||||
@@ -92,3 +93,38 @@ class TestBuildProvider:
|
||||
await sps.update_sentiment_config(session, provider="openai")
|
||||
provider = await sps.build_sentiment_provider(session)
|
||||
assert type(provider).__name__ == "OpenAISentimentProvider"
|
||||
|
||||
async def test_builds_deepseek_with_fixed_base_url(self, session: AsyncSession):
|
||||
await sps.update_sentiment_config(session, provider="deepseek", api_key="ds-x")
|
||||
provider = await sps.build_sentiment_provider(session)
|
||||
assert type(provider).__name__ == "OpenAICompatibleSentimentProvider"
|
||||
config = await sps.get_sentiment_config(session)
|
||||
assert config["base_url"] == "https://api.deepseek.com"
|
||||
assert config["web_search"] is False
|
||||
|
||||
async def test_builds_xai_with_live_search(self, session: AsyncSession):
|
||||
await sps.update_sentiment_config(session, provider="xai", api_key="xai-x")
|
||||
provider = await sps.build_sentiment_provider(session)
|
||||
assert type(provider).__name__ == "OpenAICompatibleSentimentProvider"
|
||||
# xAI is wired with Live Search enabled
|
||||
assert provider._live_search is True
|
||||
assert provider._extra_body == {"search_parameters": {"mode": "auto", "return_citations": True}}
|
||||
config = await sps.get_sentiment_config(session)
|
||||
assert config["base_url"] == "https://api.x.ai/v1"
|
||||
assert config["web_search"] is True
|
||||
|
||||
async def test_openai_compatible_requires_base_url(self, session: AsyncSession):
|
||||
await sps.update_sentiment_config(session, provider="openai_compatible", api_key="x")
|
||||
with pytest.raises(ProviderError):
|
||||
await sps.build_sentiment_provider(session)
|
||||
|
||||
async def test_openai_compatible_with_base_url(self, session: AsyncSession):
|
||||
await sps.update_sentiment_config(
|
||||
session,
|
||||
provider="openai_compatible",
|
||||
api_key="x",
|
||||
model="llama-3.1-70b",
|
||||
base_url="https://openrouter.ai/api/v1",
|
||||
)
|
||||
provider = await sps.build_sentiment_provider(session)
|
||||
assert type(provider).__name__ == "OpenAICompatibleSentimentProvider"
|
||||
|
||||
Reference in New Issue
Block a user