Files
clawmates/crates/bins/clawmates-node/Cargo.toml
T
Omar SobhandClaude Opus 4.8 4de2f31b50
ci / gates (push) Failing after 5s
ci / rust (push) Has been skipped
ci / sandbox-k8s (push) Has been skipped
ci / frontend (push) Has been skipped
ci / e2e (push) Has been skipped
Fleet terminal: WebRTC DataChannel direct path (low-latency) + WS fallback
Terminal keystrokes were ~400ms because every byte relayed browser→Cloudflare→
gw-04 (Europe)→tailscale→node, even when the node is on the user's own LAN. Add a
direct browser↔node WebRTC DataChannel so co-located terminals run at LAN speed;
the gateway is reduced to signaling; the WebSocket relay stays as the automatic
fallback (graceful degradation — never worse than before).

Daemon (clawmates-node v0.4.0, new src/rtc.rs):
- Add the `webrtc` crate (reuses the ring crypto provider we already install — no
  conflict). Browser is the offerer; we answer, trickle ICE back over the control
  channel, and on DataChannel open spawn a host PTY (tmux) bridged DIRECTLY to the
  channel. Refactor open_pty → spawn_terminal_pty shared by both transports.
  iceServers: STUN + auto host/tailnet candidates (direct, no relay, for LAN/tailnet).

Server (cm-api):
- NodeConn.signal_sinks; Uplink WebRtcAnswer/WebRtcIce/WebRtcFailed routed to the
  browser; NodeHub webrtc_offer/ice/close + open_session/open_pty (open_terminal
  split so the PTY opens only once the transport is chosen). bridge_terminal relays
  signaling over the existing ticket-authed WS and opens the relay PTY on
  {type:"fallback"}.

Browser (NodeTerminalApp):
- RTCPeerConnection + reliable/ordered DataChannel; offer/answer/ICE over the WS;
  2.5s race → use the DataChannel if it opens, else fall back to the WS relay.
  Reconnect wraps both. A direct/relayed indicator shows the live transport.

Deployed; both nodes (morpheus, tank) updated to v0.4.0 and steady online. Direct-
path proof is a browser action (the  indicator + latency); confirmable from the
daemon's [rtc] logs.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-25 16:55:32 -07:00

31 lines
831 B
TOML

[package]
name = "clawmates-node"
version = "0.4.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
publish.workspace = true
[[bin]]
name = "clawmates-node"
path = "src/main.rs"
[dependencies]
tokio = { workspace = true, features = ["process"] }
tokio-tungstenite = { version = "0.26", features = ["rustls-tls-webpki-roots"] }
futures = "0.3"
serde = { workspace = true }
serde_json = { workspace = true }
sysinfo = "0.33"
portable-pty = "0.8"
base64 = "0.22"
cm-sandbox = { path = "../../cm-sandbox" }
# Linking cm-sandbox (bollard) brings a second rustls provider into the graph, so
# rustls can't auto-pick one — we install `ring` explicitly at startup.
rustls = { version = "0.23", default-features = false, features = ["ring"] }
webrtc = "0.17.1"
bytes = "1.12.0"
[lints]
workspace = true