#!/usr/bin/env python3 """Catalog inspection, inventory verification, and safe model discovery. The bundled catalog is a versioned capability baseline. Discovery never guesses an execution protocol for an unknown remote model. Codex account discovery can optionally create a conservative user overlay because Codex itself provides the route and wire path for built-in models. """ from __future__ import annotations import contextlib import datetime as dt import hashlib import json import os import shutil import subprocess import urllib.error import urllib.parse import urllib.request from collections.abc import Mapping, Sequence from pathlib import Path from typing import Any from mmo_catalog_data import user_catalog_root, validate_model_entry, validated_global_catalog from mmo_inventory_snapshot import ( DISCOVERY_FIELDS, FULL_FINGERPRINT_FIELDS, OPENCODE_GO_SOURCE_IDS, OPENCODE_ZEN_SOURCE_IDS, build_inventory_snapshot, build_opencode_go_snapshot, build_opencode_zen_snapshot, build_openrouter_snapshot, codex_runtime_evidence, compare_inventory_fingerprints, load_inventory_snapshots, route_catalog_key, ) from mmo_profiles import resolve_profile from mmo_util import ( atomic_write_json, atomic_write_text, config_root, filtered_environment, install_root, parse_env_file, read_json, read_json_object, strict_json_loads, toml_dumps, utc_now, valid_absolute_uri, ) from mmo_version import MMO_SCHEMA_VERSION, PACKAGE_VERSION CODEX_REASONING_VALUES = {"none", "minimal", "low", "medium", "high", "xhigh", "max", "ultra"} def _inventory_endpoint(inventory: str) -> str: entry = inventory_baseline().get("inventories", {}).get(inventory, {}) endpoint = entry.get("endpoint") if not isinstance(endpoint, str) or not endpoint: raise RuntimeError(f"inventory {inventory!r} has no declarative discovery endpoint") return endpoint def catalog_data(profile: str | None = None) -> dict[str, Any]: if profile: resolved = resolve_profile(profile) return { "routes": resolved["routes"], "models": resolved["models"], "resources": resolved["resources"], } return validated_global_catalog() def _matches_query(key: str, value: Mapping[str, Any], query: str | None) -> bool: if not query: return True needle = query.casefold() fields = [ key, str(value.get("upstream_id", "")), str(value.get("display_name", "")), str(value.get("description", "")), str(value.get("route", "")), str(value.get("maker", "")), str(value.get("inventory", "")), ] return any(needle in field.casefold() for field in fields) def list_models( *, profile: str | None = None, route: str | None = None, inventory: str | None = None, query: str | None = None, agent_compatible: bool | None = None, availability: str | None = None, ) -> dict[str, dict[str, Any]]: models = catalog_data(profile)["models"] result: dict[str, dict[str, Any]] = {} for key, value in sorted(models.items()): if route and value.get("route") != route: continue if inventory and value.get("inventory") != inventory: continue if agent_compatible is not None and bool(value.get("agent_compatible")) != agent_compatible: continue if availability and value.get("availability") != availability: continue if not _matches_query(key, value, query): continue result[key] = dict(value) return result def find_model(key: str, *, profile: str | None = None) -> dict[str, Any]: models = catalog_data(profile)["models"] if key not in models: raise FileNotFoundError(f"unknown route-qualified catalog model key: {key}") return {"key": key, **models[key]} def catalog_summary(profile: str | None = None) -> dict[str, Any]: data = catalog_data(profile) models = data["models"] by_inventory: dict[str, int] = {} by_kind: dict[str, int] = {} by_driver: dict[str, int] = {} by_maker: dict[str, int] = {} by_operator: dict[str, int] = {} for model in models.values(): inventory = str(model.get("inventory") or "unscoped") by_inventory[inventory] = by_inventory.get(inventory, 0) + 1 kind = str(model.get("kind") or "chat") by_kind[kind] = by_kind.get(kind, 0) + 1 route = data["routes"][model["route"]] driver = str(route["driver"]) by_driver[driver] = by_driver.get(driver, 0) + 1 maker = str(model["maker"]) by_maker[maker] = by_maker.get(maker, 0) + 1 operator = str(route["api_operator"]) by_operator[operator] = by_operator.get(operator, 0) + 1 return { "profile": profile, "routes": len(data["routes"]), "models": len(models), "agent_compatible_models": sum( bool(item.get("agent_compatible")) for item in models.values() ), "resources": len(data["resources"]), "models_by_inventory": dict(sorted(by_inventory.items())), "models_by_kind": dict(sorted(by_kind.items())), "models_by_driver": dict(sorted(by_driver.items())), "models_by_maker": dict(sorted(by_maker.items())), "models_by_api_operator": dict(sorted(by_operator.items())), } def inventory_baseline() -> dict[str, Any]: return read_json_object( install_root() / "config" / "upstream-inventory.json", label="inventory baseline", ) def local_inventory_report() -> dict[str, Any]: baseline = inventory_baseline() catalog = validated_global_catalog() snapshot_errors: list[str] = [] snapshot_map: dict[str, dict[str, Any]] = {} try: snapshot_map = { str(snapshot["inventory"]): snapshot for snapshot in load_inventory_snapshots( install_root() / "config" / "inventory-snapshots" ) } except (OSError, ValueError) as exc: snapshot_errors.append(f"{type(exc).__name__}: {exc}") report: dict[str, Any] = { "as_of": baseline.get("as_of"), "sources": baseline.get("sources", {}), "inventories": {}, "snapshot_errors": snapshot_errors, "passed": not snapshot_errors, } for inventory_id, expected in sorted(baseline.get("inventories", {}).items()): expected_ids = set(expected.get("models", [])) catalog_items = { key: model for key, model in catalog["models"].items() if model.get("inventory") == inventory_id } actual_ids = {str(model["upstream_id"]) for model in catalog_items.values()} missing = sorted(expected_ids - actual_ids) extra = sorted(actual_ids - expected_ids) expected_keys = set(expected.get("catalog_keys", [])) actual_keys = set(catalog_items) missing_keys = sorted(expected_keys - actual_keys) extra_keys = sorted(actual_keys - expected_keys) expected_count = expected.get("expected_count") count_ok = expected_count is None or len(actual_ids) == int(expected_count) snapshot = snapshot_map.get(inventory_id) record_mismatches: list[str] = [] if snapshot: for key in sorted(set(catalog_items) & set(snapshot["models"])): actual_record = catalog_items[key] snapshot_record = snapshot["models"][key]["catalog"] normalized_snapshot_record = validate_model_entry( key, snapshot_record, catalog["routes"] ) if actual_record != normalized_snapshot_record: record_mismatches.append(key) expected_discovery = {key: expected[key] for key in DISCOVERY_FIELDS if key in expected} snapshot_ok = bool( snapshot and snapshot.get("models_sha256") == expected.get("models_sha256") and snapshot.get("as_of") == expected.get("as_of") and snapshot.get("dynamic") == expected.get("dynamic") and snapshot.get("adapter") == expected.get("adapter") and snapshot.get("fingerprint_fields") == expected.get("fingerprint_fields") and snapshot.get("captures", []) == expected.get("captures", []) and snapshot.get("discovery") == expected_discovery ) passed = ( not missing and not extra and not missing_keys and not extra_keys and not record_mismatches and count_ok and snapshot_ok ) report["inventories"][inventory_id] = { "passed": passed, "dynamic": bool(expected.get("dynamic", False)), "expected_count": expected_count, "actual_count": len(actual_ids), "missing": missing, "extra": extra, "missing_catalog_keys": missing_keys, "extra_catalog_keys": extra_keys, "catalog_record_mismatches": record_mismatches, "snapshot": expected.get("snapshot"), "models_sha256": expected.get("models_sha256"), "snapshot_ok": snapshot_ok, "catalog_keys": sorted(catalog_items), } report["passed"] = report["passed"] and passed known_sources = set(baseline.get("sources", {})) source_errors: list[str] = [] for model_key, model in sorted(catalog["models"].items()): if model.get("inventory") not in baseline.get("inventories", {}): continue for field in ("source", "availability_source", "capability_source", "pricing_source"): source = model.get(field) if source is not None and source not in known_sources: source_errors.append(f"{model_key}.{field}: unknown source {source!r}") report["source_errors"] = source_errors untracked_snapshots = sorted(set(snapshot_map) - set(baseline.get("inventories", {}))) report["untracked_snapshots"] = untracked_snapshots report["passed"] = report["passed"] and not source_errors and not untracked_snapshots return report def _http_bytes( url: str, timeout: float, *, headers: Mapping[str, str] | None = None, accept: str = "application/json", ) -> bytes: if not isinstance(url, str) or not valid_absolute_uri(url): raise ValueError("catalog discovery URL must be an absolute HTTP(S) URL") try: parsed = urllib.parse.urlsplit(url) _ = parsed.port except ValueError as exc: raise ValueError("catalog discovery URL must be an absolute HTTP(S) URL") from exc if ( parsed.scheme.lower() not in {"http", "https"} or not parsed.hostname or parsed.username is not None or parsed.password is not None or parsed.fragment ): raise ValueError("catalog discovery URL must be an absolute HTTP(S) URL") request_headers = { "Accept": accept, "User-Agent": f"codex-mmo/{PACKAGE_VERSION} catalog-discovery", } request_headers.update(dict(headers or {})) request = urllib.request.Request(url, headers=request_headers) opener = urllib.request.build_opener(_SameOriginRedirectHandler()) with opener.open(request, timeout=timeout) as response: return response.read() def _http_json( url: str, timeout: float, *, headers: Mapping[str, str] | None = None, ) -> Any: return strict_json_loads(_http_bytes(url, timeout, headers=headers).decode("utf-8")) class _SameOriginRedirectHandler(urllib.request.HTTPRedirectHandler): """Permit discovery redirects without forwarding credentials off-origin.""" @staticmethod def _origin(url: str) -> tuple[str, str, int | None]: parsed = urllib.parse.urlsplit(url) port = parsed.port if port is None: port = 443 if parsed.scheme.lower() == "https" else 80 return parsed.scheme.lower(), (parsed.hostname or "").lower(), port def redirect_request( self, req: urllib.request.Request, fp: Any, code: int, msg: str, headers: Any, newurl: str, ) -> urllib.request.Request | None: if self._origin(req.full_url) != self._origin(newurl): with contextlib.suppress(Exception): fp.close() raise urllib.error.URLError( f"cross-origin discovery redirect rejected ({code}): {newurl}" ) return super().redirect_request(req, fp, code, msg, headers, newurl) def _model_rows(document: Any) -> list[dict[str, Any]]: if isinstance(document, list): rows = document elif isinstance(document, Mapping): rows = document.get("data") or document.get("models") or [] else: rows = [] return [dict(item) for item in rows if isinstance(item, Mapping)] def _model_slug(item: Mapping[str, Any]) -> str | None: for key in ("id", "slug", "model", "name"): value = item.get(key) if isinstance(value, str) and value: return value return None def discover_opencode_go(*, url: str | None = None, timeout: float = 10.0) -> dict[str, Any]: target = url or os.environ.get("MMO_OPENCODE_MODELS_URL") or _inventory_endpoint("opencode-go") started = utc_now() try: document = _http_json(target, timeout) rows = _model_rows(document) ids = sorted({slug for item in rows if (slug := _model_slug(item))}) return { "inventory": "opencode-go", "url": target, "observed_at": started, "passed": bool(ids), "models": ids, "count": len(ids), "raw_metadata": rows, } except (OSError, ValueError, urllib.error.URLError, json.JSONDecodeError) as exc: return { "inventory": "opencode-go", "url": target, "observed_at": started, "passed": False, "models": [], "count": 0, "error": f"{type(exc).__name__}: {exc}", } def discover_opencode_zen(*, url: str | None = None, timeout: float = 10.0) -> dict[str, Any]: """Discover the public OpenCode Zen availability listing.""" target = ( url or os.environ.get("MMO_OPENCODE_ZEN_MODELS_URL") or _inventory_endpoint("opencode-zen") ) started = utc_now() try: document = _http_json(target, timeout) rows = _model_rows(document) ids = sorted({slug for item in rows if (slug := _model_slug(item))}) return { "inventory": "opencode-zen", "url": target, "observed_at": started, "passed": bool(ids), "models": ids, "count": len(ids), "raw_metadata": rows, } except (OSError, ValueError, urllib.error.URLError, json.JSONDecodeError) as exc: return { "inventory": "opencode-zen", "url": target, "observed_at": started, "passed": False, "models": [], "count": 0, "error": f"{type(exc).__name__}: {exc}", } def _catalog_credentials() -> dict[str, str]: values = parse_env_file(config_root() / "credentials.env") values.update({key: value for key, value in os.environ.items() if value}) return values def discover_openrouter( *, url: str | None = None, api_key: str | None = None, timeout: float = 10.0, ) -> dict[str, Any]: """Discover OpenRouter's public model inventory, authenticating when available.""" official_target = _inventory_endpoint("openrouter") target = url or os.environ.get("MMO_OPENROUTER_MODELS_URL") or official_target # A configured credential is sent implicitly only to the reviewed official # endpoint. Callers that deliberately target another URL must explicitly # provide its credential, preventing URL overrides from exfiltrating the # user's OpenRouter key. configured_token = ( _catalog_credentials().get("OPENROUTER_API_KEY") if api_key is None and target == official_target else None ) token = ( api_key if api_key is not None else (configured_token if target == official_target else None) ) headers = {"Authorization": f"Bearer {token}"} if token else None started = utc_now() try: document = _http_json(target, timeout, headers=headers) if not isinstance(document, Mapping): raise ValueError("OpenRouter model listing must be an object") rows = _model_rows(document) if "total_count" not in document or "links" not in document: raise ValueError("OpenRouter model listing lacks required pagination metadata") total_count = document["total_count"] if ( not isinstance(total_count, int) or isinstance(total_count, bool) or total_count != len(rows) ): raise ValueError( "OpenRouter model listing is paginated or incomplete: " f"total_count={total_count!r}, rows={len(rows)}" ) links = document["links"] if not isinstance(links, Mapping) or "next" not in links: raise ValueError("OpenRouter model listing has invalid pagination links") if links["next"] not in (None, ""): raise ValueError("OpenRouter model listing has an unconsumed next page") ids = sorted({slug for item in rows if (slug := _model_slug(item))}) return { "inventory": "openrouter", "url": target, "observed_at": started, "passed": bool(ids), "authenticated_request": bool(token), "models": ids, "count": len(ids), "raw_metadata": rows, } except (OSError, ValueError, urllib.error.URLError, json.JSONDecodeError) as exc: return { "inventory": "openrouter", "url": target, "observed_at": started, "passed": False, "authenticated_request": bool(token), "models": [], "count": 0, "error": f"{type(exc).__name__}: {exc}", } def discover_zai( inventory: str, *, url: str | None = None, api_key: str | None = None, timeout: float = 10.0, ) -> dict[str, Any]: """Discover model IDs advertised by one Z.AI OpenAI-compatible endpoint. Z.AI's complete catalog also includes media and hosted-agent services that are not necessarily returned by ``/models``. Those remain represented by the versioned documentation inventory. Live discovery is used to detect newly advertised coding/chat IDs without guessing capabilities for unknown services. """ if inventory not in {"zai-api", "zai-coding-plan"}: raise ValueError("inventory must be zai-api or zai-coding-plan") if inventory == "zai-api": official_target = _inventory_endpoint("zai-api") target = url or os.environ.get("MMO_ZAI_MODELS_URL") or official_target credential_names = ["ZAI_API_KEY"] else: official_target = _inventory_endpoint("zai-coding-plan") target = url or os.environ.get("MMO_ZAI_CODING_MODELS_URL") or official_target credential_names = ["ZAI_CODING_API_KEY"] values = _catalog_credentials() configured_token = next( (values.get(name) for name in credential_names if values.get(name)), None ) # Never send a configured Z.AI credential to an operator-overridden URL. # Custom endpoints require an explicit credential, matching the discovery # boundary used for OpenRouter above. An explicit blank disables implicit # authentication even for the official endpoint. token = ( api_key if api_key is not None else (configured_token if target == official_target else None) ) started = utc_now() if not token: return { "inventory": inventory, "url": target, "observed_at": started, "passed": False, "skipped": True, "authenticated_request": False, "models": [], "count": 0, "error": "missing credential: " + "/".join(credential_names), } try: document = _http_json( target, timeout, headers={"Authorization": f"Bearer {token}"}, ) rows = _model_rows(document) ids = sorted({slug for item in rows if (slug := _model_slug(item))}) return { "inventory": inventory, "url": target, "observed_at": started, "passed": bool(ids), "skipped": False, "authenticated_request": True, "models": ids, "count": len(ids), "raw_metadata": rows, } except (OSError, ValueError, urllib.error.URLError, json.JSONDecodeError) as exc: return { "inventory": inventory, "url": target, "observed_at": started, "passed": False, "skipped": False, "authenticated_request": True, "models": [], "count": 0, "error": f"{type(exc).__name__}: {exc}", } def _load_json_output(result: subprocess.CompletedProcess[str]) -> Any | None: text = result.stdout.strip() if not text: return None with contextlib.suppress(json.JSONDecodeError, ValueError): return strict_json_loads(text) # Some Codex versions print a short informational line before the JSON. for offset, char in enumerate(text): if char not in "[{": continue with contextlib.suppress(json.JSONDecodeError, ValueError): return strict_json_loads(text[offset:]) return None def _run_codex_models(binary: str, home: Path, *, bundled: bool) -> dict[str, Any]: command = [binary, "debug", "models"] if bundled: command.append("--bundled") try: result = subprocess.run( command, env=filtered_environment(extra={"CODEX_HOME": str(home)}), text=True, capture_output=True, timeout=45, check=False, ) except (OSError, subprocess.SubprocessError) as exc: return { "command": command, "passed": False, "models": [], "error": f"{type(exc).__name__}: {exc}", } document = _load_json_output(result) rows = _model_rows(document) return { "command": command, "passed": result.returncode == 0 and bool(rows), "exit_code": result.returncode, "models": rows, "stderr": result.stderr[-4000:], } def _read_codex_cache(home: Path) -> dict[str, Any]: path = home / "models_cache.json" if not path.is_file(): return {"path": str(path), "passed": False, "models": [], "error": "not found"} try: document = read_json(path) rows = _model_rows(document) return { "path": str(path), "passed": bool(rows), "models": rows, "client_version": document.get("client_version") if isinstance(document, Mapping) else None, "fetched_at": document.get("fetched_at") if isinstance(document, Mapping) else None, } except (OSError, ValueError, json.JSONDecodeError) as exc: return { "path": str(path), "passed": False, "models": [], "error": f"{type(exc).__name__}: {exc}", } def discover_codex( *, binary: str = "codex", home: Path | None = None, include_bundled: bool = True, ) -> dict[str, Any]: codex_home = (home or Path(os.environ.get("CODEX_HOME", "~/.codex"))).expanduser().resolve() candidate = Path(binary).expanduser() resolved_binary = shutil.which(binary) or ( str(candidate.resolve()) if candidate.is_file() else None ) sources: dict[str, Any] = {"cache": _read_codex_cache(codex_home)} if resolved_binary: sources["authenticated"] = _run_codex_models(resolved_binary, codex_home, bundled=False) if include_bundled: sources["bundled"] = _run_codex_models(resolved_binary, codex_home, bundled=True) else: sources["authenticated"] = { "passed": False, "models": [], "error": f"Codex binary not found: {binary}", } if include_bundled: sources["bundled"] = { "passed": False, "models": [], "error": f"Codex binary not found: {binary}", } merged: dict[str, dict[str, Any]] = {} availability: dict[str, list[str]] = {} for source_name in ("authenticated", "bundled", "cache"): source = sources.get(source_name, {}) for row in source.get("models", []): slug = _model_slug(row) if not slug: continue merged.setdefault(slug, dict(row)) availability.setdefault(slug, []).append(source_name) return { "inventory": "openai-codex", "observed_at": utc_now(), "codex_home": str(codex_home), "codex_binary": resolved_binary, "passed": bool(merged), "models": sorted(merged), "count": len(merged), "availability_sources": {key: sorted(value) for key, value in sorted(availability.items())}, "metadata": merged, "sources": sources, } def _compare(observed: Sequence[str], expected: Sequence[str]) -> dict[str, Any]: observed_set = set(observed) expected_set = set(expected) return { "observed_count": len(observed_set), "expected_count": len(expected_set), "missing_from_observed": sorted(expected_set - observed_set), "unknown_to_catalog": sorted(observed_set - expected_set), "exact": observed_set == expected_set, } def _snapshot_map() -> dict[str, dict[str, Any]]: return { str(snapshot["inventory"]): snapshot for snapshot in load_inventory_snapshots(install_root() / "config" / "inventory-snapshots") } def _source_bytes( snapshot: Mapping[str, Any], source: str, timeout: float, *, override: str | None = None ) -> tuple[str, bytes]: sources = snapshot.get("sources", {}) if not isinstance(sources, Mapping) or not isinstance(sources.get(source), str): raise ValueError(f"inventory snapshot lacks source {source!r}") url = override or str(sources[source]) accept = "text/plain" if source.endswith("docs-source") else "application/json" return url, _http_bytes(url, timeout, accept=accept) def _build_observed_public_snapshot( inventory: str, expected: Mapping[str, Any], *, timeout: float, endpoint_override: str | None, ) -> dict[str, Any]: """Rebuild a dynamic public inventory with its declared source adapter.""" adapter = expected.get("adapter") observed_at = dt.datetime.now(dt.UTC).strftime("%Y-%m-%dT%H:%M:%SZ") if adapter == "openrouter_models_api": source_url, raw = _source_bytes( expected, "openrouter-models-api", timeout, override=endpoint_override ) zdr_source_url, zdr_raw = _source_bytes(expected, "openrouter-zdr-endpoints", timeout) return build_openrouter_snapshot( strict_json_loads(raw), strict_json_loads(zdr_raw), as_of=str(expected["as_of"]), retrieved_at=observed_at, response_sha256=hashlib.sha256(raw).hexdigest(), zdr_response_sha256=hashlib.sha256(zdr_raw).hexdigest(), source_url=source_url, zdr_source_url=zdr_source_url, endpoint_selections=expected["discovery"]["endpoint_selections"], ) if adapter not in {"opencode_go_join", "opencode_zen_join"}: raise ValueError( f"inventory {inventory!r} adapter {adapter!r} cannot produce a full live fingerprint" ) if adapter == "opencode_go_join": prefix = "opencode-go" builder = build_opencode_go_snapshot else: prefix = "opencode-zen" builder = build_opencode_zen_snapshot listing_url, listing_raw = _source_bytes( expected, f"{prefix}-models", timeout, override=endpoint_override ) models_dev_url, models_dev_raw = _source_bytes(expected, f"models-dev-{prefix}", timeout) docs_source_id = f"{prefix}-docs-source" live_docs_url = ( OPENCODE_GO_SOURCE_IDS[docs_source_id] if adapter == "opencode_go_join" else OPENCODE_ZEN_SOURCE_IDS[docs_source_id] ) # Snapshot captures remain immutable commit URLs. Live verification uses # the provider's current branch so a documentation/protocol change cannot # hide behind the reviewed capture. docs_url, docs_raw = _source_bytes( expected, docs_source_id, timeout, override=live_docs_url, ) return builder( strict_json_loads(listing_raw), strict_json_loads(models_dev_raw), docs_raw.decode("utf-8"), as_of=str(expected["as_of"]), retrieved_at=observed_at, listing_sha256=hashlib.sha256(listing_raw).hexdigest(), models_dev_sha256=hashlib.sha256(models_dev_raw).hexdigest(), docs_sha256=hashlib.sha256(docs_raw).hexdigest(), listing_url=listing_url, models_dev_url=models_dev_url, docs_url=docs_url, ) def _id_only_fingerprint_comparison( observed: Sequence[str], expected_snapshot: Mapping[str, Any] ) -> dict[str, Any]: expected_by_id = { str(record["catalog"]["upstream_id"]): str(record["catalog"]["route"]) for record in expected_snapshot["models"].values() } ids = sorted(set(observed)) membership = _compare(ids, sorted(expected_by_id)) incomplete = [ { "route": expected_by_id[model_id], "upstream_id": model_id, "fields": list(FULL_FINGERPRINT_FIELDS[1:]), } for model_id in sorted(set(ids) & set(expected_by_id)) ] return { **membership, "fingerprint_mismatches": [], "incomplete_evidence": incomplete, "verified_fields": ["upstream_id"] if not membership["unknown_to_catalog"] else [], "exact": False, } def _verify_source_captures(snapshot: Mapping[str, Any], timeout: float) -> dict[str, Any]: captures: list[dict[str, Any]] = [] for capture in snapshot.get("captures", []): source = str(capture["source"]) item: dict[str, Any] = { "source": source, "expected_sha256": capture["response_sha256"], } try: url, raw = _source_bytes(snapshot, source, timeout) observed = hashlib.sha256(raw).hexdigest() item.update( { "url": url, "observed_sha256": observed, "passed": observed == capture["response_sha256"], } ) except (OSError, ValueError, urllib.error.URLError) as exc: item.update({"passed": False, "error": f"{type(exc).__name__}: {exc}"}) captures.append(item) return { "captures": captures, "passed": bool(captures) and all(item["passed"] for item in captures), } def _codex_fingerprint_comparison( discovery: Mapping[str, Any], expected: Mapping[str, Any] ) -> dict[str, Any]: metadata = discovery.get("metadata", {}) if not isinstance(metadata, Mapping): raise ValueError("Codex discovery metadata is missing") records: dict[str, dict[str, Any]] = {} for key, expected_record in expected["models"].items(): slug = str(expected_record["catalog"]["upstream_id"]) row = metadata.get(slug) if not isinstance(row, Mapping): continue records[str(key)] = { "catalog": dict(expected_record["catalog"]), "evidence": { "codex_runtime": codex_runtime_evidence(row), "verified_fingerprint_fields": list(FULL_FINGERPRINT_FIELDS), }, } observed = build_inventory_snapshot( inventory="openai-codex", adapter="codex_installed_models_join", fingerprint_fields=FULL_FINGERPRINT_FIELDS, as_of=str(expected["as_of"]), dynamic=False, sources=expected["sources"], discovery=expected["discovery"], captures=[], models=records, ) return compare_inventory_fingerprints(expected, observed) def verify_catalog( *, remote: bool = False, include_codex: bool = False, opencode_url: str | None = None, opencode_zen_url: str | None = None, openrouter_url: str | None = None, zai_coding_url: str | None = None, codex_binary: str = "codex", codex_home: Path | None = None, timeout: float = 10.0, ) -> dict[str, Any]: baseline = inventory_baseline() local = local_inventory_report() result: dict[str, Any] = { "checked_at": utc_now(), "local": local, "remote": {}, "passed": bool(local["passed"]), } inventories = baseline["inventories"] snapshots = _snapshot_map() if remote: public_overrides = { "opencode-go": opencode_url, "opencode-zen": opencode_zen_url, "openrouter": openrouter_url, } for inventory_id, endpoint_override in public_overrides.items(): expected_snapshot = snapshots[inventory_id] report: dict[str, Any] = { "inventory": inventory_id, "adapter": expected_snapshot["adapter"], "observed_at": utc_now(), "fingerprint_fields": list(expected_snapshot["fingerprint_fields"]), } try: observed_snapshot = _build_observed_public_snapshot( inventory_id, expected_snapshot, timeout=timeout, endpoint_override=endpoint_override, ) comparison = compare_inventory_fingerprints(expected_snapshot, observed_snapshot) report.update( { "url": observed_snapshot["discovery"].get("endpoint"), "models": sorted( str(item["catalog"]["upstream_id"]) for item in observed_snapshot["models"].values() ), "count": len(observed_snapshot["models"]), "comparison": comparison, "full_fingerprint_verified": bool(comparison["exact"]), "passed": bool(comparison["exact"]), } ) except (OSError, ValueError, urllib.error.URLError, json.JSONDecodeError) as exc: report.update( { "passed": False, "full_fingerprint_verified": False, "error": f"{type(exc).__name__}: {exc}", } ) result["remote"][inventory_id] = report result["passed"] = result["passed"] and bool(report["passed"]) # The bundled portfolio uses the Coding Plan, not the unrelated Z.AI # general API product. Its authenticated model IDs establish live # availability while exact official Markdown captures establish the # reviewed capability fingerprint. inventory_id = "zai-coding-plan" zai = discover_zai(inventory_id, url=zai_coding_url, timeout=timeout) expected_ids = sorted( str(record["catalog"]["upstream_id"]) for record in snapshots[inventory_id]["models"].values() ) membership = _compare(zai.get("models", []), expected_ids) source_verification = _verify_source_captures(snapshots[inventory_id], timeout) full_verified = bool( zai.get("passed") and membership["exact"] and source_verification["passed"] ) zai.update( { "comparison": membership, "source_capture_verification": source_verification, "fingerprint_fields": list(FULL_FINGERPRINT_FIELDS), "verified_fields": list(FULL_FINGERPRINT_FIELDS) if full_verified else [], "full_fingerprint_verified": full_verified, } ) result["remote"][inventory_id] = zai result["passed"] = result["passed"] and full_verified if include_codex: codex = discover_codex(binary=codex_binary, home=codex_home) codex_inventory = inventories["openai-codex"] observed = [item for item in codex.get("models", []) if isinstance(item, str)] ignored_prefixes = tuple(codex_inventory.get("ignored_model_prefixes", [])) deprecated = set(codex_inventory.get("known_deprecated_models", [])) codex["ignored_internal_models"] = sorted( item for item in observed if ignored_prefixes and item.startswith(ignored_prefixes) ) codex["known_deprecated_models_observed"] = sorted(set(observed) & deprecated) comparable = [ item for item in observed if item not in deprecated and not (ignored_prefixes and item.startswith(ignored_prefixes)) ] try: codex["comparison"] = _codex_fingerprint_comparison(codex, snapshots["openai-codex"]) except ValueError as exc: codex["comparison"] = _id_only_fingerprint_comparison( comparable, snapshots["openai-codex"] ) codex["fingerprint_error"] = f"{type(exc).__name__}: {exc}" codex["full_fingerprint_verified"] = bool(codex["comparison"]["exact"]) codex["runtime_source_ok"] = any( bool(codex.get("sources", {}).get(source, {}).get("passed")) for source in ("authenticated", "bundled") ) result["remote"]["openai-codex"] = codex result["passed"] = ( result["passed"] and bool(codex["passed"]) and bool(codex["runtime_source_ok"]) and bool(codex["full_fingerprint_verified"]) ) return result def _reasoning_levels(row: Mapping[str, Any]) -> list[str]: raw = row.get("supported_reasoning_levels") or row.get("supportedReasoningLevels") or [] if not isinstance(raw, list): return [] values: list[str] = [] for item in raw: effort = item.get("effort") if isinstance(item, Mapping) else item if isinstance(effort, str) and effort in CODEX_REASONING_VALUES and effort not in values: values.append(effort) return values def _metadata_boolean(value: Any, *, default: bool) -> bool: if isinstance(value, bool): return value if isinstance(value, int) and value in {0, 1}: return bool(value) if isinstance(value, str) and value.casefold() in {"true", "false"}: return value.casefold() == "true" return default def build_codex_discovery_overlay(discovery: Mapping[str, Any]) -> dict[str, Any]: catalog = validated_global_catalog() known_ids = { str(model["upstream_id"]) for model in catalog["models"].values() if model.get("inventory") == "openai-codex" } codex_inventory = inventory_baseline().get("inventories", {}).get("openai-codex", {}) ignored_prefixes = tuple(codex_inventory.get("ignored_model_prefixes", [])) deprecated = set(codex_inventory.get("known_deprecated_models", [])) models: dict[str, Any] = {} seen_slugs: set[str] = set() metadata = discovery.get("metadata", {}) if not isinstance(metadata, Mapping): metadata = {} for slug in discovery.get("models", []): if not isinstance(slug, str) or not slug: continue if ( slug in seen_slugs or slug in known_ids or slug in deprecated or (ignored_prefixes and slug.startswith(ignored_prefixes)) ): continue seen_slugs.add(slug) row = metadata.get(slug, {}) if not isinstance(row, Mapping): row = {} safe = route_catalog_key("codex_chatgpt_builtin", slug, set(models)) raw_context = row.get("context_window") or row.get("max_context_window") try: if isinstance(raw_context, bool) or not isinstance(raw_context, (int, str)): raise ValueError context = int(raw_context) except (TypeError, ValueError, OverflowError): continue if not 1024 <= context <= 20_000_000: continue levels = _reasoning_levels(row) if not levels: continue modalities = row.get("input_modalities") or row.get("inputModalities") if not isinstance(modalities, list) or not all( isinstance(item, str) for item in modalities ): continue if ( not modalities or len(modalities) != len(set(modalities)) or set(modalities) - {"text", "image", "audio", "video", "file"} ): continue models[safe] = { "maker": "openai", "route": "codex_chatgpt_builtin", "upstream_id": slug, "display_name": str(row.get("display_name") or row.get("displayName") or slug), "description": "Discovered from the local authenticated Codex model catalog", "kind": "vision_chat" if "image" in modalities else "chat", # Discovery alone never grants execution authority. An operator # must review the generated fragment before opting a model into an # agent binding. "agent_compatible": False, "context_window": context, "reasoning_levels": levels, "default_reasoning": "high" if "high" in levels else levels[-1], "modalities": modalities, "output_modalities": ["text"], "tool_calling": False, "parallel_tool_calls": False, "supports_reasoning_summaries": _metadata_boolean( row.get("supports_reasoning_summaries"), default=False ), "structured_output": False, "availability": "account-discovered", "capability_confidence": "codex-runtime", "source": "codex-debug-models", "inventory": "openai-codex-discovered", "resource_group": "chatgpt_subscription", } return {"schema_version": MMO_SCHEMA_VERSION, "models": models} def refresh_discovery( *, remote: bool = True, include_codex: bool = True, install_codex_overlay: bool = False, opencode_url: str | None = None, opencode_zen_url: str | None = None, openrouter_url: str | None = None, zai_coding_url: str | None = None, codex_binary: str = "codex", codex_home: Path | None = None, timeout: float = 10.0, ) -> dict[str, Any]: report = verify_catalog( remote=remote, include_codex=include_codex, opencode_url=opencode_url, opencode_zen_url=opencode_zen_url, openrouter_url=openrouter_url, zai_coding_url=zai_coding_url, codex_binary=codex_binary, codex_home=codex_home, timeout=timeout, ) output = config_root() / "catalog-discovery.json" atomic_write_json(output, report, 0o600) overlay_path = None overlay_models = 0 if install_codex_overlay and include_codex: discovery = report["remote"].get("openai-codex", {}) if not discovery.get("passed") or not discovery.get("runtime_source_ok"): raise RuntimeError("Codex discovery did not produce a live model catalog") overlay = build_codex_discovery_overlay(discovery) overlay_path = user_catalog_root() / "90-codex-discovered.toml" overlay_models = len(overlay.get("models", {})) header = ( "# Generated by codex-mmo catalog refresh --install-codex-overlay.\n" "# Remove this file to return to the bundled Codex model baseline.\n\n" ) atomic_write_text(overlay_path, header + toml_dumps(overlay), 0o600) return { "report_path": str(output), "overlay_path": str(overlay_path) if overlay_path else None, "overlay_models": overlay_models, "report": report, }