warpgate-ssh: remote Linux/macOS terminals through the relay; oregon launched remotely

The dispatcher moves to an LXC without agent CLIs (design 9), so every terminal is
reached through Warpgate. The relay call (agent-access.py run --target <t>) lives in
one helper; the target comes from the terminal config.

os linux/darwin (PosixWarpgateTransport): each primitive is one bash -c call. Files
go up as base64 (chunked above 60k), start_run stages prompt.md + run.sh and launches
in a single round trip; the runner is detached with setsid nohup (pid == pgid == sid,
$! kept in launch.pid); kill signals the process group and session (TERM, then KILL),
skipped once exit.txt exists. macOS detaches with perl POSIX::setsid.

os windows keeps the win10-ps.sh / win10-put.sh helper scripts (target win10) and
schtasks, now through the shared call() helper.

oregon is now warpgate-ssh (target oregon, run_root ~/.gwent-board/agentd-runs);
the local transport stays for co-located setups and tests.
This commit is contained in:
jj.wang
2026-10-21 08:08:01 +00:00
parent f2f7e4308a
commit dc8271a06a
9 changed files with 490 additions and 45 deletions
+10 -4
View File
@@ -4,17 +4,23 @@ import signal
import subprocess
from pathlib import Path
# Shared with the remote POSIX transport (warpgate_ssh): plain sh + `date +FMT`, so it also runs on macOS.
RUNNER = """#!/usr/bin/env bash
cd {cwd} || {{ echo "exit=97 at $(date -Is) (cd failed)" > {d}/exit.txt; exit 97; }}
cd {cwd} || {{ echo "exit=97 at $(date +%Y-%m-%dT%H:%M:%S%z) (cd failed)" > {d}/exit.txt; exit 97; }}
echo $$ > {d}/pid.txt
date -Is > {d}/started.txt
date +%Y-%m-%dT%H:%M:%S%z > {d}/started.txt
(
{command}
) < {d}/prompt.md > {d}/{stdout} 2> {d}/stderr.txt
echo "exit=$? at $(date -Is)" > {d}/exit.txt
echo "exit=$? at $(date +%Y-%m-%dT%H:%M:%S%z)" > {d}/exit.txt
"""
def sh_quote(s):
"""POSIX shell single-quote literal (always quoted, `'` -> `'\\''`)."""
return "'" + str(s).replace("'", "'\\''") + "'"
class LocalTransport:
os = "linux"
@@ -28,7 +34,7 @@ class LocalTransport:
return os.path.join(*parts)
def quote(self, s):
return "'" + str(s).replace("'", "'\\''") + "'"
return sh_quote(s)
def mkdir(self, path, clean=False):
p = Path(path)