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.
50_005
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
259 260 261 262 263 264 265 266 |
# File 'lib/e2b/sandbox.rb', line 259 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
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/e2b/sandbox.rb', line 160 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 |
# 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 body[:autoResume] = { enabled: lifecycle[:auto_resume] } if body[:autoPause] 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.
221 222 223 224 225 226 227 228 |
# File 'lib/e2b/sandbox.rb', line 221 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
239 240 241 242 243 244 245 246 |
# File 'lib/e2b/sandbox.rb', line 239 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.
187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/e2b/sandbox.rb', line 187 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.
205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/e2b/sandbox.rb', line 205 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
327 328 329 330 331 332 333 |
# File 'lib/e2b/sandbox.rb', line 327 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
348 349 350 351 |
# File 'lib/e2b/sandbox.rb', line 348 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
403 404 405 406 407 408 409 410 411 412 413 |
# File 'lib/e2b/sandbox.rb', line 403 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)
386 387 388 |
# File 'lib/e2b/sandbox.rb', line 386 def get_host(port) "#{port}-#{@sandbox_id}.#{@domain}" end |
#get_info ⇒ Hash
Get sandbox info from the API
271 272 273 274 275 |
# File 'lib/e2b/sandbox.rb', line 271 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.
378 379 380 |
# File 'lib/e2b/sandbox.rb', line 378 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.
371 372 373 |
# File 'lib/e2b/sandbox.rb', line 371 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)
437 438 439 440 441 442 443 |
# File 'lib/e2b/sandbox.rb', line 437 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
394 395 396 |
# File 'lib/e2b/sandbox.rb', line 394 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.
308 309 310 311 312 313 |
# File 'lib/e2b/sandbox.rb', line 308 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.
358 359 360 361 362 363 364 365 366 |
# File 'lib/e2b/sandbox.rb', line 358 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
450 451 452 453 454 455 456 |
# File 'lib/e2b/sandbox.rb', line 450 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)
316 317 318 319 |
# File 'lib/e2b/sandbox.rb', line 316 def pause @http_client.post("/sandboxes/#{@sandbox_id}/pause") @state = "paused" end |
#resume(timeout: nil) ⇒ Object
Resume a paused sandbox
338 339 340 341 342 343 |
# File 'lib/e2b/sandbox.rb', line 338 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
281 282 283 284 285 286 287 288 |
# File 'lib/e2b/sandbox.rb', line 281 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
293 294 295 296 297 298 299 300 301 |
# File 'lib/e2b/sandbox.rb', line 293 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
461 462 463 464 465 466 |
# File 'lib/e2b/sandbox.rb', line 461 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
420 421 422 423 424 425 426 427 428 429 430 |
# File 'lib/e2b/sandbox.rb', line 420 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 |