mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-12 13:52:15 +00:00
fix(agent): honor auxiliary.<task>.base_url/api_key when provider is passed explicitly
_resolve_task_provider_model returns early on an explicit provider arg, which skips the config block that consults auxiliary.<task>.base_url / api_key. Any caller passing provider explicitly (e.g. resolve_vision_provider_client(provider="custom", ...)) bypasses the configured custom endpoint and falls through to main-runtime resolution, silently routing the task to the wrong backend. Adopt the task's configured base_url/api_key before the early returns, but only when no explicit base_url was given and the config targets the same provider (or names none) — a caller forcing a *different* provider keeps full explicit-arg priority, and an explicit base_url still wins over config. Fixes #58515
This commit is contained in:
parent
e985e34659
commit
9ad912a791
2 changed files with 118 additions and 0 deletions
|
|
@ -5532,6 +5532,18 @@ def _resolve_task_provider_model(
|
|||
if cfg_provider:
|
||||
cfg_provider, cfg_base_url = _expand_direct_api_alias(cfg_provider, cfg_base_url)
|
||||
|
||||
# An explicit provider arg without an explicit base_url must not bypass
|
||||
# the task's configured endpoint: adopt auxiliary.<task>.base_url/api_key
|
||||
# when the config targets the same provider (or names none), so the
|
||||
# early `if provider:` return below carries the configured endpoint
|
||||
# instead of falling through to main-runtime resolution (#58515).
|
||||
# An explicit "auto" is excluded — it means "inherit / auto-detect" and
|
||||
# must keep flowing through the existing auto-resolution chain.
|
||||
if provider and provider != "auto" and not base_url and cfg_base_url and cfg_provider in (None, provider):
|
||||
base_url = cfg_base_url
|
||||
if not api_key:
|
||||
api_key = cfg_api_key
|
||||
|
||||
if base_url and _preserve_provider_with_base_url(provider):
|
||||
return provider, resolved_model, base_url, api_key, resolved_api_mode
|
||||
if base_url:
|
||||
|
|
|
|||
|
|
@ -168,6 +168,112 @@ class TestResolveTaskProviderModel:
|
|||
assert api_key == "sk-test"
|
||||
assert api_mode is None
|
||||
|
||||
def test_explicit_provider_adopts_configured_task_endpoint(self):
|
||||
"""Explicit provider matching the configured one must not bypass
|
||||
auxiliary.<task>.base_url/api_key (#58515)."""
|
||||
task_config = {
|
||||
"provider": "custom",
|
||||
"model": "meta/llama-3.2-11b-vision-instruct",
|
||||
"base_url": "https://integrate.api.nvidia.com/v1",
|
||||
"api_key": "nvapi-secret",
|
||||
}
|
||||
with patch("agent.auxiliary_client._get_auxiliary_task_config", return_value=task_config):
|
||||
resolved_provider, model, base_url, api_key, api_mode = _resolve_task_provider_model(
|
||||
task="vision",
|
||||
provider="custom",
|
||||
model="meta/llama-3.2-11b-vision-instruct",
|
||||
)
|
||||
|
||||
assert resolved_provider == "custom"
|
||||
assert base_url == "https://integrate.api.nvidia.com/v1"
|
||||
assert api_key == "nvapi-secret"
|
||||
assert model == "meta/llama-3.2-11b-vision-instruct"
|
||||
assert api_mode is None
|
||||
|
||||
def test_explicit_provider_adopts_endpoint_when_config_names_no_provider(self):
|
||||
task_config = {
|
||||
"base_url": "https://nim.example/v1",
|
||||
"api_key": "cfg-key",
|
||||
}
|
||||
with patch("agent.auxiliary_client._get_auxiliary_task_config", return_value=task_config):
|
||||
resolved_provider, model, base_url, api_key, api_mode = _resolve_task_provider_model(
|
||||
task="vision",
|
||||
provider="custom",
|
||||
)
|
||||
|
||||
assert resolved_provider == "custom"
|
||||
assert base_url == "https://nim.example/v1"
|
||||
assert api_key == "cfg-key"
|
||||
|
||||
def test_explicit_first_class_provider_with_matching_config_keeps_identity(self):
|
||||
task_config = {
|
||||
"provider": "anthropic",
|
||||
"base_url": "https://anthropic-proxy.example/v1",
|
||||
"api_key": "cfg-key",
|
||||
}
|
||||
with patch("agent.auxiliary_client._get_auxiliary_task_config", return_value=task_config):
|
||||
resolved_provider, model, base_url, api_key, api_mode = _resolve_task_provider_model(
|
||||
task="compression",
|
||||
provider="anthropic",
|
||||
)
|
||||
|
||||
assert resolved_provider == "anthropic"
|
||||
assert base_url == "https://anthropic-proxy.example/v1"
|
||||
assert api_key == "cfg-key"
|
||||
|
||||
def test_explicit_auto_provider_keeps_auto_resolution(self):
|
||||
"""provider="auto" is a sentinel for "inherit / auto-detect" and must
|
||||
not adopt the configured endpoint — the auto chain owns resolution."""
|
||||
task_config = {
|
||||
"base_url": "https://nim.example/v1",
|
||||
"api_key": "cfg-key",
|
||||
}
|
||||
with patch("agent.auxiliary_client._get_auxiliary_task_config", return_value=task_config):
|
||||
resolved_provider, model, base_url, api_key, api_mode = _resolve_task_provider_model(
|
||||
task="vision",
|
||||
provider="auto",
|
||||
)
|
||||
|
||||
assert resolved_provider == "auto"
|
||||
assert base_url is None
|
||||
assert api_key is None
|
||||
|
||||
def test_explicit_provider_differing_from_config_ignores_config_endpoint(self):
|
||||
"""A caller forcing a different provider keeps full explicit-arg
|
||||
priority — the configured endpoint belongs to cfg_provider only."""
|
||||
task_config = {
|
||||
"provider": "custom",
|
||||
"base_url": "https://nim.example/v1",
|
||||
"api_key": "cfg-key",
|
||||
}
|
||||
with patch("agent.auxiliary_client._get_auxiliary_task_config", return_value=task_config):
|
||||
resolved_provider, model, base_url, api_key, api_mode = _resolve_task_provider_model(
|
||||
task="vision",
|
||||
provider="nous",
|
||||
)
|
||||
|
||||
assert resolved_provider == "nous"
|
||||
assert base_url is None
|
||||
assert api_key is None
|
||||
|
||||
def test_explicit_provider_and_base_url_still_win_over_config(self):
|
||||
task_config = {
|
||||
"provider": "custom",
|
||||
"base_url": "https://configured.example/v1",
|
||||
"api_key": "cfg-key",
|
||||
}
|
||||
with patch("agent.auxiliary_client._get_auxiliary_task_config", return_value=task_config):
|
||||
resolved_provider, model, base_url, api_key, api_mode = _resolve_task_provider_model(
|
||||
task="vision",
|
||||
provider="custom",
|
||||
base_url="https://explicit.example/v1",
|
||||
api_key="explicit-key",
|
||||
)
|
||||
|
||||
assert resolved_provider == "custom"
|
||||
assert base_url == "https://explicit.example/v1"
|
||||
assert api_key == "explicit-key"
|
||||
|
||||
|
||||
class TestBuildCallKwargsMaxTokens:
|
||||
"""_build_call_kwargs should not cap output by default (#34530).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue