From 005b2ca460cbee98d473b528a84fa4addf58218b Mon Sep 17 00:00:00 2001 From: nesquena-hermes Date: Fri, 12 Jun 2026 07:54:48 +0000 Subject: [PATCH] fix(#4022): preserve different-endpoint config base_url override (Codex CORE) Codex caught a regression: the contributor's _runtime_preferred_base_url preferred the runtime base_url for ALL non-custom providers, which would clobber an explicit providers..base_url override pointing at a different host/port (LM Studio at a LAN IP, an OpenRouter mirror). Now only prefer the runtime URL when it's the SAME scheme+host+port as the configured one (the #3895 /v1-dedup case is path-only on the same host); a genuinely different configured endpoint wins. Added _same_base_url_endpoint() + 2 regression tests (different-endpoint preserved, same-endpoint normalization). --- api/streaming.py | 50 ++++++++++++++++++- ...test_issue3895_opencode_go_model_picker.py | 34 +++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/api/streaming.py b/api/streaming.py index 4c2802c50..d1ed35836 100644 --- a/api/streaming.py +++ b/api/streaming.py @@ -237,17 +237,58 @@ def _resolve_custom_provider_runtime_overrides( return resolved_provider, resolved_api_key, resolved_base_url +def _same_base_url_endpoint(url_a: str, url_b: str) -> bool: + """True if two base URLs point at the same scheme+host+port endpoint. + + Used to decide whether a runtime base_url is just a normalized form of the + configured one (e.g. OpenCode-Go's ``/v1`` de-duplication on the same host) + versus a genuinely different endpoint (an explicit ``providers..base_url`` + override at a different host/port that must be preserved). Path/query are + intentionally ignored — the normalization #3895 fixes is path-only. + """ + from urllib.parse import urlsplit + try: + a = urlsplit((url_a or "").strip()) + b = urlsplit((url_b or "").strip()) + except Exception: + return False + _default_port = {"http": 80, "https": 443} + a_host = (a.hostname or "").lower() + b_host = (b.hostname or "").lower() + a_scheme = (a.scheme or "").lower() + b_scheme = (b.scheme or "").lower() + a_port = a.port or _default_port.get(a_scheme) + b_port = b.port or _default_port.get(b_scheme) + return bool(a_host) and a_host == b_host and a_scheme == b_scheme and a_port == b_port + + def _runtime_preferred_base_url( runtime_provider: dict | None, resolved_provider: str | None, configured_base_url: str | None, ) -> str | None: - """Prefer runtime-normalized URLs except for named custom endpoints.""" + """Prefer the runtime-normalized base_url, but never override an explicit + configured endpoint that points somewhere genuinely different. + + The #3895 bug was that WebUI used the *configured* base_url (which can carry a + duplicated ``/v1``) instead of the runtime provider's per-model-normalized + base_url, 404ing OpenCode-Go. But blindly preferring the runtime URL would + clobber a legitimate ``providers..base_url`` override (e.g. LM Studio at a + LAN IP, an OpenRouter mirror). So: + - no runtime URL -> keep configured + - no configured URL -> use runtime (all we have) + - named ``custom:`` endpoint -> configured wins (then runtime as fallback) + - same scheme+host+port -> runtime wins (it's the normalized/corrected + form of the same endpoint — the #3895 case) + - different endpoint -> configured override wins (no regression) + """ runtime_base_url = None if isinstance(runtime_provider, dict): runtime_base_url = runtime_provider.get("base_url") if not runtime_base_url: return configured_base_url + if not configured_base_url: + return runtime_base_url provider_id = str( resolved_provider @@ -256,7 +297,12 @@ def _runtime_preferred_base_url( ).strip().lower() if provider_id.startswith("custom:"): return configured_base_url or runtime_base_url - return runtime_base_url + + # An explicit configured override at a DIFFERENT endpoint must be preserved; + # only prefer the runtime URL when it's the same endpoint (path-normalized). + if _same_base_url_endpoint(configured_base_url, runtime_base_url): + return runtime_base_url + return configured_base_url def _is_fallback_lifecycle_message(kind: str, message: str) -> bool: diff --git a/tests/test_issue3895_opencode_go_model_picker.py b/tests/test_issue3895_opencode_go_model_picker.py index 7567e16b1..177511e96 100644 --- a/tests/test_issue3895_opencode_go_model_picker.py +++ b/tests/test_issue3895_opencode_go_model_picker.py @@ -35,6 +35,40 @@ def test_runtime_preferred_base_url_uses_runtime_for_custom_provider_without_con ) == "https://runtime.example.com" +def test_runtime_preferred_base_url_preserves_different_endpoint_config_override(): + """Codex CORE regression guard: an explicit providers..base_url override + at a DIFFERENT host/port must NOT be clobbered by the runtime default. Only a + same-endpoint runtime URL (the #3895 /v1-dedup case) should win.""" + # LM Studio pinned at a LAN IP — must be preserved over the runtime localhost default. + assert streaming._runtime_preferred_base_url( + {"provider": "lmstudio", "base_url": "http://localhost:1234/v1"}, + "lmstudio", + "http://10.0.0.5:1234/v1", + ) == "http://10.0.0.5:1234/v1" + # OpenRouter mirror override preserved over the runtime canonical host. + assert streaming._runtime_preferred_base_url( + {"provider": "openrouter", "base_url": "https://openrouter.ai/api/v1"}, + "openrouter", + "https://my-mirror.example.com/api/v1", + ) == "https://my-mirror.example.com/api/v1" + + +def test_runtime_preferred_base_url_prefers_runtime_for_same_endpoint_path_normalization(): + """The #3895 case: same scheme+host+port, runtime just strips a duplicated + path segment — runtime (corrected) form wins.""" + assert streaming._runtime_preferred_base_url( + {"provider": "opencode-go", "base_url": "https://opencode.example.com/zen/go"}, + "opencode-go", + "https://opencode.example.com/zen/go/v1", + ) == "https://opencode.example.com/zen/go" + # Same host different port = different endpoint → configured wins. + assert streaming._runtime_preferred_base_url( + {"provider": "someprov", "base_url": "https://host.example.com:8080/v1"}, + "someprov", + "https://host.example.com:9090/v1", + ) == "https://host.example.com:9090/v1" + + def test_streaming_passes_target_model_and_prefers_runtime_base_url(monkeypatch): captured = {}