-
Notifications
You must be signed in to change notification settings - Fork 695
Description
Summary
Ref #455 the execd component already exposes a full interactive bash session API over WebSocket (GET /ws/session/:sessionId), but the opensandbox-server currently rejects WebSocket upgrades with a 400 error. This means clients that route through the server (K8s, NAT, cloud deployments) cannot reach bash sessions.
This issue tracks adding a transparent WebSocket proxy route to the server.
User Cases
UC-1 — Interactive terminal in cloud / Kubernetes
A developer uses the Python SDK with
use_server_proxy=True(the default in K8s).
They want to open an interactive bash terminal inside the sandbox.
Today this fails. After this change they connect via:WS /sandboxes/{id}/proxy/8080/ws/session/{sessionId}?pty=1and get a fully functional PTY-backed terminal.
UC-2 — Agent scripting with stateful sessions
An AI agent creates a bash session, runs multiple commands in sequence (state preserved between commands), and reads streaming output — all through the server proxy.
UC-3 — Reconnect / replay after network blip
A client disconnects briefly. On reconnect it passes
?since=<offset>and the server transparently forwards it to execd's replay buffer, so no output is lost.
Implementation Scope
| File | Change |
|---|---|
server/pyproject.toml |
Add websockets>=13.0 dependency |
server/src/api/lifecycle.py |
New @router.websocket("/sandboxes/{id}/proxy/{port}/{path}") handler with bidirectional frame relay |
server/tests/test_routes_proxy.py |
7 new unit tests covering text/binary relay, query forwarding, header filtering, error codes |
Key design decisions:
- Resolve sandbox endpoint before
accept()so a 1008 close can be sent without accepting - Filter
Authorization,Cookie, and WS handshake headers; forward custom headers and endpoint egress-auth token - Python 3.10-compatible (
asyncio.waitinstead ofTaskGroup) - Existing HTTP proxy 400-guard for non-WS-upgrade probes is preserved
Out of Scope
- SDK-level
bash_session()helper method (follow-up issue) - Authentication on the WebSocket proxy path (proxy paths are already auth-exempt, consistent with HTTP proxy)