fix(model_metadata): never fuzzy-match an empty model name against endpoint catalogs
'' is a substring of every catalog key, so _resolve_endpoint_context_length with an empty model name "matched" whatever the endpoint listed first — on the Nous portal that is currently a 32K embedding model, which poisoned the resolved context length and made AIAgent init fail the 64K minimum. This is what turned tests/run_agent/test_primary_runtime_restore.py:: TestTryRecoverPrimaryTransport::test_allowed_for_nous_anthropic_messages red on every PR (CI slice 7/12) after the portal catalog reordered. Single-model endpoints still resolve with an empty name (unambiguous); non-empty names keep the substring fuzzy match.
This commit is contained in:
parent
996ae10ebd
commit
1a796a1247
|
|
@ -1399,7 +1399,12 @@ def _resolve_endpoint_context_length(
|
|||
if not matched:
|
||||
if len(endpoint_metadata) == 1:
|
||||
matched = next(iter(endpoint_metadata.values()))
|
||||
else:
|
||||
elif model:
|
||||
# Substring fuzzy match — only meaningful with a non-empty model
|
||||
# name. An empty string is a substring of EVERY key, which would
|
||||
# "match" whatever model the endpoint happens to list first (e.g.
|
||||
# a 32K embedding model on the Nous portal) and poison the
|
||||
# resolved context length for the whole agent.
|
||||
for key, entry in endpoint_metadata.items():
|
||||
if model in key or key in model:
|
||||
matched = entry
|
||||
|
|
|
|||
|
|
@ -591,6 +591,30 @@ class TestNousPortalContextResolution:
|
|||
|
||||
|
||||
|
||||
@patch("agent.model_metadata.fetch_endpoint_model_metadata")
|
||||
def test_empty_model_never_fuzzy_matches_endpoint_catalog(self, mock_fetch):
|
||||
"""An empty model name must not substring-match arbitrary catalog
|
||||
entries — '' is a substring of every key, so pre-fix it "matched"
|
||||
whatever the endpoint listed first (e.g. a 32K embedding model on
|
||||
the Nous portal) and poisoned the resolved context length."""
|
||||
import agent.model_metadata as mm
|
||||
mock_fetch.return_value = {
|
||||
"voyageai/voyage-code-4": {"context_length": 32_000},
|
||||
"x-ai/grok-4.6": {"context_length": 500_000},
|
||||
}
|
||||
assert mm._resolve_endpoint_context_length(
|
||||
"", "https://inference-api.nousresearch.com/v1"
|
||||
) is None
|
||||
# Non-empty names still fuzzy-match.
|
||||
assert mm._resolve_endpoint_context_length(
|
||||
"grok-4.6", "https://inference-api.nousresearch.com/v1"
|
||||
) == 500_000
|
||||
# Single-model endpoints still resolve even with an empty name.
|
||||
mock_fetch.return_value = {"only-model": {"context_length": 131_072}}
|
||||
assert mm._resolve_endpoint_context_length(
|
||||
"", "http://localhost:8080/v1"
|
||||
) == 131_072
|
||||
|
||||
@patch("agent.model_metadata.fetch_endpoint_model_metadata")
|
||||
@patch("agent.model_metadata.fetch_model_metadata")
|
||||
def test_openrouter_fallback_is_not_persisted(
|
||||
|
|
|
|||
Loading…
Reference in New Issue