Files
openchamber/packages/web/server/TERMINAL_INPUT_WS_PROTOCOL.md
T
shekohex a630b8860e feat(terminal): add persistent websocket transport for low-latency input (#348)
* fix(server): resolve terminal WebSocket proxy conflict and implement server-side transport

- Disables proxy websocket handling conflict in server proxy config to fix 1006 abnormal closes.
- Implements server-side WebSocket upgrade and connection handling for terminal input.
- Adds server-side debug instrumentation for WS lifecycle events.
- Includes terminal input WS protocol definition and unit tests.

* feat(ui): implement hardened terminal WebSocket transport with idempotency and diagnostics

- Adds client-side WebSocket transport manager with automatic reconnection and jitter.
- Implements idempotency and debug instrumentation for terminal input WS.
- Adds HMR dispose cleanup for terminal WS transport manager.
- Primes terminal input transport when terminal view becomes active.
- Updates terminal session types to include input capabilities.

* refactor(terminal): remove temporary websocket debug instrumentation
2026-02-08 15:39:22 +02:00

1.7 KiB

Terminal Input WS Protocol

Goal

Reduce terminal input latency by replacing per-keystroke HTTP requests with a persistent WebSocket input channel, while keeping SSE output and HTTP endpoints as compatibility fallback.

Scope

  • Input path: WebSocket (/api/terminal/input-ws)
  • Output path: SSE (/api/terminal/:sessionId/stream)
  • HTTP input fallback remains: POST /api/terminal/:sessionId/input

Framing

  • Text frame: terminal keystroke payload (hot path)
    • Examples: "\r", "\u001b[A", "\u0003"
  • Binary frame: control envelope
    • Byte 0: tag (0x01 = JSON control)
    • Bytes 1..N: UTF-8 JSON payload

Control Messages

  • Bind active socket to terminal session:
    • client -> server: {"t":"b","s":"<sessionId>","v":1}
  • Keepalive ping:
    • client -> server: {"t":"p","v":1}
    • server -> client: {"t":"po","v":1}
  • Server control responses:
    • ready: {"t":"ok","v":1}
    • bind ok: {"t":"bok","v":1}
    • error: {"t":"e","c":"<code>","f":true|false}

Multiplexing Model

  • Single shared socket per client runtime.
  • Socket has one mutable boundSessionId.
  • Client sends bind control when active terminal changes.
  • Keystroke frames apply to currently bound session.
  • Client keeps socket open and sends periodic keepalive pings so the channel stays ready for next input.
  • Client primes/opens this socket when the Terminal tab is opened (not per keystroke).

Security

  • UI auth session required when UI password is enabled.
  • Origin validation enforced for cookie-authenticated browser upgrades.
  • Invalid/malformed frames are rate-limited and may close socket.

Fallback Behavior

  • On WS unavailable/error/close, client falls back to HTTP input immediately.
  • Existing terminal behavior remains functional during mixed-version rollout.