← Files Codex ReplayARCHIVED FILE
scripts/metrics/replay_metrics_common.py
8.95 KB · Oct 4, 2026 · 12:19 UTC
"""Shared state-reading and trusted-sidecar primitives for Replay metrics scripts."""
from __future__ import annotations
import argparse
import datetime as dt
import json
import math
import os
import re
import sys
import time
from collections.abc import Mapping, Sequence
from pathlib import Path
from typing import Any, BinaryIO
METRICS_OUTPUT_ENV = "CODEX_PLUGIN_METRICS_OUTPUT"
DEFAULT_RUN_ROOT = Path.home() / ".cache" / "codex-replay" / "runs"
STATE_NAME = "controller-state.json"
MAX_MODELS = 8
MODEL_SLOTS = ("one", "two", "three", "four", "five", "six", "seven", "eight")
TERMINAL_STATUSES = frozenset({"completed", "failed", "cancelled"})
MAX_OUTPUT_BYTES = 64 * 1024
MAX_STATE_BYTES = 512 * 1024
# Match the server budget for an accepted HTTP request plus lifecycle metadata.
MAX_ATTEMPT_BYTES = 2 * 1024 * 1024 + MAX_STATE_BYTES
DEFAULT_PRE_START_TIMEOUT_SECONDS = 10 * 60
def model_family(model: object, families: Sequence[str]) -> str:
if not isinstance(model, str):
return "other"
lowered = model.lower()
for family in families:
if re.search(rf"(?:^|[^a-z]){re.escape(family)}(?:[^a-z]|$)", lowered):
return family
return "other"
def timestamp(value: object) -> dt.datetime | None:
if not isinstance(value, str):
return None
try:
parsed = dt.datetime.fromisoformat(value)
except ValueError:
return None
return parsed if parsed.tzinfo is not None else None
def measurement(name: str, value: int | float, dimensions: Mapping[str, str]) -> dict[str, object]:
row: dict[str, object] = {"name": name, "value": value}
if dimensions:
row["dimensions"] = dict(dimensions)
return row
def encode_measurements(rows: Sequence[Mapping[str, object]]) -> bytes:
return (
json.dumps(
{"version": 1, "measurements": rows},
ensure_ascii=True,
separators=(",", ":"),
allow_nan=False,
)
+ "\n"
).encode("utf-8")
def nonnegative_seconds(raw: str) -> float:
try:
value = float(raw)
except ValueError as error:
raise argparse.ArgumentTypeError("must be a finite nonnegative number") from error
if not math.isfinite(value) or value < 0:
raise argparse.ArgumentTypeError("must be a finite nonnegative number")
return value
def observed_json(path: Path, *, maximum: int | None = MAX_STATE_BYTES) -> Mapping[str, Any] | None:
"""Absence is unresolved; malformed or inaccessible evidence is unreadable."""
try:
with path.open("rb") as stream:
raw = stream.read() if maximum is None else stream.read(maximum + 1)
except FileNotFoundError:
return None
if maximum is not None and len(raw) > maximum:
raise ValueError("Replay state exceeds its size limit")
value = json.loads(raw)
if not isinstance(value, dict):
raise ValueError("Replay state must be an object")
return value
def read_attempt(path: Path, session: str) -> Mapping[str, Any]:
attempt = observed_json(path, maximum=MAX_ATTEMPT_BYTES)
if (
attempt is None
or attempt.get("controller_session_id") != session
or attempt.get("version") != 1
):
raise ValueError("Invalid attempt identity")
return attempt
def read_attempt_if_present(path: Path, session: str) -> Mapping[str, Any] | None:
attempt = observed_json(path, maximum=MAX_ATTEMPT_BYTES)
if attempt is None:
return None
if attempt.get("controller_session_id") != session or attempt.get("version") != 1:
raise ValueError("Invalid attempt identity")
return attempt
def preserve_payload(path: Path, payload: bytes) -> None:
try:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(payload)
except OSError as error:
print(f"Unable to preserve local Codex Replay metrics: {error.strerror}.", file=sys.stderr)
def arguments(argv: Sequence[str] | None = None, *, launch: bool = False) -> argparse.Namespace:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--controller-session-id", required=not launch)
parser.add_argument("--codex-cli-path")
parser.add_argument("--run-root", type=Path, default=None)
parser.add_argument("--run-timeout-seconds", type=nonnegative_seconds, default=3600)
parser.add_argument(
"--pre-start-timeout-seconds",
type=nonnegative_seconds,
default=DEFAULT_PRE_START_TIMEOUT_SECONDS,
)
parser.add_argument("--poll-interval-seconds", type=nonnegative_seconds, default=1)
return parser.parse_args(argv)
def approved_models(attempt: Mapping[str, Any]) -> list[str]:
entries = attempt.get("models", [])
if not isinstance(entries, list) or len(entries) > MAX_MODELS:
raise ValueError("Invalid approved model list")
selected: list[str] = []
for entry in entries:
if (
not isinstance(entry, dict)
or not isinstance(entry.get("model"), str)
or not entry["model"]
or entry["model"] in selected
):
raise ValueError("Invalid approved model")
selected.append(entry["model"])
return selected
def start_time(attempt: Mapping[str, Any], selected: Sequence[str]) -> dt.datetime | None:
if attempt.get("start_requested") is not True:
return None
started_at = timestamp(attempt.get("start_requested_at"))
if started_at is None or not selected:
raise ValueError("Invalid persisted run start")
return started_at
def run_root(arguments: argparse.Namespace) -> Path:
return (
Path(arguments.run_root or os.environ.get("CODEX_REPLAY_RUN_ROOT", DEFAULT_RUN_ROOT))
.expanduser()
.resolve()
)
def require_session(session: str) -> None:
if re.fullmatch(r"[a-f0-9]{32}", session) is None:
raise ValueError("Invalid Codex Replay controller session ID")
def observer_started(stage: str, session: str) -> None:
print(
json.dumps({"observer_started": True, "stage": stage, "controller_session_id": session}),
flush=True,
)
def analytics_available() -> bool:
if os.environ.get(METRICS_OUTPUT_ENV):
return True
print(json.dumps({"observer_started": False, "reason": "analytics_unavailable"}), flush=True)
return False
def open_sidecar() -> BinaryIO | None:
"""Pin the host-owned inode before waiting; never create or follow a link."""
output = os.environ.get(METRICS_OUTPUT_ENV)
return os.fdopen(os.open(output, os.O_WRONLY | os.O_NOFOLLOW), "wb") if output else None
def write_sidecar(destination: BinaryIO, payload: bytes) -> None:
if len(payload) > MAX_OUTPUT_BYTES:
raise ValueError("Replay measurements exceed the sidecar limit")
destination.truncate()
destination.write(payload)
def persisted_pid(attempt: Mapping[str, Any], previous: int | None) -> int | None:
pid = attempt.get("controller_pid")
return pid if isinstance(pid, int) and not isinstance(pid, bool) and pid > 0 else previous
def controller_dead(
root: Path, session: str, pid: int | None, *, stopped: bool = False
) -> tuple[bool, int | None]:
# A durable shutdown receipt is authoritative even before the PID is reaped
# or after that PID has been reused by another process.
if stopped:
return True, pid
# Missing runtime metadata alone is not evidence that the supervisor died.
runtime = observed_json(root / "controller-server.json")
if runtime is not None and runtime.get("controller_session_id") == session:
candidate = runtime.get("pid")
if isinstance(candidate, int) and not isinstance(candidate, bool) and candidate > 0:
pid = candidate
if pid is not None:
try:
os.kill(pid, 0)
except ProcessLookupError:
return True, pid
except PermissionError:
pass
return False, pid
def model_state(entry: Mapping[str, Any], run_root: Path, session: str) -> Mapping[str, Any] | None:
run_id = entry["run_id"]
if (
not isinstance(run_id, str)
or re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9_.-]{0,127}", run_id) is None
):
raise ValueError("Invalid run ID")
directory = run_root / run_id
if directory.resolve().parent != run_root or entry.get("run_directory") != str(directory):
raise ValueError("Invalid run directory")
state = observed_json(directory / STATE_NAME)
if state is not None and (
state.get("controller_session_id") != session or state.get("model") != entry["model"]
):
raise ValueError("Invalid run owner")
return state
def observation_deadline(started_at: dt.datetime, timeout_seconds: float) -> float:
elapsed = max(0, (dt.datetime.now(dt.timezone.utc) - started_at).total_seconds())
return time.monotonic() + timeout_seconds - elapsed
def pause(poll_interval: float, deadline: float | None = None) -> None:
delay = poll_interval
if deadline is not None:
delay = min(delay, max(0, deadline - time.monotonic()))
time.sleep(max(0.01, delay))
SHA-256: 9a3e62438ee30485c8163d37fa2e6876842a369b1c5bd9ee42ac11e18ea0f9c8