Class: E2B::Sandbox
- Inherits:
-
Object
- Object
- E2B::Sandbox
- Extended by:
- SandboxHelpers
- Defined in:
- lib/e2b/sandbox.rb
Overview
Represents an E2B Sandbox instance
A Sandbox is an isolated cloud environment for running code, executing commands, and managing files securely. Create sandboxes using class methods or through Client.
Constant Summary collapse
- DEFAULT_DOMAIN =
Default domain for E2B sandboxes
"e2b.app"- DEFAULT_TIMEOUT =
Default sandbox timeout in seconds
300- DEFAULT_MCP_TEMPLATE =
Default template used when enabling MCP without an explicit template.
"mcp-gateway"- MCP_PORT =
MCP gateway port.
50005
Instance Attribute Summary collapse
-
#alias_name ⇒ String?
readonly
Sandbox alias/name.
-
#client_id ⇒ String
readonly
Client ID.
-
#commands ⇒ Services::Commands
readonly
Command execution service.
-
#cpu_count ⇒ Integer?
readonly
CPU count.
-
#end_at ⇒ Time?
readonly
When the sandbox will timeout.
-
#envd_access_token ⇒ String?
readonly
Access token for envd authentication.
-
#envd_version ⇒ String?
readonly
Envd version reported by the control plane.
-
#files ⇒ Services::Filesystem
readonly
Filesystem service.
-
#git ⇒ Services::Git
readonly
Git operations service.
-
#memory_mb ⇒ Integer?
readonly
Memory in MB.
-
#metadata ⇒ Hash
readonly
Metadata.
-
#pty ⇒ Services::Pty
readonly
PTY (pseudo-terminal) service.
-
#sandbox_id ⇒ String
(also: #id)
readonly
Unique sandbox ID.
-
#started_at ⇒ Time?
readonly
When the sandbox was started.
-
#state ⇒ String?
readonly
Current sandbox state.
-
#template_id ⇒ String
readonly
Template ID used to create this sandbox.
-
#traffic_access_token ⇒ String?
readonly
Access token required for proxied public traffic.
Class Method Summary collapse
-
.connect(sandbox_id, timeout: DEFAULT_TIMEOUT, api_key: nil, access_token: nil, domain: nil) ⇒ Sandbox
Connect to an existing running sandbox.
-
.create(template: "base", timeout: DEFAULT_TIMEOUT, metadata: nil, envs: nil, secure: true, allow_internet_access: true, network: nil, lifecycle: nil, auto_pause: nil, mcp: nil, api_key: nil, access_token: nil, domain: nil, request_timeout: 120) ⇒ Sandbox
Create a new sandbox.
-
.delete_snapshot(snapshot_id, api_key: nil, access_token: nil, domain: nil) ⇒ Boolean
Delete a snapshot template.
-
.kill(sandbox_id, api_key: nil, access_token: nil, domain: nil) ⇒ Boolean
Kill a sandbox by ID (idempotent).
-
.list(query: nil, limit: 100, next_token: nil, api_key: nil, access_token: nil, domain: nil) ⇒ SandboxPaginator
List running sandboxes.
-
.list_snapshots(sandbox_id: nil, limit: 100, next_token: nil, api_key: nil, access_token: nil, domain: nil) ⇒ SnapshotPaginator
List snapshots for the team, optionally filtered by source sandbox.
Instance Method Summary collapse
-
#connect(timeout: nil) ⇒ Object
deprecated
Deprecated.
Use #resume instead. The instance-level ‘#connect` collides in name with the class-level Sandbox.connect, which has different semantics (it builds a new Sandbox instance from a sandbox_id). The instance method only resumes the current sandbox.
-
#create_snapshot ⇒ Hash
Create a snapshot of the sandbox.
-
#download_url(path, user: nil, use_signature_expiration: nil) ⇒ String
Get URL for downloading a file.
-
#get_host(port) ⇒ String
Get the host string for a port (without protocol).
-
#get_info ⇒ Hash
Get sandbox info from the API.
-
#get_mcp_token ⇒ String?
Get the MCP token for the sandbox.
-
#get_mcp_url ⇒ String
Get the MCP URL for the sandbox.
-
#get_metrics(start_time: nil, end_time: nil) ⇒ Array<Hash>
Get sandbox metrics (CPU, memory, disk usage).
-
#get_url(port) ⇒ String
Get full URL for a port.
-
#initialize(sandbox_data:, http_client:, api_key:, domain: DEFAULT_DOMAIN) ⇒ Sandbox
constructor
Initialize a new Sandbox instance.
-
#kill ⇒ Boolean
Kill/terminate the sandbox (idempotent).
-
#list_snapshots(limit: 100, next_token: nil) ⇒ SnapshotPaginator
List snapshots that were created from this sandbox.
-
#logs(start_time: nil, limit: 100) ⇒ Array<Hash>
Get sandbox logs.
-
#pause ⇒ Object
Pause the sandbox (saves state for later resume).
-
#resume(timeout: nil) ⇒ Object
Resume a paused sandbox.
-
#running?(request_timeout: 10) ⇒ Boolean
Check if the sandbox is running.
-
#set_timeout(timeout) ⇒ Object
Set the sandbox timeout.
-
#time_remaining ⇒ Integer
Time remaining until sandbox timeout.
-
#upload_url(path = nil, user: nil, use_signature_expiration: nil) ⇒ String
Get URL for uploading a file.
Constructor Details
#initialize(sandbox_data:, http_client:, api_key:, domain: DEFAULT_DOMAIN) ⇒ Sandbox
Initialize a new Sandbox instance
262 263 264 265 266 267 268 269 |
# File 'lib/e2b/sandbox.rb', line 262 def initialize(sandbox_data:, http_client:, api_key:, domain: DEFAULT_DOMAIN) @http_client = http_client @api_key = api_key @domain = domain process_sandbox_data(sandbox_data) initialize_services end |
Instance Attribute Details
#alias_name ⇒ String? (readonly)
Returns Sandbox alias/name.
49 50 51 |
# File 'lib/e2b/sandbox.rb', line 49 def alias_name @alias_name end |
#client_id ⇒ String (readonly)
Returns Client ID.
52 53 54 |
# File 'lib/e2b/sandbox.rb', line 52 def client_id @client_id end |
#commands ⇒ Services::Commands (readonly)
Returns Command execution service.
82 83 84 |
# File 'lib/e2b/sandbox.rb', line 82 def commands @commands end |
#cpu_count ⇒ Integer? (readonly)
Returns CPU count.
61 62 63 |
# File 'lib/e2b/sandbox.rb', line 61 def cpu_count @cpu_count end |
#end_at ⇒ Time? (readonly)
Returns When the sandbox will timeout.
58 59 60 |
# File 'lib/e2b/sandbox.rb', line 58 def end_at @end_at end |
#envd_access_token ⇒ String? (readonly)
Returns Access token for envd authentication.
76 77 78 |
# File 'lib/e2b/sandbox.rb', line 76 def envd_access_token @envd_access_token end |
#envd_version ⇒ String? (readonly)
Returns Envd version reported by the control plane.
73 74 75 |
# File 'lib/e2b/sandbox.rb', line 73 def envd_version @envd_version end |
#files ⇒ Services::Filesystem (readonly)
Returns Filesystem service.
85 86 87 |
# File 'lib/e2b/sandbox.rb', line 85 def files @files end |
#git ⇒ Services::Git (readonly)
Returns Git operations service.
91 92 93 |
# File 'lib/e2b/sandbox.rb', line 91 def git @git end |
#memory_mb ⇒ Integer? (readonly)
Returns Memory in MB.
64 65 66 |
# File 'lib/e2b/sandbox.rb', line 64 def memory_mb @memory_mb end |
#metadata ⇒ Hash (readonly)
Returns Metadata.
67 68 69 |
# File 'lib/e2b/sandbox.rb', line 67 def @metadata end |
#pty ⇒ Services::Pty (readonly)
Returns PTY (pseudo-terminal) service.
88 89 90 |
# File 'lib/e2b/sandbox.rb', line 88 def pty @pty end |
#sandbox_id ⇒ String (readonly) Also known as: id
Returns Unique sandbox ID.
43 44 45 |
# File 'lib/e2b/sandbox.rb', line 43 def sandbox_id @sandbox_id end |
#started_at ⇒ Time? (readonly)
Returns When the sandbox was started.
55 56 57 |
# File 'lib/e2b/sandbox.rb', line 55 def started_at @started_at end |
#state ⇒ String? (readonly)
Returns Current sandbox state.
70 71 72 |
# File 'lib/e2b/sandbox.rb', line 70 def state @state end |
#template_id ⇒ String (readonly)
Returns Template ID used to create this sandbox.
46 47 48 |
# File 'lib/e2b/sandbox.rb', line 46 def template_id @template_id end |
#traffic_access_token ⇒ String? (readonly)
Returns Access token required for proxied public traffic.
79 80 81 |
# File 'lib/e2b/sandbox.rb', line 79 def traffic_access_token @traffic_access_token end |
Class Method Details
.connect(sandbox_id, timeout: DEFAULT_TIMEOUT, api_key: nil, access_token: nil, domain: nil) ⇒ Sandbox
Connect to an existing running sandbox
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/e2b/sandbox.rb', line 162 def connect(sandbox_id, timeout: DEFAULT_TIMEOUT, api_key: nil, access_token: nil, domain: nil) credentials = resolve_credentials(api_key: api_key, access_token: access_token) domain = resolve_domain(domain) http_client = build_http_client(**credentials, domain: domain) response = http_client.post("/sandboxes/#{sandbox_id}/connect", body: { timeout: timeout || DEFAULT_TIMEOUT }) new( sandbox_data: response, http_client: http_client, api_key: credentials[:api_key], domain: domain ) end |
.create(template: "base", timeout: DEFAULT_TIMEOUT, metadata: nil, envs: nil, secure: true, allow_internet_access: true, network: nil, lifecycle: nil, auto_pause: nil, mcp: nil, api_key: nil, access_token: nil, domain: nil, request_timeout: 120) ⇒ Sandbox
Create a new sandbox
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/e2b/sandbox.rb', line 114 def create(template: "base", timeout: DEFAULT_TIMEOUT, metadata: nil, envs: nil, secure: true, allow_internet_access: true, network: nil, lifecycle: nil, auto_pause: nil, mcp: nil, api_key: nil, access_token: nil, domain: nil, request_timeout: 120) credentials = resolve_credentials(api_key: api_key, access_token: access_token) domain = resolve_domain(domain) http_client = build_http_client(**credentials, domain: domain) template = resolved_template(template, mcp: mcp) lifecycle = normalized_lifecycle(lifecycle: lifecycle, auto_pause: auto_pause) body = { templateID: template, timeout: timeout, secure: secure, allow_internet_access: allow_internet_access, autoPause: lifecycle[:on_timeout] == "pause" } body[:metadata] = if body[:envVars] = envs if envs body[:mcp] = mcp if mcp body[:network] = network if network if body[:autoPause] body[:autoResume] = { enabled: lifecycle[:auto_resume] } end response = http_client.post("/sandboxes", body: body, timeout: request_timeout) ensure_supported_envd_version!(response, http_client) sandbox = new( sandbox_data: response, http_client: http_client, api_key: credentials[:api_key], domain: domain ) start_mcp_gateway(sandbox, mcp) if mcp sandbox end |
.delete_snapshot(snapshot_id, api_key: nil, access_token: nil, domain: nil) ⇒ Boolean
Delete a snapshot template.
223 224 225 226 227 228 229 230 |
# File 'lib/e2b/sandbox.rb', line 223 def delete_snapshot(snapshot_id, api_key: nil, access_token: nil, domain: nil) credentials = resolve_credentials(api_key: api_key, access_token: access_token) http_client = build_http_client(**credentials, domain: resolve_domain(domain)) http_client.delete("/templates/#{snapshot_id}") true rescue E2B::NotFoundError false end |
.kill(sandbox_id, api_key: nil, access_token: nil, domain: nil) ⇒ Boolean
241 242 243 244 245 246 247 248 |
# File 'lib/e2b/sandbox.rb', line 241 def kill(sandbox_id, api_key: nil, access_token: nil, domain: nil) credentials = resolve_credentials(api_key: api_key, access_token: access_token) http_client = build_http_client(**credentials, domain: resolve_domain(domain)) http_client.delete("/sandboxes/#{sandbox_id}") true rescue E2B::NotFoundError true end |
.list(query: nil, limit: 100, next_token: nil, api_key: nil, access_token: nil, domain: nil) ⇒ SandboxPaginator
List running sandboxes
Returns a paginator that yields sandbox info hashes one page at a time. Use BasePaginator#has_next? and BasePaginator#next_items to iterate through pages.
189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/e2b/sandbox.rb', line 189 def list(query: nil, limit: 100, next_token: nil, api_key: nil, access_token: nil, domain: nil) credentials = resolve_credentials(api_key: api_key, access_token: access_token) http_client = build_http_client(**credentials, domain: resolve_domain(domain)) SandboxPaginator.new( http_client: http_client, query: query, limit: limit, next_token: next_token ) end |
.list_snapshots(sandbox_id: nil, limit: 100, next_token: nil, api_key: nil, access_token: nil, domain: nil) ⇒ SnapshotPaginator
List snapshots for the team, optionally filtered by source sandbox.
207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/e2b/sandbox.rb', line 207 def list_snapshots(sandbox_id: nil, limit: 100, next_token: nil, api_key: nil, access_token: nil, domain: nil) credentials = resolve_credentials(api_key: api_key, access_token: access_token) http_client = build_http_client(**credentials, domain: resolve_domain(domain)) SnapshotPaginator.new( http_client: http_client, sandbox_id: sandbox_id, limit: limit, next_token: next_token ) end |
Instance Method Details
#connect(timeout: nil) ⇒ Object
330 331 332 333 334 335 336 |
# File 'lib/e2b/sandbox.rb', line 330 def connect(timeout: nil) warn "[DEPRECATION] Sandbox#connect is deprecated; use Sandbox#resume " \ "instead. (Sandbox.connect class method is unchanged.) " \ "Called from #{caller(1, 1).first}" resume(timeout: timeout) self end |
#create_snapshot ⇒ Hash
Create a snapshot of the sandbox
351 352 353 354 |
# File 'lib/e2b/sandbox.rb', line 351 def create_snapshot response = @http_client.post("/sandboxes/#{@sandbox_id}/snapshots") Models::SnapshotInfo.from_hash(response) end |
#download_url(path, user: nil, use_signature_expiration: nil) ⇒ String
Get URL for downloading a file
406 407 408 409 410 411 412 413 414 415 416 |
# File 'lib/e2b/sandbox.rb', line 406 def download_url(path, user: nil, use_signature_expiration: nil) user = resolve_legacy_file_user(user) query = build_file_url_query( path: path, user: user, operation: "read", use_signature_expiration: use_signature_expiration ) base = "https://#{Services::BaseService::ENVD_PORT}-#{@sandbox_id}.#{@domain}/files" query.empty? ? base : "#{base}?#{URI.encode_www_form(query)}" end |
#get_host(port) ⇒ String
Get the host string for a port (without protocol)
389 390 391 |
# File 'lib/e2b/sandbox.rb', line 389 def get_host(port) "#{port}-#{@sandbox_id}.#{@domain}" end |
#get_info ⇒ Hash
Get sandbox info from the API
274 275 276 277 278 |
# File 'lib/e2b/sandbox.rb', line 274 def get_info response = @http_client.get("/sandboxes/#{@sandbox_id}") process_sandbox_data(response) response end |
#get_mcp_token ⇒ String?
Get the MCP token for the sandbox.
381 382 383 |
# File 'lib/e2b/sandbox.rb', line 381 def get_mcp_token @mcp_token ||= @files.read("/etc/mcp-gateway/.token", user: "root") end |
#get_mcp_url ⇒ String
Get the MCP URL for the sandbox.
374 375 376 |
# File 'lib/e2b/sandbox.rb', line 374 def get_mcp_url "https://#{get_host(MCP_PORT)}/mcp" end |
#get_metrics(start_time: nil, end_time: nil) ⇒ Array<Hash>
Get sandbox metrics (CPU, memory, disk usage)
440 441 442 443 444 445 446 |
# File 'lib/e2b/sandbox.rb', line 440 def get_metrics(start_time: nil, end_time: nil) params = {} params[:start] = start_time.iso8601 if start_time params[:end] = end_time.iso8601 if end_time @http_client.get("/sandboxes/#{@sandbox_id}/metrics", params: params) end |
#get_url(port) ⇒ String
Get full URL for a port
397 398 399 |
# File 'lib/e2b/sandbox.rb', line 397 def get_url(port) "https://#{get_host(port)}" end |
#kill ⇒ Boolean
Kill/terminate the sandbox (idempotent)
Returns ‘true` whether the sandbox was running or already gone.
311 312 313 314 315 316 |
# File 'lib/e2b/sandbox.rb', line 311 def kill @http_client.delete("/sandboxes/#{@sandbox_id}") true rescue E2B::NotFoundError true end |
#list_snapshots(limit: 100, next_token: nil) ⇒ SnapshotPaginator
List snapshots that were created from this sandbox.
361 362 363 364 365 366 367 368 369 |
# File 'lib/e2b/sandbox.rb', line 361 def list_snapshots(limit: 100, next_token: nil) self.class.list_snapshots( sandbox_id: @sandbox_id, limit: limit, next_token: next_token, api_key: @api_key, domain: @domain ) end |
#logs(start_time: nil, limit: 100) ⇒ Array<Hash>
Get sandbox logs
453 454 455 456 457 458 459 |
# File 'lib/e2b/sandbox.rb', line 453 def logs(start_time: nil, limit: 100) params = { limit: limit } params[:start] = start_time.iso8601 if start_time response = @http_client.get("/sandboxes/#{@sandbox_id}/logs", params: params) response.is_a?(Hash) ? (response["logs"] || []) : response end |
#pause ⇒ Object
Pause the sandbox (saves state for later resume)
319 320 321 322 |
# File 'lib/e2b/sandbox.rb', line 319 def pause @http_client.post("/sandboxes/#{@sandbox_id}/pause") @state = "paused" end |
#resume(timeout: nil) ⇒ Object
Resume a paused sandbox
341 342 343 344 345 346 |
# File 'lib/e2b/sandbox.rb', line 341 def resume(timeout: nil) body = { timeout: timeout || DEFAULT_TIMEOUT } response = @http_client.post("/sandboxes/#{@sandbox_id}/connect", body: body) process_sandbox_data(response) if response.is_a?(Hash) end |
#running?(request_timeout: 10) ⇒ Boolean
Check if the sandbox is running
284 285 286 287 288 289 290 291 |
# File 'lib/e2b/sandbox.rb', line 284 def running?(request_timeout: 10) return false if @end_at && Time.now >= @end_at get_info @state != "paused" rescue NotFoundError, E2BError false end |
#set_timeout(timeout) ⇒ Object
Set the sandbox timeout
296 297 298 299 300 301 302 303 304 |
# File 'lib/e2b/sandbox.rb', line 296 def set_timeout(timeout) raise ArgumentError, "Timeout must be positive" if timeout <= 0 raise ArgumentError, "Timeout cannot exceed 24 hours (86400s)" if timeout > 86_400 @http_client.post("/sandboxes/#{@sandbox_id}/timeout", body: { timeout: timeout }) @end_at = Time.now + timeout end |
#time_remaining ⇒ Integer
Time remaining until sandbox timeout
464 465 466 467 468 469 |
# File 'lib/e2b/sandbox.rb', line 464 def time_remaining return 0 if @end_at.nil? remaining = (@end_at - Time.now).to_i remaining.positive? ? remaining : 0 end |
#upload_url(path = nil, user: nil, use_signature_expiration: nil) ⇒ String
Get URL for uploading a file
423 424 425 426 427 428 429 430 431 432 433 |
# File 'lib/e2b/sandbox.rb', line 423 def upload_url(path = nil, user: nil, use_signature_expiration: nil) user = resolve_legacy_file_user(user) base = "https://#{Services::BaseService::ENVD_PORT}-#{@sandbox_id}.#{@domain}/files" query = build_file_url_query( path: path, user: user, operation: "write", use_signature_expiration: use_signature_expiration ) query.empty? ? base : "#{base}?#{URI.encode_www_form(query)}" end |