#!/usr/bin/env python3 """Private Unix-socket bridge for owner-approved CodexPi master sessions.""" from __future__ import annotations import argparse import hmac import json import os import socket import subprocess from pathlib import Path def receive(connection: socket.socket, limit: int = 100_000) -> dict: chunks, size = [], 0 while True: block = connection.recv(8192) if not block: break size += len(block) if size > limit: raise ValueError("request too large") chunks.append(block) if b"\n" in block: break return json.loads(b"".join(chunks).split(b"\n", 1)[0]) def run_agent(codex: str, prompt: str, privileged: bool) -> tuple[bool, int, str]: rules = ( "Tu es l’agent maître CodexPi sur l’hôte réel. Vérifie la cible avant toute écriture, protège les secrets, " "utilise des commandes structurées, évite toute action destructive non explicitement demandée et rends compte des vérifications. " "Les privilèges disponibles proviennent uniquement de l’identité de ce service et de la politique sudo de l’hôte." ) if privileged: rules += " Cette demande a reçu la confirmation privilégiée du propriétaire." command = [codex, "--dangerously-bypass-approvals-and-sandbox", "exec", "--json", "--skip-git-repo-check", rules + "\n\nDEMANDE DU PROPRIÉTAIRE\n" + prompt] process = subprocess.run(command, cwd="/", text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, timeout=3600, check=False) answers = [] for line in process.stdout.splitlines(): try: event = json.loads(line) except ValueError: continue item = event.get("item") or {} text = item.get("text") if item.get("type") in {"agent_message", "assistant_message"} else None if text: answers.append(str(text)) answer = answers[-1] if answers else "L’agent maître n’a produit aucun compte rendu exploitable." return process.returncode == 0, process.returncode, answer def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--socket", required=True) parser.add_argument("--token-file", required=True) parser.add_argument("--codex", default="codex") args = parser.parse_args() socket_path, token_path = Path(args.socket), Path(args.token_file) token = token_path.read_text(encoding="utf-8").strip() if len(token) < 32 or token_path.stat().st_mode & 0o077: raise SystemExit("unsafe host-agent token") socket_path.parent.mkdir(parents=True, exist_ok=True) if socket_path.exists(): socket_path.unlink() with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as server: server.bind(str(socket_path)) os.chmod(socket_path, 0o660) server.listen(4) while True: connection, _ = server.accept() with connection: try: request = receive(connection) if not hmac.compare_digest(str(request.get("token") or ""), token): raise PermissionError("unauthorized") ok, code, answer = run_agent(args.codex, str(request.get("prompt") or ""), bool(request.get("privileged"))) response = {"ok": ok, "exit_code": code, "answer": answer} except Exception: response = {"ok": False, "exit_code": 1, "answer": "Le canal hôte a refusé ou interrompu la demande."} connection.sendall(json.dumps(response, ensure_ascii=False).encode() + b"\n") return 0 if __name__ == "__main__": raise SystemExit(main())