Files
bullpen/bin/bullpen-coder
T
claude-noether 959581f5a6 add @coder worker (write+run Lua) + multi-worker back-and-forth demo
@coder: reactive worker on the shared harness; dspark (via gated proxy) generates Lua,
writes to a sandbox, runs it as 'nobody' with a timeout, returns code+output. Verified a
full 3-way chain: pipi (dspark, research-constrained) -> @callboy (fetch lua-users CsvUtils)
-> @coder (write+run csvtest.lua) -> pipi saves ~/csvtest.lua & reports. dspark never
self-implemented; the no-Lua-knowledge constraint forced delegation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 14:50:18 +02:00

61 lines
2.6 KiB
Python
Executable File

#!/usr/bin/env python3
"""@coder — bullpen worker: turn a request into a Lua file, write it, run it, report.
Reactive. Engine = dspark via the gated proxy. It ONLY ever writes into its sandbox and
runs `lua5.4` there as an unprivileged user with a timeout — nothing else (mechanical bound).
bullpen-coder # room loop (systemd)
bullpen-coder --once "a lua function that reverses a string, with a self-test"
"""
import json, os, re, subprocess, sys, urllib.request
sys.path.insert(0, "/usr/local/lib/bullpen")
import bullpen_worker as bw
SANDBOX = "/var/lib/bullpen/coder"
ENGINE = "http://hossenfelder.fritz.box:8082/v1/chat/completions" # gated proxy (gate+failover)
MODEL = "deepseek-v4-flash-dspark"
MAXBODY = 1400
SYS = ("You are a Lua coder. Given a task and any reference material, output ONLY valid Lua "
"source that solves it AND includes a small self-test with sample data printed to stdout. "
"No markdown, no prose, no code fences — just the Lua.")
def gen_code(request):
payload = json.dumps({"model": MODEL,
"messages": [{"role": "system", "content": SYS}, {"role": "user", "content": request}],
"temperature": 0.2, "max_tokens": 1400}).encode()
req = urllib.request.Request(ENGINE, payload, {"Content-Type": "application/json"})
with urllib.request.urlopen(req, timeout=200) as r:
txt = json.load(r)["choices"][0]["message"]["content"]
m = re.search(r"```(?:lua)?\s*(.*?)```", txt, re.S) # strip fences if the model adds them
return (m.group(1) if m else txt).strip()
def run_lua(path):
os.chmod(path, 0o644)
r = subprocess.run(
["timeout", "10", "su", "-s", "/bin/sh", "nobody", "-c", f"cd {SANDBOX} && lua5.4 {path}"],
capture_output=True, text=True)
out = r.stdout.strip()
if r.stderr.strip():
out += ("\n[stderr] " + r.stderr.strip())
return out.strip(), r.returncode
def dispatch(msg):
req, rid = msg.get("body", ""), msg.get("id")
os.makedirs(SANDBOX, exist_ok=True)
try:
code = gen_code(req)
except Exception as e:
return f"codegen error: {e}"
path = f"{SANDBOX}/job{rid}.lua"
open(path, "w").write(code + "\n")
out, rc = run_lua(path)
status = "ran OK" if rc == 0 else f"exit {rc}"
body = f"wrote {path} ({len(code)} chars) — {status}. output:\n{out[:400]}\n--- code ---\n{code}"
return body
if __name__ == "__main__":
if len(sys.argv) > 2 and sys.argv[1] == "--once":
print(dispatch({"body": sys.argv[2], "id": 0}))
else:
bw.run("coder", dispatch, online="coder online — writes+runs Lua (sandboxed). @coder <task>",
ack="…coding")