From 9ad912a79145651fa1b6441dca1377b68bf78b08 Mon Sep 17 00:00:00 2001 From: falkoro <39274208+falkoro@users.noreply.github.com> Date: Sun, 5 Jul 2026 00:00:33 +0200 Subject: [PATCH] fix(agent): honor auxiliary..base_url/api_key when provider is passed explicitly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _resolve_task_provider_model returns early on an explicit provider arg, which skips the config block that consults auxiliary..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 --- agent/auxiliary_client.py | 12 +++ tests/agent/test_auxiliary_client.py | 106 +++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) diff --git a/agent/auxiliary_client.py b/agent/auxiliary_client.py index 094c154310a..adefff19240 100644 --- a/agent/auxiliary_client.py +++ b/agent/auxiliary_client.py @@ -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..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: diff --git a/tests/agent/test_auxiliary_client.py b/tests/agent/test_auxiliary_client.py index b5901391ee9..fd501bde940 100644 --- a/tests/agent/test_auxiliary_client.py +++ b/tests/agent/test_auxiliary_client.py @@ -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..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).