fix(model dropdown): stop injecting default into unrelated providers
This commit is contained in:
@@ -245,6 +245,10 @@ def _available_models_with_full_cfg(provider, default, base_url):
|
||||
'default': default,
|
||||
'base_url': base_url,
|
||||
}
|
||||
try:
|
||||
_cfg._cfg_mtime = _cfg.Path(_cfg._get_config_path()).stat().st_mtime
|
||||
except Exception:
|
||||
pass
|
||||
# Clear model-override env vars to prevent the real profile from leaking in
|
||||
_model_env_keys = ('HERMES_MODEL', 'OPENAI_MODEL', 'LLM_MODEL')
|
||||
_saved_env = {k: os.environ.pop(k, None) for k in _model_env_keys}
|
||||
@@ -318,16 +322,59 @@ def test_default_model_lands_under_active_provider_group(monkeypatch):
|
||||
)
|
||||
groups = {g['provider']: [m['id'] for m in g['models']] for g in result['groups']}
|
||||
assert 'OpenAI Codex' in groups, f"OpenAI Codex group missing: {list(groups)}"
|
||||
assert 'gpt-5.4' in groups['OpenAI Codex'], (
|
||||
norm = lambda mid: mid.split('/', 1)[-1].split(':', 1)[-1]
|
||||
assert 'gpt-5.4' in {norm(mid) for mid in groups['OpenAI Codex']}, (
|
||||
f"gpt-5.4 not in OpenAI Codex group; contents: {groups['OpenAI Codex']}"
|
||||
)
|
||||
# And crucially, it must NOT have landed in the alphabetically-first
|
||||
# group (Anthropic) via the fallback path.
|
||||
assert 'gpt-5.4' not in groups.get('Anthropic', []), (
|
||||
assert 'gpt-5.4' not in {norm(mid) for mid in groups.get('Anthropic', [])}, (
|
||||
f"gpt-5.4 leaked into Anthropic group via fallback: {groups.get('Anthropic')}"
|
||||
)
|
||||
|
||||
|
||||
def test_unknown_providers_do_not_inherit_default_model(monkeypatch):
|
||||
"""Detected providers without their own model catalog must not be filled
|
||||
with the global default_model placeholder.
|
||||
|
||||
Regression guard for the bug where Alibaba / Minimax-Cn ended up showing
|
||||
gpt-5.4-mini even though those providers do not serve it.
|
||||
"""
|
||||
import sys, types
|
||||
|
||||
fake_mod = types.ModuleType('hermes_cli.models')
|
||||
fake_mod.list_available_providers = lambda: [
|
||||
{'id': 'openai-codex', 'authenticated': True},
|
||||
{'id': 'alibaba', 'authenticated': True},
|
||||
{'id': 'minimax-cn', 'authenticated': True},
|
||||
]
|
||||
fake_auth = types.ModuleType('hermes_cli.auth')
|
||||
fake_auth.get_auth_status = lambda pid: {'key_source': 'env'}
|
||||
monkeypatch.setitem(sys.modules, 'hermes_cli.models', fake_mod)
|
||||
monkeypatch.setitem(sys.modules, 'hermes_cli.auth', fake_auth)
|
||||
|
||||
result = _available_models_with_full_cfg(
|
||||
provider='openai-codex',
|
||||
default='gpt-5.4-mini',
|
||||
base_url='',
|
||||
)
|
||||
groups = {g['provider']: [m['id'] for m in g['models']] for g in result['groups']}
|
||||
norm = lambda mid: mid.split('/', 1)[-1].split(':', 1)[-1]
|
||||
|
||||
assert 'Alibaba' not in groups, (
|
||||
f"Alibaba should not inherit the default model placeholder: {groups}"
|
||||
)
|
||||
assert 'Minimax-Cn' not in groups, (
|
||||
f"Minimax-Cn should not inherit the default model placeholder: {groups}"
|
||||
)
|
||||
assert not any(
|
||||
norm(mid) == 'gpt-5.4-mini'
|
||||
for mid in groups.get('Alibaba', []) + groups.get('Minimax-Cn', [])
|
||||
), (
|
||||
f"Unknown provider groups still inherited the default model: {groups}"
|
||||
)
|
||||
|
||||
|
||||
def test_custom_endpoint_uses_model_config_api_key_for_model_discovery(monkeypatch):
|
||||
"""Custom endpoint model discovery must use model.api_key from config.yaml,
|
||||
not only environment variables, otherwise the dropdown collapses to the
|
||||
@@ -342,6 +389,10 @@ def test_custom_endpoint_uses_model_config_api_key_for_model_discovery(monkeypat
|
||||
'base_url': 'https://example.test/v1',
|
||||
'api_key': 'sk-test-model-key',
|
||||
}
|
||||
try:
|
||||
_cfg._cfg_mtime = _cfg.Path(_cfg._get_config_path()).stat().st_mtime
|
||||
except Exception:
|
||||
pass
|
||||
_cfg.cfg.pop('providers', None)
|
||||
|
||||
captured = {}
|
||||
|
||||
Reference in New Issue
Block a user