fix(/model): surface Nous Portal models from remote catalog manifest (#23912)

The /model picker for Nous Portal users was returning the in-repo
_PROVIDER_MODELS["nous"] snapshot — which only updates on Hermes
releases — instead of the remote manifest published at
https://hermes-agent.nousresearch.com/docs/api/model-catalog.json.

OpenRouter already pulled from the manifest via fetch_openrouter_models;
"nous" was the only curated provider where the existing manifest
plumbing (get_curated_nous_model_ids → get_curated_nous_models) was
defined but not wired into the picker pipeline. Switch the curated
build in list_authenticated_providers to use it, with the same
graceful fallback to the in-repo snapshot when the manifest is
unreachable.

Test: tests/hermes_cli/test_model_catalog.py exercises the picker with
a patched manifest and asserts the manifest's nous list reaches
list_picker_providers. Falls-back-to-static path was already covered
by test_curated_nous_ids_falls_back_to_hardcoded_on_empty_catalog.
This commit is contained in:
Teknium 2026-05-11 10:15:30 -07:00 committed by GitHub
parent cc9e788c14
commit 8e2eb4b511
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 53 additions and 3 deletions

View file

@ -1079,6 +1079,7 @@ def list_authenticated_providers(
from hermes_cli.models import (
OPENROUTER_MODELS, _PROVIDER_MODELS,
_MODELS_DEV_PREFERRED, _merge_with_models_dev, provider_model_ids,
get_curated_nous_model_ids,
)
results: List[dict] = []
@ -1160,9 +1161,12 @@ def list_authenticated_providers(
# Build curated model lists keyed by hermes provider ID
curated: dict[str, list[str]] = dict(_PROVIDER_MODELS)
curated["openrouter"] = [mid for mid, _ in OPENROUTER_MODELS]
# "nous" shares OpenRouter's curated list if not separately defined
if "nous" not in curated:
curated["nous"] = curated["openrouter"]
# "nous" pulls from the remote model-catalog manifest published at
# https://hermes-agent.nousresearch.com/docs/api/model-catalog.json so
# newly added Portal models surface in the /model picker without
# requiring a Hermes release. Falls back to the in-repo
# _PROVIDER_MODELS["nous"] snapshot when the manifest is unreachable.
curated["nous"] = get_curated_nous_model_ids()
# Ollama Cloud uses dynamic discovery (no static curated list)
if "ollama-cloud" not in curated:
from hermes_cli.models import fetch_ollama_cloud_models