#!/usr/bin/env python3 """Direct BigHelp execution provider. This is the first-class alternative to meshd. Run it anywhere that has Docker and git; SignalMesh can bind its stable `bighelp_lab.*` coordinates directly to this worker with SIGNALMESH_BIGHELP_WORKER_URL. The worker keeps the existing Docker-only BigHelp executor as the implementation engine, but exposes it as an authenticated HTTP capability instead of requiring an edge daemon/harness transport. """ from __future__ import annotations import hmac import json import os import subprocess import sys from pathlib import Path from fastapi import FastAPI, Header, HTTPException from pydantic import BaseModel from fastapi.responses import JSONResponse ROOT = Path(__file__).resolve().parents[1] EXECUTOR = Path(os.environ.get( "SIGNALMESH_BIGHELP_EXECUTOR", str(ROOT / "edge_harnesses" / "bighelp-lab" / "bighelp_lab.py"), )).resolve() TOKEN = os.environ.get("SIGNALMESH_BIGHELP_WORKER_TOKEN", "").strip() ALLOW_INSECURE = os.environ.get("SIGNALMESH_BIGHELP_WORKER_ALLOW_INSECURE", "0") == "1" OPS = { "prepare", "install", "start", "status", "checks", "read_file", "file_pair", "apply_patch", "diff", "reset", "stop", } app = FastAPI(title="SignalMesh BigHelp Runtime Worker", version="1") class Call(BaseModel): payload_b64: str def _auth(value: str | None) -> None: if not TOKEN: if ALLOW_INSECURE: return raise HTTPException(503, "worker token is not configured") if not value or not hmac.compare_digest(value, TOKEN): raise HTTPException(401, "invalid BigHelp worker key") def _timeout(op: str) -> int: return 780 if op in {"install", "checks"} else 360 if op in {"prepare", "start", "apply_patch"} else 120 @app.get("/health", include_in_schema=False) def health(): return { "ok": EXECUTOR.is_file(), "provider": "bighelp.direct_worker", "executor": EXECUTOR.name, "auth": "configured" if TOKEN else "insecure" if ALLOW_INSECURE else "missing", "ops": sorted(OPS), } @app.post("/api/bighelp/{op}") def call(op: str, body: Call, x_bighelp_worker_key: str | None = Header(default=None)): _auth(x_bighelp_worker_key) if op not in OPS: raise HTTPException(404, "unknown BigHelp operation") if not EXECUTOR.is_file(): raise HTTPException(503, f"BigHelp executor missing: {EXECUTOR}") try: proc = subprocess.run( [sys.executable, str(EXECUTOR), op, body.payload_b64], cwd=str(ROOT), text=True, capture_output=True, timeout=_timeout(op), shell=False, ) except subprocess.TimeoutExpired: return JSONResponse( content={"ok": False, "error": "BigHelp operation timed out", "op": op}, status_code=504, ) lines = [line for line in proc.stdout.splitlines() if line.strip()] try: data = json.loads(lines[-1]) if lines else {} except Exception: data = { "ok": False, "error": "BigHelp executor returned non-JSON output", "stdout": proc.stdout[-12000:], "stderr": proc.stderr[-12000:], } if not isinstance(data, dict): data = {"ok": False, "error": "invalid BigHelp executor envelope", "raw": data} data.setdefault("provider", "bighelp.direct_worker") data.setdefault("op", op) if proc.returncode and data.get("ok") is not False: data["ok"] = False data["error"] = data.get("error") or f"executor exited {proc.returncode}" status = 200 if data.get("ok") is not False else 422 return JSONResponse(content=data, status_code=status) if __name__ == "__main__": import uvicorn host = os.environ.get("SIGNALMESH_BIGHELP_WORKER_HOST", "127.0.0.1") port = int(os.environ.get("SIGNALMESH_BIGHELP_WORKER_PORT", "8799")) uvicorn.run(app, host=host, port=port)