fix(fallback): let custom_providers shadow built-in aliases
When a user defines `custom_providers: [{name: kimi, ...}]` and references
`provider: kimi` from fallback_model or the main config, the built-in alias
rewriting (`kimi` → `kimi-coding`) was hijacking the request before the
named-custom lookup ran. `_get_named_custom_provider` also refused to
return a match when the raw name resolved to any built-in (including aliases),
so the custom endpoint was unreachable.
Fix at both layers of the resolution chain so every caller benefits, not
just `_try_activate_fallback`:
- hermes_cli/runtime_provider.py: narrow `_get_named_custom_provider`'s
built-in-wins guard to canonical provider names only. An alias like
`kimi` that resolves to a different canonical (`kimi-coding`) no longer
blocks the custom lookup; a canonical name like `nous` still does.
- agent/auxiliary_client.py: in `resolve_provider_client`, try the named-
custom lookup with the original (pre-alias-normalization) name before the
alias-normalized one, so aliased requests reach the user's custom entry.
Also honour `explicit_base_url` and `explicit_api_key` in the API-key
provider branch so callers that pass explicit hints (e.g. fallback
activation) can override the registered defaults.
Tests added for:
- custom `kimi` shadowing built-in alias (regression for #15743)
- custom `nous` NOT shadowing canonical built-in (behaviour preserved)
- bare `kimi` without any custom entry still routing to built-in
- explicit base_url/api_key override on the API-key provider branch
Original PR #17827 by @Feranmi10 identified the same bug class and
implemented a narrower fix in `_try_activate_fallback`; this reshapes the
fix to live in the shared resolution layer so all callers benefit.
Fixes #15743
Co-authored-by: Feranmi10 <89228157+Feranmi10@users.noreply.github.com>
This commit is contained in:
@@ -358,11 +358,20 @@ def _get_named_custom_provider(requested_provider: str) -> Optional[Dict[str, An
|
||||
return None
|
||||
if not requested_norm.startswith("custom:"):
|
||||
try:
|
||||
auth_mod.resolve_provider(requested_norm)
|
||||
canonical = auth_mod.resolve_provider(requested_norm)
|
||||
except AuthError:
|
||||
pass
|
||||
else:
|
||||
return None
|
||||
# A user-declared ``custom_providers`` entry whose name matches
|
||||
# only an *alias* (``kimi`` → built-in ``kimi-coding``) is the
|
||||
# user's intended target — alias rewriting would otherwise hijack
|
||||
# the request. We only defer to the built-in when the raw name is
|
||||
# the canonical provider itself (``nous``, ``openrouter``, …) so
|
||||
# accidentally shadowing a canonical provider still resolves to
|
||||
# the built-in. See tests/hermes_cli/test_runtime_provider_resolution.py
|
||||
# ``test_named_custom_provider_does_not_shadow_builtin_provider``.
|
||||
if (canonical or "").strip().lower() == requested_norm:
|
||||
return None
|
||||
|
||||
config = load_config()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user