Releases: e2b-dev/E2B
Release list
e2b@2.31.0
Minor Changes
-
7e7e951: Add an object form to the sandbox
lifecycle.onTimeout(on_timeoutin Python)
that controls the snapshot kind taken when a sandbox auto-pauses on timeout, via
keepMemory(keep_memory).onTimeoutnow accepts either the existing bare action ('pause'/'kill') or
the object form. The object form is a discriminated union onaction:
keepMemoryis only accepted alongsideaction: 'pause'— pairing it with
action: 'kill'is a compile-time type error (and is rejected at runtime for
untyped callers). WhenkeepMemoryisfalse, a timeout auto-pause drops the
in-memory state and persists only the filesystem (a filesystem-only snapshot);
resuming such a sandbox cold-boots (reboots) it from disk, losing running
processes and open connections. Defaults totrue(full memory snapshot). It
cannot be combined with auto-resume: auto-resume wakes a paused sandbox on
inbound traffic by restoring its memory snapshot in place, and a filesystem-only
snapshot has no memory to restore (resuming cold-boots it), so it must be resumed
explicitly. The bare string form is unchanged.# Python sbx = Sandbox.create( lifecycle={"on_timeout": {"action": "pause", "keep_memory": False}} )
// JS/TS const sbx = await Sandbox.create({ lifecycle: { onTimeout: { action: 'pause', keepMemory: false } }, })
-
cb5a387: Add a
keepMemory(keep_memoryin Python) option topausefor
filesystem-only snapshots.When
keepMemoryisfalse, pausing drops the in-memory state and captures
only the filesystem (no memory snapshot); resuming such a snapshot cold-boots
(reboots) the sandbox from disk, losing running processes and open connections.
Defaults totrue(full memory snapshot), so existing callers are unaffected.# Python sbx.pause(keep_memory=False) # filesystem-only snapshot
// JS/TS await sandbox.pause({ keepMemory: false }) // filesystem-only snapshot
Patch Changes
- de0c401: Fix three filesystem watch handle bugs:
- JS:
WatchHandlenow awaits asynconEvent/onExitcallbacks. A rejecting asynconEventis routed toonExitand stops the watch instead of becoming an unhandled promise rejection that can crash Node, and async callbacks get backpressure/ordering — matchingCommandHandle. - Python (sync):
WatchHandle.get_new_events()andstop()now send a request timeout (default 60s, overridable viarequest_timeout) so a stalled call can't hang the thread forever, and include the authentication header so the polling/stop calls aren't sent unauthenticated on older envd. - Python (async):
AsyncWatchHandlenow invokeson_exitwhen the stream ends cleanly (withNone) and whenstop()is called, in addition to on error — matching the JS SDK.
- JS:
e2b@2.30.6
Patch Changes
- 2a98cce: Fix
CommandHandle.disconnect()leaking the output subscription in the JS SDK.disconnect()now cooperatively gates event handling with a flag that is checked before every dispatch, soonStdout/onStderr/onPtyare guaranteed not to fire for output that arrives after the call (previously they could keep firing when the underlying HTTP/2 abort did not promptly tear down the stream). The call returns promptly and never blocks on an idle command's stream.
@e2b/python-sdk@2.30.0
Minor Changes
-
7e7e951: Add an object form to the sandbox
lifecycle.onTimeout(on_timeoutin Python)
that controls the snapshot kind taken when a sandbox auto-pauses on timeout, via
keepMemory(keep_memory).onTimeoutnow accepts either the existing bare action ('pause'/'kill') or
the object form. The object form is a discriminated union onaction:
keepMemoryis only accepted alongsideaction: 'pause'— pairing it with
action: 'kill'is a compile-time type error (and is rejected at runtime for
untyped callers). WhenkeepMemoryisfalse, a timeout auto-pause drops the
in-memory state and persists only the filesystem (a filesystem-only snapshot);
resuming such a sandbox cold-boots (reboots) it from disk, losing running
processes and open connections. Defaults totrue(full memory snapshot). It
cannot be combined with auto-resume: auto-resume wakes a paused sandbox on
inbound traffic by restoring its memory snapshot in place, and a filesystem-only
snapshot has no memory to restore (resuming cold-boots it), so it must be resumed
explicitly. The bare string form is unchanged.# Python sbx = Sandbox.create( lifecycle={"on_timeout": {"action": "pause", "keep_memory": False}} )
// JS/TS const sbx = await Sandbox.create({ lifecycle: { onTimeout: { action: 'pause', keepMemory: false } }, })
-
cb5a387: Add a
keepMemory(keep_memoryin Python) option topausefor
filesystem-only snapshots.When
keepMemoryisfalse, pausing drops the in-memory state and captures
only the filesystem (no memory snapshot); resuming such a snapshot cold-boots
(reboots) the sandbox from disk, losing running processes and open connections.
Defaults totrue(full memory snapshot), so existing callers are unaffected.# Python sbx.pause(keep_memory=False) # filesystem-only snapshot
// JS/TS await sandbox.pause({ keepMemory: false }) // filesystem-only snapshot
Patch Changes
- de0c401: Fix three filesystem watch handle bugs:
- JS:
WatchHandlenow awaits asynconEvent/onExitcallbacks. A rejecting asynconEventis routed toonExitand stops the watch instead of becoming an unhandled promise rejection that can crash Node, and async callbacks get backpressure/ordering — matchingCommandHandle. - Python (sync):
WatchHandle.get_new_events()andstop()now send a request timeout (default 60s, overridable viarequest_timeout) so a stalled call can't hang the thread forever, and include the authentication header so the polling/stop calls aren't sent unauthenticated on older envd. - Python (async):
AsyncWatchHandlenow invokeson_exitwhen the stream ends cleanly (withNone) and whenstop()is called, in addition to on error — matching the JS SDK.
- JS:
@e2b/python-sdk@2.29.6
Patch Changes
- 2a98cce: Fix
CommandHandle(sync and async) recording the command result after yielding the flushed end-event chunks. The decoders are now flushed and theCommandResultis recorded before the trailing chunks are yielded, so a consumer that stops iterating on the first flushed chunk still observes the exit code. - 21af1f8: Avoid quadratic-time stdout/stderr accumulation in command handles by buffering decoded chunks in a list and joining on read instead of repeatedly concatenating onto an instance attribute.
@e2b/cli@2.13.0
Minor Changes
- 5370d54: Replace legacy access token auth with OAuth 2.0 refresh token flow. The CLI now authenticates via a public OAuth client using PKCE, receiving Hydra JWTs that are refreshed automatically. Config schema bumped to v1 with nested
identity,oauth, andtokenssections. Old flat configs are deprecated and require re-login.
Patch Changes
- Updated dependencies [2a98cce]
- e2b@2.30.6
e2b@2.30.5
Patch Changes
-
60feee3: Stream uploads instead of buffering streaming input entirely in memory:
Sandbox.files.write()/write_files():ReadableStreamdata (JS, outside the browser) and file-like objects (Python) are streamed to the sandbox, including whengzipis enabled (compression now happens chunk by chunk).useOctetStream/use_octet_streamnow defaults to auto-detect — octet-stream is used when any entry is streamable (so streamed uploads aren't silently buffered) andmultipart/form-dataotherwise; browsers always usemultipart/form-data. A streamed upload is bounded by a per-chunk timeout on the wire (Python's per-writehttpxtimeout, default the request timeout); a stalled upload that this can't observe is bounded server-side. On Python'sAsyncSandbox, the blocking file reads and gzip compression of a streamed upload now run in a worker thread so a large upload doesn't stall the event loop.Sandbox.files.read(format="stream"): the request timeout now bounds only the initial handshake instead of killing the stream while it's being consumed. The body is bounded by a per-chunk idle timeout on the wire (streamIdleTimeoutMsin JS,stream_idle_timeoutin Python, default the request timeout — 60s —0/Noneto disable): it aborts only when the server stops sending mid-stream, and a slow or paused consumer never trips it (a held-but-unread stream is reclaimed server-side). Usesignal(JS) to cancel an in-flight stream. A dropped connection during the stream handshake now surfaces the same typed, health-checked error as non-stream reads. The stream holds a pooled connection until it is consumed to the end, cancelled/closed, errors, or the idle timeout fires — consume it fully, use the context manager, or close it.- Python
Sandbox.files.read(format="stream"): the response body is now streamed from the sandbox instead of being downloaded into memory before iteration (sync and async). - JS
Sandbox.files.read()withbloborstreamformat now returns an emptyBlob/ReadableStreamfor empty files instead of"".
-
c1415f3: Stream volume file uploads and downloads instead of buffering in memory:
Volume.writeFile()/Volume.write_file():ReadableStreamdata (JS, outside the browser) and file-like objects (Python) are now streamed to the API in chunks.Volume.readFile(format="stream")/read_file(format="stream"): the request timeout now bounds only the initial handshake instead of killing the stream while it's being consumed (Python disables the read timeout; JS bounds the handshake and supportssignalto cancel an in-flight stream). A dropped connection during the stream handshake now surfaces the same typed, health-checked error as non-stream reads.
@e2b/python-sdk@2.29.5
Patch Changes
-
60feee3: Stream uploads instead of buffering streaming input entirely in memory:
Sandbox.files.write()/write_files():ReadableStreamdata (JS, outside the browser) and file-like objects (Python) are streamed to the sandbox, including whengzipis enabled (compression now happens chunk by chunk).useOctetStream/use_octet_streamnow defaults to auto-detect — octet-stream is used when any entry is streamable (so streamed uploads aren't silently buffered) andmultipart/form-dataotherwise; browsers always usemultipart/form-data. A streamed upload is bounded by a per-chunk timeout on the wire (Python's per-writehttpxtimeout, default the request timeout); a stalled upload that this can't observe is bounded server-side. On Python'sAsyncSandbox, the blocking file reads and gzip compression of a streamed upload now run in a worker thread so a large upload doesn't stall the event loop.Sandbox.files.read(format="stream"): the request timeout now bounds only the initial handshake instead of killing the stream while it's being consumed. The body is bounded by a per-chunk idle timeout on the wire (streamIdleTimeoutMsin JS,stream_idle_timeoutin Python, default the request timeout — 60s —0/Noneto disable): it aborts only when the server stops sending mid-stream, and a slow or paused consumer never trips it (a held-but-unread stream is reclaimed server-side). Usesignal(JS) to cancel an in-flight stream. A dropped connection during the stream handshake now surfaces the same typed, health-checked error as non-stream reads. The stream holds a pooled connection until it is consumed to the end, cancelled/closed, errors, or the idle timeout fires — consume it fully, use the context manager, or close it.- Python
Sandbox.files.read(format="stream"): the response body is now streamed from the sandbox instead of being downloaded into memory before iteration (sync and async). - JS
Sandbox.files.read()withbloborstreamformat now returns an emptyBlob/ReadableStreamfor empty files instead of"".
-
8171a03: Fix Python SDK header precedence so a custom
Authorizationpassed viaapi_headersis no longer overwritten by the deprecatedaccess_token. The deprecated access token is now applied beforeapi_headers, matching the JS SDK where a customAuthorizationwins. -
c1415f3: Stream volume file uploads and downloads instead of buffering in memory:
Volume.writeFile()/Volume.write_file():ReadableStreamdata (JS, outside the browser) and file-like objects (Python) are now streamed to the API in chunks.Volume.readFile(format="stream")/read_file(format="stream"): the request timeout now bounds only the initial handshake instead of killing the stream while it's being consumed (Python disables the read timeout; JS bounds the handshake and supportssignalto cancel an in-flight stream). A dropped connection during the stream handshake now surfaces the same typed, health-checked error as non-stream reads.
e2b@2.30.4
Patch Changes
- 726ced6: Fix duplicate logo on NPM/PyPI by switching to
<picture>element.
e2b@2.30.3
Patch Changes
-
f3e7f33: Tidy up SDK authentication and deprecate the access token in
ConnectionConfig.- Deprecated the
accessToken(JS) /access_token(Python) option onConnectionConfig. It still works exactly as before — when set (or viaE2B_ACCESS_TOKEN), theAuthorization: Bearerheader is still sent — but you should pass custom auth throughapiHeadersinstead, e.g.new ConnectionConfig({ apiHeaders: { Authorization: 'Bearer <token>' } }). - The SDK now raises a clear error when no API key is supplied, pointing to the API Keys tab (
https://e2b.dev/dashboard?tab=keys). In JS this is controlled by arequireApiKeyoption (defaulttrue) so callers that authenticate differently — like the CLI hitting/teamswith an access token — can opt out; in Python the API key is always required. - Removed the unused access-token toggle from the API clients:
requireAccessToken(JS) andrequire_access_token(Python). No caller ever set it to a non-default value, so behavior is unchanged. - The CLI now passes the access token to the
/teamsendpoint throughapiHeadersinstead of the deprecated option. - Decoupled the sandbox-scoped envd access token from
ConnectionConfig:EnvdApiClientnow owns its ownaccessTokenfield and sets theX-Access-Tokenheader itself.
- Deprecated the
-
0a5d524: Update package logos with theme-aware dark/light variants for GitHub.
@e2b/python-sdk@2.29.4
Patch Changes
- 726ced6: Fix duplicate logo on NPM/PyPI by switching to
<picture>element.