Class: E2B::Services::Pty

Inherits:
BaseService show all
Includes:
LiveStreamable
Defined in:
lib/e2b/services/pty.rb

Overview

PTY (pseudo-terminal) service for E2B sandbox.

Provides methods to create, connect to, and manage interactive pseudo-terminals inside the sandbox. Uses Connect RPC protocol with the process.Process service.

Examples:

Create a PTY and send commands

pty = sandbox.pty
handle = pty.create
handle.send_stdin("ls -la\n")
result = handle.wait(on_pty: ->(data) { print data })

Resize a PTY

pty.resize(handle.pid, PtySize.new(cols: 120, rows: 40))

Connect to an existing PTY

handle = pty.connect(pid)

Constant Summary collapse

DEFAULT_SHELL =

Default shell to use for PTY sessions

"/bin/bash"
DEFAULT_SHELL_ARGS =

Default shell arguments for interactive login shell

["-i", "-l"].freeze

Constants inherited from BaseService

BaseService::DEFAULT_USERNAME, BaseService::ENVD_DEFAULT_USER_VERSION, BaseService::ENVD_PORT, BaseService::ENVD_RECURSIVE_WATCH_VERSION

Instance Method Summary collapse

Methods inherited from BaseService

#initialize

Constructor Details

This class inherits a constructor from E2B::Services::BaseService

Instance Method Details

#close_stdin(pid) ⇒ void

This method returns an undefined value.

Close the stdin of a PTY process.

After calling this, no more input can be sent to the PTY via #send_stdin.

Parameters:

  • pid (Integer)

    Process ID of the PTY

Raises:



208
209
210
211
212
# File 'lib/e2b/services/pty.rb', line 208

def close_stdin(pid)
  envd_rpc("process.Process", "CloseStdin", body: {
    process: { pid: pid }
  })
end

#connect(pid, timeout: 60) ⇒ CommandHandle

Connect to an existing PTY process.

Attaches to a running PTY process by PID and returns a handle for sending input and receiving output.

Examples:

handle = sandbox.pty.connect(12345)
handle.send_stdin("whoami\n")

Parameters:

  • pid (Integer)

    Process ID of the PTY to connect to

  • timeout (Integer) (defaults to: 60)

    Timeout for the connection in seconds

Returns:

Raises:

  • (E2B::E2BError)

    if the process is not found or connection fails



125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/e2b/services/pty.rb', line 125

def connect(pid, timeout: 60)
  body = {
    process: { pid: pid }
  }

  build_live_handle(
    rpc_method: "Connect",
    body: body,
    headers: user_auth_headers(nil),
    timeout: timeout + 30
  )
end

#create(size: PtySize.new, user: nil, cwd: nil, envs: nil, cmd: DEFAULT_SHELL, args: DEFAULT_SHELL_ARGS, timeout: 60) ⇒ CommandHandle

Create a new PTY (pseudo-terminal) session in the sandbox.

Starts an interactive shell process with a PTY attached. The returned CommandHandle can be used to send input, receive output, and manage the PTY lifecycle.

Examples:

handle = sandbox.pty.create(
  size: PtySize.new(cols: 120, rows: 40),
  cwd: "/home/user/project",
  envs: { "EDITOR" => "vim" }
)

Parameters:

  • size (PtySize) (defaults to: PtySize.new)

    Terminal size (default: 80 columns x 24 rows)

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

    User to run the PTY as

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

    Working directory for the PTY shell

  • envs (Hash{String => String}, nil) (defaults to: nil)

    Environment variables

  • cmd (String) (defaults to: DEFAULT_SHELL)

    Shell executable (default: /bin/bash)

  • args (Array<String>) (defaults to: DEFAULT_SHELL_ARGS)

    Shell arguments (default: [“-i”, “-l”])

  • timeout (Integer) (defaults to: 60)

    Timeout for the PTY session in seconds

Returns:

Raises:



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/e2b/services/pty.rb', line 85

def create(size: PtySize.new, user: nil, cwd: nil, envs: nil,
           cmd: DEFAULT_SHELL, args: DEFAULT_SHELL_ARGS, timeout: 60)
  envs = build_pty_envs(envs)
  headers = user_auth_headers(user)

  process_spec = {
    cmd: cmd,
    args: args,
    envs: envs
  }
  process_spec[:cwd] = cwd if cwd

  body = {
    process: process_spec,
    pty: {
      size: size.to_h
    }
  }

  build_live_handle(
    rpc_method: "Start",
    body: body,
    headers: headers,
    timeout: timeout + 30
  )
end

#kill(pid, headers: nil) ⇒ Boolean

Kill a PTY process with SIGKILL.

Examples:

sandbox.pty.kill(12345)

Parameters:

  • pid (Integer)

    Process ID of the PTY to kill

Returns:

  • (Boolean)

    true if the signal was sent, false if the process was not found



169
170
171
172
173
174
175
176
177
# File 'lib/e2b/services/pty.rb', line 169

def kill(pid, headers: nil)
  envd_rpc("process.Process", "SendSignal", body: {
    process: { pid: pid },
    signal: 9 # SIGKILL
  }, headers: headers)
  true
rescue E2B::E2BError
  false
end

#listArray<Hash>

List running processes in the sandbox.

Returns:

  • (Array<Hash>)

    List of running process descriptors



217
218
219
220
# File 'lib/e2b/services/pty.rb', line 217

def list
  response = envd_rpc("process.Process", "List", body: {})
  response["processes"] || response[:processes] || []
end

#resize(pid, size) ⇒ void

This method returns an undefined value.

Resize a PTY terminal.

Should be called when the terminal window size changes to keep the remote PTY in sync.

Examples:

sandbox.pty.resize(pid, PtySize.new(cols: 120, rows: 40))

Parameters:

  • pid (Integer)

    Process ID of the PTY

  • size (PtySize)

    New terminal size

Raises:



191
192
193
194
195
196
197
198
# File 'lib/e2b/services/pty.rb', line 191

def resize(pid, size)
  envd_rpc("process.Process", "Update", body: {
    process: { pid: pid },
    pty: {
      size: size.to_h
    }
  })
end

#send_stdin(pid, data, headers: nil) ⇒ void

This method returns an undefined value.

Send input data to a PTY.

The data is base64-encoded and sent as PTY input (not stdin), which means it goes through the terminal emulator and supports control characters, escape sequences, etc.

Examples:

Send a command

sandbox.pty.send_stdin(pid, "echo hello\n")

Send Ctrl+C

sandbox.pty.send_stdin(pid, "\x03")

Parameters:

  • pid (Integer)

    Process ID of the PTY

  • data (String)

    Input data to send (e.g., “ls -lan”)

Raises:



154
155
156
157
158
159
160
# File 'lib/e2b/services/pty.rb', line 154

def send_stdin(pid, data, headers: nil)
  encoded = Base64.strict_encode64(data.is_a?(String) ? data : data.to_s)
  envd_rpc("process.Process", "SendInput", body: {
    process: { pid: pid },
    input: { pty: encoded }
  }, headers: headers)
end