Skip to content

fix(doctor): honor providers.py ALIASES for local-server provider names#15778

Closed
cirwel wants to merge 1 commit into
NousResearch:mainfrom
cirwel:fix/doctor-provider-alias-resolution
Closed

fix(doctor): honor providers.py ALIASES for local-server provider names#15778
cirwel wants to merge 1 commit into
NousResearch:mainfrom
cirwel:fix/doctor-provider-alias-resolution

Conversation

@cirwel

@cirwel cirwel commented Apr 25, 2026

Copy link
Copy Markdown

Summary

hermes doctor rejects model.provider: "ollama" (and "lmstudio", "vllm", "llamacpp") with "is unknown" even though hermes_cli/providers.py ALIASES maps these to virtual canonicals ("custom", "local") and the config template documents them as user-facing values:

# scripts/install/.../cli-config.yaml (excerpt)
#   "custom"       - Any OpenAI-compatible endpoint. Set base_url below.
#   Aliases: "lmstudio", "ollama", "vllm", "llamacpp" all map to "custom".
#   Example for LM Studio:
#     provider: "lmstudio"

So provider: "ollama" is the documented surface for "local Ollama via OpenAI-compatible endpoint" — but doctor surfaces it as a configuration error.

Repro

# ~/.hermes/config.yaml
model:
  provider: "ollama"
  base_url: "http://localhost:11434/v1"
  default: "qwen3.6:27b-coding-nvfp4"
$ hermes doctor
...
Found 2 issue(s) to address:

  1. model.provider 'ollama' is unknown. Valid providers: ai-gateway, alibaba, ...
     Fix: run 'hermes config set model.provider <valid_provider>'

(End user — me — hit this trying to point Hermes at a local Ollama for qwen3.6:27b-coding-nvfp4. The agent ran fine; only doctor complained.)

Root cause

Two separate gaps in hermes_cli/doctor.py:

  1. _resolve_provider_full("ollama") returns None. normalize_provider("ollama") returns "custom" per ALIASES, but get_provider("custom") is None because "custom" is a sentinel for "use whatever base_url is set" — not a real entry in models.dev / built-in registry. So provider_def is Nonecanonical_provider = None → the membership check fails.

  2. known_providers is missing virtual canonicals like "local" and "lmstudio". Built from PROVIDER_REGISTRY.keys() | {"openrouter", "custom", "auto"}, it excludes alias targets that aren't in the registry — so even if step 1 is fixed, vllmlocal and bare lmstudio would still fail.

Fix

Two-part, both in hermes_cli/doctor.py:

  1. When _resolve_provider_full returns None, fall back to normalize_provider so the ALIASES table's canonical value is honored.
  2. Extend known_providers |= set(ALIASES.values()) so virtual canonicals are accepted.

Net effect: ollamacustom ✓, lmstudiolmstudio ✓, vllmlocal ✓, llamacpplocal ✓. Real typos (ollam, gpt, etc.) still fail because normalize_provider is the identity for unknown keys, and unknown keys aren't in known_providers.

Test

New parametrized test test_run_doctor_accepts_local_provider_aliases covering all four aliases. Modeled on existing test_run_doctor_accepts_named_provider_from_providers_section (added in ccc8fccf).

Full tests/hermes_cli/test_doctor.py — 26 tests, 0 failures, 14 prior audioop deprecation warnings (unrelated).

Test plan

  • Run tests/hermes_cli/test_doctor.py — all pass (26 tests, 4 new)
  • Confirmed provider: "ollama" config now passes hermes doctor on local install
  • Maintainer: run full CI suite

Notes

  • No behavioral change for the agent path — provider: "ollama" already worked at runtime (ALIASES is consulted at every other call site). This only fixes the doctor's report.
  • No new public API. ALIASES is already exported as a module-level dict.
  • I'm a downstream user, not a regular contributor — happy to adjust the fix shape if a different layering is preferred (e.g., move the alias-known-providers union into providers.py as a new helper).

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard area/config Config system, migrations, profiles labels Apr 25, 2026
@stevenchanin

Copy link
Copy Markdown
Contributor

FYI — #16086 generalises along the same axis: it also unions ALIASES.values() into the acceptable set (mechanism #2 from your PR), and additionally accepts {raw input, normalize_provider(input), resolve_provider_full(input).id} so the same code path also catches the canonical-id mismatches in bedrock (#15358), opencode-zen, ai-gateway, copilot (#16076), kilocode, kimi-coding, and kimi-coding-cn. Cross-linking in case it's useful to the maintainer triaging this area; the structural angle here is yours, the broader scope just falls out for free once ALIASES.values() is in the mix.

Doctor's provider validation rejected `model.provider: "ollama"` (and
"lmstudio", "vllm", "llamacpp") with "is unknown" even though
`providers.py` ALIASES maps these to virtual canonicals ("custom",
"local") and the config docstring documents them as user-facing values
(`provider: "lmstudio"` is shown as the LM Studio example at lines
36-39 of `cli-config.yaml`).

Two-part fix:

1. `_resolve_provider_full(name)` returns None for virtual canonicals
   like "custom" / "local" because `get_provider("custom")` is None
   (custom is a sentinel, not a real provider definition). Fall back
   to `normalize_provider(name)` so the alias map's canonical value
   is honored.

2. Extend `known_providers` with `set(ALIASES.values())` so virtual
   canonicals like "local" and "lmstudio" — which aren't in
   PROVIDER_REGISTRY but are valid configuration values — pass the
   membership check.

Adds parametrized test covering ollama / lmstudio / vllm / llamacpp.
@cirwel cirwel force-pushed the fix/doctor-provider-alias-resolution branch from 1838658 to 27c9ffe Compare May 1, 2026 01:56
@cirwel

cirwel commented May 1, 2026

Copy link
Copy Markdown
Author

Thanks for the cross-link, @stevenchanin — agreed, the broader scope in #16086 makes sense if the maintainer wants to take it that direction. Happy for either approach to land first; the ALIASES.values() union is the load-bearing piece for the local-server provider names regardless of which PR carries it.

@cirwel

cirwel commented May 4, 2026

Copy link
Copy Markdown
Author

Closing in favor of #16086 to avoid duplicate maintainer triage. The local-provider alias behavior is covered there. Thanks for the cross-link.

@cirwel cirwel closed this May 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants