fix(models): reject ambiguous catalog evidence

This commit is contained in:
RaresKeY 2026-07-18 11:38:52 +00:00
parent 3ec6cb4b50
commit 6e6543ab13
3 changed files with 53 additions and 19 deletions

View file

@ -178,9 +178,11 @@ def model_id_from(raw: Mapping[str, Any], *keys: str) -> str:
def int_limit(value: Any) -> int | None:
if isinstance(value, bool):
return None
try:
limit = int(value)
except (TypeError, ValueError):
except (OverflowError, TypeError, ValueError):
return None
return limit if limit > 0 else None

View file

@ -322,7 +322,7 @@ CHATGPT_MODELS_SHAPE = ProviderCatalogShape(
envelope=ENVELOPE_MODELS,
identity_paths=("slug",),
required_item_any_paths=("visibility", "priority"),
detection_priority=90,
detection_priority=0,
)
SGLANG_MODEL_INFO_SHAPE = ProviderCatalogShape(
shape_id="sglang.model-info.v2",
@ -605,11 +605,11 @@ def native_shape_for_payload(
matches = [shape for shape in shapes if shape.matches(payload)]
if not matches:
return None
priority = max(shape.detection_priority for shape in matches)
best = [shape for shape in matches if shape.detection_priority == priority]
providers = {shape.provider_id for shape in best}
providers = {shape.provider_id for shape in matches}
if len(providers) != 1:
return None
priority = max(shape.detection_priority for shape in matches)
best = [shape for shape in matches if shape.detection_priority == priority]
return sorted(best, key=lambda shape: shape.shape_id)[0]

View file

@ -240,7 +240,12 @@ def test_native_catalog_shapes_resolve_with_required_provider_context():
),
)
explicit_context_providers = {"cohere", "lmstudio", "mistral"}
explicit_context_providers = {
"chatgpt_subscription",
"cohere",
"lmstudio",
"mistral",
}
for payload, expected_provider, expected_shape in cases:
explicit_provider = (
expected_provider if expected_provider in explicit_context_providers else None
@ -273,6 +278,10 @@ def test_ambiguous_common_fields_do_not_infer_provider_from_payload_alone():
{"models": [{"name": "generic", "endpoints": ["chat"], "context_length": 4096}]},
"cohere",
),
(
{"models": [{"slug": "generic", "visibility": "list", "priority": 1}]},
"chatgpt_subscription",
),
)
for payload, provider_id in cases:
@ -284,6 +293,26 @@ def test_ambiguous_common_fields_do_not_infer_provider_from_payload_alone():
assert contextual.provider_id == provider_id
def test_payload_matching_multiple_providers_degrades_to_fallback():
payload = _openrouter_payload(
{
**_openrouter_payload()["data"][0],
"model_picker_enabled": True,
"capabilities": {"supports": {"tool_calls": True}},
}
)
resolution = pcs.resolve_provider(payload)
record = records_from_payload(payload)[0]
assert resolution.provider_id == pcs.PROVIDER_UNKNOWN
assert resolution.shape_id == "fallback.models.data.v1"
assert resolution.fallback is True
assert record.vendor == pcs.PROVIDER_UNKNOWN
assert record.capability.family == mc.FAMILY_UNKNOWN
assert record.capability.capabilities == ()
assert record.fallback is True
def test_openrouter_payload_detection_requires_the_compound_official_shape():
complete = _openrouter_payload()
assert pcs.resolve_provider(complete).shape_id == "openrouter.models.rich.v1"
@ -574,18 +603,21 @@ def test_sglang_openai_catalog_preserves_only_valid_native_context_limit():
]
}
)[0]
nonpositive = sglang.records_from_payload(
{
"data": [
{
"id": "served-model",
"owned_by": "sglang",
"root": "org/model",
"max_model_len": 0,
}
]
}
)[0]
malformed = [
records_from_payload(
{
"data": [
{
"id": "served-model",
"owned_by": "sglang",
"root": "org/model",
"max_model_len": value,
}
]
}
)[0]
for value in (0, True, float("inf"))
]
assert valid.vendor == "sglang"
assert valid.capability.family == mc.FAMILY_UNKNOWN
@ -593,7 +625,7 @@ def test_sglang_openai_catalog_preserves_only_valid_native_context_limit():
assert dict(valid.capability.limits) == {"context_tokens": 131072}
assert valid.catalog_shape_id == "sglang.models.openai.v1"
assert valid.fallback is False
assert dict(nonpositive.capability.limits) == {}
assert all(dict(record.capability.limits) == {} for record in malformed)
def test_identity_only_native_catalogs_remain_unknown():