Streams
Live frames and pty bytes over the websocket gateway.
Frames and pty bytes do not go through the API — they go through a gateway the API mints a short-lived ticket for. Both SDKs do the ticket, the socket and the frame decoding for you.
In Python this needs the realtime extra:
pip install "raster[realtime]"
Screen
const stream = await machine.screen.stream();
for await (const frame of stream) {
frame.seq; // monotonic
frame.width;
frame.height;
frame.image; // Uint8Array — a JPEG
}
stream.close();with machine.screen.stream() as stream:
for frame in stream:
frame.seq # monotonic
frame.width
frame.height
frame.image # bytes — a JPEGA screen stream opens a session but never takes the input lease, so watching a desktop cannot evict whoever is driving it.
A frame is decoded from the gateway’s 20-byte binary header rather than from JSON, so its fields
are read as properties in both languages — this is the one place the Python SDK hands back a
dataclass instead of a TypedDict.
Terminals
const term = await machine.terminal.connect(); // opens a pty if you pass no id
term.write("ls -la\n");
term.resize(120, 32);
for await (const bytes of term) process.stdout.write(bytes);
term.close(); // closes the pty inside the machinewith machine.terminal.connect() as term: # opens a pty if you pass no id
term.write("ls -la\n")
term.resize(120, 32)
for chunk in term:
print(chunk.decode(errors="replace"), end="")Bytes go both ways unmodified. Pass an existing terminal id to attach to one you already opened
with terminal.open; with no id, one is opened first,
which is what makes the common case a single call.
A terminal that already has a client refuses a second at the handshake. In TypeScript, connect
also takes the open options (cols, rows, command, cwd, user) for the pty it creates;
in Python it takes cols and rows.
term.exitCode (TypeScript) and term.exit_code (Python) are the shell’s exit code once it has
exited, and null while it is running.
Lifetime and failure
Closing the connection closes the pty inside the machine. Closing a screen stream just stops the frames.
A refused handshake surfaces as a RasterError carrying the gateway’s close code translated into
the product’s vocabulary — unauthenticated for an expired ticket, conflict for a terminal that
already has a client, compute_unavailable when the control plane could not be reached. That last
one is worth retrying; the others are not. See
close codes.
There is no automatic reconnect. A closed socket stays closed, and a caller that wants to resume
mints a fresh ticket by calling stream() or connect() again.
Options
TypeScript accepts an AbortSignal and a webSocket implementation for environments without a
global one:
const controller = new AbortController();
const stream = await machine.screen.stream({ signal: controller.signal });
For what travels on the wire — channels, the frame header, backpressure and the fence — see the realtime gateway.