hermes-agent/tests/hermes_cli/test_model_picker_excluded_providers.py
Teknium 6b81590c55
test: prune low-value tests suite-wide (wave 1) — 46,820 → 28,106 test functions
Systematic prune per AGENTS.md test policy, one pass over every major
test tree (gateway, hermes_cli, tools, agent, run_agent, plugins, cli,
cron, tui_gateway, honcho/openviking, root-level):

- DELETE: source-reading tests (read_text/getsource on prod files),
  change-detector tests (exact catalog counts, model-name snapshots,
  config version literals), mock-echo tests (assert a mock returns what
  it was told), assertion-free/trivial tests, near-duplicate
  parametrizations (boundaries + one representative kept), async/sync
  twin duplicates, cosmetic within-file variations.
- KEEP (mandatory): security/redaction/approval guards, message-role
  alternation invariants, prompt-caching/deterministic-call-id
  invariants, issue-number regression tests (deduped), E2E tests.
- 6 test files deleted outright (script-style/no-assert or fully
  redundant); conftest.py, fakes/, fixtures/ untouched.
- tests/acp/conftest.py added: autouse fixture stubs the live
  models.dev/GitHub/Copilot/Anthropic inventory fetches that ACP server
  tests performed on every session create — test_server.py 147s → 3.4s,
  and the tests are now genuinely hermetic.
- Sleep-based slowness shrunk where safe (codex_ttfb_watchdog,
  compression_concurrent_fork, etc.); no wall-clock assertion tightened.

Verification: full hermetic suite via scripts/run_tests.sh —
2439 files, 31,130 tests passed, 0 failed, 0 flaky retries, 315s wall
(baseline: 583s wall, 13,564s subprocess CPU).
2026-07-29 13:10:23 -07:00

119 lines
4.5 KiB
Python

"""Tests that ``model_catalog.excluded_providers`` hides providers from the
interactive ``hermes model`` CLI picker.
The CLI picker (``hermes_cli.main.select_provider_and_model``) builds its
provider menu from ``CANONICAL_PROVIDERS`` via ``group_providers`` — a
separate code path from ``list_authenticated_providers``. These tests
verify the exclusion config is honored there too, matching the
gateway/TUI picker behavior.
"""
from unittest.mock import patch
import pytest
@pytest.fixture
def config_home(tmp_path, monkeypatch):
"""Isolated HERMES_HOME with a minimal config."""
home = tmp_path / "hermes"
home.mkdir()
config_yaml = home / "config.yaml"
config_yaml.write_text("model: old-model\ncustom_providers: []\n")
env_file = home / ".env"
env_file.write_text("")
monkeypatch.setenv("HERMES_HOME", str(home))
monkeypatch.delenv("HERMES_MODEL", raising=False)
monkeypatch.delenv("LLM_MODEL", raising=False)
monkeypatch.delenv("HERMES_INFERENCE_PROVIDER", raising=False)
monkeypatch.delenv("OPENAI_BASE_URL", raising=False)
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
return home
def _write_config(home, **top_level):
import yaml
cfg = {"model": "old-model", "custom_providers": []}
cfg.update(top_level)
(home / "config.yaml").write_text(yaml.safe_dump(cfg))
def _capture_provider_labels(config_home):
"""Drive ``select_provider_and_model`` and return the provider-menu labels
shown to the user (the first ``_prompt_provider_choice`` call). Cancels
immediately after capturing."""
from hermes_cli.main import select_provider_and_model
captured: dict = {}
def _capture_and_cancel(labels, default=0, title=None):
# Only capture the top-level provider menu (the first call).
if "labels" not in captured:
captured["labels"] = list(labels)
return None # cancel
with patch("hermes_cli.main._prompt_provider_choice",
side_effect=_capture_and_cancel), \
patch("builtins.print"):
select_provider_and_model()
return captured.get("labels", [])
def test_cli_picker_hides_excluded_provider(config_home):
"""``excluded_providers: [openrouter]`` must remove the OpenRouter row
from the ``hermes model`` provider menu."""
_write_config(config_home, **{"model_catalog": {"excluded_providers": ["openrouter"]}})
labels = _capture_provider_labels(config_home)
assert labels, "provider menu was empty"
assert not any("OpenRouter" in lbl for lbl in labels), (
f"OpenRouter should be hidden by excluded_providers, got: {labels}"
)
def test_cli_picker_hides_excluded_provider_by_alias(config_home):
"""Exclusion by an alias (not the canonical slug) must also hide the
provider, matching ``list_authenticated_providers``' matching against
hermes_id / alias names."""
# 'openai' is an alias-style hermes id; ensure excluding it hides the
# canonical openai provider row if present. Use the canonical slug's
# alias from _PROVIDER_ALIASES to stay robust to renames.
from hermes_cli.models import _PROVIDER_ALIASES, CANONICAL_PROVIDERS
# Find a canonical provider that has at least one alias and is a leaf
# row (not folded into a multi-member group) so its label appears
# directly. Pick the first such provider.
target_slug = None
target_alias = None
for alias, canon in _PROVIDER_ALIASES.items():
if canon and any(p.slug == canon for p in CANONICAL_PROVIDERS):
target_slug = canon
target_alias = alias
break
if target_slug is None:
pytest.skip("no aliased canonical provider available to test")
from hermes_cli.models import _PROVIDER_LABELS
target_label_fragment = _PROVIDER_LABELS.get(target_slug, target_slug)
# Baseline: the provider appears without exclusion.
_write_config(config_home)
baseline = _capture_provider_labels(config_home)
assert any(target_label_fragment in lbl for lbl in baseline), (
f"sanity: {target_slug} ({target_label_fragment!r}) should appear by "
f"default; labels={baseline}"
)
# Excluding by alias hides it.
_write_config(
config_home,
**{"model_catalog": {"excluded_providers": [target_alias]}},
)
excluded_labels = _capture_provider_labels(config_home)
assert not any(target_label_fragment in lbl for lbl in excluded_labels), (
f"excluding alias {target_alias!r} should hide {target_slug}; "
f"labels={excluded_labels}"
)