Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0726e-5232-73f2-aaca-2c05ceb62efb
67 lines
2.8 KiB
Python
67 lines
2.8 KiB
Python
"""Build a standalone rein-aharness runtime for the fixed bwrap mount path.
|
|
|
|
Only package installation occurs here. No credentials or model calls are used.
|
|
Run with the sand-boxer Python environment; uv must be available on PATH.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
from sandboxer.extensions.runtime import RUNTIME_MOUNT, runtime_digest
|
|
|
|
|
|
def checked(command: list[str]) -> str:
|
|
result = subprocess.run(command, capture_output=True, text=True, timeout=300)
|
|
if result.returncode:
|
|
raise RuntimeError(f"runtime build command failed: {Path(command[0]).name}")
|
|
return result.stdout.strip()
|
|
|
|
|
|
def build(output: Path, rein_source: Path, llm_source: Path) -> dict:
|
|
revisions = {}
|
|
for name, source in (("rein-aharness", rein_source), ("llm-connect", llm_source)):
|
|
if checked(["git", "-C", str(source), "status", "--porcelain"]):
|
|
raise ValueError(f"{name} source must be committed before building")
|
|
revisions[name] = checked(["git", "-C", str(source), "rev-parse", "HEAD"])
|
|
output.mkdir(parents=True, exist_ok=False)
|
|
checked(["/usr/bin/python3", "-m", "venv", "--copies", "--without-pip", str(output)])
|
|
checked(["uv", "pip", "install", "--python", str(output / "bin/python3"),
|
|
str(rein_source), str(llm_source)])
|
|
# Console entrypoints must reference the in-sandbox mount, not the build host.
|
|
for path in (output / "bin").iterdir():
|
|
if not path.is_file() or path.is_symlink():
|
|
continue
|
|
with path.open("rb") as stream:
|
|
first_line = stream.readline(4096)
|
|
if first_line.startswith(f"#!{output}/bin/python".encode()):
|
|
body = path.read_bytes().partition(b"\n")[2]
|
|
path.write_bytes(f"#!{RUNTIME_MOUNT}/bin/python3\n".encode() + body)
|
|
metadata = json.loads(checked([
|
|
str(output / "bin/python3"), "-c",
|
|
"import importlib.metadata,json,platform; "
|
|
"print(json.dumps({'python':platform.python_version(),'packages':"
|
|
"{d.metadata['Name']:d.version for d in importlib.metadata.distributions()}}))",
|
|
]))
|
|
metadata["source_revisions"] = revisions
|
|
(output / "build-info.json").write_text(json.dumps(metadata, indent=2) + "\n")
|
|
return {"runtime": {"path": str(output), "sha256": runtime_digest(output)},
|
|
"build": metadata}
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--output", type=Path, required=True)
|
|
parser.add_argument("--rein-source", type=Path, required=True)
|
|
parser.add_argument("--llm-source", type=Path, required=True)
|
|
args = parser.parse_args()
|
|
result = build(args.output.resolve(), args.rein_source.resolve(), args.llm_source.resolve())
|
|
print(json.dumps(result, indent=2))
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|