fix(runtime): keep the bare-custom fail-fast off local aliases
Key the post-ladder AuthError on the literal `custom` request again, in addition to the dead runtime shape (provider=custom, empty api_key). The previous commit widened it to every alias that resolves to custom (ollama, vllm), which broke `/model <direct-alias>` switching: _creds_for_switched_provider resolves the alias provider tolerantly and _apply_direct_alias_endpoint supplies the alias endpoint AFTER that call, so the early raise turned a working switch into "ollama is not connected" (tests/hermes_cli/test_models.py::TestLocalOllamaModelDiscovery, red in CI). The issue's own scope (#111741) is the bare non-routable placeholder; a credential-less local alias is a legitimate intermediate state there.
This commit is contained in:
@@ -866,14 +866,16 @@ def resolve_runtime_provider(*, requested: Optional[str] = None, explicit_api_ke
|
||||
|
||||
|
||||
def _raise_for_credentialless_bare_custom(requested_provider: str, runtime: Dict[str, Any]) -> None:
|
||||
"""Reject a bare ``custom`` placeholder (or an alias resolving to it: ollama, vllm, …) that fell
|
||||
through the whole ladder to the OpenRouter default endpoint with no credential. Every other
|
||||
custom rung (named entry, direct alias, local bypass, pool, ``key_cmd``) yields a key, a callable
|
||||
or the ``no-key-required`` placeholder, so an EMPTY key on a ``custom`` runtime is exactly the
|
||||
dead shape that otherwise dies at agent construction as ``No LLM provider configured``. Typed
|
||||
"""Reject a bare ``custom`` placeholder request that fell through the whole ladder to the
|
||||
OpenRouter default endpoint with no credential. Every other custom rung (named entry, local
|
||||
bypass, pool, ``key_cmd``) yields a key, a callable or the ``no-key-required`` placeholder, so
|
||||
an EMPTY key on a ``custom`` runtime is exactly the dead shape that otherwise dies at agent
|
||||
construction as ``No LLM provider configured``. Keyed on the literal request, not the resolved
|
||||
shape: local aliases (``ollama``, ``vllm``) are resolved tolerantly by ``/model`` direct-alias
|
||||
switching, which supplies the alias endpoint AFTER this call and must not fail here. Typed
|
||||
``AuthError`` so every caller's fallback chain (CLI, gateway, TUI, cron) still advances (#17929).
|
||||
"""
|
||||
if runtime.get("provider") != "custom" or runtime.get("api_key"):
|
||||
if requested_provider != "custom" or runtime.get("provider") != "custom" or runtime.get("api_key"):
|
||||
return
|
||||
raise AuthError(
|
||||
f"provider '{requested_provider}' resolved without credentials (no endpoint or API key configured). "
|
||||
|
||||
@@ -759,10 +759,11 @@ def test_bare_custom_resolves_providers_dict_entry_named_custom(monkeypatch):
|
||||
|
||||
|
||||
def test_bare_custom_without_credentials_for_remote_endpoint_fails_fast(monkeypatch):
|
||||
"""#111741: a bare ``custom`` placeholder (or an alias resolving to it) that falls through to the
|
||||
OpenRouter default with no key must raise a typed AuthError naming the request at resolve time,
|
||||
instead of returning a dead runtime that dies later as "No LLM provider configured". With an
|
||||
OpenRouter key present the same request keeps resolving exactly as before."""
|
||||
"""#111741: a bare ``custom`` placeholder that falls through to the OpenRouter default with no
|
||||
key must raise a typed AuthError naming the request at resolve time, instead of returning a
|
||||
dead runtime that dies later as "No LLM provider configured". A local alias (``ollama``) in the
|
||||
same state keeps resolving tolerantly: ``/model`` direct-alias switching supplies its endpoint
|
||||
after this call. With an OpenRouter key present the bare request resolves exactly as before."""
|
||||
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
|
||||
monkeypatch.delenv("OPENROUTER_API_KEY", raising=False)
|
||||
monkeypatch.delenv("CUSTOM_BASE_URL", raising=False)
|
||||
@@ -786,8 +787,8 @@ def test_bare_custom_without_credentials_for_remote_endpoint_fails_fast(monkeypa
|
||||
assert error.value.provider == "custom"
|
||||
assert error.value.code == "missing_api_key"
|
||||
|
||||
with pytest.raises(rp.AuthError, match="provider 'ollama'"):
|
||||
rp.resolve_runtime_provider(requested="ollama")
|
||||
alias = rp.resolve_runtime_provider(requested="ollama")
|
||||
assert alias["provider"] == "custom" and not alias["api_key"]
|
||||
|
||||
monkeypatch.setenv("OPENROUTER_API_KEY", "sk-or-v1-usable-key")
|
||||
resolved = rp.resolve_runtime_provider(requested="custom")
|
||||
|
||||
Reference in New Issue
Block a user