Interactive PTY (pseudo-terminal) sessions inside a sandbox.
A PTY is a real terminal: interactive programs (shells, REPLs, editors, anything that needs a TTY) run in it, and I/O flows over a websocket.
{:ok, pty} = ExDaytona.Pty.create(sandbox, cols: 120, rows: 30)
{:ok, ws} = ExDaytona.Pty.connect(pty)
:ok = ExDaytona.Pty.send_input(ws, "echo hello\n")
receive do
{:ex_daytona_ws, ^ws, {:binary, output}} -> IO.write(output)
end
:ok = ExDaytona.Pty.resize(pty, 200, 50)
:ok = ExDaytona.Pty.disconnect(ws)
:ok = ExDaytona.Pty.delete(pty)Terminal output arrives at the connecting process as
{:ex_daytona_ws, ws_pid, {:binary, data}} messages (see
ExDaytona.WebSocket for the full message shapes).
Summary
Functions
Open the PTY's websocket. Terminal output is delivered to the calling
process (override with :owner) as {:ex_daytona_ws, ws, {:binary, data}}
messages; {:ex_daytona_ws, ws, {:closed, reason}} signals the end.
Create a PTY session.
Kill the PTY session. Returns :ok.
Close the websocket connection (the PTY session keeps running — use
delete/1 to kill it).
The PTY's current state as an ExDaytona.Model.PtySessionInfo.
List the sandbox's PTY sessions as ExDaytona.Model.PtySessionInfo
structs.
Resize the terminal.
Write input to the terminal (what a user would type). ws is the
connection from connect/2.
Types
@type t() :: %ExDaytona.Pty{id: String.t(), sandbox: ExDaytona.Sandbox.t()}
A PTY session bound to its sandbox.
Functions
@spec connect( t(), keyword() ) :: {:ok, pid()} | {:error, ExDaytona.Error.t()}
Open the PTY's websocket. Terminal output is delivered to the calling
process (override with :owner) as {:ex_daytona_ws, ws, {:binary, data}}
messages; {:ex_daytona_ws, ws, {:closed, reason}} signals the end.
Options are passed to ExDaytona.WebSocket.connect/3 (:owner,
:connect_timeout).
@spec create( ExDaytona.Sandbox.t(), keyword() ) :: {:ok, t()} | {:error, ExDaytona.Error.t()}
Create a PTY session.
Options
:id— session id (default: a generated"ex-daytona-pty-"id):cols/:rows— terminal size (server defaults apply when omitted):cwd— working directory:env— environment variables (map):lazy_start— don't start the shell until the first connect
@spec delete(t()) :: :ok | {:error, ExDaytona.Error.t()}
Kill the PTY session. Returns :ok.
@spec disconnect(pid()) :: :ok
Close the websocket connection (the PTY session keeps running — use
delete/1 to kill it).
@spec info(t()) :: {:ok, ExDaytona.Model.PtySessionInfo.t()} | {:error, ExDaytona.Error.t()}
The PTY's current state as an ExDaytona.Model.PtySessionInfo.
@spec list(ExDaytona.Sandbox.t()) :: {:ok, [ExDaytona.Model.PtySessionInfo.t()]} | {:error, ExDaytona.Error.t()}
List the sandbox's PTY sessions as ExDaytona.Model.PtySessionInfo
structs.
@spec resize(t(), pos_integer(), pos_integer()) :: {:ok, ExDaytona.Model.PtySessionInfo.t()} | {:error, ExDaytona.Error.t()}
Resize the terminal.
@spec send_input(pid(), iodata()) :: :ok | {:error, ExDaytona.Error.t()}
Write input to the terminal (what a user would type). ws is the
connection from connect/2.