feat(registry): reject image-only models in chat model saves

This commit is contained in:
m4
2026-07-24 07:36:34 +08:00
parent a57c52c676
commit ccf4173990
3 changed files with 34 additions and 0 deletions
+2
View File
@@ -52,6 +52,7 @@ CAPABILITY_UNSUPPORTED_BY_ADAPTER = "CAPABILITY_UNSUPPORTED_BY_ADAPTER"
MODEL_CAPABILITY_UNAVAILABLE = "MODEL_CAPABILITY_UNAVAILABLE"
UNSUPPORTED_RUNTIME_PARAMETER = "UNSUPPORTED_RUNTIME_PARAMETER"
MODEL_LIMITS_UNCONFIRMED = "MODEL_LIMITS_UNCONFIRMED"
IMAGE_MODEL_NOT_CHAT_MODEL = "IMAGE_MODEL_NOT_CHAT_MODEL"
CONTEXT_BUDGET_UNSATISFIABLE = "CONTEXT_BUDGET_UNSATISFIABLE"
PROVIDER_UNREACHABLE = "PROVIDER_UNREACHABLE"
@@ -88,6 +89,7 @@ ERROR_HTTP_STATUS: dict[str, int] = {
MODEL_CAPABILITY_UNAVAILABLE: 422,
UNSUPPORTED_RUNTIME_PARAMETER: 422,
MODEL_LIMITS_UNCONFIRMED: 422,
IMAGE_MODEL_NOT_CHAT_MODEL: 422,
CONTEXT_BUDGET_UNSATISFIABLE: 422,
PROVIDER_UNREACHABLE: 422,
VALIDATION_FAILED: 422,
+21
View File
@@ -51,6 +51,7 @@ from .endpoint_policy import EndpointPolicy
from .errors import (
CREDENTIAL_NOT_CONFIGURED,
FORBIDDEN,
IMAGE_MODEL_NOT_CHAT_MODEL,
INVALID_REQUEST,
MODEL_LIMITS_UNCONFIRMED,
MODEL_NOT_AVAILABLE,
@@ -381,6 +382,26 @@ def validate_registry_save(
``resolve_parameters``, and the resolve-time tightening rules are
enforced by the resolver/adapter layer.
"""
from EvoScientist.image_gen import is_image_generation_model
for provider_index, provider in enumerate(registry.providers):
for model_index, model in enumerate(provider.models):
if model.enabled and is_image_generation_model(model.upstream_model_id):
raise ModelRegistryError(
IMAGE_MODEL_NOT_CHAT_MODEL,
"Image-only models must be configured in the "
"image_generation section of config.yaml, not as chat models.",
details=[
{
"path": (
f"providers[{provider_index}].models"
f"[{model_index}].upstream_model_id"
),
"code": IMAGE_MODEL_NOT_CHAT_MODEL,
}
],
)
for provider_index, provider in enumerate(registry.providers):
provider_path = f"providers[{provider_index}]"
try:
+11
View File
@@ -384,6 +384,17 @@ def test_put_registry_rejects_ssrf_endpoint(active_client):
assert body["details"][0]["path"].startswith("providers[0].base_url")
def test_put_registry_rejects_image_only_model(active_client):
registry = _current_registry(active_client)["registry"]
registry["providers"][0]["models"][0]["upstream_model_id"] = "gpt-image-2"
response = _put(active_client, registry)
assert response.status_code == 422
body = response.json()
assert body["code"] == "IMAGE_MODEL_NOT_CHAT_MODEL"
assert body["details"][0]["path"].endswith("upstream_model_id")
def test_put_registry_rejects_unsupported_parameter(active_client):
registry = _current_registry(active_client)["registry"]
# The glm-5.2 contract caps temperature at 1.