-
Notifications
You must be signed in to change notification settings - Fork 5
Open
Description
Part of #271 — Gastown Cloud Proposal A (Sandbox-per-Town)
Goal
Build a WebSocket server that runs inside the gastown sandbox and streams tmux pane output to web clients, enabling observation and interaction with agent sessions.
Context
Gastown agents run as tmux sessions. To provide a web UI, we need to stream terminal output from these sessions to the browser. This proxy sits inside the sandbox and connects the tmux server to WebSocket clients.
Requirements
Terminal Proxy Binary
A small Go binary (or Node.js server) that:
- Listens on a dedicated port (e.g., 8081) for WebSocket connections
- Streams output: Periodically runs
tmux capture-pane -p -t <session>(200ms interval) and sends the output to connected clients - Accepts input: Receives text from clients and injects via
tmux send-keys -t <session> <text> Enter - Handles resize: Accepts resize events and runs
tmux resize-pane -t <session> -x <cols> -y <rows> - Supports multiple viewers: Multiple clients can connect to the same session (broadcast)
- Session routing: WebSocket path includes session name:
ws://localhost:8081/sessions/<name>
Auth
x-internal-api-keyquery parameter or header on WebSocket upgrade- Same key as the sandbox internal API (PR 3)
- Reject connections without valid key
Output Format
Each WebSocket message is JSON:
{
"type": "output",
"data": "<captured pane content>",
"timestamp": 1700000000
}Input messages:
{
"type": "input",
"data": "the text to send"
}Resize messages:
{
"type": "resize",
"cols": 120,
"rows": 40
}Session Discovery
GET /sessions endpoint (HTTP, not WebSocket) returns available tmux sessions:
{
"sessions": [
{ "name": "Mayor", "role": "mayor", "alive": true },
{ "name": "Witness-myrig", "role": "witness", "alive": true },
{ "name": "polecat-Toast", "role": "polecat", "alive": true }
]
}Performance
- Capture interval: 200ms (configurable)
- Only send output when content has changed (diff detection via checksum)
- Buffer: keep last 1000 lines for new client catch-up
- Max concurrent viewers per session: 10
Files
cloud/infra/gastown-sandbox/terminal-proxy/(new directory)main.go(orserver.ts)go.mod/go.sum(orpackage.json)
- Updates to
cloud/infra/gastown-sandbox/Dockerfile— add binary to image - Updates to
cloud/infra/gastown-sandbox/startup.sh— start proxy
Acceptance Criteria
- WebSocket server starts on port 8081
- Clients can connect and receive tmux pane output stream
- Output only sent when content changes (no redundant frames)
- Input messages inject text into the correct tmux session
- Resize messages resize the tmux pane
- Multiple clients can view the same session simultaneously
- Session discovery endpoint returns available sessions with roles
- Auth rejects connections without valid key
- New clients receive buffered history (last 1000 lines)
- Proxy handles non-existent sessions gracefully (error message, not crash)
- Binary is included in the Docker image and started by
startup.sh
Dependencies
- PR 1 (Sandbox Docker Image) — startup.sh launches this proxy
- PR 3 (Sandbox Internal API) — shared auth key
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels