fix: wire up Ollama Cloud dynamic model discovery in /model TUI picker

provider_model_ids() and list_authenticated_providers() had no case for
"ollama-cloud", so the /model slash command showed 0 models despite
fetch_ollama_cloud_models() being fully implemented. The CLI subcommand
worked because it called fetch_ollama_cloud_models() directly.

- Add ollama-cloud case to provider_model_ids() in models.py
- Populate curated dict for ollama-cloud in list_authenticated_providers()
- Add tests for both code paths
This commit is contained in:
Jorge 2026-04-16 20:03:31 +09:30 committed by kshitij
parent 45fc0bd83a
commit 5b4773fc20
3 changed files with 67 additions and 0 deletions

View file

@ -807,6 +807,10 @@ def list_authenticated_providers(
# "nous" shares OpenRouter's curated list if not separately defined # "nous" shares OpenRouter's curated list if not separately defined
if "nous" not in curated: if "nous" not in curated:
curated["nous"] = curated["openrouter"] curated["nous"] = curated["openrouter"]
# Ollama Cloud uses dynamic discovery (no static curated list)
if "ollama-cloud" not in curated:
from hermes_cli.models import fetch_ollama_cloud_models
curated["ollama-cloud"] = fetch_ollama_cloud_models()
# --- 1. Check Hermes-mapped providers --- # --- 1. Check Hermes-mapped providers ---
for hermes_id, mdev_id in PROVIDER_TO_MODELS_DEV.items(): for hermes_id, mdev_id in PROVIDER_TO_MODELS_DEV.items():

View file

@ -1286,6 +1286,10 @@ def provider_model_ids(provider: Optional[str], *, force_refresh: bool = False)
live = _fetch_ai_gateway_models() live = _fetch_ai_gateway_models()
if live: if live:
return live return live
if normalized == "ollama-cloud":
live = fetch_ollama_cloud_models(force_refresh=force_refresh)
if live:
return live
if normalized == "custom": if normalized == "custom":
base_url = _get_custom_base_url() base_url = _get_custom_base_url()
if base_url: if base_url:

View file

@ -114,6 +114,65 @@ class TestOllamaCloudModelCatalog:
assert "ollama-cloud" in _PROVIDER_LABELS assert "ollama-cloud" in _PROVIDER_LABELS
assert _PROVIDER_LABELS["ollama-cloud"] == "Ollama Cloud" assert _PROVIDER_LABELS["ollama-cloud"] == "Ollama Cloud"
def test_provider_model_ids_returns_dynamic_models(self, tmp_path, monkeypatch):
"""provider_model_ids('ollama-cloud') should call fetch_ollama_cloud_models()."""
from hermes_cli.models import provider_model_ids
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
monkeypatch.setenv("OLLAMA_API_KEY", "test-key")
mock_mdev = {
"ollama-cloud": {
"models": {
"qwen3.5:397b": {"tool_call": True},
"glm-5": {"tool_call": True},
}
}
}
with patch("hermes_cli.models.fetch_api_models", return_value=["qwen3.5:397b"]), \
patch("agent.models_dev.fetch_models_dev", return_value=mock_mdev):
result = provider_model_ids("ollama-cloud", force_refresh=True)
assert len(result) > 0
assert "qwen3.5:397b" in result
# ── Model Picker (list_authenticated_providers) ──
class TestOllamaCloudModelPicker:
def test_ollama_cloud_shows_model_count(self, tmp_path, monkeypatch):
"""Ollama Cloud should show non-zero model count in provider picker."""
from hermes_cli.model_switch import list_authenticated_providers
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
monkeypatch.setenv("OLLAMA_API_KEY", "test-key")
mock_mdev = {
"ollama-cloud": {
"models": {
"qwen3.5:397b": {"tool_call": True},
"glm-5": {"tool_call": True},
}
}
}
with patch("hermes_cli.models.fetch_api_models", return_value=["qwen3.5:397b"]), \
patch("agent.models_dev.fetch_models_dev", return_value=mock_mdev):
providers = list_authenticated_providers(current_provider="ollama-cloud")
ollama = next((p for p in providers if p["slug"] == "ollama-cloud"), None)
assert ollama is not None, "ollama-cloud should appear when OLLAMA_API_KEY is set"
assert ollama["total_models"] > 0, "ollama-cloud should show non-zero model count"
def test_ollama_cloud_not_shown_without_creds(self, monkeypatch):
"""Ollama Cloud should not appear without credentials."""
from hermes_cli.model_switch import list_authenticated_providers
monkeypatch.delenv("OLLAMA_API_KEY", raising=False)
providers = list_authenticated_providers(current_provider="openrouter")
ollama = next((p for p in providers if p["slug"] == "ollama-cloud"), None)
assert ollama is None, "ollama-cloud should not appear without OLLAMA_API_KEY"
# ── Merged Model Discovery ── # ── Merged Model Discovery ──