ExDaytona.Session (ex_daytona v0.2.0)

Copy Markdown View Source

Long-running command sessions inside a sandbox.

Where ExDaytona.Sandbox.exec/3 runs one command to completion, a session is a persistent shell: commands share state (working directory, environment) and can run asynchronously — start a command, poll or stream its logs, and collect its exit code when it finishes.

{:ok, session} = ExDaytona.Session.create(sandbox)

# Synchronous: waits for the command
{:ok, %{exit_code: 0, output: out}} = ExDaytona.Session.run(session, "echo hi")

# Asynchronous: start, follow the logs, then reap the exit code
{:ok, cmd_id} = ExDaytona.Session.run_async(session, "sleep 5 && echo done")
:ok = ExDaytona.Session.stream_logs(session, cmd_id, &IO.write/1)
{:ok, %{exit_code: 0}} = ExDaytona.Session.await(session, cmd_id)

:ok = ExDaytona.Session.delete(session)

Summary

Types

t()

A session bound to the sandbox it runs in.

Functions

Poll until the command finishes, then return {:ok, %{exit_code: integer, command: String.t()}}.

A command's current state (ExDaytona.Model.Command) — exitCode is nil while it is still running.

Create a session in the sandbox.

Delete the session. Returns :ok.

The sandbox's entrypoint session (where a configured entrypoint runs), as an ExDaytona.Model.Session.

The entrypoint's logs so far, as a binary (fetched raw — see logs/2 for why the generated operation is bypassed).

Fetch a session's current state (its command history) as an ExDaytona.Model.Session.

List the sandbox's sessions as ExDaytona.Model.Session structs.

The logs a command has produced so far, as a binary (stdout and stderr merged, as the sandbox emits them).

Open a structured, bounded log stream for a command — separate :stdout/:stderr events over the provider's websocket protocol, pull-based via ExDaytona.LogStream.next/2. See ExDaytona.LogStream for the full contract (ownership, bounds, timeouts, close semantics).

Run a command in the session and wait for it to finish.

Start a command in the session without waiting. Returns {:ok, cmd_id} — follow it with stream_logs/4, logs/2, and await/3.

Send input to an interactive command's stdin (e.g. answering a confirmation prompt). Returns :ok.

Follow a command's logs in real time: fun is invoked with each chunk as the sandbox produces it, and the call returns :ok when the stream closes (the command finished). Returning :halt from fun cancels the stream.

Types

t()

@type t() :: %ExDaytona.Session{id: String.t(), sandbox: ExDaytona.Sandbox.t()}

A session bound to the sandbox it runs in.

Functions

await(session, cmd_id, opts \\ [])

@spec await(t(), String.t(), keyword()) ::
  {:ok, %{exit_code: integer(), command: String.t() | nil}}
  | {:error, ExDaytona.Error.t()}

Poll until the command finishes, then return {:ok, %{exit_code: integer, command: String.t()}}.

Options: :timeout (default 120_000 ms), :poll_interval (default 1_000 ms).

command(session, cmd_id)

@spec command(t(), String.t()) ::
  {:ok, ExDaytona.Model.Command.t()} | {:error, ExDaytona.Error.t()}

A command's current state (ExDaytona.Model.Command) — exitCode is nil while it is still running.

create(sandbox, opts \\ [])

@spec create(
  ExDaytona.Sandbox.t(),
  keyword()
) :: {:ok, t()} | {:error, ExDaytona.Error.t()}

Create a session in the sandbox.

Options: :id — the session id (default: a generated "ex-daytona-" id).

delete(session)

@spec delete(t()) :: :ok | {:error, ExDaytona.Error.t()}

Delete the session. Returns :ok.

entrypoint(sandbox)

@spec entrypoint(ExDaytona.Sandbox.t()) ::
  {:ok, ExDaytona.Model.Session.t()} | {:error, ExDaytona.Error.t()}

The sandbox's entrypoint session (where a configured entrypoint runs), as an ExDaytona.Model.Session.

entrypoint_logs(sandbox)

@spec entrypoint_logs(ExDaytona.Sandbox.t()) ::
  {:ok, binary()} | {:error, ExDaytona.Error.t()}

The entrypoint's logs so far, as a binary (fetched raw — see logs/2 for why the generated operation is bypassed).

get(session)

@spec get(t()) :: {:ok, ExDaytona.Model.Session.t()} | {:error, ExDaytona.Error.t()}

Fetch a session's current state (its command history) as an ExDaytona.Model.Session.

list(sandbox)

@spec list(ExDaytona.Sandbox.t()) ::
  {:ok, [ExDaytona.Model.Session.t()]} | {:error, ExDaytona.Error.t()}

List the sandbox's sessions as ExDaytona.Model.Session structs.

logs(session, cmd_id)

@spec logs(t(), String.t()) :: {:ok, binary()} | {:error, ExDaytona.Error.t()}

The logs a command has produced so far, as a binary (stdout and stderr merged, as the sandbox emits them).

Note: the OpenAPI spec declares a JSON model for this endpoint, but the live server returns text/plain — so this bypasses the generated operation and reads the raw body.

open_log_stream(session, cmd_id, opts \\ [])

@spec open_log_stream(t(), String.t(), keyword()) ::
  {:ok, pid()} | {:error, ExDaytona.Error.t()}

Open a structured, bounded log stream for a command — separate :stdout/:stderr events over the provider's websocket protocol, pull-based via ExDaytona.LogStream.next/2. See ExDaytona.LogStream for the full contract (ownership, bounds, timeouts, close semantics).

Options are passed to ExDaytona.LogStream.open/3 (:owner, :max_buffer_bytes, :max_frames, :max_frame_bytes, :idle_timeout, :overall_timeout, :connect_timeout).

run(session, command)

@spec run(t(), String.t()) ::
  {:ok,
   %{
     cmd_id: String.t() | nil,
     exit_code: integer() | nil,
     output: String.t() | nil,
     stdout: String.t() | nil,
     stderr: String.t() | nil
   }}
  | {:error, ExDaytona.Error.t()}

Run a command in the session and wait for it to finish.

Returns {:ok, %{cmd_id, exit_code, output, stdout, stderr}}.

run_async(session, command, opts \\ [])

@spec run_async(t(), String.t(), keyword()) ::
  {:ok, String.t()} | {:error, ExDaytona.Error.t()}

Start a command in the session without waiting. Returns {:ok, cmd_id} — follow it with stream_logs/4, logs/2, and await/3.

send_input(session, cmd_id, data)

@spec send_input(t(), String.t(), iodata()) :: :ok | {:error, ExDaytona.Error.t()}

Send input to an interactive command's stdin (e.g. answering a confirmation prompt). Returns :ok.

stream_logs(session, cmd_id, fun, opts \\ [])

@spec stream_logs(t(), String.t(), (binary() -> any()), keyword()) ::
  :ok | {:error, ExDaytona.Error.t()}

Follow a command's logs in real time: fun is invoked with each chunk as the sandbox produces it, and the call returns :ok when the stream closes (the command finished). Returning :halt from fun cancels the stream.

Merged output

This HTTP follow delivers stdout and stderr merged, exactly as 0.1.0 did. For separated, bounded, pull-based streaming use open_log_stream/3 / ExDaytona.LogStream.

Options: :timeout — max milliseconds to wait between chunks (default :infinity); :deadline — overall milliseconds for the stream.