You can now open a real shell on any connected node from the dashboard — the
daemon spawns a host PTY and streams it over the existing outbound control
channel (no inbound port, no Tailscale brokering needed).
Daemon:
- portable-pty host shell sessions: pty_open/pty_in/pty_resize/pty_close ops; a
reader thread streams base64 pty_out frames. Outbound frames now funnel through
one mpsc channel so PTY output and heartbeats interleave.
cm-api NodeHub:
- per-connection pty_sinks + sid multiplexing; open_terminal/terminal_input/
terminal_resize/terminal_close; in-memory single-use terminal tickets (the
browser WS can't carry a bearer, and the session is instance-local anyway).
- routes/nodes.rs: POST /api/nodes/{id}/terminal/ticket + GET .../terminal/ws
(bridges browser xterm <-> node PTY: binary = keystrokes, text = resize).
Frontend:
- NodeTerminal xterm modal (reuses the agent Terminal's xterm setup); a Terminal
button on each online node card opens a shell.
This proves the bidirectional streaming-over-channel mechanism the RemoteDriver
will reuse. Remaining P2: RemoteDriver + placement (run agent workloads on nodes).
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
25 lines
520 B
TOML
25 lines
520 B
TOML
[package]
|
|
name = "clawmates-node"
|
|
version = "0.1.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"
|
|
|
|
[lints]
|
|
workspace = true
|