mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-04 07:31:58 +00:00
fix(runtime): treat 'ollama'/'vllm'/'llamacpp' aliases like 'custom' for base_url trust (#27132)
When config.yaml has provider: ollama (or vllm/llamacpp/llama-cpp) with a
non-loopback base_url, auth.py's resolve_provider() correctly normalises
the alias to 'custom' at the top level, but two sites in runtime_provider.py
were still comparing the *original* string against the literal 'custom':
- _config_base_url_trustworthy_for_bare_custom() rejected non-loopback
URLs because cfg_provider_norm was 'ollama', not 'custom'.
- _resolve_openrouter_runtime() only entered the trust branch when
requested_norm == 'custom'.
Both sites now consult resolve_provider() and treat any alias that
resolves to 'custom' identically. Result: provider: ollama + LAN IP no
longer silently falls through to OpenRouter (HTTP 401), matching the
behaviour of provider: custom with the same base_url.
E2E verified across 6 cases (ollama/vllm/llamacpp/custom + LAN; ollama +
loopback; openrouter + cloud) — all route to the configured endpoint;
'frobnicate' + LAN still rejects with AuthError as before.
Also adds scripts/release.py AUTHOR_MAP entry for @stepanov1975
(PR #22074 — wizard config picker preservation, cherry-picked into the
preceding commit).
This commit is contained in:
parent
e13f242f01
commit
6a159be7ca
3 changed files with 111 additions and 1 deletions
|
|
@ -2321,3 +2321,74 @@ def test_minimax_oauth_pool_forces_anthropic_messages_despite_stale_config(monke
|
|||
assert resolved["provider"] == "minimax-oauth"
|
||||
assert resolved["api_mode"] == "anthropic_messages"
|
||||
assert resolved["base_url"] == "https://api.minimax.io/anthropic"
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# GitHub #27132 — provider aliases (ollama/vllm/llamacpp/llama-cpp) must
|
||||
# follow the same base_url trust + routing rules as bare `provider: custom`.
|
||||
# Without this, a YAML `provider: ollama` with a LAN/WireGuard `base_url`
|
||||
# silently falls through to OpenRouter (HTTP 401).
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"alias,base_url",
|
||||
[
|
||||
("ollama", "http://192.168.0.103:11434/v1"),
|
||||
("vllm", "http://192.168.0.103:8000/v1"),
|
||||
("llamacpp", "http://192.168.0.103:8080/v1"),
|
||||
("llama-cpp", "http://192.168.0.103:8080/v1"),
|
||||
],
|
||||
)
|
||||
def test_custom_aliases_with_lan_base_url_route_to_custom_not_openrouter(
|
||||
monkeypatch, alias, base_url
|
||||
):
|
||||
"""provider: ollama|vllm|llamacpp + LAN IP must NOT fall through to OpenRouter."""
|
||||
monkeypatch.setattr(
|
||||
rp,
|
||||
"_get_model_config",
|
||||
lambda: {"provider": alias, "base_url": base_url},
|
||||
)
|
||||
# Pretend OPENROUTER_API_KEY is set so the openrouter fallback would
|
||||
# otherwise succeed — we want to prove the alias short-circuits before
|
||||
# reaching it.
|
||||
monkeypatch.setenv("OPENROUTER_API_KEY", "sk-or-fake-test")
|
||||
# No custom credential pool — exercise the bare-alias path.
|
||||
monkeypatch.setattr(rp, "load_pool", lambda provider: None)
|
||||
|
||||
resolved = rp.resolve_runtime_provider()
|
||||
|
||||
assert resolved["provider"] == "custom", (
|
||||
f"alias {alias!r} with LAN base_url should resolve to provider=custom, "
|
||||
f"got {resolved['provider']!r}"
|
||||
)
|
||||
assert resolved["base_url"] == base_url.rstrip("/"), (
|
||||
f"base_url should be the configured LAN endpoint, got {resolved['base_url']!r}"
|
||||
)
|
||||
|
||||
|
||||
def test_custom_alias_with_loopback_base_url_routes_to_custom(monkeypatch):
|
||||
"""provider: ollama + loopback should also route to custom (regression guard)."""
|
||||
monkeypatch.setattr(
|
||||
rp,
|
||||
"_get_model_config",
|
||||
lambda: {"provider": "ollama", "base_url": "http://localhost:11434/v1"},
|
||||
)
|
||||
monkeypatch.setenv("OPENROUTER_API_KEY", "sk-or-fake-test")
|
||||
monkeypatch.setattr(rp, "load_pool", lambda provider: None)
|
||||
|
||||
resolved = rp.resolve_runtime_provider()
|
||||
|
||||
assert resolved["provider"] == "custom"
|
||||
assert resolved["base_url"] == "http://localhost:11434/v1"
|
||||
|
||||
|
||||
def test_trustworthy_check_accepts_custom_aliases():
|
||||
"""_config_base_url_trustworthy_for_bare_custom() must accept aliases for custom."""
|
||||
fn = rp._config_base_url_trustworthy_for_bare_custom
|
||||
for alias in ("ollama", "vllm", "llamacpp", "llama-cpp", "llama.cpp"):
|
||||
assert fn("http://192.168.0.103:11434/v1", alias) is True, (
|
||||
f"alias {alias!r} should be trusted with non-loopback base_url"
|
||||
)
|
||||
# Unrelated provider name should still be rejected with non-loopback URL.
|
||||
assert fn("http://192.168.0.103:11434/v1", "openrouter") is False
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue