feat(nous): drive model picker from Portal recommended-models endpoint - #14936
Closed
benbarclay wants to merge 1 commit into
Closed
feat(nous): drive model picker from Portal recommended-models endpoint#14936benbarclay wants to merge 1 commit into
benbarclay wants to merge 1 commit into
Conversation
…els endpoint
Replace the hardcoded _PROVIDER_MODELS["nous"] catalog (~29 entries that
had to be updated manually on every Portal model release) with a live
fetch from /api/nous/recommended-models, keyed off the user's free/paid
tier. The Portal is now the single source of truth — adding or removing
a Nous model no longer requires a Hermes release.
## What changes
hermes_cli/models.py
- Remove the hardcoded "nous": [...] list from _PROVIDER_MODELS.
- Add get_nous_recommended_catalog(): reuses the existing 10-minute
TTL cache in fetch_nous_recommended_models() (no extra HTTP per
call; shares the cache with the aux/vision model helper). Selects
freeRecommendedModels vs paidRecommendedModels based on
check_nous_free_tier(), preserves server-specified ordering
(the endpoint already orders each array by "position"), and does
case-insensitive dedup.
- Add _nous_catalog(): exception-safe wrapper returning [] on any
failure, so callers treat Portal unavailability as "no catalog"
rather than a crash.
- Rewire provider_model_ids("nous"): Portal recommended-models is
now primary; the inference /models endpoint stays as a secondary
live fallback for offline/misconfigured-portal resilience.
- get_default_model_for_provider("nous") and detect_provider_for_model()
now route through _nous_catalog() instead of the removed dict key.
hermes_cli/auth.py
- _login_nous() swapped _PROVIDER_MODELS.get("nous", []) → _nous_catalog().
hermes_cli/main.py
- /model command nous branch: same swap.
## Design notes
- Free-tier detection happens inside the helper, so single call sites
don't have to plumb the tier bool around.
- On tier-detection exception, defaults to paid — matches the existing
convention (never block paying users).
- The _AGGREGATORS gate in detect_provider_for_model()'s cross-provider
match loop already skipped "nous" when it was in _PROVIDER_MODELS,
so removing the key changes nothing in that loop.
- partition_nous_models_by_tier() is kept in the call sites; it becomes
mostly a no-op on the server-tier-filtered list but preserves the
"upgrade at {portal}" messaging for free-tier users with no free
models available.
## Tests
tests/hermes_cli/test_nous_recommended_models.py (new, 22 tests):
- Server-order preservation
- Free vs paid routing, auto-detection + exception-defaults-to-paid
- Empty / missing-field / malformed entries → []
- Case-insensitive dedup preserving first-seen casing
- provider_model_ids("nous") rewiring: Portal-first, inference fallback,
force_refresh propagation, exception-falls-through
- _PROVIDER_MODELS["nous"] is absent
- get_default_model_for_provider("nous") Portal-driven,
non-nous providers unaffected
- detect_provider_for_model() bare-name + current-provider paths
- _nous_catalog() swallows exceptions → []
- curated_models_for_provider("nous") routes through Portal
tests/hermes_cli/test_auth_nous_provider.py:
- Add get_nous_recommended_catalog stub to _patch_login_internals so
the login flow has models to present without a live network call.
## Verification
scripts/run_tests.sh tests/hermes_cli/ tests/test_empty_model_fallback.py
tests/acp/test_server.py tests/test_tui_gateway_server.py
tests/agent/test_bedrock_integration.py
→ 2752 passed. The 4 remaining failures + 1 collection race are
pre-existing on main (unrelated — skills filtering, tip length,
Linux stdlib ssl quirk, xdist race), confirmed via git-stash diff.
19 tasks
Contributor
|
Closing as superseded by #24082. Triage notes (high confidence): Thanks for the contribution — the underlying problem this PR addresses has been resolved by the linked PR on current main. If you believe this was closed in error, please comment and we'll reopen. (Bulk-closed during a CLI PR triage sweep.) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replace the hardcoded _PROVIDER_MODELS["nous"] catalog (~29 entries that had to be updated manually on every Portal model release) with a live fetch from /api/nous/recommended-models, keyed off the user's free/paid tier. The Portal is now the single source of truth — adding or removing a Nous model no longer requires a Hermes release.
What changes
hermes_cli/models.py
hermes_cli/auth.py
hermes_cli/main.py
Design notes
Tests
tests/hermes_cli/test_nous_recommended_models.py (new, 22 tests):
tests/hermes_cli/test_auth_nous_provider.py:
Verification
scripts/run_tests.sh tests/hermes_cli/ tests/test_empty_model_fallback.py
tests/acp/test_server.py tests/test_tui_gateway_server.py
tests/agent/test_bedrock_integration.py
→ 2752 passed. The 4 remaining failures + 1 collection race are
pre-existing on main (unrelated — skills filtering, tip length,
Linux stdlib ssl quirk, xdist race), confirmed via git-stash diff.