withruntime 0.11.1 → 0.12.0
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.
- package/BLAXEL.md +3 -3
- package/COMPATIBILITY.md +74 -9
- package/DAYTONA.md +33 -5
- package/E2B.md +137 -48
- package/README.md +11 -9
- package/README.src.md +11 -9
- package/VERCEL.md +43 -5
- package/compatibility-lock.json +58 -49
- package/dist/billing-cli.d.ts +1 -1
- package/dist/billing-cli.js +77 -1
- package/dist/blaxel/errors.d.ts +14 -0
- package/dist/blaxel/errors.js +33 -4
- package/dist/blaxel/index.d.ts +2 -2
- package/dist/blaxel/index.js +4 -4
- package/dist/blaxel/interpreter.d.ts +2 -5
- package/dist/blaxel/sandbox.d.ts +15 -7
- package/dist/blaxel/sandbox.js +64 -9
- package/dist/blaxel/snapshot.d.ts +4 -0
- package/dist/blaxel/snapshot.js +4 -0
- package/dist/cli/logs.d.ts +21 -0
- package/dist/cli/logs.js +188 -0
- package/dist/cli/logs.test.d.ts +1 -0
- package/dist/cli/logs.test.js +272 -0
- package/dist/cli-extras.d.ts +3 -3
- package/dist/cli-extras.js +17 -12
- package/dist/cli-words.d.ts +10 -1
- package/dist/cli-words.js +18 -0
- package/dist/cli.d.ts +6 -2
- package/dist/cli.js +468 -219
- package/dist/client.d.ts +13 -63
- package/dist/client.js +35 -124
- package/dist/cloudflare/errors.d.ts +143 -0
- package/dist/cloudflare/errors.js +167 -0
- package/dist/cloudflare/index.d.ts +175 -6
- package/dist/cloudflare/index.js +416 -26
- package/dist/cloudflare/interpreter.d.ts +119 -0
- package/dist/cloudflare/interpreter.js +223 -0
- package/dist/cloudflare/streams.d.ts +38 -0
- package/dist/cloudflare/streams.js +145 -0
- package/dist/cloudflare/watch.d.ts +9 -0
- package/dist/cloudflare/watch.js +24 -0
- package/dist/codesandbox/index.d.ts +216 -28
- package/dist/codesandbox/index.js +478 -78
- package/dist/compat/core.d.ts +18 -0
- package/dist/compat/core.js +29 -0
- package/dist/compat/files.d.ts +1 -0
- package/dist/compat/files.js +25 -5
- package/dist/daytona/computer-use.d.ts +13 -4
- package/dist/daytona/computer-use.js +66 -8
- package/dist/daytona/daytona.d.ts +7 -2
- package/dist/daytona/daytona.js +31 -5
- package/dist/daytona/errors.d.ts +11 -0
- package/dist/daytona/errors.js +18 -0
- package/dist/daytona/filesystem.js +2 -1
- package/dist/daytona/image.d.ts +13 -9
- package/dist/daytona/image.js +18 -12
- package/dist/daytona/index.d.ts +1 -1
- package/dist/daytona/sandbox.d.ts +9 -3
- package/dist/daytona/sandbox.js +17 -3
- package/dist/domains/index.d.ts +9 -0
- package/dist/domains/index.js +10 -0
- package/dist/e2b/client.d.ts +15 -2
- package/dist/e2b/client.js +61 -7
- package/dist/e2b/commands.d.ts +4 -1
- package/dist/e2b/commands.js +17 -7
- package/dist/e2b/errors.d.ts +43 -2
- package/dist/e2b/errors.js +78 -6
- package/dist/e2b/filesystem.d.ts +1 -1
- package/dist/e2b/filesystem.js +82 -16
- package/dist/e2b/index.d.ts +3 -3
- package/dist/e2b/index.js +2 -2
- package/dist/e2b/sandbox.d.ts +50 -35
- package/dist/e2b/sandbox.js +228 -185
- package/dist/e2b/unsupported.d.ts +19 -0
- package/dist/e2b/unsupported.js +22 -1
- package/dist/e2b/users.d.ts +9 -0
- package/dist/e2b/users.js +22 -0
- package/dist/errors.d.ts +14 -5
- package/dist/errors.js +28 -14
- package/dist/freestyle/index.d.ts +285 -37
- package/dist/freestyle/index.js +656 -144
- package/dist/identity.d.ts +3 -0
- package/dist/identity.js +27 -0
- package/dist/images/index.d.ts +9 -0
- package/dist/images/index.js +10 -0
- package/dist/index.d.ts +1 -0
- package/dist/ips/index.d.ts +9 -0
- package/dist/ips/index.js +10 -0
- package/dist/jobs/index.d.ts +9 -0
- package/dist/jobs/index.js +10 -0
- package/dist/keys.js +2 -0
- package/dist/login.js +2 -0
- package/dist/machine.d.ts +189 -0
- package/dist/machine.js +521 -0
- package/dist/mcp.js +1 -1
- package/dist/modal/index.d.ts +339 -61
- package/dist/modal/index.js +781 -121
- package/dist/network-cli.d.ts +3 -1
- package/dist/network-cli.js +78 -36
- package/dist/networks/index.d.ts +11 -0
- package/dist/networks/index.js +10 -0
- package/dist/openai-agents/index.d.ts +1 -1
- package/dist/openai-agents/index.js +1 -1
- package/dist/ports/index.d.ts +9 -0
- package/dist/ports/index.js +10 -0
- package/dist/product-names.d.ts +52 -0
- package/dist/product-names.js +164 -0
- package/dist/product-renames.d.ts +103 -0
- package/dist/product-renames.js +189 -0
- package/dist/products/apps.d.ts +176 -0
- package/dist/products/apps.js +165 -0
- package/dist/products/billing.d.ts +41 -0
- package/dist/products/billing.js +13 -0
- package/dist/products/browser.d.ts +10 -0
- package/dist/products/browsers.d.ts +71 -0
- package/dist/products/browsers.js +102 -0
- package/dist/products/builds.d.ts +126 -0
- package/dist/products/builds.js +221 -0
- package/dist/products/index.d.ts +3 -16
- package/dist/products/index.js +3 -14
- package/dist/products/jobs.d.ts +19 -3
- package/dist/products/jobs.js +28 -12
- package/dist/products/limits.d.ts +4 -10
- package/dist/products/logs.d.ts +245 -0
- package/dist/products/logs.js +274 -0
- package/dist/products/logs.test.d.ts +1 -0
- package/dist/products/logs.test.js +343 -0
- package/dist/products/network-products.d.ts +38 -7
- package/dist/products/network-products.js +31 -18
- package/dist/products/network.d.ts +1 -1
- package/dist/products/observability.d.ts +3 -2
- package/dist/products/private-network.js +1 -1
- package/dist/products/queues.d.ts +149 -0
- package/dist/products/queues.js +213 -0
- package/dist/products/referrals.d.ts +21 -7
- package/dist/products/referrals.js +3 -3
- package/dist/products/secrets.d.ts +8 -4
- package/dist/products/secrets.js +39 -18
- package/dist/products/signed-requests.d.ts +21 -0
- package/dist/products/signed-requests.js +11 -0
- package/dist/products/streams.d.ts +73 -0
- package/dist/products/streams.js +17 -0
- package/dist/products/switching.d.ts +37 -10
- package/dist/products/switching.js +4 -3
- package/dist/products/volumes.d.ts +3 -0
- package/dist/record-cli.d.ts +23 -0
- package/dist/record-cli.js +308 -0
- package/dist/renamed-products.d.ts +38 -0
- package/dist/renamed-products.js +34 -0
- package/dist/runloop/index.d.ts +9 -2
- package/dist/runloop/index.js +29 -8
- package/dist/runloop/sdk.d.ts +131 -0
- package/dist/runloop/sdk.js +167 -0
- package/dist/sandbox.d.ts +10 -94
- package/dist/sandbox.js +22 -371
- package/dist/sandboxes/index.d.ts +11 -0
- package/dist/sandboxes/index.js +12 -0
- package/dist/snapshots/index.d.ts +9 -0
- package/dist/snapshots/index.js +11 -0
- package/dist/snapshots.d.ts +7 -4
- package/dist/sprites/index.d.ts +343 -31
- package/dist/sprites/index.js +866 -84
- package/dist/ssh.d.ts +1 -1
- package/dist/ssh.js +11 -11
- package/dist/terminal.d.ts +24 -0
- package/dist/terminal.js +32 -0
- package/dist/transport.d.ts +18 -2
- package/dist/transport.js +61 -6
- package/dist/tunnel.js +1 -1
- package/dist/types.d.ts +116 -8
- package/dist/vercel/sandbox.d.ts +1 -2
- package/dist/vercel/sandbox.js +6 -5
- package/dist/vercel/snapshot.js +10 -2
- package/dist/volumes/index.d.ts +9 -0
- package/dist/volumes/index.js +10 -0
- package/package.json +48 -2
package/BLAXEL.md
CHANGED
|
@@ -34,7 +34,7 @@ name, or through `getByExternalId`, use the same Runtime key.
|
|
|
34
34
|
- **Machine:** Blaxel's default of 4096 MB. vCPUs follow Blaxel's rule of one
|
|
35
35
|
per 2048 MB (at least one, at most 16): 2 for the default, 4 for 8192 MB. A
|
|
36
36
|
trial sandbox has at most 4096 MB (2 vCPUs); `memory: 8192` or more needs
|
|
37
|
-
prepaid credit, and on the trial is refused with a 400 (`
|
|
37
|
+
prepaid credit, and on the trial is refused with a 400 (`no_credit_size_limit`)
|
|
38
38
|
saying so.
|
|
39
39
|
- **Image:** Blaxel's `base-image`, `py-app`, `ts-app`, `node`,
|
|
40
40
|
`docker-in-sandbox` and `jupyter-server` are Runtime's stock image (Ubuntu
|
|
@@ -42,7 +42,7 @@ name, or through `getByExternalId`, use the same Runtime key.
|
|
|
42
42
|
`sudo enable-docker`). Any other image `ns/name:tag` is the ready Runtime
|
|
43
43
|
image named `ns-name` (every `/` becomes `-`, as Runtime names hold none) at
|
|
44
44
|
tag `tag` (`latest` when none is given). Build it once with
|
|
45
|
-
`npx withruntime
|
|
45
|
+
`npx withruntime images build --dockerfile Dockerfile --name ns-name -t ns-name:tag`,
|
|
46
46
|
and the code keeps `image: "ns/name:tag"` as it is.
|
|
47
47
|
- **Standby and lifetime:** a Blaxel sandbox goes to standby when unused and
|
|
48
48
|
resumes on the next call. On Runtime it pauses after 60 seconds without a
|
|
@@ -121,7 +121,7 @@ names the gap and its `alternative` says what to use.
|
|
|
121
121
|
|
|
122
122
|
| Blaxel | Use instead |
|
|
123
123
|
| ------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
|
|
124
|
-
| An `image` with no ready Runtime image of the name it maps to (Blaxel's other templates too) | Build it: `npx withruntime
|
|
124
|
+
| An `image` with no ready Runtime image of the name it maps to (Blaxel's other templates too) | Build it: `npx withruntime images build --dockerfile Dockerfile --name ns-name -t ns-name:tag`; the error gives the exact command. |
|
|
125
125
|
| A region outside the US | Runtime runs in one US region. |
|
|
126
126
|
| `extraArgs` other than `iptables`; network `egress`, `firewall`, `subnet`, and a `proxy` with more than its domain lists | Remove them; `allowedDomains` and `forbiddenDomains` (on the network or its proxy); Runtime secrets. |
|
|
127
127
|
| Read-only and ephemeral volumes; a volume with no Runtime volume of that name | Mount read-write; write scratch files under `/workspace`; `runtime.volumes.create`. |
|
package/COMPATIBILITY.md
CHANGED
|
@@ -18,14 +18,79 @@ published 30 September 2026, is a different package: it removes `getSandbox`, th
|
|
|
18
18
|
pin stays 0.12.10; `compatibility-lock.json` records 1.0.0 as reviewed and
|
|
19
19
|
unsupported, and `bun run compat:upstream` flags any other release.
|
|
20
20
|
|
|
21
|
-
| Provider | Published package inspected | Runtime import | Implemented sandbox surface
|
|
22
|
-
| ----------- | --------------------------------------- | ------------------------- |
|
|
23
|
-
| Runloop | `@runloop/api-client`
|
|
24
|
-
| CodeSandbox | `@codesandbox/sdk` 2.4.2 | `withruntime/codesandbox` | `CodeSandbox`, `VMTier`, create/fork/resume/shutdown/restart/hibernate/delete/list/get; connected command and file clients; output/status subscriptions and same-client command restart; configured tasks and setup steps; public preview ports and readiness checks
|
|
25
|
-
| Fly Sprites | `@fly/sprites` 0.2.3 | `withruntime/sprites` | `SpritesClient`, create/lookup/list/delete/restart; `exec`, `execFile`, Node streams and event-based `spawn`; attachable native processes; binary/text/JSON files, directory traversal, append, chmod; preview access settings
|
|
26
|
-
| Freestyle | `freestyle` 0.2.
|
|
27
|
-
| Modal | `modal` 0.11.0 | `withruntime/modal` | `ModalClient`, app-name grouping, registry images and Dockerfile layers, CPU sandbox create/get/list/name lookup, text/binary process streams and stdin, command completion, filesystem transfer and metadata, tags, encrypted public previews, outbound allowlists, memory snapshot capture
|
|
28
|
-
| Cloudflare | `@cloudflare/sandbox` 0.12.10 (0.x API) | `withruntime/cloudflare` | `getSandbox`, named Runtime sandboxes, explicit execution sessions, text exec and SSE output, background processes, logs/signals/waits, binary/text files, recursive listings, environment updates, signed Runtime previews, conditional Worker Durable Object entry, Worker preview proxy, destruction
|
|
21
|
+
| Provider | Published package inspected | Runtime import | Implemented sandbox surface |
|
|
22
|
+
| ----------- | --------------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
23
|
+
| Runloop | `@runloop/api-client` 2.0.0 | `withruntime/runloop` | `Runloop`, basic `RunloopSDK` command handles, devbox create/get/list/suspend/resume/shutdown, disk snapshots; synchronous and asynchronous commands, resident named shells with variables, functions, aliases, options and working directory, execution completion/output/stdin/signals, text files |
|
|
24
|
+
| CodeSandbox | `@codesandbox/sdk` 2.4.2 | `withruntime/codesandbox` | `CodeSandbox`, `VMTier`, create/fork/resume/shutdown/restart/hibernate/delete/list/get; connected command and file clients; output/status subscriptions and same-client command restart; configured tasks and setup steps; public preview ports and readiness checks |
|
|
25
|
+
| Fly Sprites | `@fly/sprites` 0.2.3 | `withruntime/sprites` | `SpritesClient`, create/lookup/list/delete/restart; `exec`, `execFile`, Node streams and event-based `spawn`; attachable native processes; binary/text/JSON files, directory traversal, append, chmod, chown and `asRoot` through sudo, file watches; preview access settings; checkpoints as disk snapshots; domain network policy; session kill; port watcher and port proxy; `APIError` with the vendor's limit codes |
|
|
26
|
+
| Freestyle | `freestyle` 0.2.17 | `withruntime/freestyle` | `Freestyle`, VM create/ref/get/list/start/pause/delete/update; command execution, binary/text files and streams, filesystem metadata; native snapshots; explicit deny-all or outbound-public firewall intent |
|
|
27
|
+
| Modal | `modal` 0.11.0 | `withruntime/modal` | `ModalClient`, app-name grouping, registry images and Dockerfile layers, CPU sandbox create/get/list/name lookup, text/binary process streams and stdin, command completion, filesystem transfer and metadata, tags, encrypted public previews, outbound allowlists, memory snapshot capture |
|
|
28
|
+
| Cloudflare | `@cloudflare/sandbox` 0.12.10 (0.x API) | `withruntime/cloudflare` | `getSandbox`, named Runtime sandboxes, explicit execution sessions, text exec and SSE output, background processes, logs/signals/waits, binary/text files, recursive listings, environment updates, signed Runtime previews, conditional Worker Durable Object entry, Worker preview proxy, destruction |
|
|
29
|
+
|
|
30
|
+
### Freestyle 0.2.17 review (11 October 2026)
|
|
31
|
+
|
|
32
|
+
The pin advances from 0.2.16; support remains partial. The exact npm tarballs
|
|
33
|
+
were compared without installing or executing them.
|
|
34
|
+
|
|
35
|
+
- New `FreestyleTransportError` (a `TypeError` with `errors` and `toJSON`) for a
|
|
36
|
+
fetch that got no HTTP response. The adapter throws it, with the native
|
|
37
|
+
`ConnectionError` as `cause`, where it used to throw `FreestyleApiError`.
|
|
38
|
+
- `exec` accepts `timeoutMs` up to 24 hours on guest agents with native
|
|
39
|
+
resumable exec, else 5 minutes (`AGENT_UNSUPPORTED`). Runtime passes the
|
|
40
|
+
value to its native exec unchanged; no adapter change.
|
|
41
|
+
- `ListObjects` joins the S3 operations of the TLS edge (refused here with the
|
|
42
|
+
rest of `tls`). Identity-token clients now background execs; identity tokens
|
|
43
|
+
are refused here. Docs-only changes elsewhere.
|
|
44
|
+
|
|
45
|
+
### Runloop 2.0.0 review (8 October 2026)
|
|
46
|
+
|
|
47
|
+
Both `@runloop/api-client` and Python `runloop-api-client` 2.0.0 retain the
|
|
48
|
+
covered sandbox API. Both pins advance; support remains partial. The exact npm
|
|
49
|
+
tarballs and every PyPI wheel/source archive for 1.32.0 and 2.0.0 were compared
|
|
50
|
+
without installing or executing them. Python wheel and source package contents
|
|
51
|
+
match. The upstream checker needs no new record type: this is a sandbox adapter
|
|
52
|
+
update, not a refusal of the major release or deferred source qualification.
|
|
53
|
+
|
|
54
|
+
- Both releases remove benchmark jobs/runs, scenarios, scorers, their types and
|
|
55
|
+
pagination, shared `RunProfile`, benchmark/scenario key scopes, and the
|
|
56
|
+
`scenario`/`scoring_validation` devbox initiators. Python also removes
|
|
57
|
+
`InputContextPreview`. None was implemented by these sandbox adapters.
|
|
58
|
+
- JavaScript execution `sendStdIn` now requires a body; the options-only overload
|
|
59
|
+
is removed. Both languages require exactly one nonempty text value or signal.
|
|
60
|
+
The adapters validate before lookup and map text, EOF and INTERRUPT to native
|
|
61
|
+
process input, EOF and SIGINT. Python's new synchronous/asynchronous
|
|
62
|
+
`Execution.send_std_in` and `close_std_in` helpers are implemented with scoped
|
|
63
|
+
request timeouts. JavaScript adds `RunloopSDK.devbox.create`/`fromId`,
|
|
64
|
+
`cmd.exec`/`execAsync`, and execution handles with `sendStdIn`/`closeStdIn`,
|
|
65
|
+
state, kill and result/output methods. The handle calls the same validated
|
|
66
|
+
low-level input path and throws `RunloopError` on an unsuccessful reply.
|
|
67
|
+
This is a basic command facade, not the full upstream high-level SDK:
|
|
68
|
+
callback streaming and extra polling options refuse with native alternatives;
|
|
69
|
+
file, shell, snapshot and list workflows still use the low-level adapter.
|
|
70
|
+
- New `SecretById`/`AsyncSecretById` handles and retrieve/update/delete-by-ID calls
|
|
71
|
+
select exact secret rows. Name reads/updates instead select the greatest ID;
|
|
72
|
+
deletion removes all selected same-name rows nonatomically. Runloop's duplicate
|
|
73
|
+
secret rows and injected environment-secret semantics are not Runtime's
|
|
74
|
+
host-scoped secret API. Access to the secret namespace refuses explicitly and
|
|
75
|
+
names that native alternative.
|
|
76
|
+
- Objects add `upload_headers`; upload helpers preserve those headers, isolate
|
|
77
|
+
API credentials, refuse redirects/retries and redact upload errors. Python's
|
|
78
|
+
storage wrappers accept optional headers and clear them on completion. The
|
|
79
|
+
adapter refuses Runloop storage objects and points to Runtime sandbox files.
|
|
80
|
+
- Axons add `deleted_at_ms` and retain readable deleted registry entries while
|
|
81
|
+
refusing updates; gateway/MCP/network-policy names become reusable labels, and
|
|
82
|
+
devbox gateway/MCP names bind the newest configuration. Those provider service
|
|
83
|
+
namespaces refuse explicitly, naming Runtime events, secrets or sandbox egress
|
|
84
|
+
settings as the alternative; these are not equivalent Runloop services.
|
|
85
|
+
- Tunnel documentation clarifies that omitted authentication means open/public.
|
|
86
|
+
Runloop tunnels remain outside the covered surface; use Runtime signed
|
|
87
|
+
previews. Python custom CPU annotations change from integer to float, allowing
|
|
88
|
+
0.5 cores upstream; the adapters still refuse fractional CPU before allocation
|
|
89
|
+
and direct callers to Runtime whole cores.
|
|
90
|
+
|
|
91
|
+
The focused tests use simulated native processes/transports and guest state.
|
|
92
|
+
They do not execute the downloaded SDKs or prove live Runloop behavior,
|
|
93
|
+
Linux isolation, durability, host recovery, or a competitor performance margin.
|
|
29
94
|
|
|
30
95
|
## Authentication and resources
|
|
31
96
|
|
|
@@ -128,7 +193,7 @@ Remaining implementation work is tracked only in the repository `WORKLIST.md`.
|
|
|
128
193
|
| All six | Default sandboxes use Runtime's environment. Explicit vendor image/template/snapshot IDs require migration to Runtime; arbitrary foreign IDs are not substituted with a stock image. Provider credential formats, wire protocols, error hierarchies and every optional transport hook are not interchangeable. Retained process output is bounded. Binary process mode requires the native byte-output capability (`outputEncoding`); an API or guest without it refuses before execution. This capability has only local release evidence here. |
|
|
129
194
|
| Runloop | Blueprints name Runtime image IDs/names; snapshots name Runtime snapshots. No provider blueprint builds, mounts, secret gateways, MCP grants, lifecycle hooks or ARM placement. `X_SMALL`/fractional CPU shapes are refused. Named shells use a resident Bash process. Interactive stdin in named shells is explicitly refused. `snapshotDisk` takes a blocking disk-only native snapshot; `snapshotDiskAsync` is refused, a memory snapshot is refused as a disk snapshot, and snapshot metadata beyond Runtime's label bounds is refused. `diskSnapshots` lists, updates, polls and deletes them. Devbox and snapshot lists return cursor pages that can be awaited or iterated across pages; the generated `APIPromise` wrapper and its response helpers are not reproduced. |
|
|
130
195
|
| CodeSandbox | No browser editor/Pitcher protocol, browser-session tokens, interpreters, live VM resizing, fork tier changes, read-only or global editor sessions, or private host-token emulation. Configured tasks run under a guest supervisor and setup steps under a guest runner, both started by the adapter and surviving client disconnects; a task's port must be configured with `task.preview.port`, because automatic task-to-port discovery is refused. Private host-only preview requests fail explicitly; native signed preview URLs remain available. Public port discovery lists registered previews, not all listening sockets. Default workspace is prepared at `/project/sandbox`. Command restart preserves the originating client's captured argv, environment and working directory; a command discovered by another client refuses restart because its private spawn recipe is unavailable. |
|
|
131
|
-
| Sprites | No control-mode WebSocket protocol, managed services,
|
|
196
|
+
| Sprites | No control-mode WebSocket protocol, managed services, in-place checkpoint restore (start a new sandbox from the snapshot), checkpoint history filters, network presets (`include`), an allow rule inside a denied wildcard (Runtime's deny always wins), privilege or resource policies, `maxRunAfterDisconnect`, Fly token exchange or Sprite list streaming; each is refused by name. A checkpoint is a Runtime disk snapshot (files, not running processes); the Sprite pauses for the moment it takes. An allow rule makes an allowlist, as Sprites' DNS allowlist does. The port watcher polls `ss` once a second. Session handles use native process IDs, not tmux. The sprite URL maps port 8080. File bytes and process byte streams preserve binary data. |
|
|
132
197
|
| Freestyle | Provider catalog snapshot slugs are not Runtime snapshots and are refused. Firewall support is limited to an explicit empty rule set or the exact allow-public-outbound shape; arbitrary rule selectors, TLS policies and private networks are refused. No automatic-restart guarantee, retention scheduler, placement constraints, live resize, Linux-user switching, PTY namespace, public IPv6 or account-owned egress address emulation. Native snapshot retention is positive whole days. |
|
|
133
198
|
| Modal | CPU sandboxes only; different resource reservation/limit values, fractional CPU, GPU and foreign placement are refused. Named Apps group Runtime sandboxes; they do not deploy Functions. Registry authentication uses Runtime's registry configuration. No Functions/Cls, volumes/bucket mounts, GPU image steps, readiness probes, sidecars, directory mounts, filesystem-only images from snapshots, or snapshot restoration API. Entry-point completion stops the sandbox while the originating client is alive; the native lease remains the bound if that client disappears. A different client can reconnect using the saved entrypoint process ID. |
|
|
134
199
|
| Cloudflare | The conditional Worker entry supplies a Durable Object bridge and custom-hostname preview proxy; infrastructure configuration must still remove the vendor Container declaration and provide Runtime secrets. Custom preview routing is implemented but has no live public-hostname acceptance evidence. No isolated PID namespaces, interpreter contexts, bucket mounts, backup format, terminal WebSocket protocol, watchers/change versions, custom process IDs or provider cleanup-record semantics. Foreground named sessions use resident Bash; background processes inherit exported state/cwd but do not yet inherit every local variable/function/option. |
|
package/DAYTONA.md
CHANGED
|
@@ -17,7 +17,8 @@ from withruntime.daytona import AsyncDaytona # was: from daytona import AsyncDa
|
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
The mapping was written against `@daytona/sdk` 0.220.0 and `daytona` 0.220.0
|
|
20
|
-
on PyPI, checked
|
|
20
|
+
on PyPI, and checked against `@daytona/sdk` and `daytona` 0.223.1 on
|
|
21
|
+
9 October 2026 (below, "0.223.1"). The exact releases and artifact hashes
|
|
21
22
|
are kept in `compatibility-lock.json`.
|
|
22
23
|
|
|
23
24
|
## Keys
|
|
@@ -65,7 +66,7 @@ package talks only to Runtime.
|
|
|
65
66
|
| `resources`, `envVars`, `labels`, `name`, `volumes` | `vcpu`, `memoryMiB`, `diskMiB`; environment given to every command; labels; name; Runtime volumes by id or by name. |
|
|
66
67
|
| `setLabels` (Python `set_labels`) | Replaces customer labels while preserving the language and Runtime compatibility labels; reconnects retain the language. |
|
|
67
68
|
| `networkBlockAll`, `networkAllowList`, `domainAllowList`, `outboundProxyUrl` | Runtime network rules (`internet: false`, or an `allow` list); the proxy as `HTTP_PROXY` and `HTTPS_PROXY` for commands. |
|
|
68
|
-
| `public: true`
|
|
69
|
+
| `public: true`, `setPublic` (Python `set_public`) | `getPreviewLink(port)` shares the port publicly; without it, privately with a token. `setPublic` turns every port already shared public or private at once, at the same address. |
|
|
69
70
|
| `language` | The language of `codeRun`, kept in Daytona's `code-toolbox-language` label so a sandbox found later keeps it. |
|
|
70
71
|
| `daytona.get(idOrName)`, `daytona.list(query)` | `sandboxes.get`, or the newest live sandbox with that name; `sandboxes.list` by labels and states, then Daytona's other filters (`id` and `name` prefixes, CPU, memory, disk, dates), `sort` and `order` here. Awaiting `list()` gives the older `{ items, total }` shape. |
|
|
71
72
|
| `process.executeCommand(cmd, cwd, env, timeout)` | `exec` under bash with stderr joined to stdout, as Daytona's `result`, streamed so the whole output comes back. A non-zero exit is a result. Past `timeout` (seconds): `DaytonaProcessExecutionTimeoutError`. |
|
|
@@ -82,7 +83,7 @@ package talks only to Runtime.
|
|
|
82
83
|
| `getUserHomeDir`, `getWorkDir`, `user` | `/workspace`, and `daytona`, so `/home/daytona` (linked to `/workspace` the first time something names it) works. |
|
|
83
84
|
| `create({ user })` (Python `os_user`) | The user must exist in the image, as on Daytona. Commands, sessions and terminals run as it through `sudo`; files written through `fs` are given to it. It joins the owner's group, so both can share `/workspace`. |
|
|
84
85
|
| `process.createPty`, `connectPty`, `listPtySessions`, `resizePtySession` | A shell started with a terminal, which outlives the connection: `disconnect()` leaves it running, `connectPty` attaches again with what it printed so far, `killPtySession` ends it. |
|
|
85
|
-
| `computerUse.mouse`, `keyboard`, `screenshot`, `display`, `recording` | Runtime's desktop. `start()` installs it the first time, which takes a minute or two. Key names are Daytona's or xdotool's.
|
|
86
|
+
| `computerUse.mouse`, `keyboard`, `screenshot`, `display`, `recording` | Runtime's desktop. `start()` installs it the first time, which takes a minute or two. Key names are Daytona's or xdotool's. `mouse.down` and `up` hold and release a button; `scroll` goes up, down, left or right. |
|
|
86
87
|
| `daytona.snapshot.create`, `get`, `list`, `delete` | Runtime images built, found, listed and deleted by name. |
|
|
87
88
|
| `daytona.volume.get`, `list`, `delete` | Runtime volumes by name. |
|
|
88
89
|
| Error classes | Daytona's names and parents, by HTTP status. Each also carries Runtime's `code`, `hint` and `requestId`, with the original error as `cause`. |
|
|
@@ -94,14 +95,16 @@ Each of these throws `NotSupportedError` before anything happens. Its
|
|
|
94
95
|
|
|
95
96
|
| Daytona | Use instead |
|
|
96
97
|
| --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
97
|
-
| A snapshot name with no Runtime image or snapshot | `daytona.snapshot.create({ name, image })` here, or `npx withruntime
|
|
98
|
+
| A snapshot name with no Runtime image or snapshot | `daytona.snapshot.create({ name, image })` here, or `npx withruntime images build`. This throws `DaytonaNotFoundError`. |
|
|
98
99
|
| GPUs, `spot`, `linkedSandbox`, `secrets`, `otelEndpointOverride` | Runtime runs Linux on CPUs. For `secrets`, a Runtime secret (`npx withruntime secrets set NAME --host <host>`): the sandbox sees a placeholder. For telemetry, `runtime.otel.create()`. |
|
|
99
100
|
| A `target` other than `us`, `jwtToken` | Runtime runs in one US region and signs in with keys. |
|
|
100
101
|
| The entrypoint session, language servers | Sessions with `runAsync`. |
|
|
101
102
|
| Screenshots of a region, with the cursor, scaled, or as WebP | The whole screen as PNG or JPEG; crop and scale it yourself. |
|
|
102
103
|
| `computerUse.accessibility`, the desktop's processes one by one | Screenshots with the mouse and keyboard; `computerUse.getStatus()`, `stop()` and `start()`. |
|
|
104
|
+
| `keyboard.down` and `up`, `modifiers` on a click, drag or scroll | `keyboard.press(key, modifiers)` or `keyboard.hotkey("ctrl+shift+t")`: the keys pressed together at once. |
|
|
105
|
+
| `clicks` above 2 | One click, or two with `double`; to select a line, click once and press shift+End. |
|
|
103
106
|
| `resize`, `recover` | Set labels and resources at create; create a new sandbox. |
|
|
104
|
-
| Signed preview URLs, signed upload and download URLs, SSH access | `getPreviewLink`, `fs.uploadFile` and `downloadFile`, `npx withruntime
|
|
107
|
+
| Signed preview URLs, signed upload and download URLs, SSH access | `getPreviewLink`, `fs.uploadFile` and `downloadFile`, `npx withruntime sandboxes ssh <id>`. |
|
|
105
108
|
| `getMetrics` | `sandbox.withruntime.metrics()`: its CPU and memory over time. |
|
|
106
109
|
| `Image.pipInstallFromPyproject`, snapshot `resources` or `entrypoint` | `pipInstallFromRequirements`; resources at create; a session after create. |
|
|
107
110
|
| `volume.create(name)` | Runtime volumes have a size: `runtime.volumes.create({ name, sizeMiB })`. |
|
|
@@ -123,6 +126,31 @@ Some differences are not refusals:
|
|
|
123
126
|
- `autoArchiveInterval` is recorded only: Runtime has no archive tier.
|
|
124
127
|
- Runtime's stock image is Ubuntu 24.04 with Python 3.12, Node.js 24 and Bun.
|
|
125
128
|
|
|
129
|
+
## 0.223.1, 9 October 2026
|
|
130
|
+
|
|
131
|
+
Reviewed the published npm tarballs for `@daytona/sdk`, `@daytona/api-client`,
|
|
132
|
+
`@daytona/toolbox-api-client` and `@daytona/analytics-api-client` 0.223.0 →
|
|
133
|
+
0.223.1, and the PyPI wheel and sdist for `daytona` 0.223.0 → 0.223.1. Each was
|
|
134
|
+
its registry's latest when checked. Every pinned file matched the hash already
|
|
135
|
+
in `compatibility-lock.json`, and every new file matched its registry's SHA-512
|
|
136
|
+
integrity or SHA-256 digest; each wheel's Python source is byte for byte its
|
|
137
|
+
sdist's. Nothing was installed, imported or run. The three API clients changed
|
|
138
|
+
only their version. `@daytona/sdk` changed `Sandbox` and `Process` (ESM and
|
|
139
|
+
CommonJS alike), and `daytona` the same two modules, sync and async.
|
|
140
|
+
|
|
141
|
+
| Upstream change | Drop-in disposition |
|
|
142
|
+
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
143
|
+
| `sandbox.setPublic(isPublic)` (Python `set_public(public, request_timeout=None)`) makes the sandbox's preview URLs public or private, and sets `sandbox.public`. | Followed, in both languages. Every port already shared whose visibility differs is shared again with the new one, at the same address, and later `getPreviewLink` calls use it. Without credit Runtime refuses a public share (`public_preview_not_allowed`) and `public` is unchanged. |
|
|
144
|
+
| `executeCommand` (Python `exec`) documents that commands run under zsh, bash or sh (zsh in Daytona's images), how to start a server in the background, and that `nproc` may report the host's CPUs. | Documentation only. The drop-in keeps running commands under bash, which is what Daytona's quoting advice is for; a sandbox's `nproc` reports its own vCPUs. |
|
|
145
|
+
| `getPreviewLink` and `getSignedPreviewUrl` (Python `create_signed_preview_url`) document the token header, the API key as a bearer token, and a longer expiry. | Documentation only. A Runtime private preview takes its token as `x-runtime-preview-token`; signed preview URLs stay refused, as above. |
|
|
146
|
+
| `@daytona/sdk` requires `shell-quote` ^1.11.0, was ^1.8.2. | The oracle's `bun.lock` already resolved 1.11.0. |
|
|
147
|
+
|
|
148
|
+
`tests/daytona/daytona-0-223-1.test.ts` and
|
|
149
|
+
`sdks/python/tests/test_daytona_0_223_1.py` check `setPublic` both ways, that
|
|
150
|
+
a public port is not shared again, and the refusal without credit; they fail
|
|
151
|
+
without this change. The oracle was not run against the new release, since it
|
|
152
|
+
executes Daytona's code; the provider remains marked `partial`.
|
|
153
|
+
|
|
126
154
|
## Tests
|
|
127
155
|
|
|
128
156
|
`bun run test` in `packages/cloud-sdk` runs the unit tests of both languages
|
package/E2B.md
CHANGED
|
@@ -20,40 +20,64 @@ from withruntime.e2b import Sandbox # was: from e2b import Sandbox
|
|
|
20
20
|
from withruntime.e2b.code_interpreter import Sandbox # was: from e2b_code_interpreter import Sandbox
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
The mapping was written against `e2b` 2.51.0 and checked against `e2b` 2.
|
|
24
|
-
and `@e2b/code-interpreter` 2.8.
|
|
25
|
-
2.
|
|
26
|
-
`compatibility-lock.json`.
|
|
23
|
+
The mapping was written against `e2b` 2.51.0 and checked against `e2b` 2.55.0
|
|
24
|
+
and `@e2b/code-interpreter` 2.8.3 on 9 October 2026. Python was checked
|
|
25
|
+
against `e2b` 2.55.1 and `e2b-code-interpreter` 2.10.5 the same day. The exact
|
|
26
|
+
package releases and artifact hashes are kept in `compatibility-lock.json`.
|
|
27
27
|
|
|
28
28
|
## Keys
|
|
29
29
|
|
|
30
30
|
The package uses, in order: an `apiKey` you pass, `RUNTIME_API_KEY`, a Runtime
|
|
31
31
|
key left in `E2B_API_KEY`, and the key `npx withruntime login` saved on this
|
|
32
32
|
machine. An E2B key (`e2b_...`) is never sent anywhere. If one is passed as
|
|
33
|
-
`apiKey` and `RUNTIME_API_KEY` is not set, the call
|
|
34
|
-
`AuthenticationError
|
|
33
|
+
`apiKey`, or left in `E2B_API_KEY`, and `RUNTIME_API_KEY` is not set, the call
|
|
34
|
+
fails with `AuthenticationError` (Python: `AuthenticationException`) saying
|
|
35
|
+
so, rather than fall back to a saved login that may be another account's.
|
|
36
|
+
When `RUNTIME_API_KEY` and `E2B_API_KEY` hold two different Runtime keys, which
|
|
37
|
+
may be two accounts, a warning says so once (`RUNTIME_E2B_TWO_KEYS`; Python: a
|
|
38
|
+
`RuntimeWarning`). A template with no image of its name fails naming the
|
|
39
|
+
account the key belongs to and where the key came from.
|
|
35
40
|
|
|
36
41
|
## What a sandbox gets
|
|
37
42
|
|
|
38
43
|
- **Machine:** E2B's default, 2 vCPU and 512 MiB. For another, pass
|
|
39
44
|
`runtime: { create: { memoryMiB: 4096 } }` (Python:
|
|
40
45
|
`runtime_create={"memory_mib": 4096}`).
|
|
41
|
-
- **Timeout:**
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
- **Timeout:** kept by Runtime's server, never by a timer in your process,
|
|
47
|
+
so it holds after the process that made the sandbox exits. A `timeoutMs`
|
|
48
|
+
you give (Python `timeout`, seconds), up to 24 hours, deletes the sandbox
|
|
49
|
+
when it runs out, as E2B kills it; so does `lifecycle: { onTimeout: "kill" }`.
|
|
50
|
+
With no timeout, E2B's default of 300 seconds applies, and when it runs out
|
|
51
|
+
the sandbox **pauses** instead: nobody asked for it to end, so nothing is
|
|
52
|
+
lost, and the next call wakes it. E2B deletes it at that point.
|
|
53
|
+
`lifecycle: { onTimeout: "pause" }` pauses at any timeout.
|
|
54
|
+
- **What a pause keeps, and costs:** memory, files and running processes, for
|
|
55
|
+
as long as the account has credit, billed as paused storage by the GB a
|
|
56
|
+
month for what the sandbox alone holds (`pricing.md`, "Paused storage").
|
|
57
|
+
Sandboxes created with no timeout and never killed pile up as paused
|
|
58
|
+
storage: call `kill()` when the work is done, or give a `timeoutMs`.
|
|
59
|
+
- **On a pilot account:** the server keeps every sandbox running until you
|
|
60
|
+
end it, with no idle pause, whatever `timeoutMs` says, and machine size is
|
|
61
|
+
the pilot's. `kill()` deletes it.
|
|
62
|
+
- **Kill:** `kill()` deletes the sandbox for good, as E2B's does: its disk,
|
|
63
|
+
memory and shared ports go, and it no longer counts against the account's
|
|
64
|
+
sandboxes.
|
|
44
65
|
- **Idle pause:** Runtime's default, which E2B does not have. After 60
|
|
45
66
|
seconds with nothing happening in it (no request, running command, open
|
|
46
67
|
connection, traffic or CPU use) the sandbox pauses with its memory kept, and
|
|
47
|
-
the next command or file call wakes it.
|
|
48
|
-
|
|
49
|
-
|
|
68
|
+
the next command or file call wakes it. To code written for E2B it is still
|
|
69
|
+
running: `isRunning()` is `true`, `getInfo()` says `running` and
|
|
70
|
+
`list({ query: { state: ["running"] } })` includes it. Pass
|
|
50
71
|
`runtime: { create: { idlePauseSeconds: 0 } }` (Python:
|
|
51
72
|
`runtime_create={"idle_pause_seconds": 0}`) to keep it running, as on E2B.
|
|
52
|
-
- **Connections:** one client per key, holding
|
|
53
|
-
API at once,
|
|
54
|
-
|
|
55
|
-
commands at once from one process
|
|
56
|
-
|
|
73
|
+
- **Connections:** one client per key, holding up to 4,096 connections to
|
|
74
|
+
the API at once, the most Runtime's edge gives an address that has used a
|
|
75
|
+
valid key. E2B's SDK holds no call back, and neither does this one: a
|
|
76
|
+
thousand commands at once from one process all run at once. Past an
|
|
77
|
+
account's room the API answers with a retry, which the client waits out. If
|
|
78
|
+
calls ever wait for a connection, a warning says so once
|
|
79
|
+
(`RUNTIME_E2B_QUEUED`). Runtime's own SDK keeps 48; pass your own client
|
|
80
|
+
with `runtime: { client: new Runtime({ maxConnections }) }` (Python:
|
|
57
81
|
`client=Runtime(max_connections=...)`).
|
|
58
82
|
- **Funding:** left to Runtime, as `withruntime`'s own `create()` does. The
|
|
59
83
|
free trial is used while the account has trial time, then prepaid credit.
|
|
@@ -67,38 +91,38 @@ machine. An E2B key (`e2b_...`) is never sent anywhere. If one is passed as
|
|
|
67
91
|
|
|
68
92
|
| E2B | On Runtime |
|
|
69
93
|
| ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
70
|
-
| `Sandbox.create()`, `Sandbox.create(template, opts)` | `sandboxes.create`. `base` and `code-interpreter-v1` are Runtime's stock image. Any other name
|
|
71
|
-
| `timeoutMs` (Python `timeout`, seconds) |
|
|
94
|
+
| `Sandbox.create()`, `Sandbox.create(template, opts)` | `sandboxes.create`. `base` and `code-interpreter-v1` are Runtime's stock image. Any other name, with its `:tag`, is a Runtime image of that name, resolved by the create itself; E2B's `team/` prefix is dropped, since an account's images are its own. A UUID is an image or a snapshot. A name no image has throws `TemplateError` saying how to build it. |
|
|
95
|
+
| `timeoutMs` (Python `timeout`, seconds) | `timeoutSeconds`, rounded up, kept by the server, with `onTimeout: "delete"`. Left out, 300 s with `onTimeout: "pause"`. Under 60 s becomes 60 s, with a warning. Up to 24 hours, as on E2B; over throws `InvalidArgumentError`. |
|
|
72
96
|
| `metadata` | labels (at most 32). |
|
|
73
97
|
| `envs` | Given to every command and code run through this object. |
|
|
74
98
|
| `allowInternetAccess: false` | `network: { internet: false }`. |
|
|
75
|
-
| `lifecycle.onTimeout` | `
|
|
99
|
+
| `lifecycle.onTimeout` | `onTimeout`: `kill` is `delete`, `pause` is `pause`; `{ action: "pause", mode: "full" }` is `pause`. |
|
|
76
100
|
| `commands.run(cmd, { cwd, envs, timeoutMs, onStdout, onStderr })` | A native process started by a streamed exec that reads it from the first byte, so Runtime holds a fast writer back rather than drop output: the result is whole, however long. The default command connection deadline is 60 s; `0` disables it. The process lives up to 24 hours, within the sandbox lease. |
|
|
77
101
|
| Non-zero exit | Throws `CommandExitError` with `exitCode`, `stdout`, `stderr` and `error` (`exit status N`). A command killed by a signal has `exitCode` -1. |
|
|
78
|
-
| Command past its timeout | Disconnects with `TimeoutError` (Python: `TimeoutException`) without killing the command; reconnect by pid to keep reading.
|
|
102
|
+
| Command past its timeout | Disconnects with `TimeoutError` (Python: `TimeoutException`) without killing the command; reconnect by pid to keep reading. A JavaScript command whose sandbox is killed under it throws `SandboxNotRunningError`, a `TimeoutError`, saying the sandbox was killed or reached its end of life. |
|
|
79
103
|
| `commands.run(cmd, { background: true })` | `spawn`. Returns a `CommandHandle` with `pid`, `wait()`, `kill()` (SIGKILL), `sendStdin`, `closeStdin`, `disconnect`, `stdout`, `stderr`, `exitCode`. Runtime keeps the last 1 MiB a process printed; anything older that was not read in time is lost, which sets `truncated` and warns. A command with `stdin: true` starts the same way. |
|
|
80
104
|
| `user` (commands, PTY and files) | Runs as that Linux user through `sudo -u`; `root` needs nothing more. A user the sandbox lacks throws `InvalidArgumentError` saying how to add one; none is ever created. `user: "user"` is the sandbox's own user. Watching a directory as another user is refused. |
|
|
81
|
-
| `commands.list`, `kill(pid)`, `sendStdin(pid)`, `closeStdin(pid)`, `connect(pid)` | Runtime's processes. A pid is a number derived from Runtime's process id, not the Linux pid.
|
|
105
|
+
| `commands.list`, `kill(pid)`, `sendStdin(pid)`, `closeStdin(pid)`, `connect(pid)` | Runtime's processes. A pid is a number derived from Runtime's process id, not the Linux pid. `commands.list` shows each command as E2B starts it: `cmd` `/bin/bash`, `args` `["-l", "-c", "<your command>"]` (a PTY: `["-i", "-l"]`), the command cut at 256 characters, `envs` empty. |
|
|
82
106
|
| `pty.create`, `connect`, `sendInput`, `resize`, `kill` (Python snake_case) | Native PTY processes with lossless byte callbacks. A reader timeout or disconnect detaches without killing the process; reconnect resumes reading. |
|
|
83
107
|
| `files.read(path, { format })` | `files.read`. `text`, `bytes`, `blob` and `stream` (Python: `text`, `bytes`, `stream`). |
|
|
84
108
|
| `files.write(path, data)`, `write([...])`, `writeFiles` | `files.write`. Parent directories are made, and a file that exists is replaced. |
|
|
85
|
-
| `files.list(path, { depth })` | `files.list`, hidden files included. `owner` and `group` come from native metadata, with `""` for older guests that omit them.
|
|
86
|
-
| `files.makeDir`, `exists`, `getInfo`, `rename`, `remove` | `files.stat`, `mkdir`, `rename` (replacing a file that exists) and `remove` (recursive). A missing file throws `FileNotFoundError`.
|
|
87
|
-
| Relative paths | Resolved against the home directory, `/workspace` on Runtime.
|
|
109
|
+
| `files.list(path, { depth })` | `files.list`, hidden files included. `owner` and `group` come from native metadata, with `""` for older guests that omit them. `depth` below one throws `InvalidArgumentError` "depth should be at least one". |
|
|
110
|
+
| `files.makeDir`, `exists`, `getInfo`, `rename`, `remove` | `files.stat`, `mkdir`, `rename` (replacing a file that exists) and `remove` (recursive). A missing file throws `FileNotFoundError`. Entries read as envd gives them: `permissions` begins with the kind's letter (`-rw-r--r--`, `drwxr-xr-x`, `L` for a link), the sandbox user is `user`, and a link's `symlinkTarget` is absolute. |
|
|
111
|
+
| Relative paths | Resolved against the home directory, `/workspace` on Runtime, and given back under `/home/user`, as E2B gives them: `write("a.txt")` returns `/home/user/a.txt`. A path given in full comes back as given. `pwd` in a command prints `/workspace`. |
|
|
88
112
|
| `/home/user` (E2B's home) | The first time a path, `cwd` or command names it, it becomes a link to `/workspace`, unless something is already there. |
|
|
89
|
-
| `sandbox.kill()`, `Sandbox.kill(id)` | `
|
|
90
|
-
| `sandbox.setTimeout(ms)`, `Sandbox.setTimeout(id, ms)` | `extend`: the end moves to now + ms, up to 24 hours
|
|
113
|
+
| `sandbox.kill()`, `Sandbox.kill(id)` | `delete`: gone for good. `false` when the sandbox was not found or was already deleted. |
|
|
114
|
+
| `sandbox.setTimeout(ms)`, `Sandbox.setTimeout(id, ms)` | `extend`: the end moves to now + ms, up to 24 hours. An earlier end is refused: Runtime cannot bring a time limit forward. A sandbox with no time limit (a pilot's) has no end to move, and nothing changes. |
|
|
91
115
|
| `Sandbox.connect(id, { timeoutMs })`, `sandbox.connect()` | `get`. A paused sandbox is woken. A running one's end moves later, never earlier, up to 24 hours. An ended one throws `SandboxNotFoundError`. |
|
|
92
116
|
| `sandbox.pause()`, `betaPause`, `Sandbox.pause(id)` | `pause`, keeping memory and files. `false` when it was already paused. |
|
|
93
|
-
| `getInfo`, `isRunning` | `get`. `templateId` is
|
|
117
|
+
| `getInfo`, `isRunning` | `get`. `templateId` is the template the sandbox was created from, as you named it (kept in the label `e2b-template`, which `metadata` leaves out), or `base`. `envdVersion` is `runtime`. A sandbox Runtime paused for being idle is `running`. `endAt` is when it ends by itself; one that never will (no time limit, as a pilot's) reads 24 hours ahead, the furthest E2B allows. |
|
|
94
118
|
| `Sandbox.list({ query: { metadata, state }, limit })` | `sandboxes.list` by labels and state, oldest first, with E2B's paginator (`hasNext`, `nextItems()`, `nextToken`). A `template` or `startedAfter` filter, `order: "desc"` and a saved `nextToken` are applied by the adapter, which reads every match once and pages through them. |
|
|
95
|
-
| `fork`, `createSnapshot`, `deleteSnapshot` | Runtime's memory-preserving forks and snapshots;
|
|
119
|
+
| `fork`, `createSnapshot`, `deleteSnapshot` | Runtime's memory-preserving forks and snapshots; `createSnapshot({ mode: "filesystem" })` is a disk snapshot, from which a sandbox boots afresh. Deleting a snapshot removes that saved capture. A fork's `count` is 1 to 20, as E2B checks it. |
|
|
96
120
|
| `getHost(port)` | `<port>-<id>.runtimehost.com` at once, as E2B answers it, and the port is shared as a public Runtime preview beside the caller (the sync Python sandbox shares it before returning). `await sandbox.getPublicHost(port)` returns once the share has landed. On the free trial a shared port is private and a host alone cannot reach it, so both throw `PublicPreviewNotAllowedError` (Python: `PublicPreviewNotAllowedException`, a kind of `NotSupportedError`) at once. Use `(await sandbox.runtime.previews.create(port)).urlWithToken`, or send its token as the `x-runtime-preview-token` header. |
|
|
97
121
|
| `runCode(code, { language, context, onStdout, onStderr, onResult, onError, timeoutMs })` | Runtime's interpreter: Python, JavaScript, TypeScript, R, Java and Bash, plus Go. The sandbox's `envs` reach code through a context made once for them. `onResult` streams each result and waits for asynchronous callbacks. |
|
|
98
122
|
| `Execution`, `Result`, `Logs`, `ExecutionError`, `OutputMessage` | The same shapes. Results that are too large to send inline are fetched and inlined. `logs.stdout` has one entry per line. |
|
|
99
123
|
| `createCodeContext`, `listCodeContexts`, `restartCodeContext`, `removeCodeContext` | Runtime's interpreter contexts. |
|
|
100
124
|
| `getMetrics({ start, end })`, `Sandbox.getMetrics(id)` | Runtime's measured CPU and memory, one entry per host reading. `diskUsed` is null: Runtime does not read disk use inside the sandbox. |
|
|
101
|
-
| Error classes
|
|
125
|
+
| Error classes and other exports | Every name `e2b` and the code interpreter export imports, errors with E2B's names and parents. Python also imports each from the module E2B defines it in, so `from e2b.exceptions import TimeoutException` becomes `from withruntime.e2b.exceptions import TimeoutException`, and `WriteEntry` comes from `withruntime.e2b.sandbox.filesystem.filesystem`. Each error also carries Runtime's `code`, `hint` and `requestId`, with the original error as `cause`. |
|
|
102
126
|
|
|
103
127
|
## Gaps
|
|
104
128
|
|
|
@@ -106,23 +130,23 @@ Each of these throws `NotSupportedError` (Python: `NotSupportedException`)
|
|
|
106
130
|
before anything happens. The error's `feature` names the gap and its
|
|
107
131
|
`alternative` says what to use.
|
|
108
132
|
|
|
109
|
-
| E2B | Use instead
|
|
110
|
-
| ------------------------------------------------------------- |
|
|
111
|
-
| An E2B template name with no Runtime image of that name | Build it: `npx withruntime
|
|
112
|
-
| `Template`, `waitForPort` and the other ready checks | `runtime.images.build(...)`
|
|
113
|
-
| `setTimeout` to an earlier time | `kill()` when the work is done.
|
|
114
|
-
| `keepMemory: false`
|
|
115
|
-
| `onResume: "reboot"` | Stop the sandbox and create a new one.
|
|
116
|
-
| `fork({ timeoutMs })` | Fork without it, then call `setTimeout` on each fork.
|
|
117
|
-
| `network`, `updateNetwork` | `runtime: { create: { network } }` and `sandbox.runtime.network.set(...)`.
|
|
118
|
-
| `mcp`, `getMcpUrl`, `getMcpToken` | Runtime's own MCP server, `npx withruntime mcp`.
|
|
119
|
-
| `iam`, `Secret` | A Runtime secret (`npx withruntime secrets set NAME --host <host>`): the sandbox sees a placeholder.
|
|
120
|
-
| `volumeMounts`, `Volume` | Runtime volumes: `runtime: { create: { volumes: [{ volumeId, path }] } }`.
|
|
121
|
-
| `git` | `commands.run("git ...")`. E2B has deprecated its git module too.
|
|
122
|
-
| File `metadata` | Keep it in a file beside the data.
|
|
123
|
-
| `uploadUrl`, `downloadUrl` | `files.write` and `files.read`.
|
|
124
|
-
| `runCode(code, { envs })` | A context made with them: `sandbox.runtime.interpreter.contexts.create({ env })`.
|
|
125
|
-
| `domain`, `apiUrl`, `sandboxUrl`, `headers`, `proxy`, `debug` | Remove them. `RUNTIME_API_URL` sets Runtime's origin, and `HTTPS_PROXY` sets a proxy.
|
|
133
|
+
| E2B | Use instead |
|
|
134
|
+
| ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
135
|
+
| An E2B template name with no Runtime image of that name | Build it: `npx withruntime images build --dockerfile e2b.Dockerfile --name <template>`. This throws `TemplateError`. |
|
|
136
|
+
| `Template`, `waitForPort` and the other ready checks | `runtime.images.build(...)` |
|
|
137
|
+
| `setTimeout` to an earlier time | `kill()` when the work is done. |
|
|
138
|
+
| A pause with `mode: "filesystem"` or `keepMemory: false` | Runtime's pause keeps memory. For the files alone, `createSnapshot({ mode: "filesystem" })`. |
|
|
139
|
+
| `onResume: "reboot"` | Stop the sandbox and create a new one. |
|
|
140
|
+
| `fork({ timeoutMs })` | Fork without it, then call `setTimeout` on each fork. |
|
|
141
|
+
| `network`, `updateNetwork` | `runtime: { create: { network } }` and `sandbox.runtime.network.set(...)`. |
|
|
142
|
+
| `mcp`, `getMcpUrl`, `getMcpToken` | Runtime's own MCP server, `npx withruntime mcp`. |
|
|
143
|
+
| `iam`, `Secret` | A Runtime secret (`npx withruntime secrets set NAME --host <host>`): the sandbox sees a placeholder. |
|
|
144
|
+
| `volumeMounts`, `Volume` | Runtime volumes: `runtime: { create: { volumes: [{ volumeId, path }] } }`. |
|
|
145
|
+
| `git` | `commands.run("git ...")`. E2B has deprecated its git module too. |
|
|
146
|
+
| File `metadata` | Keep it in a file beside the data. |
|
|
147
|
+
| `uploadUrl`, `downloadUrl` | `files.write` and `files.read`. |
|
|
148
|
+
| `runCode(code, { envs })` | A context made with them: `sandbox.runtime.interpreter.contexts.create({ env })`. |
|
|
149
|
+
| `domain`, `apiUrl`, `sandboxUrl`, `headers`, `proxy`, `debug` | Remove them. `RUNTIME_API_URL` sets Runtime's origin, and `HTTPS_PROXY` sets a proxy. |
|
|
126
150
|
|
|
127
151
|
Directory watches use Runtime's native watch stream. JavaScript uses
|
|
128
152
|
`files.watchDir(path, onEvent, options)`. Python's synchronous `watch_dir(path)`
|
|
@@ -131,6 +155,10 @@ returns a handle with `get_new_events()` and `stop()`; asynchronous
|
|
|
131
155
|
a callback. Stream failures and lost events are reported, never treated as a
|
|
132
156
|
successful empty watch. A positive watch timeout bounds the client subscription and stops its owned watch;
|
|
133
157
|
zero leaves the subscription unlimited. The sandbox lease still applies. Both languages refuse watching network mounts.
|
|
158
|
+
As on envd, a path that is a file is refused with `InvalidArgumentError`
|
|
159
|
+
(Python: `InvalidArgumentException`). Runtime writes a file whole, by a rename
|
|
160
|
+
into place, which its watch sees as a create; a file's create is therefore
|
|
161
|
+
followed by a write event, which E2B code waiting for the write receives.
|
|
134
162
|
|
|
135
163
|
PTY `timeoutMs` (Python `timeout`, seconds) defaults to sixty seconds, including
|
|
136
164
|
the opening handshake; zero leaves the reader unlimited. Callbacks receive raw
|
|
@@ -161,7 +189,7 @@ every refusal: `tests/e2b` here and `sdks/python/tests/test_e2b_*.py`.
|
|
|
161
189
|
|
|
162
190
|
The end-to-end tests run an unmodified E2B program against the real API with
|
|
163
191
|
its one import changed. They create six sandboxes on the key's account. Each
|
|
164
|
-
has 2 vCPU and 512 MiB, lasts at most five minutes and is
|
|
192
|
+
has 2 vCPU and 512 MiB, lasts at most five minutes and is deleted when its
|
|
165
193
|
case ends. They are not part of `bun run test`.
|
|
166
194
|
|
|
167
195
|
```bash no-run
|
|
@@ -171,3 +199,64 @@ RUNTIME_API_KEY=... python3 sdks/python/scripts/e2b_e2e.py # the same cas
|
|
|
171
199
|
|
|
172
200
|
Either one run with `--dry` sets up and shows the one-line change without
|
|
173
201
|
creating anything.
|
|
202
|
+
|
|
203
|
+
## JavaScript qualification, 6 October 2026
|
|
204
|
+
|
|
205
|
+
Reviewed the published npm tarballs for `e2b` 2.52.1 → 2.53.1 and
|
|
206
|
+
`@e2b/code-interpreter` 2.8.0 → 2.8.2. Both new versions were npm's latest
|
|
207
|
+
when checked. All four downloaded tarballs matched their registry SHA-512
|
|
208
|
+
integrities; the new values are in `compatibility-lock.json` and the oracle's
|
|
209
|
+
`bun.lock`. No package code was executed during source review.
|
|
210
|
+
|
|
211
|
+
Each package changed its manifest and six distribution files: CommonJS and
|
|
212
|
+
ES-module JavaScript, their source maps, and both declaration formats. The
|
|
213
|
+
source maps contain the TypeScript sources (no separate `src` directory ships);
|
|
214
|
+
CommonJS and ES-module source contents match. Ten E2B source files and three
|
|
215
|
+
interpreter source files changed. The changes and their dispositions:
|
|
216
|
+
|
|
217
|
+
| Upstream change | Drop-in disposition |
|
|
218
|
+
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
219
|
+
| `SandboxNotRunningError` and `SandboxUnreachableError`, exported by E2B and re-exported by the interpreter; both extend `TimeoutError` and accept `ErrorOptions.cause`. | Mirrored: both imports, names, parents, constructor signatures and causes match. Runtime's explicit `sandbox_stopped`, `sandbox_paused` and `sandbox_not_running` codes select the first; `sandbox_not_ready` and `host_unavailable` select the second. |
|
|
220
|
+
| HTTP 502 and RPC Unavailable distinguish a stopped sandbox from an unreachable one. Failed connection and ambiguous stream errors use a health probe; browser network failures are recognized too. Process and watch startup no longer replace Unavailable with `SandboxNotFoundError`. | Mirrored through Runtime's explicit state codes, including command, file, watch and interpreter guards. A command losing its sandbox now throws `SandboxNotRunningError`. E2B's envd health probes, proxy message matching and RPC parsing are not copied: Runtime uses its own API. An unclassified connection failure does not establish sandbox state and retains its existing error. |
|
|
221
|
+
| Streaming RPCs preserve a plain-text or JSON proxy 502 message; recognized Connect error codes retain their meaning. HTTP error-body extraction is shared with the health probe. | Not mirrored: E2B's proxy and Connect transport are not used. Runtime's structured code, message, hint, request id and original cause remain available. |
|
|
222
|
+
| Removed `E2B_USER_AGENT_SOURCE`, `ConnectionConfig.requestSource`, user-agent source suffixes, automatic CI error logging and trace-id diagnostics. Logger middleware now returns the request and response. | Not mirrored: Runtime never implemented those E2B transport diagnostics; `ConnectionConfig` and `ApiClient` remain unsupported. |
|
|
223
|
+
| Create, connect and fork share a response mapper and a private response type; the protected return annotations allow optional transport fields. | Not mirrored: this refactors E2B's transport response without changing public Sandbox behavior; Runtime builds its own sandbox objects. |
|
|
224
|
+
| Interpreter errors include a nonempty trimmed response body for generic HTTP failures, without a CI-only switch or trace suffix; 404 and 502 retain their previous classes. | Already preserves server explanations: Runtime translates its structured API errors, including the message, hint and request id. E2B's private Jupyter HTTP formatter and status-line wording are not used. |
|
|
225
|
+
| Interpreter request URLs no longer append the traffic-source query; private diagnostic helpers disappear from declarations. | Not mirrored: Runtime does not send requests to E2B's Jupyter endpoints or append that query. |
|
|
226
|
+
| Interpreter streaming uses one UTF-8 decoder across chunks and flushes it at EOF. | Already matched by Runtime's `TextDecoderStream`. A `runCode` test sends every byte separately, including two-, three- and four-byte characters and a final line without a newline; callbacks and final results retain the text. |
|
|
227
|
+
| Interpreter dependency rises from `e2b ^2.48.0` to `^2.53.1`; package versions and build metadata advance. | Oracle pins both exact releases. No other public exports, caller options, defaults or method signatures changed. |
|
|
228
|
+
|
|
229
|
+
`tests/e2b/exports.test.ts` checks both import surfaces, constructor causes and
|
|
230
|
+
Runtime error translation. `tests/e2b/sandbox.test.ts` checks the error when a
|
|
231
|
+
running command loses its sandbox. `tests/e2b/code-interpreter.test.ts` exercises
|
|
232
|
+
the real native transport beneath `runCode` with in-memory HTTP replies, including
|
|
233
|
+
split UTF-8 and server failures without replay. These fixtures do not establish
|
|
234
|
+
live-host behavior, isolation, recovery, performance superiority or full E2B
|
|
235
|
+
compatibility; the provider remains marked `partial`.
|
|
236
|
+
|
|
237
|
+
## e2b 2.55.0, 9 October 2026
|
|
238
|
+
|
|
239
|
+
Reviewed the published npm tarballs for `e2b` 2.53.1 → 2.55.0 and
|
|
240
|
+
`@e2b/code-interpreter` 2.8.2 → 2.8.3, and the PyPI wheels and sdists for
|
|
241
|
+
`e2b` 2.53.1 → 2.55.0 → 2.55.1 and `e2b-code-interpreter` 2.10.3 → 2.10.4 →
|
|
242
|
+
2.10.5. Each was npm's or PyPI's latest when checked. Every pinned file matched
|
|
243
|
+
the hash already in `compatibility-lock.json`, and every new file matched its
|
|
244
|
+
registry's SHA-512 integrity or SHA-256 digest; each wheel's Python source is
|
|
245
|
+
byte for byte its sdist's. Nothing was installed, imported or run. JavaScript
|
|
246
|
+
sources were read from the source maps, which carry the TypeScript. Nine `e2b`
|
|
247
|
+
source files changed, one was removed, and one interpreter file changed.
|
|
248
|
+
|
|
249
|
+
| Upstream change | Drop-in disposition |
|
|
250
|
+
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
251
|
+
| `pause`, `betaPause`, `createSnapshot` and `lifecycle.onTimeout` take `mode: "full" \| "filesystem"` (Python `mode=`, keyword-only); `keepMemory` (`keep_memory`) is deprecated. Both at once, an unknown mode, or a mode on `action: "kill"` throws `InvalidArgumentError`. `SnapshotMode` is exported. | Followed, in both languages. `createSnapshot({ mode: "filesystem" })` takes a Runtime disk snapshot and `"full"` the whole machine. A pause with `"filesystem"` throws `NotSupportedError`, as `keepMemory: false` did, naming the disk snapshot. `"full"` pauses. The same `InvalidArgumentError`s, with E2B's messages. Until now a `mode` was ignored: a pause asked to drop memory kept it. |
|
|
252
|
+
| `DockerfileSyntaxError` is exported (from the new `@e2b/dockerfile-utils` / `e2b-dockerfile-utils` 0.1.0): a plain `Error` (Python `ValueError`) with `line`. The template builder's Dockerfile and `.dockerignore` parsing moves into that package, replacing `dockerfile-ast` / `dockerfile-parse`. | Exported with E2B's parent, message and `line`, also from `e2b.template.dockerfile_parser`. Templates stay refused, naming `npx withruntime images build`, so nothing throws it. |
|
|
253
|
+
| Template `copy` and `makeDir` keep `mode: 0` instead of dropping it. | Not mirrored: templates are refused. |
|
|
254
|
+
| A file entry for a symlink is `FileType.SYMLINK` when newer envd reports the target's type with an `isSymlink` flag. | Already matched: Runtime's listing marks the link itself `symlink`. |
|
|
255
|
+
| Python's command stream decodes empty output chunks instead of skipping them, still yielding only nonempty text. A JavaScript comment is removed. | No change in what a caller sees; Runtime's own stream is used. |
|
|
256
|
+
| The interpreter builds its Jupyter address with `getSandboxUrl` (Python `get_sandbox_url(port=)`, added in `e2b` 2.55.1) instead of a direct URL. Interpreter dependencies rise to `e2b ^2.55.0` (Python `>=2.55.1`). | Not mirrored: Runtime does not call E2B's Jupyter endpoints. The oracle and the Python contract requirements pin the exact releases, with `@e2b/dockerfile-utils` and `e2b-dockerfile-utils` 0.1.0 in place of the parsers. |
|
|
257
|
+
| API documentation: `team_id` may be a `prj_` project id; `secret_limit_reached` is a listed error code. | Not used by the drop-in. |
|
|
258
|
+
|
|
259
|
+
`tests/e2b/e2b-2-55.test.ts` and `sdks/python/tests/test_e2b_2_55.py` check the
|
|
260
|
+
modes, the refusals, their messages and the new exports; they fail without
|
|
261
|
+
this change. The official differential contracts were not run against the new
|
|
262
|
+
releases, since they execute E2B's code; the provider remains marked `partial`.
|