feat(llm): refresh the model lists to each provider's current lineup

- xAI: Grok 4.6 and 4.5; DeepSeek: deepseek-flash (V4.1); Qwen: the 3.8 series; Mistral: the current dated snapshots
- every provider can name a model the picker does not list
- retired IDs stay valid, so existing configs run without a warning
This commit is contained in:
Yijia-Xiao
2026-09-18 01:14:05 +00:00
parent ed6eae44b6
commit 10cc070fa3
2 changed files with 71 additions and 18 deletions

View File

@@ -64,3 +64,37 @@ def test_legacy_ids_stay_valid_without_being_offered():
for model in ids: for model in ids:
assert validate_model(provider, model), model assert validate_model(provider, model), model
assert model not in offered, f"{model} is legacy but still in the picker" assert model not in offered, f"{model} is legacy but still in the picker"
@pytest.mark.unit
def test_an_explicit_alias_of_a_listed_model_is_known():
"""gpt-5.6 is served under its own name and as gpt-5.6-sol; naming the
explicit one should not warn that the model is unknown."""
from tradingagents.llm_clients.validators import validate_model
assert validate_model("openai", "gpt-5.6-sol")
@pytest.mark.unit
@pytest.mark.parametrize("provider", ["openai", "anthropic", "google", "xai"])
@pytest.mark.parametrize("mode", ["quick", "deep"])
def test_every_provider_lets_you_name_your_own_model(provider, mode):
"""The docs tell users to name any model their provider serves; the picker
has to offer that too, or a new model is unreachable until we ship a list."""
from tradingagents.llm_clients.model_catalog import get_model_options
assert "custom" in [value for _, value in get_model_options(provider, mode)]
@pytest.mark.unit
@pytest.mark.parametrize("provider, model", [
("xai", "grok-4.20-0309-reasoning"),
("deepseek", "deepseek-v4-flash"),
("qwen", "qwen3.7-max"),
])
def test_a_retired_model_id_still_runs_without_a_warning(provider, model):
"""A config written against an earlier release keeps working: the provider
still serves these, they are just no longer offered in the picker."""
from tradingagents.llm_clients.validators import validate_model
assert validate_model(provider, model)

View File

@@ -45,14 +45,12 @@ _GLM_MODELS: dict[str, list[ModelOption]] = {
# "Custom model ID". # "Custom model ID".
_QWEN_MODELS: dict[str, list[ModelOption]] = { _QWEN_MODELS: dict[str, list[ModelOption]] = {
"quick": [ "quick": [
("Qwen 3.7 Plus - Latest, balanced speed/cost", "qwen3.7-plus"), ("Qwen 3.8 Flash - Latest fast model, 1M ctx", "qwen3.8-flash"),
("Qwen 3.6 Plus - Previous-gen balanced", "qwen3.6-plus"),
("Custom model ID", "custom"), ("Custom model ID", "custom"),
], ],
"deep": [ "deep": [
("Qwen 3.7 Max - Latest flagship, most intelligent, 1M ctx", "qwen3.7-max"), ("Qwen 3.8 Max - Latest flagship", "qwen3.8-max"),
("Qwen 3.6 Max - Previous-gen flagship", "qwen3.6-max"), ("Qwen 3.8 Flash - Fast alternative, 1M ctx", "qwen3.8-flash"),
("Qwen 3.7 Plus - Balanced alternative", "qwen3.7-plus"),
("Custom model ID", "custom"), ("Custom model ID", "custom"),
], ],
} }
@@ -101,23 +99,27 @@ MODEL_OPTIONS: ProviderModeOptions = {
("GPT-5.6 Luna - Fast, cost-efficient frontier", "gpt-5.6-luna"), ("GPT-5.6 Luna - Fast, cost-efficient frontier", "gpt-5.6-luna"),
("GPT-5.6 Terra - Balances intelligence and cost", "gpt-5.6-terra"), ("GPT-5.6 Terra - Balances intelligence and cost", "gpt-5.6-terra"),
("GPT-5.4 Mini - Fast, strong coding and tool use", "gpt-5.4-mini"), ("GPT-5.4 Mini - Fast, strong coding and tool use", "gpt-5.4-mini"),
("Custom model ID", "custom"),
], ],
"deep": [ "deep": [
("GPT-6 Astra - Latest frontier reasoning", "gpt-6-astra"), ("GPT-6 Astra - Latest frontier reasoning", "gpt-6-astra"),
("GPT-5.6 - Frontier reasoning (Sol)", "gpt-5.6"), ("GPT-5.6 - Frontier reasoning (Sol)", "gpt-5.6"),
("GPT-5.6 Terra - Balances intelligence and cost", "gpt-5.6-terra"), ("GPT-5.6 Terra - Balances intelligence and cost", "gpt-5.6-terra"),
("GPT-5.5 - Previous-gen frontier, 1M context", "gpt-5.5"), ("GPT-5.5 - Previous-gen frontier, 1M context", "gpt-5.5"),
("Custom model ID", "custom"),
], ],
}, },
"anthropic": { "anthropic": {
"quick": [ "quick": [
("Claude Sonnet 5 - Best speed and intelligence balance", "claude-sonnet-5"), ("Claude Sonnet 5 - Best speed and intelligence balance", "claude-sonnet-5"),
("Claude Haiku 4.5 - Fastest with near-frontier intelligence", "claude-haiku-4-5"), ("Claude Haiku 4.5 - Fastest with near-frontier intelligence", "claude-haiku-4-5"),
("Custom model ID", "custom"),
], ],
"deep": [ "deep": [
("Claude Opus 5 - Frontier agentic and enterprise work", "claude-opus-5"), ("Claude Opus 5 - Frontier agentic and enterprise work", "claude-opus-5"),
("Claude Fable 5.1 - Most capable, demanding long-horizon reasoning", "claude-fable-5-1"), ("Claude Fable 5.1 - Most capable, demanding long-horizon reasoning", "claude-fable-5-1"),
("Claude Sonnet 5 - Near-frontier intelligence at Sonnet cost", "claude-sonnet-5"), ("Claude Sonnet 5 - Near-frontier intelligence at Sonnet cost", "claude-sonnet-5"),
("Custom model ID", "custom"),
], ],
}, },
"google": { "google": {
@@ -125,23 +127,26 @@ MODEL_OPTIONS: ProviderModeOptions = {
("Gemini 3.8 Flash - Most capable Flash", "gemini-3.8-flash"), ("Gemini 3.8 Flash - Most capable Flash", "gemini-3.8-flash"),
("Gemini 3.5 Flash Lite - Fast and cost-efficient", "gemini-3.5-flash-lite"), ("Gemini 3.5 Flash Lite - Fast and cost-efficient", "gemini-3.5-flash-lite"),
("Gemini 3.1 Flash Lite - Most cost-efficient", "gemini-3.1-flash-lite"), ("Gemini 3.1 Flash Lite - Most cost-efficient", "gemini-3.1-flash-lite"),
("Custom model ID", "custom"),
], ],
"deep": [ "deep": [
("Gemini 3.8 Flash - Most capable Flash, 1M context", "gemini-3.8-flash"), ("Gemini 3.8 Flash - Most capable Flash, 1M context", "gemini-3.8-flash"),
("Gemini 3.1 Pro - Reasoning-first, complex workflows (preview)", "gemini-3.1-pro-preview"), ("Gemini 3.1 Pro - Reasoning-first, complex workflows (preview)", "gemini-3.1-pro-preview"),
("Gemini 3.5 Flash - Previous Flash, strong agentic + coding", "gemini-3.5-flash"), ("Gemini 3.5 Flash - Previous Flash, strong agentic + coding", "gemini-3.5-flash"),
("Custom model ID", "custom"),
], ],
}, },
"xai": { "xai": {
"quick": [ "quick": [
("Grok 4.3 - Latest flagship, fast with built-in reasoning", "grok-4.3"), ("Grok 4.6 - Latest flagship, fastest, 500K ctx", "grok-4.6"),
("Grok 4.20 (Non-Reasoning) - Speed-optimized", "grok-4.20-0309-non-reasoning"),
("Grok Build 0.1 - Coding-specialized, 256K ctx", "grok-build-0.1"), ("Grok Build 0.1 - Coding-specialized, 256K ctx", "grok-build-0.1"),
("Custom model ID", "custom"),
], ],
"deep": [ "deep": [
("Grok 4.3 - Latest flagship, built-in reasoning, 1M ctx", "grok-4.3"), ("Grok 4.6 - Latest flagship, 500K ctx", "grok-4.6"),
("Grok 4.20 (Reasoning) - Previous-gen reasoning", "grok-4.20-0309-reasoning"), ("Grok 4.5 - Previous flagship, coding and agentic", "grok-4.5"),
("Grok 4.20 Multi-Agent - Multi-agent reasoning", "grok-4.20-multi-agent-0309"), ("Grok 4.3 - Older generation, 1M ctx", "grok-4.3"),
("Custom model ID", "custom"),
], ],
}, },
# DeepSeek: the deepseek-chat / deepseek-reasoner aliases are deprecated # DeepSeek: the deepseek-chat / deepseek-reasoner aliases are deprecated
@@ -150,12 +155,12 @@ MODEL_OPTIONS: ProviderModeOptions = {
# handles the reasoning_content round-trip). # handles the reasoning_content round-trip).
"deepseek": { "deepseek": {
"quick": [ "quick": [
("DeepSeek V4 Flash - Latest fast model, thinking + non-thinking", "deepseek-v4-flash"), ("DeepSeek Flash - V4.1 Flash, fast, 1M ctx", "deepseek-flash"),
("Custom model ID", "custom"), ("Custom model ID", "custom"),
], ],
"deep": [ "deep": [
("DeepSeek V4 Pro - Latest flagship", "deepseek-v4-pro"), ("DeepSeek V4 Pro - Flagship", "deepseek-v4-pro"),
("DeepSeek V4 Flash - Fast, supports thinking", "deepseek-v4-flash"), ("DeepSeek Flash - V4.1 Flash, fast, 1M ctx", "deepseek-flash"),
("Custom model ID", "custom"), ("Custom model ID", "custom"),
], ],
}, },
@@ -201,7 +206,17 @@ MODEL_OPTIONS: ProviderModeOptions = {
# changing) models — offer "Custom model ID" rather than a list that goes # changing) models — offer "Custom model ID" rather than a list that goes
# stale. The endpoint + key are wired by the provider; the user picks the # stale. The endpoint + key are wired by the provider; the user picks the
# model their account has access to. # model their account has access to.
"mistral": _CUSTOM_ONLY, "mistral": {
"quick": [
("Mistral Small 4 - Fast, 262K ctx", "mistral-small-2603"),
("Custom model ID", "custom"),
],
"deep": [
("Mistral Medium 3.5 - 262K ctx", "mistral-medium-2604"),
("Mistral Small 4 - Fast, 262K ctx", "mistral-small-2603"),
("Custom model ID", "custom"),
],
},
"groq": _CUSTOM_ONLY, "groq": _CUSTOM_ONLY,
"nvidia": _CUSTOM_ONLY, "nvidia": _CUSTOM_ONLY,
# Bedrock model IDs / cross-region inference profile IDs are user-specified. # Bedrock model IDs / cross-region inference profile IDs are user-specified.
@@ -214,11 +229,15 @@ def get_model_options(provider: str, mode: str) -> list[ModelOption]:
return MODEL_OPTIONS[provider.lower()][mode] return MODEL_OPTIONS[provider.lower()][mode]
# Still served by the provider but no longer offered in the picker. Known to # Served by the provider but not offered in the picker: models retired from the
# validation so existing configs that name them run without an unknown-model # menu, and the explicit ID of a model listed under a shorter name. Known to
# warning. # validation so a config naming one runs without an unknown-model warning.
LEGACY_MODELS: dict[str, list[str]] = { LEGACY_MODELS: dict[str, list[str]] = {
"openai": ["gpt-5.4"], "openai": ["gpt-5.4", "gpt-5.6-sol"],
"xai": ["grok-4.20-0309-reasoning", "grok-4.20-0309-non-reasoning",
"grok-4.20-multi-agent-0309"],
"deepseek": ["deepseek-v4-flash"],
"qwen": ["qwen3.7-max", "qwen3.7-plus", "qwen3.6-max", "qwen3.6-plus"],
"anthropic": ["claude-fable-5", "claude-opus-4-8", "claude-opus-4-7"], "anthropic": ["claude-fable-5", "claude-opus-4-8", "claude-opus-4-7"],
} }