Class: Daytona::Process

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

Overview

rubocop:disable Metrics/ClassLength

Defined Under Namespace

Modules: ArtifactType

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(code_toolbox:, sandbox_id:, toolbox_api:, get_preview_link:) ⇒ Process

Initialize a new Process instance

Parameters:



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

def initialize(code_toolbox:, sandbox_id:, toolbox_api:, get_preview_link:)
  @code_toolbox = code_toolbox
  @sandbox_id = sandbox_id
  @toolbox_api = toolbox_api
  @get_preview_link = get_preview_link
end

Instance Attribute Details

#code_toolboxDaytona::SandboxPythonCodeToolbox, (readonly)

Returns Daytona::SandboxPythonCodeToolbox,.

Returns:



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

def code_toolbox
  @code_toolbox
end

Returns Function to get preview link for a port.

Returns:

  • (Proc)

    Function to get preview link for a port



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

def get_preview_link
  @get_preview_link
end

#sandbox_idString (readonly)

Returns The ID of the Sandbox.

Returns:

  • (String)

    The ID of the Sandbox



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

def sandbox_id
  @sandbox_id
end

#toolbox_apiDaytonaToolboxApiClient::ProcessApi (readonly)

Returns API client for Sandbox operations.

Returns:

  • (DaytonaToolboxApiClient::ProcessApi)

    API client for Sandbox operations



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

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



92
93
94
# File 'lib/daytona/process.rb', line 92

def code_run(code:, params: nil, timeout: nil)
  exec(command: code_toolbox.get_run_command(code, params), env: params&.env, timeout:)
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:



336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# File 'lib/daytona/process.rb', line 336

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.



304
305
306
307
308
309
310
311
312
313
314
315
316
317
# File 'lib/daytona/process.rb', line 304

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



111
112
113
# File 'lib/daytona/process.rb', line 111

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



383
384
385
# File 'lib/daytona/process.rb', line 383

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



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

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. 0 means wait indefinitely

Returns:

  • (ExecuteResponse)

    Command execution results containing exit_code, result, and artifacts



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/daytona/process.rb', line 53

def exec(command:, cwd: nil, env: nil, timeout: nil) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
  command = "echo '#{Base64.encode64(command)}' | base64 -d | sh"

  if env && !env.empty?
    safe_env_exports = env.map do |key, value|
      "export #{key}=$(echo '#{Base64.encode64(value)}' | base64 -d)"
    end.join(';')
    command = "#{safe_env_exports}; #{command}"
  end

  command = "sh -c \"#{command}\""

  response = toolbox_api.execute_command(DaytonaToolboxApiClient::ExecuteRequest.new(command:, cwd:, timeout:))
  # Post-process the output to extract ExecutionArtifacts
  artifacts = parse_output(response.result.split("\n"))

  # Create new response with processed output and charts
  ExecuteResponse.new(
    exit_code: response.exit_code,
    result: artifacts.stdout,
    artifacts: artifacts
  )
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:



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/daytona/process.rb', line 165

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)
  )

  stdout, stderr = Util.demux(response.output || '')

  SessionExecuteResponse.new(
    cmd_id: response.cmd_id,
    output: response.output,
    stdout:,
    stderr:,
    exit_code: response.exit_code,
    # TODO: DaytonaApiClient::SessionExecuteResponse doesn't have additional_properties attribute
    additional_properties: {}
  )
end

#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



416
417
418
# File 'lib/daytona/process.rb', line 416

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



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

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



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

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:



194
195
196
197
198
199
200
201
# File 'lib/daytona/process.rb', line 194

def get_session_command_logs(session_id:, command_id:)
  parse_session_command_logs(
    toolbox_api.get_session_command_logs(
      session_id,
      command_id
    )
  )
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)


218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/daytona/process.rb', line 218

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'

  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'
    )
  ) do |ws|
    ws.on(:message) do |message|
      if message.type == :close
        ws.close
        next
      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
  end
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



396
397
398
# File 'lib/daytona/process.rb', line 396

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



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

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



366
367
368
369
370
371
372
373
374
# File 'lib/daytona/process.rb', line 366

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