#!/usr/bin/env python3 """Provider/model catalog loading, overlays, and semantic validation.""" from __future__ import annotations import math import re from collections.abc import Mapping from pathlib import Path from typing import Any from urllib.parse import urlsplit from mmo_util import ( config_root, deep_merge, install_root, read_toml, valid_absolute_uri, valid_http_header_value, validate_id, ) from mmo_version import MMO_SCHEMA_VERSION ALLOWED_DRIVERS = { "switchyard", "codex_builtin", "codex_custom", "codex_oss", "catalog_only", } ALLOWED_WIRE_PROTOCOLS = { "openai_chat", "openai_responses", "anthropic_messages", "codex_builtin", "codex_oss", "catalog_only", } ALLOWED_BILLING_MODES = {"api", "subscription", "chatgpt_subscription", "local", "catalog_only"} ALLOWED_MODEL_KINDS = { "chat", "vision_chat", "ocr", "image_generation", "video_generation", "audio_transcription", "agent_service", } ALLOWED_MODALITIES = {"text", "image", "audio", "video", "file"} ALLOWED_REASONING = {"none", "minimal", "low", "medium", "high", "xhigh", "max", "ultra"} def user_catalog_root() -> Path: return config_root() / "catalog.d" ROUTE_FIELDS = { "driver", "name", "api_operator", "access_product", "wire_protocol", "billing_mode", "base_url", "provider_id", "auth", "auth_link_mode", "wire_api", "credential_envs", "http_headers", "env_http_headers", "extra_headers", "request_max_retries", "stream_max_retries", "stream_idle_timeout_ms", "max_retries", "transport_modalities", "transport_output_modalities", "tool_calling", "parallel_tool_calls", "preserves_tool_media", "tool_result_modalities", "supports_documents", "resource_group", "inventory", "openrouter_policy", } ROUTE_COMMON_FIELDS = { "driver", "name", "api_operator", "access_product", "wire_protocol", "billing_mode", "transport_modalities", "transport_output_modalities", "tool_calling", "parallel_tool_calls", "preserves_tool_media", "tool_result_modalities", "supports_documents", "resource_group", "inventory", "openrouter_policy", } ROUTE_DRIVER_FIELDS = { "switchyard": { "base_url", "credential_envs", "extra_headers", "max_retries", }, "codex_custom": { "base_url", "wire_api", "credential_envs", "http_headers", "env_http_headers", "request_max_retries", "stream_max_retries", "stream_idle_timeout_ms", }, "codex_builtin": {"provider_id", "auth", "auth_link_mode"}, "codex_oss": {"provider_id"}, # Catalog-only providers retain endpoint/auth facts for inventory and # operator diagnostics, but none of these fields is emitted for execution. "catalog_only": { "base_url", "wire_api", "credential_envs", "auth", }, } MODEL_FIELDS = { "maker", "route", "upstream_id", "display_name", "description", "kind", "agent_compatible", "context_window", "max_output_tokens", "reasoning_levels", "default_reasoning", "modalities", "output_modalities", "supports_tool_images", "supports_documents", "tool_calling", "supports_custom_tools", "parallel_tool_calls", "supports_reasoning_summaries", "structured_output", "availability", "capability_confidence", "source", "availability_source", "capability_source", "pricing_source", "inventory", "resource_group", "input_cost_per_million", "cached_input_cost_per_million", "cache_write_input_cost_per_million", "output_cost_per_million", "unit_cost_usd", "extra_body", "route_policy", } OPENROUTER_POLICY_FIELDS = { "only", "order", "allow_fallbacks", "require_parameters", "data_collection", "zdr", "quantizations", "sort", "max_price", } RESOURCE_FIELDS = {"description", "lock_key", "max_active"} def _reject_unknown_fields(value: Mapping[str, Any], allowed: set[str], label: str) -> None: unknown = sorted(set(value) - allowed) if unknown: raise ValueError(f"{label} has unknown fields: {', '.join(unknown)}") def _schema_version(value: Any, expected: int, label: str) -> int: if not isinstance(value, int) or isinstance(value, bool) or value != expected: raise ValueError(f"unsupported {label} schema_version") return value def _nonempty_string(value: Any, label: str) -> str: if not isinstance(value, str) or not value.strip(): raise ValueError(f"{label} must be a non-empty string") return value def _optional_nonempty_string(value: Any, label: str) -> str | None: if value is None: return None return _nonempty_string(value, label) def _enum_string(value: Any, allowed: set[str], label: str) -> str: if not isinstance(value, str) or value not in allowed: raise ValueError(f"{label} must be one of {sorted(allowed)}") return value def _load_catalog_fragment(path: Path) -> dict[str, Any]: data = read_toml(path) _reject_unknown_fields( data, {"schema_version", "routes", "models", "resources"}, f"catalog {path}" ) try: _schema_version(data.get("schema_version"), MMO_SCHEMA_VERSION, "catalog") except ValueError as exc: raise ValueError(f"unsupported catalog schema_version in {path}") from exc result: dict[str, Any] = {} for section in ("routes", "models", "resources"): value = data.get(section, {}) if not isinstance(value, Mapping): raise ValueError(f"catalog {section!r} must be a table in {path}") if not all(isinstance(item, Mapping) for item in value.values()): raise ValueError(f"catalog {section!r} entries must be tables in {path}") result[section] = value return result def load_global_catalog() -> dict[str, Any]: """Load the bundled catalog plus deterministic user overlays. User fragments are merged lexicographically so an operator can override or extend a provider/model without editing installed files. Profile-local fragments are applied separately by :func:`load_catalog`. """ catalog = _load_catalog_fragment(install_root() / "config" / "catalog.toml") root = user_catalog_root() if root.is_dir(): for path in sorted(root.glob("*.toml")): catalog = deep_merge(catalog, _load_catalog_fragment(path)) return catalog def validate_catalog_data(catalog: Mapping[str, Any], *, label: str = "catalog") -> dict[str, Any]: """Validate one fully merged catalog and all cross-section references.""" if not isinstance(catalog, Mapping): raise ValueError(f"{label} must be a table") _reject_unknown_fields(catalog, {"schema_version", "routes", "models", "resources"}, label) if "schema_version" in catalog: _schema_version(catalog["schema_version"], MMO_SCHEMA_VERSION, label) sections: dict[str, Mapping[str, Any]] = {} for section in ("routes", "models", "resources"): value = catalog.get(section, {}) if not isinstance(value, Mapping): raise ValueError(f"{label}.{section} must be a table") if not all(isinstance(item, Mapping) for item in value.values()): raise ValueError(f"{label}.{section} entries must be tables") sections[section] = value routes = {key: _validate_route(key, value) for key, value in sections["routes"].items()} resources = _validate_resources(sections["resources"]) models = _validate_models(sections["models"], routes) for key, route in routes.items(): resource = route.get("resource_group") if resource is not None and resource not in resources: raise ValueError(f"route {key}: unknown resource group {resource!r}") for key, model in models.items(): resource = model.get("resource_group") if resource is not None and resource not in resources: raise ValueError(f"model {key}: unknown resource group {resource!r}") return {"routes": routes, "models": models, "resources": resources} def validated_global_catalog() -> dict[str, Any]: """Return the merged global catalog after full semantic validation.""" return validate_catalog_data(load_global_catalog(), label="global catalog") def load_catalog(profile_dir: Path, profile_data: Mapping[str, Any]) -> dict[str, Any]: catalog = load_global_catalog() profile_catalog = profile_data.get("catalog", "catalog.toml") if not isinstance(profile_catalog, str) or not profile_catalog: raise ValueError("profile.catalog must be a non-empty relative path string") if Path(profile_catalog).is_absolute(): raise ValueError("profile.catalog must be a non-empty relative path string") path = (profile_dir / profile_catalog).resolve() if profile_dir not in path.parents: raise ValueError("profile catalog path escapes the profile pack") if path.is_file(): catalog = deep_merge(catalog, _load_catalog_fragment(path)) elif "catalog" in profile_data: raise ValueError(f"explicit profile catalog file is missing: {profile_catalog}") return catalog def _string_list(value: Any, label: str, *, allow_empty: bool = True) -> list[str]: if value is None and allow_empty: return [] if not isinstance(value, list) or not all(isinstance(item, str) for item in value): raise ValueError(f"{label} must be an array of strings") if any(not item.strip() for item in value): raise ValueError(f"{label} cannot contain empty strings") if not allow_empty and not value: raise ValueError(f"{label} cannot be empty") if len(value) != len(set(value)): raise ValueError(f"{label} cannot contain duplicates") return list(value) def _positive_int(value: Any, label: str, minimum: int = 1, maximum: int = 1_000_000) -> int: if not isinstance(value, int) or isinstance(value, bool) or not minimum <= value <= maximum: raise ValueError(f"{label} must be an integer between {minimum} and {maximum}") return value _HEADER_NAME = re.compile(r"[!#$%&'*+.^_`|~0-9A-Za-z-]+") _ENVIRONMENT_NAME = re.compile(r"[A-Za-z_][A-Za-z0-9_]*") def _validate_http_base_url(value: Any, label: str) -> str: """Validate an HTTP API root before downstream endpoint concatenation.""" if not isinstance(value, str) or not valid_absolute_uri(value): raise ValueError(f"{label}: valid HTTP(S) base_url is required") try: parsed = urlsplit(value) # Accessing ``port`` performs the range and syntax checks that # ``urlsplit`` intentionally defers. _parsed_port = parsed.port except ValueError as exc: raise ValueError(f"{label}: valid HTTP(S) base_url is required") from exc if ( parsed.scheme.lower() not in {"http", "https"} or parsed.hostname is None or parsed.username is not None or parsed.password is not None # Codex 0.149 trims slashes before appending the endpoint path, while # Switchyard 0.2.0 also normalizes known endpoint suffixes. Neither # treats a query or fragment embedded in the base as a URI join input. or "?" in value or "#" in value ): raise ValueError(f"{label}: valid HTTP(S) base_url is required") return value def _header_map(value: Any, label: str, *, environment_values: bool = False) -> dict[str, str]: if not isinstance(value, Mapping): raise ValueError(f"{label} must be a string-to-string table") result: dict[str, str] = {} seen: set[str] = set() for raw_name, raw_value in value.items(): if not isinstance(raw_name, str) or not _HEADER_NAME.fullmatch(raw_name): raise ValueError(f"{label}: invalid HTTP header name {raw_name!r}") normalized_name = raw_name.lower() if normalized_name in seen: raise ValueError(f"{label}: duplicate case-insensitive HTTP header name {raw_name!r}") seen.add(normalized_name) if not isinstance(raw_value, str): raise ValueError(f"{label}.{raw_name} must be a string") if environment_values: if not _ENVIRONMENT_NAME.fullmatch(raw_value): raise ValueError( f"{label}.{raw_name}: invalid environment variable name {raw_value!r}" ) elif not valid_http_header_value(raw_value): raise ValueError(f"{label}.{raw_name} contains a prohibited control character") result[raw_name] = raw_value return result def _json_compatible_value(value: Any, label: str) -> Any: """Validate a value destined for Switchyard's serde_json::Value map.""" if isinstance(value, (str, bool)): return value if isinstance(value, int) and not isinstance(value, bool): if -(2**63) <= value <= 2**63 - 1: return value raise ValueError(f"{label} integer is outside the TOML/JSON target range") if isinstance(value, float): if math.isfinite(value): return value raise ValueError(f"{label} must not contain a non-finite number") if isinstance(value, list): return [ _json_compatible_value(item, f"{label}[{index}]") for index, item in enumerate(value) ] if isinstance(value, Mapping): result: dict[str, Any] = {} for key, item in value.items(): if not isinstance(key, str): raise ValueError(f"{label} object keys must be strings") result[key] = _json_compatible_value(item, f"{label}.{key}") return result raise ValueError(f"{label} must contain only JSON-compatible TOML values") def _credential_envs(route: Mapping[str, Any], label: str) -> list[str]: """Validate a route's ordered credential environment names.""" raw = route.get("credential_envs", []) values = _string_list(raw, f"{label}.credential_envs") for value in values: if not re.fullmatch(r"[A-Za-z_][A-Za-z0-9_]*", value): raise ValueError(f"{label}: invalid credential environment variable {value!r}") return list(dict.fromkeys(values)) def _validate_openrouter_policy(value: Any, label: str) -> dict[str, Any] | None: if value is None: return None if not isinstance(value, Mapping): raise ValueError(f"{label} must be a table") _reject_unknown_fields(value, OPENROUTER_POLICY_FIELDS, label) result = dict(value) for field in ("only", "order", "quantizations"): if field in result: result[field] = _string_list(result[field], f"{label}.{field}", allow_empty=False) for field in ("allow_fallbacks", "require_parameters", "zdr"): if field in result and not isinstance(result[field], bool): raise ValueError(f"{label}.{field} must be boolean") if "data_collection" in result: result["data_collection"] = _enum_string( result["data_collection"], {"allow", "deny"}, f"{label}.data_collection" ) if "sort" in result: result["sort"] = _enum_string( result["sort"], {"price", "throughput", "latency"}, f"{label}.sort" ) if "max_price" in result: price = result["max_price"] if not isinstance(price, Mapping): raise ValueError(f"{label}.max_price must be a table") unknown = sorted(set(price) - {"prompt", "completion", "request", "image"}) if unknown: raise ValueError(f"{label}.max_price has unknown fields: {', '.join(unknown)}") normalized: dict[str, float] = {} for field, raw in price.items(): if not isinstance(raw, (int, float)) or isinstance(raw, bool) or raw < 0: raise ValueError(f"{label}.max_price.{field} must be non-negative and finite") try: numeric = float(raw) except OverflowError: raise ValueError( f"{label}.max_price.{field} must be non-negative and finite" ) from None if not math.isfinite(numeric): raise ValueError(f"{label}.max_price.{field} must be non-negative and finite") normalized[str(field)] = numeric result["max_price"] = normalized return result def _validate_route(key: str, route: Mapping[str, Any]) -> dict[str, Any]: validate_id(key, "route id") _reject_unknown_fields(route, ROUTE_FIELDS, f"route {key}") driver = _enum_string(route.get("driver"), ALLOWED_DRIVERS, f"route {key}.driver") unsupported = sorted(set(route) - ROUTE_COMMON_FIELDS - ROUTE_DRIVER_FIELDS[driver]) if unsupported: raise ValueError(f"route {key}: fields unsupported by driver {driver!r}: {unsupported}") result = dict(route) result.setdefault("name", key) result["name"] = _nonempty_string(result["name"], f"route {key}.name") for field in ("api_operator", "access_product"): result[field] = _nonempty_string(result.get(field), f"route {key}.{field}") result["wire_protocol"] = _enum_string( result.get("wire_protocol"), ALLOWED_WIRE_PROTOCOLS, f"route {key}.wire_protocol" ) result["billing_mode"] = _enum_string( result.get("billing_mode"), ALLOWED_BILLING_MODES, f"route {key}.billing_mode" ) expected_protocols = { "switchyard": {"openai_chat", "openai_responses", "anthropic_messages"}, "codex_custom": {"openai_responses"}, "codex_builtin": {"codex_builtin"}, "codex_oss": {"codex_oss"}, "catalog_only": {"catalog_only", "openai_chat", "openai_responses", "anthropic_messages"}, }[driver] if result["wire_protocol"] not in expected_protocols: raise ValueError(f"route {key}.wire_protocol is incompatible with driver {driver!r}") result["openrouter_policy"] = _validate_openrouter_policy( result.get("openrouter_policy"), f"route {key}.openrouter_policy" ) if result["openrouter_policy"] is not None and result["api_operator"] != "openrouter": raise ValueError(f"route {key}: openrouter_policy requires api_operator='openrouter'") result.setdefault("transport_modalities", ["text"]) result["transport_modalities"] = _string_list( result["transport_modalities"], f"route {key}.transport_modalities", allow_empty=False ) unknown_modalities = sorted(set(result["transport_modalities"]) - ALLOWED_MODALITIES) if unknown_modalities: raise ValueError(f"route {key}: invalid transport modalities {unknown_modalities}") result.setdefault( "transport_output_modalities", ["text", "image", "video", "audio", "file"] if driver == "catalog_only" else ["text"], ) result["transport_output_modalities"] = _string_list( result["transport_output_modalities"], f"route {key}.transport_output_modalities", allow_empty=False, ) unknown_output_modalities = sorted( set(result["transport_output_modalities"]) - ALLOWED_MODALITIES ) if unknown_output_modalities: raise ValueError(f"route {key}: invalid output modalities {unknown_output_modalities}") result.setdefault("tool_calling", driver != "catalog_only") result.setdefault("parallel_tool_calls", driver != "catalog_only") result.setdefault( "preserves_tool_media", driver in {"codex_builtin", "codex_custom"}, ) result.setdefault( "tool_result_modalities", list(result["transport_modalities"]) if result["preserves_tool_media"] else ["text"], ) result["tool_result_modalities"] = _string_list( result["tool_result_modalities"], f"route {key}.tool_result_modalities", allow_empty=False, ) unknown_tool_modalities = sorted(set(result["tool_result_modalities"]) - ALLOWED_MODALITIES) if unknown_tool_modalities: raise ValueError(f"route {key}: invalid tool-result modalities {unknown_tool_modalities}") result.setdefault("supports_documents", "file" in result["transport_modalities"]) for boolean_field in ( "tool_calling", "parallel_tool_calls", "preserves_tool_media", "supports_documents", ): if not isinstance(result[boolean_field], bool): raise ValueError(f"route {key}.{boolean_field} must be boolean") if result["parallel_tool_calls"] and not result["tool_calling"]: raise ValueError(f"route {key}: parallel_tool_calls requires tool_calling") if not result["preserves_tool_media"] and set(result["tool_result_modalities"]) - {"text"}: raise ValueError( f"route {key}: non-text tool_result_modalities require preserves_tool_media=true" ) result.setdefault("resource_group", None) result.setdefault("inventory", None) for field in ("resource_group", "inventory"): result[field] = _optional_nonempty_string(result[field], f"route {key}.{field}") credentials = _credential_envs(result, f"route {key}") result["credential_envs"] = credentials if driver == "switchyard": if "extra_headers" in result: result["extra_headers"] = _header_map( result["extra_headers"], f"route {key}.extra_headers" ) result["base_url"] = _validate_http_base_url(result.get("base_url"), f"route {key}") result.setdefault("max_retries", 1) result["max_retries"] = _positive_int( result["max_retries"], f"route {key}.max_retries", 0, 10 ) elif driver == "codex_custom": if "http_headers" in result: result["http_headers"] = _header_map( result["http_headers"], f"route {key}.http_headers" ) if "env_http_headers" in result: result["env_http_headers"] = _header_map( result["env_http_headers"], f"route {key}.env_http_headers", environment_values=True, ) static_names = {name.lower() for name in result.get("http_headers", {})} environment_names = {name.lower() for name in result.get("env_http_headers", {})} overlap = sorted(static_names & environment_names) if overlap: raise ValueError( f"route {key} defines headers in both http_headers and env_http_headers: " + ", ".join(overlap) ) result["base_url"] = _validate_http_base_url(result.get("base_url"), f"route {key}") result.setdefault("wire_api", "responses") if not isinstance(result["wire_api"], str) or result["wire_api"] != "responses": raise ValueError(f"route {key}: Codex custom routes require wire_api='responses'") for field, default, minimum, maximum in ( ("request_max_retries", 1, 0, 2**63 - 1), ("stream_max_retries", 1, 0, 2**63 - 1), ("stream_idle_timeout_ms", 600_000, 1_000, 2**63 - 1), ): result.setdefault(field, default) result[field] = _positive_int(result[field], f"route {key}.{field}", minimum, maximum) elif driver == "codex_builtin": provider_id = result.get("provider_id") provider_id = _nonempty_string(provider_id, f"route {key}.provider_id") if provider_id not in {"openai", "amazon-bedrock"}: raise ValueError( f"route {key}: Codex built-in provider_id must be openai or amazon-bedrock" ) result["provider_id"] = provider_id result.setdefault("auth", "chatgpt" if provider_id == "openai" else "builtin") expected_auth = "chatgpt" if provider_id == "openai" else "builtin" if result.get("auth") != expected_auth: raise ValueError( f"route {key}: auth must be {expected_auth!r} for built-in {provider_id!r}" ) if result.get("auth_link_mode") is not None and not isinstance( result.get("auth_link_mode"), str ): raise ValueError(f"route {key}: invalid auth_link_mode") if result.get("auth_link_mode") not in {None, "shared", "copy", "none"}: raise ValueError(f"route {key}: invalid auth_link_mode") elif driver == "codex_oss": provider_id = result.get("provider_id") if not isinstance(provider_id, str) or provider_id not in {"ollama", "lmstudio"}: raise ValueError(f"route {key}: codex_oss provider_id must be ollama or lmstudio") elif driver == "catalog_only": if "base_url" in result: result["base_url"] = _validate_http_base_url(result["base_url"], f"route {key}") for field in ("wire_api", "auth"): if field in result: result[field] = _nonempty_string(result[field], f"route {key}.{field}") header_fields = {"http_headers", "env_http_headers", "extra_headers"} allowed_header_fields = { "switchyard": {"extra_headers"}, "codex_custom": {"http_headers", "env_http_headers"}, }.get(driver, set()) unsupported_headers = sorted((header_fields & set(result)) - allowed_header_fields) if unsupported_headers: detail = f"header fields are unsupported by driver {driver}" raise ValueError(f"route {key}: {detail}: {unsupported_headers}") return result def validate_model_entry( key: str, model: Mapping[str, Any], routes: Mapping[str, Any] ) -> dict[str, Any]: validate_id(key, "model id") _reject_unknown_fields(model, MODEL_FIELDS, f"model {key}") route_key = model.get("route") if not isinstance(route_key, str) or route_key not in routes: raise ValueError(f"model {key}: unknown route {route_key!r}") if not key.startswith(f"{route_key}__"): raise ValueError( f"model {key}: catalog key must start with exact route namespace " f"{route_key!r} followed by '__'" ) if not isinstance(model.get("upstream_id"), str) or not model["upstream_id"].strip(): raise ValueError(f"model {key}: upstream_id is required") if not isinstance(model.get("maker"), str) or not model["maker"].strip(): raise ValueError(f"model {key}: maker is required") result = dict(model) result.setdefault("display_name", key) result.setdefault("description", "") result.setdefault("kind", "chat") result["display_name"] = _nonempty_string(result["display_name"], f"model {key}.display_name") if not isinstance(result["description"], str): raise ValueError(f"model {key}.description must be a string") result["kind"] = _enum_string(result["kind"], ALLOWED_MODEL_KINDS, f"model {key}.kind") result.setdefault( "agent_compatible", result["kind"] in {"chat", "vision_chat"} and routes[route_key]["driver"] != "catalog_only", ) if not isinstance(result["agent_compatible"], bool): raise ValueError(f"model {key}.agent_compatible must be boolean") result.setdefault("context_window", 131072 if result["agent_compatible"] else 0) result["context_window"] = _positive_int( result["context_window"], f"model {key}.context_window", 1024 if result["agent_compatible"] else 0, 20_000_000, ) result.setdefault("reasoning_levels", ["none", "low", "medium", "high"]) result["reasoning_levels"] = _string_list( result["reasoning_levels"], f"model {key}.reasoning_levels", allow_empty=False ) unknown_reasoning = sorted(set(result["reasoning_levels"]) - ALLOWED_REASONING) if unknown_reasoning: raise ValueError(f"model {key}: invalid reasoning levels {unknown_reasoning}") result.setdefault("default_reasoning", result["reasoning_levels"][-1]) if ( not isinstance(result["default_reasoning"], str) or result["default_reasoning"] not in result["reasoning_levels"] ): raise ValueError(f"model {key}: default_reasoning is not supported") route = routes[route_key] result["route_policy"] = _validate_openrouter_policy( result.get("route_policy"), f"model {key}.route_policy" ) if result["route_policy"] is not None and route["api_operator"] != "openrouter": raise ValueError(f"model {key}: route_policy requires an OpenRouter route") if "extra_body" in result: if route["driver"] != "switchyard": raise ValueError(f"model {key}: extra_body is supported only by Switchyard targets") if not isinstance(result["extra_body"], Mapping): raise ValueError(f"model {key}.extra_body must be a table") result["extra_body"] = _json_compatible_value( result["extra_body"], f"model {key}.extra_body" ) result.setdefault("modalities", route.get("transport_modalities", ["text"])) result["modalities"] = _string_list( result["modalities"], f"model {key}.modalities", allow_empty=False ) unknown_modalities = sorted(set(result["modalities"]) - ALLOWED_MODALITIES) if unknown_modalities: raise ValueError(f"model {key}: invalid modalities {unknown_modalities}") missing_input_transport = sorted(set(result["modalities"]) - set(route["transport_modalities"])) if missing_input_transport: raise ValueError( f"model {key}: route transport cannot carry input modalities {missing_input_transport}" ) result.setdefault("output_modalities", ["text"]) result["output_modalities"] = _string_list( result["output_modalities"], f"model {key}.output_modalities", allow_empty=False ) unknown_output_modalities = sorted(set(result["output_modalities"]) - ALLOWED_MODALITIES) if unknown_output_modalities: raise ValueError(f"model {key}: invalid output modalities {unknown_output_modalities}") missing_output_transport = sorted( set(result["output_modalities"]) - set(route["transport_output_modalities"]) ) if missing_output_transport: raise ValueError( f"model {key}: route transport cannot carry output modalities " f"{missing_output_transport}" ) result.setdefault( "supports_tool_images", "image" in result["modalities"] and route.get("preserves_tool_media", False) and "image" in route.get("tool_result_modalities", []), ) result.setdefault( "supports_documents", "file" in result["modalities"] and route.get("supports_documents", False), ) for boolean_field in ("supports_tool_images", "supports_documents"): if not isinstance(result[boolean_field], bool): raise ValueError(f"model {key}.{boolean_field} must be boolean") if result["supports_tool_images"] and "image" not in result["modalities"]: raise ValueError(f"model {key}: supports_tool_images requires image input") if result["supports_documents"] and "file" not in result["modalities"]: raise ValueError(f"model {key}: supports_documents requires file input") result.setdefault("tool_calling", route.get("tool_calling", True)) # OpenAI Responses distinguishes schema-defined function tools from # free-form custom tools. Some compatible endpoints implement the former # but reject the latter. Keep that narrower capability independent so a # model can still use shell and MCP function tools without receiving # Codex's free-form apply_patch tool. result.setdefault("supports_custom_tools", result["tool_calling"]) result.setdefault("parallel_tool_calls", route.get("parallel_tool_calls", True)) result.setdefault("supports_reasoning_summaries", False) result.setdefault("structured_output", False) for boolean_field in ( "tool_calling", "supports_custom_tools", "parallel_tool_calls", "supports_reasoning_summaries", "structured_output", ): if not isinstance(result[boolean_field], bool): raise ValueError(f"model {key}.{boolean_field} must be boolean") if result["tool_calling"] and not route["tool_calling"]: raise ValueError(f"model {key}: tool_calling exceeds route transport capability") if result["supports_custom_tools"] and not result["tool_calling"]: raise ValueError(f"model {key}: supports_custom_tools requires tool_calling") if result["parallel_tool_calls"] and not result["tool_calling"]: raise ValueError(f"model {key}: parallel_tool_calls requires tool_calling") if result["parallel_tool_calls"] and not route["parallel_tool_calls"]: raise ValueError(f"model {key}: parallel_tool_calls exceeds route transport capability") result.setdefault("max_output_tokens", None) if result["max_output_tokens"] is not None: result["max_output_tokens"] = _positive_int( result["max_output_tokens"], f"model {key}.max_output_tokens", 1, 20_000_000 ) result.setdefault("availability", "current") result.setdefault("capability_confidence", "documented") result.setdefault("source", "bundled-catalog") for field in ("availability", "capability_confidence", "source"): result[field] = _nonempty_string(result[field], f"model {key}.{field}") for field in ( "availability_source", "capability_source", "pricing_source", "inventory", "resource_group", ): if field in result: result[field] = _optional_nonempty_string(result[field], f"model {key}.{field}") result.setdefault("resource_group", route.get("resource_group")) for field in ( "input_cost_per_million", "cached_input_cost_per_million", "cache_write_input_cost_per_million", "output_cost_per_million", "unit_cost_usd", ): if field not in result: continue value = result[field] if ( not isinstance(value, (int, float)) or isinstance(value, bool) or (isinstance(value, float) and not math.isfinite(value)) or value < 0 ): raise ValueError(f"model {key}.{field} must be a non-negative finite number") return result def _validate_models( values: Mapping[str, Any], routes: Mapping[str, Any] ) -> dict[str, dict[str, Any]]: """Validate model rows and reject duplicate route/upstream identities.""" result: dict[str, dict[str, Any]] = {} identities: dict[tuple[str, str], str] = {} for key, value in values.items(): model = validate_model_entry(key, value, routes) identity = (str(model["route"]), str(model["upstream_id"])) previous = identities.get(identity) if previous is not None: raise ValueError( f"models {previous!r} and {key!r} duplicate route/upstream binding {identity!r}" ) identities[identity] = key result[key] = model return result def _validate_resource(key: str, resource: Mapping[str, Any]) -> dict[str, Any]: validate_id(key, "resource group id") _reject_unknown_fields(resource, RESOURCE_FIELDS, f"resource {key}") result = dict(resource) result.setdefault("description", "") if not isinstance(result["description"], str): raise ValueError(f"resource {key}.description must be a string") result.setdefault("lock_key", key) if not isinstance(result["lock_key"], str) or not result["lock_key"]: raise ValueError(f"resource {key}: lock_key is required") result.setdefault("max_active", 4) result["max_active"] = _positive_int( result["max_active"], f"resource {key}.max_active", 1, 1024 ) return result def _validate_resources(values: Mapping[str, Any]) -> dict[str, dict[str, Any]]: result = {key: _validate_resource(key, value) for key, value in values.items()} capacities: dict[str, tuple[str, int]] = {} for key, resource in result.items(): lock_key = str(resource["lock_key"]) maximum = int(resource["max_active"]) previous = capacities.get(lock_key) if previous is not None and previous[1] != maximum: raise ValueError( f"resources {previous[0]!r} and {key!r} share lock_key {lock_key!r} " f"with conflicting max_active values {previous[1]} and {maximum}" ) capacities[lock_key] = (key, maximum) return result