Skip to content

Fix CLI routing for user-defined providers (closes #16767)#16811

Closed
westers wants to merge 2 commits into
NousResearch:mainfrom
westers:local-cli-routing-fixes
Closed

Fix CLI routing for user-defined providers (closes #16767)#16811
westers wants to merge 2 commits into
NousResearch:mainfrom
westers:local-cli-routing-fixes

Conversation

@westers

@westers westers commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Closes #16767.

User-defined providers configured in ~/.hermes/config.yaml (providers: dict + model_aliases:) were silently dropped by two CLI paths, so requests routed to the wrong endpoint. This PR fixes both paths and adds regression tests.

Commits

  • fix(cli): honor user-defined providers via chat --provider and -m <alias> (4 files, +65/−39):

    • hermes_cli/model_switch.py — root cause: _ensure_direct_aliases() rebound DIRECT_ALIASES to a freshly-loaded dict, leaving every from … import DIRECT_ALIASES caller stuck on the stale empty original. Switched to .update() so module attribute references stay valid.
    • hermes_cli/main.py — chat subcommand --provider had choices=[…] hardcoded to built-in providers, rejecting valid keys from user providers: config. Dropped the choices list; runtime resolution validates correctly downstream.
    • hermes_cli/oneshot.py-m <alias> only resolved the model name; the alias's base_url was never propagated. Now consults DIRECT_ALIASES before falling through to detect_provider_for_model, and threads the alias's base_url to resolve_runtime_provider(explicit_base_url=…).
    • hermes_cli/runtime_provider.py_resolve_named_custom_runtime now honors (provider="custom", explicit_base_url=…) so a base_url propagated from a direct-alias resolution actually builds a runtime instead of falling through to provider-registry handlers that don't know about ad-hoc local endpoints.
  • test(cli): regression coverage for user-provider routing fix (#16767) (1 file, +58):

    • test_ensure_direct_aliases_mutates_in_place — captures id(DIRECT_ALIASES) before/after _ensure_direct_aliases() and asserts it's unchanged. Catches the rebinding regression specifically.
    • test_chat_provider_argparse_acceptance — invokes main() with chat --provider my-custom-key and asserts no SystemExit plus the value propagates. Catches the choices-list regression.
    • test_resolve_named_custom_runtime_honors_explicit_base_url — calls the function with provider="custom" + an explicit base_url and asserts the returned dict has the right base_url and source == "direct-alias".

Test plan

  • pytest -q tests/hermes_cli/test_regression_16767.py passes on this branch (3/3 in ~1.4 s)
  • Same tests fail when only the four source files are reverted to main (test file kept) — produces the exact argparse error / staleness symptoms the bugs cause, confirming each test catches its target regression
  • Verified end-to-end live: hermes chat --provider <user-defined-key> -m <model> -q "…" and hermes -m <user-alias> -z "…" both reach the user-intended endpoint after the fix, observable via the target server's request log

Notes

westers and others added 2 commits April 27, 2026 21:15
…ias>

Three related issues prevented user-defined providers in `providers:` and
`model_aliases:` from being reachable through standard CLI flags. Requests
silently routed to the configured `model.base_url` instead of the user-
intended endpoint.

* hermes_cli/model_switch.py — root cause of the silent misrouting:
  `_ensure_direct_aliases()` rebound `DIRECT_ALIASES` to a freshly-loaded
  dict, leaving every `from hermes_cli.model_switch import DIRECT_ALIASES`
  caller stuck on the stale empty original. Switched to `.update()` so
  module attribute references stay valid.

* hermes_cli/main.py — chat subcommand `--provider` had `choices=[...]`
  hardcoded to built-in providers, rejecting valid keys from user
  `providers:` config. Dropped the choices list; runtime resolution
  validates correctly downstream.

* hermes_cli/oneshot.py — `-m <alias>` only resolved the model name; the
  alias's base_url was never propagated. Now consults `DIRECT_ALIASES`
  before falling through to `detect_provider_for_model`, and threads the
  alias's base_url to `resolve_runtime_provider(explicit_base_url=...)`.

* hermes_cli/runtime_provider.py — `_resolve_named_custom_runtime` now
  honors `(provider="custom", explicit_base_url=...)` so a base_url
  propagated from a direct-alias resolution actually builds a runtime
  instead of falling through to provider-registry handlers that don't
  know about ad-hoc local endpoints.

Verified: `hermes chat --provider <user-key> -m <model> -q "..."` and
`hermes -m <user-alias> -z "..."` both route to the user-intended
endpoint, observable via the target server's request log.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@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 28, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Merged via #16924 — your commits cherry-picked onto current main with your authorship preserved via rebase-merge (63 commits of drift between your branch and main made direct merge messy). Thanks for the clean root-cause writeup and regression tests; they landed as-is.

#16924

@teknium1 teknium1 closed this Apr 28, 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.

CLI doesn't honor user-defined providers via chat --provider or -m <alias>

3 participants