SignalMesh / tools /bighelp_worker.py
k0880k
fix(bighelp): return valid worker HTTP envelopes
a087d1d
Raw History Blame Contribute Delete
3.91 kB
#!/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)