fix(context-length): guard provider ownership on global model.base_url backfill (#7535)

A session on a built-in registry provider (e.g. opencode-go, endpoint in
PROVIDER_REGISTRY, empty base_url by design) had its empty base_url slot
backfilled with the global model.base_url owned by a *different* provider
(custom:ark). The context-length resolver then probed the wrong endpoint's
/models catalog and fell back to the generic 128K catalog entry for a
1M-context model, while the on-disk session and SSE stream carried 1,000,000.

Only fill the global model.base_url slot when the session provider IS the
configured model.provider owner, mirroring the ownership predicate used for
model_cfg's API key in _context_length_config_api_key_for_provider.
This commit is contained in:
webtecnica committed 2026-09-22 22:54:12 -03:00
1 parent 18db77a132
commit a8180bc51f
2 files changed
+84 -1

No files matched your search

+11 -1
View File
@@ -7183,7 +7183,17 @@ def _context_length_lookup_inputs_for_model(
if not effective_provider:
effective_provider = _canonical_context_provider(model_cfg.get("provider"))
if not effective_base_url:
effective_base_url = str(model_cfg.get("base_url") or "").strip()
# #7535: the global model.base_url may only fill an empty slot when
# the session provider IS the configured model.provider owner
# (mirror the ownership predicate used for model_cfg's API key in
# _context_length_config_api_key_for_provider). A built-in registry
# provider (empty base_url by design) must keep the slot empty so
# the registry endpoint resolves instead of another provider's URL.
_model_cfg_provider = _canonical_context_provider(model_cfg.get("provider"))
if not effective_provider or _providers_match_for_context(
_model_cfg_provider, effective_provider
):
effective_base_url = str(model_cfg.get("base_url") or "").strip()
custom_providers = cfg.get("custom_providers") if isinstance(cfg, dict) else None
if not isinstance(custom_providers, list):
@@ -631,3 +631,76 @@ def test_sse_done_path_broadened_to_any_model_window_mismatch():
assert "_model_matches_configured_default as _mmcd_cc" not in _STREAMING_SRC, (
"the old default-only save matcher (_mmcd_cc) must be removed (#4618)"
)
# --- #7535: provider-ownership guard on the global model.base_url backfill ---
# Same family as #3256: a global value scoped to its owner must not leak onto
# sessions owned by a different provider.
def test_builtin_provider_lookup_does_not_inherit_other_providers_base_url():
"""#7535: a session on a built-in registry provider (whose base_url is empty
by design because the endpoint lives in PROVIDER_REGISTRY, not config.yaml)
must NOT inherit the global ``model.base_url`` owned by a different (custom)
provider. The unguarded backfill handed the custom endpoint to the
context-length resolver, which probed the wrong ``/models`` catalog and fell
back to the generic 128K catalog entry for a 1M-context model, while the
on-disk session and SSE stream both carried 1,000,000."""
from api.routes import _context_length_lookup_inputs_for_model
ark_base = "https://ark.cn-beijing.volces.com/api/coding/v3"
cfg = {
"model": {
"provider": "custom:ark",
"base_url": ark_base,
"default": "ark-code-latest",
"context_length": 1000000,
},
"custom_providers": [
{
"name": "ark",
"base_url": ark_base,
"api_key": "ark-key",
"model": "ark-code-latest",
}
],
}
lookup = _context_length_lookup_inputs_for_model(
"@opencode-go:deepseek-v4.1-flash",
"opencode-go",
cfg=cfg,
)
assert lookup.provider == "opencode-go"
assert lookup.base_url == "", (
"the global model.base_url belongs to custom:ark; the opencode-go "
"registry slot must stay empty so PROVIDER_REGISTRY's endpoint "
"resolves the context window (#7535)"
)
def test_same_provider_session_keeps_global_base_url_backfill():
"""#7535 control (compat): when the session provider IS the configured
owner of ``model.base_url``, the backfill behavior is preserved."""
from api.routes import _context_length_lookup_inputs_for_model
ark_base = "https://ark.cn-beijing.volces.com/api/coding/v3"
cfg = {
"model": {
"provider": "custom:ark",
"base_url": ark_base,
"default": "ark-code-latest",
},
}
lookup = _context_length_lookup_inputs_for_model(
"ark-code-latest",
"custom:ark",
cfg=cfg,
)
assert lookup.provider == "custom:ark"
assert lookup.base_url == ark_base, (
"same-owner sessions must keep the model.base_url backfill (#7535 compat)"
)