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 +4 -4
- data/README.md +104 -20
- data/lib/e2b/api/http_client.rb +5 -1
- data/lib/e2b/client.rb +3 -5
- data/lib/e2b/configuration.rb +6 -6
- data/lib/e2b/models/process_result.rb +17 -17
- data/lib/e2b/models/template_log_entry.rb +1 -1
- data/lib/e2b/paginator.rb +1 -3
- data/lib/e2b/sandbox.rb +5 -10
- data/lib/e2b/sandbox_helpers.rb +5 -7
- data/lib/e2b/services/base_service.rb +75 -56
- data/lib/e2b/services/command_handle.rb +10 -22
- data/lib/e2b/services/commands.rb +26 -27
- data/lib/e2b/services/filesystem.rb +29 -32
- data/lib/e2b/services/git.rb +8 -8
- data/lib/e2b/services/live_streamable.rb +25 -25
- data/lib/e2b/services/pty.rb +15 -17
- data/lib/e2b/template.rb +32 -29
- data/lib/e2b/version.rb +1 -1
- metadata +39 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 71bb823dbcc8f1b7622aeb0ddfbb2535cab96fb26ac97409baa6d1f9a04c22be
|
|
4
|
+
data.tar.gz: b978c0e71dce188c41a679780eef5fd9c20c8cb6e71d64a2c79290d1c7920632
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
+
[](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
|
|
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.
|
|
122
|
-
| `sandbox.get_url(port)` | Get full URL for a port |
|
|
123
|
-
| `sandbox.
|
|
124
|
-
| `sandbox.
|
|
125
|
-
| `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
|
|
data/lib/e2b/api/http_client.rb
CHANGED
|
@@ -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 =
|
|
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
|
-
|
|
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
|
-
|
|
163
|
+
body: { timeout: timeout })
|
|
166
164
|
end
|
|
167
165
|
|
|
168
166
|
# Pause a sandbox
|
data/lib/e2b/configuration.rb
CHANGED
|
@@ -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
|
|
91
|
-
@access_token = access_token || ENV
|
|
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
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
|
|
92
|
+
::Regexp.last_match(1).to_i
|
|
93
93
|
elsif str =~ /(\d+)/
|
|
94
|
-
|
|
94
|
+
::Regexp.last_match(1).to_i
|
|
95
95
|
else
|
|
96
96
|
str.include?("0") ? 0 : 1
|
|
97
97
|
end
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
data/lib/e2b/sandbox_helpers.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
|
75
|
-
resolved_access_token = access_token || E2B.configuration&.access_token || ENV
|
|
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
|
-
|
|
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 }
|