e2b 0.3.4 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dfc3dc31658813cd8fb30e3ad23464287d65a0c44fe604092b88af9943e6cc95
4
- data.tar.gz: 944847469b79e7da14d8f347c21cbc564bc44d76ae426c4f338c020f1497ff45
3
+ metadata.gz: 71bb823dbcc8f1b7622aeb0ddfbb2535cab96fb26ac97409baa6d1f9a04c22be
4
+ data.tar.gz: b978c0e71dce188c41a679780eef5fd9c20c8cb6e71d64a2c79290d1c7920632
5
5
  SHA512:
6
- metadata.gz: 479f9080d1a96b9ae2e7508f79d2ee3fdd17d82519a7a395bbcd2bc7c4864d3b99b43c29a66812ba4156c43f87751d49ccec267eb36a808118bf5bffd9cf98ce
7
- data.tar.gz: ab09177f228a09b7c4c350324ab352de99d2c86ad8a8d8c25849923c3ad6b35ccb524ddbcd58f98dae7ce3a4c2920bccca57bf33cf4b91e27ec2ebfa53b0ca32
6
+ metadata.gz: b28d09048b6d48cd5ea1db1ed9dd505efb007c8ca4629c074dd28ca47efbe76d34a3928ae61b2346c4c5efacfc9df20b64a0dd68cff26db035e37a088bb712e2
7
+ data.tar.gz: f65d80825693194d3ec3b2004a5f40c050fe571ca9e0baf91700bb9bdc53cf4a346d569828996234702ee61c39917fbf100ba5c203c2baa15ce5afe6ebf17f2a
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # E2B Ruby SDK
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/e2b.svg)](https://badge.fury.io/rb/e2b)
4
+
3
5
  Ruby SDK for [E2B](https://e2b.dev) - secure cloud sandboxes for AI-generated code execution.
4
6
 
5
7
  Aligned with the [official E2B SDKs](https://github.com/e2b-dev/E2B) (Python/JS).
@@ -12,7 +14,10 @@ Aligned with the [official E2B SDKs](https://github.com/e2b-dev/E2B) (Python/JS)
12
14
  - PTY (pseudo-terminal) support for interactive sessions
13
15
  - Git operations (clone, push, pull, branches, status, commit, etc.)
14
16
  - Directory watching with event polling
15
- - Snapshot support
17
+ - Snapshot support (create, list, delete)
18
+ - Template builds (Dockerfile-style DSL, registry auth, build logs)
19
+ - Sandbox metrics & logs
20
+ - MCP gateway integration
16
21
  - Backward-compatible Client class
17
22
 
18
23
  ## Installation
@@ -79,8 +84,13 @@ sandbox.kill
79
84
  ## Configuration
80
85
 
81
86
  ```bash
82
- # Option 1: Environment variable (recommended)
87
+ # Option 1: Environment variables (recommended)
83
88
  export E2B_API_KEY=your-api-key
89
+ # Optional:
90
+ export E2B_ACCESS_TOKEN=your-access-token # alternative auth
91
+ export E2B_DOMAIN=e2b.app # custom domain
92
+ export E2B_API_URL=https://api.e2b.app # custom API URL
93
+ export E2B_DEBUG=true # enable debug logging
84
94
  ```
85
95
 
86
96
  ```ruby
@@ -90,8 +100,9 @@ E2B.configure do |config|
90
100
  config.domain = 'e2b.app'
91
101
  end
92
102
 
93
- # Option 3: Per-call
103
+ # Option 3: Per-call (api_key or access_token)
94
104
  sandbox = E2B::Sandbox.create(template: "base", api_key: "your-key")
105
+ sandbox = E2B::Sandbox.create(template: "base", access_token: "your-token")
95
106
 
96
107
  # Option 4: Client class (backward compatible)
97
108
  client = E2B::Client.new(api_key: "your-key")
@@ -102,12 +113,17 @@ sandbox = client.create(template: "base")
102
113
 
103
114
  ### Sandbox (class methods)
104
115
 
116
+ > Every class method below also accepts `access_token:` (alternative to `api_key:`)
117
+ > and `domain:` (override the default).
118
+
105
119
  | Method | Description |
106
120
  |--------|-------------|
107
- | `Sandbox.create(template:, timeout:, metadata:, envs:, api_key:)` | Create a new sandbox |
108
- | `Sandbox.connect(sandbox_id, timeout:, api_key:)` | Connect to existing sandbox |
109
- | `Sandbox.list(query:, limit:, api_key:)` | List running sandboxes |
110
- | `Sandbox.kill(sandbox_id, api_key:)` | Kill a sandbox by ID |
121
+ | `Sandbox.create(template:, timeout:, metadata:, envs:, secure:, allow_internet_access:, network:, lifecycle:, auto_pause:, mcp:, api_key:, request_timeout:)` | Create a new sandbox. `lifecycle:` / `auto_pause:` control what happens at timeout (kill vs pause); `network:` configures egress rules; `request_timeout:` is the create-call HTTP timeout (default 120s). |
122
+ | `Sandbox.connect(sandbox_id, timeout:, api_key:)` | Connect to an existing sandbox |
123
+ | `Sandbox.list(query:, limit:, next_token:, api_key:)` | List running sandboxes (returns `SandboxPaginator`) |
124
+ | `Sandbox.kill(sandbox_id, api_key:)` | Kill a sandbox by ID (idempotent) |
125
+ | `Sandbox.list_snapshots(sandbox_id:, limit:, next_token:, api_key:)` | List snapshots (returns `SnapshotPaginator`) |
126
+ | `Sandbox.delete_snapshot(snapshot_id, api_key:)` | Delete a snapshot template |
111
127
 
112
128
  ### Sandbox (instance)
113
129
 
@@ -117,30 +133,40 @@ sandbox = client.create(template: "base")
117
133
  | `sandbox.files` | Filesystem service |
118
134
  | `sandbox.pty` | PTY (terminal) service |
119
135
  | `sandbox.git` | Git operations service |
136
+ | `sandbox.get_info` | Refresh and return sandbox info from API |
137
+ | `sandbox.running?` | Check whether sandbox is currently running |
120
138
  | `sandbox.set_timeout(seconds)` | Extend sandbox lifetime |
121
- | `sandbox.get_host(port)` | Get host string for a port |
122
- | `sandbox.get_url(port)` | Get full URL for a port |
123
- | `sandbox.pause` / `sandbox.resume` | Pause/resume sandbox |
124
- | `sandbox.create_snapshot` | Create sandbox snapshot |
125
- | `sandbox.kill` | Terminate sandbox |
139
+ | `sandbox.time_remaining` | Seconds until timeout (0 if expired/unknown) |
140
+ | `sandbox.get_host(port)` / `sandbox.get_url(port)` | Get host string / full URL for a port |
141
+ | `sandbox.download_url(path, user:, use_signature_expiration:)` / `sandbox.upload_url(path = nil, user:, use_signature_expiration:)` | Pre-signed file URLs (`use_signature_expiration:` overrides the default URL TTL) |
142
+ | `sandbox.pause` / `sandbox.resume(timeout:)` | Pause/resume sandbox |
143
+ | `sandbox.create_snapshot` | Create sandbox snapshot (returns `SnapshotInfo`) |
144
+ | `sandbox.list_snapshots(limit:, next_token:)` | List snapshots from this sandbox |
145
+ | `sandbox.get_metrics(start_time:, end_time:)` | CPU / memory / disk metrics |
146
+ | `sandbox.logs(start_time:, limit:)` | Sandbox logs |
147
+ | `sandbox.get_mcp_url` / `sandbox.get_mcp_token` | MCP gateway URL and token (when `mcp:` enabled) |
148
+ | `sandbox.kill` | Terminate sandbox (idempotent) |
126
149
 
127
150
  ### Commands (`sandbox.commands`)
128
151
 
129
152
  | Method | Description |
130
153
  |--------|-------------|
131
- | `run(cmd, background:, envs:, cwd:, timeout:, on_stdout:, on_stderr:)` | Run command (returns `CommandResult` or `CommandHandle`) |
154
+ | `run(cmd, background:, envs:, user:, cwd:, timeout:, request_timeout:, stdin:, on_stdout:, on_stderr:)` | Run command (returns `CommandResult` or `CommandHandle`). `timeout` is the command timeout (seconds, default 60); `request_timeout` is the HTTP request timeout. Pass `stdin: true` if you plan to call `send_stdin` on a background handle. |
132
155
  | `list` | List running processes |
133
156
  | `kill(pid)` | Kill a process |
134
157
  | `send_stdin(pid, data)` | Send stdin to a process |
135
158
  | `close_stdin(pid)` | Close stdin (send EOF) |
136
- | `connect(pid)` | Connect to running process |
159
+ | `connect(pid, timeout:)` | Connect to a running process |
137
160
 
138
161
  ### Filesystem (`sandbox.files`)
139
162
 
163
+ > Every filesystem method also accepts `user:` (default `"user"`, pass `"root"` for
164
+ > root-owned paths) and `request_timeout:` (per-call HTTP timeout in seconds).
165
+
140
166
  | Method | Description |
141
167
  |--------|-------------|
142
- | `read(path)` | Read file content |
143
- | `write(path, data)` | Write file (via REST upload) |
168
+ | `read(path, format:)` | Read file content (`format:` `"text"` (default), `"bytes"`, or `"stream"`) |
169
+ | `write(path, data)` | Write file (via REST upload, returns `WriteInfo`) |
144
170
  | `write_files(files)` | Write multiple files |
145
171
  | `list(path, depth:)` | List directory (returns `EntryInfo[]`) |
146
172
  | `get_info(path)` | Get file/dir info (returns `EntryInfo`) |
@@ -154,8 +180,8 @@ sandbox = client.create(template: "base")
154
180
 
155
181
  | Method | Description |
156
182
  |--------|-------------|
157
- | `create(size:, cwd:, envs:)` | Create PTY session (returns `CommandHandle`) |
158
- | `connect(pid)` | Connect to existing PTY |
183
+ | `create(size:, user:, cwd:, envs:)` | Create PTY session (returns `CommandHandle`) |
184
+ | `connect(pid, timeout:)` | Connect to existing PTY (`timeout:` defaults to 60s) |
159
185
  | `send_stdin(pid, data)` | Send input to PTY |
160
186
  | `kill(pid)` | Kill PTY process |
161
187
  | `resize(pid, size)` | Resize terminal |
@@ -171,7 +197,7 @@ sandbox = client.create(template: "base")
171
197
  | `status(path)` | Get repo status (returns `GitStatus`) |
172
198
  | `branches(path)` | List branches (returns `GitBranches`) |
173
199
  | `add(path, files:, all:)` | Stage files |
174
- | `commit(path, message, author_name:, author_email:)` | Create commit |
200
+ | `commit(path, message, author_name:, author_email:, allow_empty:)` | Create commit (`allow_empty: true` allows empty commits) |
175
201
  | `push(path, remote:, branch:, username:, password:)` | Push to remote |
176
202
  | `pull(path, remote:, branch:, username:, password:)` | Pull from remote |
177
203
  | `create_branch` / `checkout_branch` / `delete_branch` | Branch management |
@@ -179,7 +205,65 @@ sandbox = client.create(template: "base")
179
205
  | `reset(path, mode:, target:)` / `restore(path, paths)` | Reset/restore changes |
180
206
  | `set_config` / `get_config` | Git configuration |
181
207
  | `configure_user(name, email)` | Set user name/email |
182
- | `dangerously_authenticate(username, password)` | Store credentials globally |
208
+ | `dangerously_authenticate(username, password, host:, protocol:)` | Store credentials globally (`host:` defaults to `github.com`, `protocol:` to `https`) |
209
+
210
+ ### Templates (`E2B::Template`)
211
+
212
+ Build custom sandbox templates using a Dockerfile-style DSL, then build them
213
+ on E2B's infrastructure.
214
+
215
+ ```ruby
216
+ template = E2B::Template.new
217
+ .from_python_image("3.12")
218
+ .pip_install(["requests", "pandas"])
219
+ .run_cmd("apt-get update && apt-get install -y curl")
220
+ .copy("./app", "/app")
221
+ .set_workdir("/app")
222
+ .set_envs("MY_ENV" => "value")
223
+
224
+ # Build (blocks until finished)
225
+ build_info = E2B::Template.build(
226
+ template,
227
+ alias_name: "my-template",
228
+ cpu_count: 2,
229
+ memory_mb: 1024,
230
+ disk_size_mb: 2048,
231
+ on_build_logs: ->(entry) { puts entry.message }
232
+ )
233
+
234
+ # Or build asynchronously
235
+ build_info = E2B::Template.build_in_background(template, alias_name: "my-template")
236
+ status = E2B::Template.get_build_status(build_info)
237
+ E2B::Template.wait_for_build_finish(build_info)
238
+
239
+ # Use the built template
240
+ sandbox = E2B::Sandbox.create(template: "my-template")
241
+ ```
242
+
243
+ | Method | Description |
244
+ |--------|-------------|
245
+ | `Template.new(file_context_path:, file_ignore_patterns:)` | Start a new template definition |
246
+ | `from_image(image, username:, password:)` | Use a custom base image (with optional registry auth) |
247
+ | `from_debian_image` / `from_ubuntu_image` / `from_python_image` / `from_node_image` / `from_bun_image` / `from_base_image` | Convenience base-image helpers |
248
+ | `from_aws_registry(image, ...)` / `from_gcp_registry(image, ...)` | Pull base from AWS ECR / GCP Artifact Registry |
249
+ | `from_dockerfile(content_or_path)` | Initialize from a Dockerfile |
250
+ | `from_template(template)` | Inherit from an existing template |
251
+ | `copy(src, dest, ...)` / `copy_items(items)` | Copy files into the image |
252
+ | `run_cmd(cmd, user:)` | Run a build-time command |
253
+ | `set_workdir(path)` / `set_user(user)` / `set_envs(envs)` | Image config |
254
+ | `pip_install` / `npm_install` / `bun_install` / `apt_install` | Package manager helpers |
255
+ | `add_mcp_server(servers)` | Register MCP servers in the template |
256
+ | `git_clone(url, path, branch:, depth:, user:)` | Clone repo at build time |
257
+ | `remove(path, ...)` / `rename(src, dest, ...)` / `make_dir(path, ...)` / `make_symlink(src, dest, ...)` | Filesystem ops |
258
+ | `set_start_cmd(cmd, ready_cmd)` / `set_ready_cmd(ready_cmd)` | Process start / readiness checks |
259
+ | `skip_cache` | Force-rebuild the next layer |
260
+ | `Template.build(template, name:, alias_name:, tags:, cpu_count:, memory_mb:, disk_size_mb:, skip_cache:, on_build_logs:)` | Build template (blocks) |
261
+ | `Template.build_in_background(template, ...)` | Start a build, return `BuildInfo` |
262
+ | `Template.get_build_status(build_info, logs_offset:)` | Poll build status |
263
+ | `Template.wait_for_build_finish(build_info, on_build_logs:)` | Block until build completes |
264
+ | `Template.exists(name)` / `Template.alias_exists(alias)` | Check template existence |
265
+ | `Template.assign_tags(name, tags)` / `Template.remove_tags(name, tags)` / `Template.get_tags(template_id)` | Tag management |
266
+ | `Template.to_dockerfile(template)` / `Template.to_json(template)` | Serialize a template definition |
183
267
 
184
268
  ## License
185
269
 
@@ -130,7 +130,11 @@ module E2B
130
130
 
131
131
  def parse_body(body, headers)
132
132
  if body.is_a?(String) && !body.empty?
133
- content_type = headers["content-type"] rescue "unknown"
133
+ content_type = begin
134
+ headers["content-type"]
135
+ rescue StandardError
136
+ "unknown"
137
+ end
134
138
  if content_type&.include?("json") || body.start_with?("{", "[")
135
139
  begin
136
140
  return JSON.parse(body)
data/lib/e2b/client.rb CHANGED
@@ -74,9 +74,7 @@ module E2B
74
74
  body[:envVars] = envs if envs
75
75
  body[:mcp] = mcp if mcp
76
76
  body[:network] = network if network
77
- if body[:autoPause]
78
- body[:autoResume] = { enabled: lifecycle[:auto_resume] }
79
- end
77
+ body[:autoResume] = { enabled: lifecycle[:auto_resume] } if body[:autoPause]
80
78
 
81
79
  response = @http_client.post("/sandboxes", body: body, timeout: request_timeout || @config.request_timeout || 120)
82
80
  ensure_supported_envd_version!(response, @http_client)
@@ -101,7 +99,7 @@ module E2B
101
99
  def connect(sandbox_id, timeout: nil)
102
100
  timeout_seconds = timeout || ((@config.sandbox_timeout_ms || (Sandbox::DEFAULT_TIMEOUT * 1000)) / 1000).to_i
103
101
  response = @http_client.post("/sandboxes/#{sandbox_id}/connect",
104
- body: { timeout: timeout_seconds })
102
+ body: { timeout: timeout_seconds })
105
103
 
106
104
  Sandbox.new(
107
105
  sandbox_data: response,
@@ -162,7 +160,7 @@ module E2B
162
160
  # @param timeout [Integer] Timeout in seconds
163
161
  def set_timeout(sandbox_id, timeout)
164
162
  @http_client.post("/sandboxes/#{sandbox_id}/timeout",
165
- body: { timeout: timeout })
163
+ body: { timeout: timeout })
166
164
  end
167
165
 
168
166
  # Pause a sandbox
@@ -87,8 +87,8 @@ module E2B
87
87
  sandbox_timeout_ms: DEFAULT_SANDBOX_TIMEOUT_MS,
88
88
  debug: false
89
89
  )
90
- @api_key = api_key || ENV["E2B_API_KEY"]
91
- @access_token = access_token || ENV["E2B_ACCESS_TOKEN"]
90
+ @api_key = api_key || ENV.fetch("E2B_API_KEY", nil)
91
+ @access_token = access_token || ENV.fetch("E2B_ACCESS_TOKEN", nil)
92
92
  @domain = domain || ENV["E2B_DOMAIN"] || DEFAULT_DOMAIN
93
93
  @debug = debug || ENV["E2B_DEBUG"]&.downcase == "true"
94
94
  @api_url = api_url || ENV["E2B_API_URL"] || self.class.default_api_url(@domain, debug: @debug)
@@ -103,10 +103,10 @@ module E2B
103
103
  #
104
104
  # @raise [ConfigurationError] If API key is missing
105
105
  def validate!
106
- if (@api_key.nil? || @api_key.empty?) && (@access_token.nil? || @access_token.empty?)
107
- raise ConfigurationError,
108
- "E2B API key is required. Set E2B_API_KEY environment variable or pass api_key option."
109
- end
106
+ return unless (@api_key.nil? || @api_key.empty?) && (@access_token.nil? || @access_token.empty?)
107
+
108
+ raise ConfigurationError,
109
+ "E2B API key is required. Set E2B_API_KEY environment variable or pass api_key option."
110
110
  end
111
111
 
112
112
  # Check if configuration is valid
@@ -55,21 +55,21 @@ module E2B
55
55
  next unless event.is_a?(Hash)
56
56
 
57
57
  # Handle nested event structure
58
- if event["event"]
59
- ev = event["event"]
60
- if ev["Stdout"]
61
- stdout += decode_base64_safe(ev["Stdout"]["data"])
62
- elsif ev["stdout"]
63
- stdout += decode_base64_safe(ev["stdout"]["data"])
64
- elsif ev["Stderr"]
65
- stderr += decode_base64_safe(ev["Stderr"]["data"])
66
- elsif ev["stderr"]
67
- stderr += decode_base64_safe(ev["stderr"]["data"])
68
- elsif ev["Exit"]
69
- exit_code = ev["Exit"]["exitCode"] || ev["Exit"]["exit_code"] || exit_code
70
- elsif ev["exit"]
71
- exit_code = ev["exit"]["exitCode"] || ev["exit"]["exit_code"] || exit_code
72
- end
58
+ next unless event["event"]
59
+
60
+ ev = event["event"]
61
+ if ev["Stdout"]
62
+ stdout += decode_base64_safe(ev["Stdout"]["data"])
63
+ elsif ev["stdout"]
64
+ stdout += decode_base64_safe(ev["stdout"]["data"])
65
+ elsif ev["Stderr"]
66
+ stderr += decode_base64_safe(ev["Stderr"]["data"])
67
+ elsif ev["stderr"]
68
+ stderr += decode_base64_safe(ev["stderr"]["data"])
69
+ elsif ev["Exit"]
70
+ exit_code = ev["Exit"]["exitCode"] || ev["Exit"]["exit_code"] || exit_code
71
+ elsif ev["exit"]
72
+ exit_code = ev["exit"]["exitCode"] || ev["exit"]["exit_code"] || exit_code
73
73
  end
74
74
  end
75
75
  end
@@ -89,9 +89,9 @@ module E2B
89
89
 
90
90
  str = value.to_s
91
91
  if str =~ /exit status (\d+)/i
92
- $1.to_i
92
+ ::Regexp.last_match(1).to_i
93
93
  elsif str =~ /(\d+)/
94
- $1.to_i
94
+ ::Regexp.last_match(1).to_i
95
95
  else
96
96
  str.include?("0") ? 0 : 1
97
97
  end
@@ -35,7 +35,7 @@ module E2B
35
35
  end
36
36
 
37
37
  def self.strip_ansi_escape_codes(message)
38
- message.gsub(/\e\[[0-9;?]*[ -\/]*[@-~]/, "")
38
+ message.gsub(%r{\e\[[0-9;?]*[ -/]*[@-~]}, "")
39
39
  end
40
40
  end
41
41
 
data/lib/e2b/paginator.rb CHANGED
@@ -34,9 +34,7 @@ module E2B
34
34
  super(limit: limit, next_token: next_token) do |limit:, next_token:|
35
35
  params = { limit: limit }
36
36
  params[:nextToken] = next_token if next_token
37
- if normalized_query[:metadata]
38
- params[:metadata] = self.class.encode_metadata(normalized_query[:metadata])
39
- end
37
+ params[:metadata] = self.class.encode_metadata(normalized_query[:metadata]) if normalized_query[:metadata]
40
38
  params[:state] = normalized_query[:state] if normalized_query[:state]
41
39
 
42
40
  response = http_client.get("/v2/sandboxes", params: params, detailed: true)
data/lib/e2b/sandbox.rb CHANGED
@@ -37,7 +37,7 @@ module E2B
37
37
  DEFAULT_MCP_TEMPLATE = "mcp-gateway"
38
38
 
39
39
  # MCP gateway port.
40
- MCP_PORT = 50005
40
+ MCP_PORT = 50_005
41
41
 
42
42
  # @return [String] Unique sandbox ID
43
43
  attr_reader :sandbox_id
@@ -133,9 +133,7 @@ module E2B
133
133
  body[:envVars] = envs if envs
134
134
  body[:mcp] = mcp if mcp
135
135
  body[:network] = network if network
136
- if body[:autoPause]
137
- body[:autoResume] = { enabled: lifecycle[:auto_resume] }
138
- end
136
+ body[:autoResume] = { enabled: lifecycle[:auto_resume] } if body[:autoPause]
139
137
 
140
138
  response = http_client.post("/sandboxes", body: body, timeout: request_timeout)
141
139
  ensure_supported_envd_version!(response, http_client)
@@ -165,7 +163,7 @@ module E2B
165
163
  http_client = build_http_client(**credentials, domain: domain)
166
164
 
167
165
  response = http_client.post("/sandboxes/#{sandbox_id}/connect",
168
- body: { timeout: timeout || DEFAULT_TIMEOUT })
166
+ body: { timeout: timeout || DEFAULT_TIMEOUT })
169
167
 
170
168
  new(
171
169
  sandbox_data: response,
@@ -246,7 +244,6 @@ module E2B
246
244
  rescue E2B::NotFoundError
247
245
  true
248
246
  end
249
-
250
247
  end
251
248
 
252
249
  # -------------------------------------------------------------------
@@ -298,7 +295,7 @@ module E2B
298
295
  raise ArgumentError, "Timeout cannot exceed 24 hours (86400s)" if timeout > 86_400
299
296
 
300
297
  @http_client.post("/sandboxes/#{@sandbox_id}/timeout",
301
- body: { timeout: timeout })
298
+ body: { timeout: timeout })
302
299
 
303
300
  @end_at = Time.now + timeout
304
301
  end
@@ -542,9 +539,7 @@ module E2B
542
539
  end
543
540
 
544
541
  def build_file_url_query(path:, user:, operation:, use_signature_expiration:)
545
- if use_signature_expiration && !@envd_access_token
546
- raise ArgumentError, "Signature expiration can be used only when the sandbox is secured"
547
- end
542
+ raise ArgumentError, "Signature expiration can be used only when the sandbox is secured" if use_signature_expiration && !@envd_access_token
548
543
 
549
544
  query = []
550
545
  query << ["path", path] if path
@@ -26,9 +26,7 @@ module E2B
26
26
  }
27
27
 
28
28
  on_timeout = raw_lifecycle[:on_timeout] || raw_lifecycle["on_timeout"] || "kill"
29
- unless %w[kill pause].include?(on_timeout)
30
- raise ArgumentError, "Lifecycle on_timeout must be 'kill' or 'pause'"
31
- end
29
+ raise ArgumentError, "Lifecycle on_timeout must be 'kill' or 'pause'" unless %w[kill pause].include?(on_timeout)
32
30
 
33
31
  auto_resume = if raw_lifecycle.key?(:auto_resume)
34
32
  raw_lifecycle[:auto_resume]
@@ -65,18 +63,18 @@ module E2B
65
63
  end
66
64
 
67
65
  raise TemplateError,
68
- "You need to update the template to use the new SDK. You can do this by running `e2b template build` in the directory with the template."
66
+ "You need to update the template to use the new SDK. You can do this by running `e2b template build` in the directory with the template."
69
67
  rescue ArgumentError
70
68
  nil
71
69
  end
72
70
 
73
71
  def resolve_credentials(api_key:, access_token:)
74
- resolved_api_key = api_key || E2B.configuration&.api_key || ENV["E2B_API_KEY"]
75
- resolved_access_token = access_token || E2B.configuration&.access_token || ENV["E2B_ACCESS_TOKEN"]
72
+ resolved_api_key = api_key || E2B.configuration&.api_key || ENV.fetch("E2B_API_KEY", nil)
73
+ resolved_access_token = access_token || E2B.configuration&.access_token || ENV.fetch("E2B_ACCESS_TOKEN", nil)
76
74
 
77
75
  unless (resolved_api_key && !resolved_api_key.empty?) || (resolved_access_token && !resolved_access_token.empty?)
78
76
  raise ConfigurationError,
79
- "E2B credentials are required. Set E2B_API_KEY or E2B_ACCESS_TOKEN, or pass api_key:/access_token:."
77
+ "E2B credentials are required. Set E2B_API_KEY or E2B_ACCESS_TOKEN, or pass api_key:/access_token:."
80
78
  end
81
79
 
82
80
  { api_key: resolved_api_key, access_token: resolved_access_token }