From 42ae62a0473f649fcc2ebeb24ea9f9c89ca1cf04 Mon Sep 17 00:00:00 2001 From: operator Date: Mon, 5 Oct 2026 15:22:39 +0000 Subject: [PATCH] feat(prompt): integrate box runtime block with SSH-signed work order read/respond paths --- bin/prompt_envelope.py | 88 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 4 deletions(-) diff --git a/bin/prompt_envelope.py b/bin/prompt_envelope.py index 91561ab..4110765 100644 --- a/bin/prompt_envelope.py +++ b/bin/prompt_envelope.py @@ -11,7 +11,88 @@ Profiles tune the spawn recipe per job family; add new ones to PROFILES. import json import re -BOX_EXEC = "https://box.muse-dev.online/exec" +BOX_API = "https://box.muse-dev.online/api/box" + +# Verified box-namespace private keys on bl (pubkey matches the agent's entry +# in /srv/board/allowed_signers). Agents without a verified key fall back to +# the [RESULT] line (harvester) until super provisions their box key. +BOX_KEY_PATHS = { + "dev": "/home/super/.ssh/id_dev", +} + + +def _response_rule(): + return ( + "\nRESPONSE RULE: in your reply, every line that is not work output" + " MUST be a curl tool call against https://box.muse-dev.online/." + " Fenced bash blocks are executed as tool calls and their output" + " returns to you; do not narrate the calls.\n" + ) + + +def _box_surface_block(agent, job_name, job_id, target): + """Thread + runtime + direct curl URL + respond command. + + READ: GET /api/box/jobs/ (signed, box namespace; live) + RESPOND: POST /api/box/job/result (signed, box namespace, own-scope; + ships with the frontdoor publish -- 404 until then) + """ + header = ( + "\n---- BOX RUNTIME ----\n" + "THREAD: " + str(target) + "\n" + "RUNTIME: https://box.muse-dev.online/\n" + "JOB: " + str(job_id) + "\n" + "AGENT: " + str(agent) + "\n" + ) + key = BOX_KEY_PATHS.get(agent) + if not key: + return ( + header + + "\nNOTE: no box signing key is provisioned for '" + str(agent) + + "' yet, so curl commands against the box API cannot authenticate." + + " Ask super to provision your box key; until then the [RESULT]" + + " line is your respond path (the harvester records it).\n" + + _response_rule() + ) + read_cmd = ( + "```bash\n" + "TS=$(date +%s)\n" + "SIG=$(printf '%s\\njobs/" + str(job_name) + "' \"$TS\"" + " | ssh-keygen -Y sign -f " + key + " -n box" + " | python3 -c 'import sys,urllib.parse;" + " print(urllib.parse.quote(sys.stdin.read().strip()))')\n" + "curl -s \"" + BOX_API + "/jobs/" + str(job_name) + + "?identity=" + str(agent) + "&ts=$TS&sig=$SIG\"\n" + "```" + ) + respond_cmd = ( + "```bash\n" + "TS=$(date +%s)\n" + "export BOX_TS=$TS\n" + "export BOX_SIG=$(printf '%s\\njob/result\\n" + str(job_id) + "' \"$TS\"" + " | ssh-keygen -Y sign -f " + key + " -n box)\n" + "python3 - <<'PYEOF' | curl -s -X POST " + BOX_API + "/job/result" + " -H 'Content-Type: application/json' -d @-\n" + "import json, os\n" + "print(json.dumps({\n" + " \"identity\": \"" + str(agent) + "\",\n" + " \"ts\": os.environ[\"BOX_TS\"],\n" + " \"sig\": os.environ[\"BOX_SIG\"],\n" + " \"job_id\": \"" + str(job_id) + "\",\n" + " \"success\": True,\n" + " \"summary\": \"[RESULT " + str(job_id) + "] \",\n" + "}))\n" + "PYEOF\n" + "```" + ) + return ( + header + + "\nREAD your work order any time:\n" + read_cmd + "\n" + + "\nRESPOND when done -- emit this exact command as a tool call:\n" + + respond_cmd + "\n" + + _response_rule() + ) + UUID_RE = re.compile(r"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}") # profile -> (spawn count, followup minutes, spawn task hint) @@ -91,10 +172,9 @@ def wrap(job_name, job_id, agent, target, rendered): "Native cron form: %s\n" "Box fallback tools: [TOOL health.check {}] [TOOL swarm.list {}] [TOOL swarm.status {\"swarm_id\": \"\"}] " "[TOOL swarm.results {\"swarm_id\": \"\"}] [TOOL quality.check {}]\n" - "Direct: curl -sk -X POST %s -H \"Authorization: Bearer \" " - "-H \"Content-Type: application/json\" -d '{\"op\":\"\",\"args\":{...}}'\n" - "Thread: %s\n" % (spawn, follow, native_followup_call(job_id, job_name, profile, agent), BOX_EXEC, thread_url(target)) + % (spawn, follow, native_followup_call(job_id, job_name, profile, agent)) ) + bottom += _box_surface_block(agent, job_name, job_id, target) if not has_result: bottom += "Close with: [RESULT %s] : \n" % job_id else: