hermes-agent/tests/hermes_cli/test_models_dev_preferred_merge.py
kshitijk4poor 66827f8947 chore: prune unused imports and duplicate import redefinitions
Remove unused imports (F401) and duplicate/shadowed import
redefinitions (F811) across the codebase using ruff's safe
autofixes. No behavioral changes -- imports only.

- ~1400 safe autofixes applied across 644 files (net -1072 lines)
- __init__.py re-exports preserved (excluded from F401 removal so
  public re-export surfaces stay intact)
- Re-exports that are imported or monkeypatched by tests but look
  unused in their defining module are kept with explicit # noqa:
  F401 (gateway/run.py load_dotenv; run_agent re-exports from
  agent.message_sanitization, agent.context_compressor,
  agent.retry_utils, agent.prompt_builder, agent.process_bootstrap,
  agent.codex_responses_adapter)
- Unsafe F841 (unused-variable) fixes deliberately skipped -- those
  can change behavior when the RHS has side effects
- ruff lints remain disabled in pyproject.toml (only PLW1514 is
  selected); this is a one-time cleanup, not a config change

Verification:
- python -m compileall: clean
- pytest --collect-only: all 27161 tests collect (zero import errors)
- core entry points import clean (run_agent, model_tools, cli,
  toolsets, hermes_state, batch_runner, gateway)
- static scan: every name any test imports directly from an edited
  module still resolves
2026-05-28 22:26:25 -07:00

122 lines
5.3 KiB
Python

"""Tests for the models.dev-preferred merge behavior in provider_model_ids
and list_authenticated_providers.
These guard the contract:
* For providers in ``_MODELS_DEV_PREFERRED`` (opencode-go, opencode-zen,
xiaomi, deepseek, smaller inference providers), both the CLI model
picker path (``provider_model_ids``) and the gateway ``/model`` picker
path (``list_authenticated_providers``) merge fresh models.dev entries
on top of the curated static list.
* OpenRouter and Nous Portal are NEVER merged — they keep their curated
(OpenRouter) or live-Portal (Nous) semantics.
* If models.dev is unreachable (offline / CI), the curated list is the
fallback — no crash, no empty list.
Merging is what lets new models (e.g. ``mimo-v2.5-pro`` on opencode-go)
appear in ``/model`` without a Hermes release.
"""
from unittest.mock import patch
from hermes_cli.models import (
_MODELS_DEV_PREFERRED,
_merge_with_models_dev,
provider_model_ids,
)
class TestMergeHelper:
def test_merge_empty_mdev_returns_curated(self):
"""When models.dev returns nothing, curated list is preserved verbatim."""
with patch("agent.models_dev.list_agentic_models", return_value=[]):
out = _merge_with_models_dev("opencode-go", ["mimo-v2-pro", "kimi-k2.6"])
assert out == ["mimo-v2-pro", "kimi-k2.6"]
def test_merge_mdev_raises_returns_curated(self):
"""Offline / broken models.dev must not break the catalog path."""
def boom(_provider):
raise RuntimeError("network down")
with patch("agent.models_dev.list_agentic_models", side_effect=boom):
out = _merge_with_models_dev("opencode-go", ["mimo-v2-pro"])
assert out == ["mimo-v2-pro"]
def test_merge_mdev_first_then_curated_extras(self):
"""models.dev entries come first; curated-only entries are appended."""
mdev = ["mimo-v2.5-pro", "mimo-v2-pro", "kimi-k2.6"]
curated = ["kimi-k2.6", "kimi-k2.5", "mimo-v2-pro"] # kimi-k2.5 is curated-only
with patch("agent.models_dev.list_agentic_models", return_value=mdev):
out = _merge_with_models_dev("opencode-go", curated)
# models.dev entries first (in order), then curated-only entries
assert out == ["mimo-v2.5-pro", "mimo-v2-pro", "kimi-k2.6", "kimi-k2.5"]
def test_merge_case_insensitive_dedup(self):
"""Dedup is case-insensitive but preserves the first occurrence's casing."""
mdev = ["MiniMax-M2.7"]
curated = ["minimax-m2.7", "minimax-m2.5"]
with patch("agent.models_dev.list_agentic_models", return_value=mdev):
out = _merge_with_models_dev("minimax", curated)
# models.dev casing wins since it came first
assert out == ["MiniMax-M2.7", "minimax-m2.5"]
class TestProviderModelIdsPreferred:
def test_opencode_go_is_preferred(self):
assert "opencode-go" in _MODELS_DEV_PREFERRED
def test_opencode_go_includes_fresh_models_dev_entries(self):
"""provider_model_ids('opencode-go') adds models.dev entries on top."""
mdev = ["mimo-v2.5-pro", "mimo-v2.5", "mimo-v2-pro", "kimi-k2.6"]
with patch("agent.models_dev.list_agentic_models", return_value=mdev):
out = provider_model_ids("opencode-go")
# Fresh models must surface (this is exactly the reported bug fix:
# mimo-v2.5-pro should be pickable on opencode-go).
assert "mimo-v2.5-pro" in out
assert "mimo-v2.5" in out
# Curated entries are still present.
assert "mimo-v2-pro" in out
assert "kimi-k2.6" in out
def test_opencode_go_offline_falls_back_to_curated(self):
"""Offline models.dev → curated-only list, no crash."""
with patch("agent.models_dev.list_agentic_models", return_value=[]):
out = provider_model_ids("opencode-go")
# Curated floor (see hermes_cli/models.py _PROVIDER_MODELS["opencode-go"])
assert "mimo-v2-pro" in out
assert "kimi-k2.6" in out
def test_opencode_zen_includes_fresh_models(self):
"""opencode-zen follows the same pattern as opencode-go."""
assert "opencode-zen" in _MODELS_DEV_PREFERRED
mdev = ["claude-opus-4-7", "kimi-k2.6", "glm-5.1"]
with patch("agent.models_dev.list_agentic_models", return_value=mdev):
out = provider_model_ids("opencode-zen")
assert "claude-opus-4-7" in out
assert "kimi-k2.6" in out
class TestOpenRouterAndNousUnchanged:
"""Per Teknium: openrouter and nous are NEVER merged with models.dev."""
def test_openrouter_not_in_preferred_set(self):
assert "openrouter" not in _MODELS_DEV_PREFERRED
def test_nous_not_in_preferred_set(self):
assert "nous" not in _MODELS_DEV_PREFERRED
def test_openrouter_does_not_call_merge(self):
"""openrouter takes its own live path — merge helper must NOT run."""
with patch(
"hermes_cli.models._merge_with_models_dev",
side_effect=AssertionError("merge should not be called for openrouter"),
):
# Even if model_ids() fails for some other reason, we just care
# that the merge path isn't invoked.
try:
provider_model_ids("openrouter")
except AssertionError:
raise
except Exception:
pass # model_ids() may fail in the hermetic test env — that's fine.