Files
aiturk-hermes-ide/scripts/generate-codex-link-control.py
T

71 lines
2.8 KiB
Python

"""Generate the IDE's narrow control contract from the reviewed gateway schema.
Usage: python generate-codex-link-control.py PATH_TO_SCHEMA [--check]
No runtime/namespace/archive messages are included in this surface.
"""
import hashlib
import json
from pathlib import Path
import sys
root = Path(__file__).resolve().parents[1]
schema = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
definitions = schema["$defs"]
selected = {}
def collect(name):
if name in selected:
return
selected[name] = definitions[name]
def visit(value):
if isinstance(value, dict):
if "$ref" in value:
collect(value["$ref"].removeprefix("#/$defs/"))
for child in value.values():
visit(child)
elif isinstance(value, list):
for child in value:
visit(child)
visit(selected[name])
for name in ("control_request", "control_response"):
collect(name)
def typename(name):
return "CodexLink" + "".join(part.title() for part in name.split("_"))
def ts(rule):
if "$ref" in rule:
return typename(rule["$ref"].split("/")[-1])
if "const" in rule:
return json.dumps(rule["const"], ensure_ascii=False)
if "enum" in rule:
return " | ".join(json.dumps(x, ensure_ascii=False) for x in rule["enum"])
for key in ("oneOf", "anyOf"):
if key in rule:
return "(" + " | ".join(ts(x) for x in rule[key]) + ")"
kind = rule["type"]
if kind == "object":
return "{ " + "; ".join(json.dumps(k) + ("" if k in rule["required"] else "?") + ": " + ts(v) for k, v in rule["properties"].items()) + " }"
if kind == "array":
return "Array<" + ts(rule["items"]) + ">"
return {"integer": "number", "boolean": "boolean", "string": "string", "null": "null"}[kind]
subset = {"$defs": {k: selected[k] for k in sorted(selected)}}
canonical = json.dumps(subset, ensure_ascii=False, sort_keys=True, separators=(",", ":")).encode()
digest = "sha256:" + hashlib.sha256(canonical).hexdigest()
types = "// Generated by scripts/generate-codex-link-control.py. Do not edit.\n"
types += "export const CODEX_LINK_CONTROL_SCHEMA_HASH = " + json.dumps(digest) + "\n"
types += "\n".join("export type " + typename(k) + " = " + ts(v) for k, v in sorted(selected.items())) + "\n"
outputs = {
root / "apps/desktop/codex-link-control.schema.json": json.dumps(subset, ensure_ascii=False, indent=2) + "\n",
root / "apps/desktop/codex-link-control.types.ts": types,
}
for path, content in outputs.items():
if "--check" in sys.argv:
if not path.exists() or path.read_text(encoding="utf-8") != content:
raise SystemExit("Generated control contract is stale: " + str(path))
else:
path.write_text(content, encoding="utf-8", newline="\n")
print(digest)