Files
codex-mmo/libexec/mmo_catalog.py
T

1178 lines
44 KiB
Python
Raw Normal View History

2026-08-24 08:11:59 -07:00
#!/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,
}