Fix CLI routing for user-defined providers (closes #16767)#16811
Closed
westers wants to merge 2 commits into
Closed
Fix CLI routing for user-defined providers (closes #16767)#16811westers wants to merge 2 commits into
westers wants to merge 2 commits into
Conversation
…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>
Contributor
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.
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()reboundDIRECT_ALIASESto a freshly-loaded dict, leaving everyfrom … import DIRECT_ALIASEScaller stuck on the stale empty original. Switched to.update()so module attribute references stay valid.hermes_cli/main.py— chat subcommand--providerhadchoices=[…]hardcoded to built-in providers, rejecting valid keys from userproviders:config. Dropped the choices list; runtime resolution validates correctly downstream.hermes_cli/oneshot.py—-m <alias>only resolved the model name; the alias'sbase_urlwas never propagated. Now consultsDIRECT_ALIASESbefore falling through todetect_provider_for_model, and threads the alias'sbase_urltoresolve_runtime_provider(explicit_base_url=…).hermes_cli/runtime_provider.py—_resolve_named_custom_runtimenow honors(provider="custom", explicit_base_url=…)so abase_urlpropagated 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— capturesid(DIRECT_ALIASES)before/after_ensure_direct_aliases()and asserts it's unchanged. Catches the rebinding regression specifically.test_chat_provider_argparse_acceptance— invokesmain()withchat --provider my-custom-keyand asserts noSystemExitplus the value propagates. Catches the choices-list regression.test_resolve_named_custom_runtime_honors_explicit_base_url— calls the function withprovider="custom"+ an explicit base_url and asserts the returned dict has the right base_url andsource == "direct-alias".Test plan
pytest -q tests/hermes_cli/test_regression_16767.pypasses on this branch (3/3 in ~1.4 s)main(test file kept) — produces the exact argparse error / staleness symptoms the bugs cause, confirming each test catches its target regressionhermes chat --provider <user-defined-key> -m <model> -q "…"andhermes -m <user-alias> -z "…"both reach the user-intended endpoint after the fix, observable via the target server's request logNotes
/modelcommand path is unaffected (it already worked correctly via a different code path).