Class: Daytona::Process

Inherits:
Object
  • Object
show all
Includes:
Instrumentation
Defined in:
lib/daytona/process.rb

Overview

rubocop:disable Metrics/ClassLength

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Instrumentation

included

Constructor Details

#initialize(sandbox_id:, toolbox_api:, get_preview_link:, language: 'python', otel_state: nil) ⇒ Process

Initialize a new Process instance

Parameters:

  • sandbox_id (String)

    The ID of the Sandbox

  • toolbox_api (DaytonaToolboxApiClient::ProcessApi)

    API client for Sandbox operations

  • get_preview_link (Proc)

    Function to get preview link for a port

  • language (String) (defaults to: 'python')

    The language for code execution

  • otel_state (Daytona::OtelState, nil) (defaults to: nil)


28
29
30
31
32
33
34
# File 'lib/daytona/process.rb', line 28

def initialize(sandbox_id:, toolbox_api:, get_preview_link:, language: 'python', otel_state: nil)
  @sandbox_id = sandbox_id
  @toolbox_api = toolbox_api
  @get_preview_link = get_preview_link
  @language = language
  @otel_state = otel_state
end

Instance Attribute Details

Returns Function to get preview link for a port.

Returns:

  • (Proc)

    Function to get preview link for a port



16
17
18
# File 'lib/daytona/process.rb', line 16

def get_preview_link
  @get_preview_link
end

#languageString (readonly)

Returns The language for code execution (e.g. ‘python’, ‘typescript’, ‘javascript’).

Returns:

  • (String)

    The language for code execution (e.g. ‘python’, ‘typescript’, ‘javascript’)



19
20
21
# File 'lib/daytona/process.rb', line 19

def language
  @language
end

#sandbox_idString (readonly)

Returns The ID of the Sandbox.

Returns:

  • (String)

    The ID of the Sandbox



10
11
12
# File 'lib/daytona/process.rb', line 10

def sandbox_id
  @sandbox_id
end

#toolbox_apiDaytonaToolboxApiClient::ProcessApi (readonly)

Returns API client for Sandbox operations.

Returns:

  • (DaytonaToolboxApiClient::ProcessApi)

    API client for Sandbox operations



13
14
15
# File 'lib/daytona/process.rb', line 13

def toolbox_api
  @toolbox_api
end

Instance Method Details

#code_run(code:, params: nil, timeout: nil) ⇒ ExecuteResponse

Execute code in the Sandbox using the appropriate language runtime

Examples:

# Run Python code
response = sandbox.process.code_run(<<~CODE)
  x = 10
  y = 20
  print(f"Sum: {x + y}")
CODE
puts response.artifacts.stdout  # Prints: Sum: 30

Parameters:

  • code (String)

    Code to execute

  • params (CodeRunParams, nil) (defaults to: nil)

    Parameters for code execution

  • timeout (Integer, nil) (defaults to: nil)

    Maximum time in seconds to wait for the code to complete. 0 means wait indefinitely

Returns:

  • (ExecuteResponse)

    Code execution result containing exit_code, result, and artifacts



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/daytona/process.rb', line 83

def code_run(code:, params: nil, timeout: nil)
  response = toolbox_api.code_run(
    DaytonaToolboxApiClient::CodeRunRequest.new(
      code:, language:, argv: params&.argv, envs: params&.env, timeout:
    )
  )

  ExecuteResponse.new(
    exit_code: response.exit_code,
    result: response.result,
    artifacts: ExecutionArtifacts.new(response.result, (response.artifacts&.charts || []).map do |c|
      Charts.parse_chart(c)
    end)
  )
end

#connect_pty_session(session_id) ⇒ PtyHandle

Connects to an existing PTY session in the Sandbox.

Establishes a WebSocket connection to an existing PTY session, allowing you to interact with a previously created terminal session.

Examples:

# Connect to an existing PTY session
pty_handle = sandbox.process.connect_pty_session("my-pty-session")
pty_handle.wait_for_connection
pty_handle.send_input("echo 'Hello World'\n")
result = pty_handle.wait
pty_handle.disconnect

Parameters:

  • session_id (String)

    Unique identifier of the PTY session to connect to.

Returns:

  • (PtyHandle)

    Handle for managing the connected PTY session.

Raises:



442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
# File 'lib/daytona/process.rb', line 442

def connect_pty_session(session_id) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
  preview_link = get_preview_link.call(WS_PORT)
  url = URI.parse(preview_link.url)
  url.scheme = url.scheme == 'https' ? 'wss' : 'ws'
  url.path = "/process/pty/#{session_id}/connect"

  PtyHandle.new(
    WebSocket::Client::Simple.connect(
      url.to_s,
      headers: toolbox_api.api_client.default_headers.dup.merge(
        'X-Daytona-Preview-Token' => preview_link.token
      )
    ),
    session_id:,

    handle_resize: ->(pty_size) { resize_pty_session(session_id, pty_size) },
    handle_kill: -> { delete_pty_session(session_id) }
  ).tap(&:wait_for_connection)
end

#create_pty_session(id:, cwd: nil, envs: nil, pty_size: nil) ⇒ PtyHandle

Creates a new PTY (pseudo-terminal) session in the Sandbox.

Creates an interactive terminal session that can execute commands and handle user input. The PTY session behaves like a real terminal, supporting features like command history.

Examples:

# Create a basic PTY session
pty_handle = sandbox.process.create_pty_session(id: "my-pty")

# Create a PTY session with specific size and environment
pty_size = Daytona::PtySize.new(rows: 30, cols: 120)
pty_handle = sandbox.process.create_pty_session(
  id: "my-pty",
  cwd: "/workspace",
  envs: {"NODE_ENV" => "development"},
  pty_size: pty_size
)

# Use the PTY session
pty_handle.wait_for_connection
pty_handle.send_input("ls -la\n")
result = pty_handle.wait
pty_handle.disconnect

Parameters:

  • id (String)

    Unique identifier for the PTY session. Must be unique within the Sandbox.

  • cwd (String, nil) (defaults to: nil)

    Working directory for the PTY session. Defaults to the sandbox’s working directory.

  • envs (Hash<String, String>, nil) (defaults to: nil)

    Environment variables to set in the PTY session. These will be merged with the Sandbox’s default environment variables.

  • pty_size (PtySize, nil) (defaults to: nil)

    Terminal size configuration. Defaults to 80x24 if not specified.

Returns:

  • (PtyHandle)

    Handle for managing the created PTY session. Use this to send input, receive output, resize the terminal, and manage the session lifecycle.

Raises:

  • (Daytona::Sdk::Error)

    If the PTY session creation fails or the session ID is already in use.



410
411
412
413
414
415
416
417
418
419
420
421
422
423
# File 'lib/daytona/process.rb', line 410

def create_pty_session(id:, cwd: nil, envs: nil, pty_size: nil) # rubocop:disable Metrics/MethodLength
  response = toolbox_api.create_pty_session(
    DaytonaToolboxApiClient::PtyCreateRequest.new(
      id:,
      cwd:,
      envs:,
      cols: pty_size&.cols,
      rows: pty_size&.rows,
      lazy_start: true
    )
  )

  connect_pty_session(response.session_id)
end

#create_session(session_id) ⇒ void

This method returns an undefined value.

Creates a new long-running background session in the Sandbox

Sessions are background processes that maintain state between commands, making them ideal for scenarios requiring multiple related commands or persistent environment setup.

Examples:

# Create a new session
session_id = "my-session"
sandbox.process.create_session(session_id)
session = sandbox.process.get_session(session_id)
# Do work...
sandbox.process.delete_session(session_id)

Parameters:

  • session_id (String)

    Unique identifier for the new session



114
115
116
# File 'lib/daytona/process.rb', line 114

def create_session(session_id)
  toolbox_api.create_session(DaytonaToolboxApiClient::CreateSessionRequest.new(session_id:))
end

#delete_pty_session(session_id) ⇒ void

This method returns an undefined value.

Deletes a PTY session, terminating the associated process

Examples:

sandbox.process.delete_pty_session("my-pty")

Parameters:

  • session_id (String)

    Unique identifier of the PTY session to delete



489
490
491
# File 'lib/daytona/process.rb', line 489

def delete_pty_session(session_id)
  toolbox_api.delete_pty_session(session_id)
end

#delete_session(session_id) ⇒ Object

Terminates and removes a session from the Sandbox, cleaning up any resources associated with it

Examples:

# Create and use a session
sandbox.process.create_session("temp-session")
# ... use the session ...

# Clean up when done
sandbox.process.delete_session("temp-session")

Parameters:

  • session_id (String)

    Unique identifier of the session to delete



375
# File 'lib/daytona/process.rb', line 375

def delete_session(session_id) = toolbox_api.delete_session(session_id)

#exec(command:, cwd: nil, env: nil, timeout: nil) ⇒ ExecuteResponse

Execute a shell command in the Sandbox

Examples:

# Simple command
response = sandbox.process.exec("echo 'Hello'")
puts response.artifacts.stdout
=> "Hello\n"

# Command with working directory
result = sandbox.process.exec("ls", cwd: "workspace/src")

# Command with timeout
result = sandbox.process.exec("sleep 10", timeout: 5)

Parameters:

  • command (String)

    Shell command to execute

  • cwd (String, nil) (defaults to: nil)

    Working directory for command execution. If not specified, uses the sandbox working directory

  • env (Hash<String, String>, nil) (defaults to: nil)

    Environment variables to set for the command

  • timeout (Integer, nil) (defaults to: nil)

    Maximum time in seconds to wait for the command to complete.

Returns:

  • (ExecuteResponse)

    Command execution results containing exit_code, result, and artifacts



55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/daytona/process.rb', line 55

def exec(command:, cwd: nil, env: nil, timeout: nil)
  envs = env&.empty? ? nil : env

  response = toolbox_api.execute_command(DaytonaToolboxApiClient::ExecuteRequest.new(command:, cwd:, envs:,
                                                                                     timeout:))
  result = response.result || ''
  ExecuteResponse.new(
    exit_code: response.exit_code,
    result:,
    artifacts: ExecutionArtifacts.new(result, [])
  )
end

#execute_session_command(session_id:, req:) ⇒ Daytona::SessionExecuteResponse

Executes a command in the session

Examples:

# Execute commands in sequence, maintaining state
session_id = "my-session"

# Change directory
req = Daytona::SessionExecuteRequest.new(command: "cd /workspace")
sandbox.process.execute_session_command(session_id:, req:)

# Create a file
req = Daytona::SessionExecuteRequest.new(command: "echo 'Hello' > test.txt")
sandbox.process.execute_session_command(session_id:, req:)

# Read the file
req = Daytona::SessionExecuteRequest.new(command: "cat test.txt")
result = sandbox.process.execute_session_command(session_id:, req:)
puts "Command stdout: #{result.stdout}"
puts "Command stderr: #{result.stderr}"

Parameters:

  • session_id (String)

    Unique identifier of the session to use

  • req (Daytona::SessionExecuteRequest)

    Command execution request containing command and run_async

Returns:



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/daytona/process.rb', line 179

def execute_session_command(session_id:, req:) # rubocop:disable Metrics/MethodLength
  response = toolbox_api.session_execute_command(
    session_id,
    DaytonaToolboxApiClient::SessionExecuteRequest.new(command: req.command, run_async: req.run_async,
                                                       suppress_input_echo: req.suppress_input_echo)
  )

  SessionExecuteResponse.new(
    cmd_id: response.cmd_id,
    output: response.output,
    stdout: response.stdout || '',
    stderr: response.stderr || '',
    exit_code: response.exit_code,
    additional_properties: {}
  )
end

#get_entrypoint_logsDaytona::SessionCommandLogsResponse

Get the sandbox entrypoint logs

Examples:

logs = sandbox.process.get_entrypoint_logs()
puts "Command stdout: #{logs.stdout}"
puts "Command stderr: #{logs.stderr}"

Returns:



277
278
279
280
# File 'lib/daytona/process.rb', line 277

def get_entrypoint_logs
  response = toolbox_api.get_entrypoint_logs
  SessionCommandLogsResponse.new(output: response.output, stdout: response.stdout, stderr: response.stderr)
end

#get_entrypoint_logs_async(on_stdout:, on_stderr:) ⇒ WebSocket::Client::Simple::Client

Asynchronously retrieves and processes the sandbox entrypoint logs as they become available

Examples:

sandbox.process.get_entrypoint_logs_async(
  on_stdout: ->(log) { puts "[STDOUT]: #{log}" },
  on_stderr: ->(log) { puts "[STDERR]: #{log}" }
)

Parameters:

  • on_stdout (Proc)

    Callback function to handle stdout log chunks as they arrive

  • on_stderr (Proc)

    Callback function to handle stderr log chunks as they arrive

Returns:

  • (WebSocket::Client::Simple::Client)


293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
# File 'lib/daytona/process.rb', line 293

def get_entrypoint_logs_async(on_stdout:, on_stderr:) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
  preview_link = get_preview_link.call(WS_PORT)
  url = URI.parse(preview_link.url)
  url.scheme = url.scheme == 'https' ? 'wss' : 'ws'
  url.path = '/process/session/entrypoint/logs'
  url.query = 'follow=true'

  completion_queue = Queue.new

  ws = WebSocket::Client::Simple.connect(
    url.to_s,
    headers: toolbox_api.api_client.default_headers.dup.merge(
      'X-Daytona-Preview-Token' => preview_link.token,
      'Content-Type' => 'text/plain',
      'Accept' => 'text/plain'
    )
  )

  ws.on(:message) do |message|
    if message.type == :close
      ws.close
      completion_queue.push(:close)
    else
      stdout, stderr = Util.demux(message.data.to_s)

      on_stdout.call(stdout) unless stdout.empty?
      on_stderr.call(stderr) unless stderr.empty?
    end
  end

  ws.on(:close) do
    completion_queue.push(:close)
  end

  ws.on(:error) do |e|
    completion_queue.push(:error)
    raise Sdk::Error, "WebSocket error: #{e.message}"
  end

  # Wait for completion
  completion_queue.pop
end

#get_entrypoint_sessionDaytonaApiClient::Session

Gets the Sandbox entrypoint session

Examples:

session = sandbox.process.get_entrypoint_session()
session.commands.each do |cmd|
  puts "Command: #{cmd.command}"
end

Returns:

  • (DaytonaApiClient::Session)

    Entrypoint session information including session_id and commands



139
# File 'lib/daytona/process.rb', line 139

def get_entrypoint_session = toolbox_api.get_entrypoint_session

#get_pty_session_info(session_id) ⇒ DaytonaApiClient::PtySessionInfo

Gets detailed information about a specific PTY session

Retrieves comprehensive information about a PTY session including its current state, configuration, and metadata.

Examples:

# Get details about a specific PTY session
session_info = sandbox.process.get_pty_session_info("my-session")
puts "Session ID: #{session_info.id}"
puts "Active: #{session_info.active}"
puts "Working Directory: #{session_info.cwd}"
puts "Terminal Size: #{session_info.cols}x#{session_info.rows}"

Parameters:

  • session_id (String)

    Unique identifier of the PTY session to retrieve information for

Returns:

  • (DaytonaApiClient::PtySessionInfo)

    Detailed information about the PTY session including ID, state, creation time, working directory, environment variables, and more



522
523
524
# File 'lib/daytona/process.rb', line 522

def get_pty_session_info(session_id)
  toolbox_api.get_pty_session(session_id)
end

#get_session(session_id) ⇒ DaytonaApiClient::Session

Gets a session in the Sandbox

Examples:

session = sandbox.process.get_session("my-session")
session.commands.each do |cmd|
  puts "Command: #{cmd.command}"
end

Parameters:

  • session_id (String)

    Unique identifier of the session to retrieve

Returns:

  • (DaytonaApiClient::Session)

    Session information including session_id and commands



128
# File 'lib/daytona/process.rb', line 128

def get_session(session_id) = toolbox_api.get_session(session_id)

#get_session_command(session_id:, command_id:) ⇒ DaytonaApiClient::Command

Gets information about a specific command executed in a session

Examples:

cmd = sandbox.process.get_session_command(session_id: "my-session", command_id: "cmd-123")
if cmd.exit_code == 0
  puts "Command #{cmd.command} completed successfully"
end

Parameters:

  • session_id (String)

    Unique identifier of the session

  • command_id (String)

    Unique identifier of the command

Returns:

  • (DaytonaApiClient::Command)

    Command information including id, command, and exit_code



152
153
154
# File 'lib/daytona/process.rb', line 152

def get_session_command(session_id:, command_id:)
  toolbox_api.get_session_command(session_id, command_id)
end

#get_session_command_logs(session_id:, command_id:) ⇒ Daytona::SessionCommandLogsResponse

Get the logs for a command executed in a session

Examples:

logs = sandbox.process.get_session_command_logs(session_id: "my-session", command_id: "cmd-123")
puts "Command stdout: #{logs.stdout}"
puts "Command stderr: #{logs.stderr}"

Parameters:

  • session_id (String)

    Unique identifier of the session

  • command_id (String)

    Unique identifier of the command

Returns:



206
207
208
209
# File 'lib/daytona/process.rb', line 206

def get_session_command_logs(session_id:, command_id:)
  response = toolbox_api.get_session_command_logs(session_id, command_id)
  SessionCommandLogsResponse.new(output: response.output, stdout: response.stdout, stderr: response.stderr)
end

#get_session_command_logs_async(session_id:, command_id:, on_stdout:, on_stderr:) ⇒ WebSocket::Client::Simple::Client

Asynchronously retrieves and processes the logs for a command executed in a session as they become available

Examples:

sandbox.process.get_session_command_logs_async(
  session_id: "my-session",
  command_id: "cmd-123",
  on_stdout: ->(log) { puts "[STDOUT]: #{log}" },
  on_stderr: ->(log) { puts "[STDERR]: #{log}" }
)

Parameters:

  • session_id (String)

    Unique identifier of the session

  • command_id (String)

    Unique identifier of the command

  • on_stdout (Proc)

    Callback function to handle stdout log chunks as they arrive

  • on_stderr (Proc)

    Callback function to handle stderr log chunks as they arrive

Returns:

  • (WebSocket::Client::Simple::Client)


226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/daytona/process.rb', line 226

def get_session_command_logs_async(session_id:, command_id:, on_stdout:, on_stderr:) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
  preview_link = get_preview_link.call(WS_PORT)
  url = URI.parse(preview_link.url)
  url.scheme = url.scheme == 'https' ? 'wss' : 'ws'
  url.path = "/process/session/#{session_id}/command/#{command_id}/logs"
  url.query = 'follow=true'

  completion_queue = Queue.new

  ws = WebSocket::Client::Simple.connect(
    url.to_s,
    headers: toolbox_api.api_client.default_headers.dup.merge(
      'X-Daytona-Preview-Token' => preview_link.token,
      'Content-Type' => 'text/plain',
      'Accept' => 'text/plain'
    )
  )

  ws.on(:message) do |message|
    if message.type == :close
      ws.close
      completion_queue.push(:close)
    else
      stdout, stderr = Util.demux(message.data.to_s)

      on_stdout.call(stdout) unless stdout.empty?
      on_stderr.call(stderr) unless stderr.empty?
    end
  end

  ws.on(:close) do
    completion_queue.push(:close)
  end

  ws.on(:error) do |e|
    completion_queue.push(:error)
    raise Sdk::Error, "WebSocket error: #{e.message}"
  end

  # Wait for completion
  completion_queue.pop
end

#list_pty_sessionsArray<DaytonaApiClient::PtySessionInfo>

Lists all PTY sessions in the Sandbox

Examples:

sessions = sandbox.process.list_pty_sessions
sessions.each do |session|
  puts "PTY Session #{session.id}: #{session.cols}x#{session.rows}"
end

Returns:

  • (Array<DaytonaApiClient::PtySessionInfo>)

    List of PTY session information



502
503
504
# File 'lib/daytona/process.rb', line 502

def list_pty_sessions
  toolbox_api.list_pty_sessions
end

#list_sessionsArray<DaytonaApiClient::Session>

Returns List of all sessions in the Sandbox.

Examples:

sessions = sandbox.process.list_sessions
sessions.each do |session|
  puts "Session #{session.session_id}:"
  puts "  Commands: #{session.commands.length}"
end

Returns:

  • (Array<DaytonaApiClient::Session>)

    List of all sessions in the Sandbox



362
# File 'lib/daytona/process.rb', line 362

def list_sessions = toolbox_api.list_sessions

#resize_pty_session(session_id, pty_size) ⇒ DaytonaApiClient::PtySessionInfo

Resizes a PTY session to the specified dimensions

Examples:

pty_size = Daytona::PtySize.new(rows: 30, cols: 120)
session_info = sandbox.process.resize_pty_session("my-pty", pty_size)
puts "PTY resized to #{session_info.cols}x#{session_info.rows}"

Parameters:

  • session_id (String)

    Unique identifier of the PTY session

  • pty_size (PtySize)

    New terminal size

Returns:

  • (DaytonaApiClient::PtySessionInfo)

    Updated PTY session information



472
473
474
475
476
477
478
479
480
# File 'lib/daytona/process.rb', line 472

def resize_pty_session(session_id, pty_size)
  toolbox_api.resize_pty_session(
    session_id,
    DaytonaToolboxApiClient::PtyResizeRequest.new(
      cols: pty_size.cols,
      rows: pty_size.rows
    )
  )
end

#send_session_command_input(session_id:, command_id:, data:) ⇒ void

This method returns an undefined value.

Sends input data to a command executed in a session

This method allows you to send input to an interactive command running in a session, such as responding to prompts or providing data to stdin.

Parameters:

  • session_id (String)

    Unique identifier of the session

  • command_id (String)

    Unique identifier of the command

  • data (String)

    Input data to send to the command



345
346
347
348
349
350
351
# File 'lib/daytona/process.rb', line 345

def send_session_command_input(session_id:, command_id:, data:)
  toolbox_api.send_input(
    session_id,
    command_id,
    DaytonaToolboxApiClient::SessionSendInputRequest.new(data:)
  )
end