Commit Graph

956 Commits

Author SHA1 Message Date
devin-ai-integration[bot] 0a5d52478c docs: update package logos with theme-aware dark/light variants (#1462)
## Summary

Replace the old `logo-circle.png` in the CLI, JS SDK, and Python SDK
READMEs with the new E2B wordmark logos that adapt to GitHub's theme
setting.

Each package README now uses a `<picture>` element:
```html
<picture>
  <source media="(prefers-color-scheme: dark)" srcset=".../logo-white.png">
  <source media="(prefers-color-scheme: light)" srcset=".../logo-black.png">
  <img alt="E2B Logo" src=".../logo-black.png" width="200">
</picture>
```

- **Light theme** → black logo (`logo-black.png`)
- **Dark theme** → white logo (`logo-white.png`)
- **NPM/PyPI** (no `<picture>` support) → falls back to the black logo
via the `<img>` tag

New logo assets added to `readme-assets/`: `logo-black.png`,
`logo-white.png`.

Includes a patch changeset for `@e2b/cli`, `e2b` (JS SDK), and
`@e2b/python-sdk`.

Link to Devin session:
https://app.devin.ai/sessions/4983f23d23934d2c9a51733f5f9920f3
Requested by: @mlejva

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: vasek <vasek.mlejnsky@gmail.com>
2026-06-19 18:48:00 +00:00
Mish Ushakov f3e7f33973 refactor(sdks): tidy SDK auth and deprecate ConnectionConfig access token (#1452)
## Summary

The access token was only ever used by the CLI, never by any SDK
operation — sandbox, template, and volume calls all authenticate with
the API key. This cleans up the auth plumbing and **deprecates** (rather
than removes) the access token on `ConnectionConfig`, so there's no
breaking change for direct SDK consumers.

## Changes

- **Deprecated** the `accessToken` (JS) / `access_token` (Python) option
on `ConnectionConfig`. It still works exactly as before — when set (or
via `E2B_ACCESS_TOKEN`) the `Authorization: Bearer` header is still sent
— but `apiHeaders` is now the recommended way to pass custom auth.
- **Clear error when the API key is missing**, pointing to the API Keys
tab (`https://e2b.dev/dashboard?tab=keys`). In JS this is gated by a
`requireApiKey` option (default `true`) so callers that authenticate
differently — like the CLI hitting `/teams` with 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) / `require_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 `/teams` endpoint via
`apiHeaders` instead of the deprecated option, and opts out of the
API-key requirement on its own clients.
- Decoupled the sandbox-scoped envd access token from
`ConnectionConfig`: `EnvdApiClient` now owns its own `envdAccessToken`
field and sets the `X-Access-Token` header itself, removing a redundant
manually-set header.

## Recommended usage

```ts
// Deprecated
new ConnectionConfig({ accessToken: 'my-token' })

// Preferred
new ConnectionConfig({ apiHeaders: { Authorization: 'Bearer my-token' } })
```

```python
# Deprecated
ConnectionConfig(access_token="my-token")

# Preferred
ConnectionConfig(api_headers={"Authorization": "Bearer my-token"})
```

## Verification

`pnpm run typecheck`, `pnpm run lint`, Python `make typecheck`, and the
unit tests all pass — including new tests for the API-key requirement
(and its opt-out) in both SDKs. Confirmed the `Authorization: Bearer`
header is still sent for both the deprecated option and
`E2B_ACCESS_TOKEN`.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 14:20:21 +02:00
github-actions[bot] 90724836a1 [skip ci] Release new versions 2026-06-17 23:01:34 +00:00
Matt Brockman 4619f8ca11 cicd/add wait for status for public traffic network tests (#1456)
when running server in sandbox, sometimes slow to start (>3s) so need to wait for status instead
2026-06-17 15:47:34 -07:00
Matt Brockman 75e27420a2 cicd/fix test_commit_creates_commit timeout (#1455)
does a bunch of actions and times out sometimes
2026-06-17 22:13:56 +00:00
Matt Brockman 432c0913c8 Add integration user agent composibility (#1454)
user agent is now composable, improving attribution
2026-06-17 14:21:50 -07:00
Mish Ushakov 706c553295 fix(sdks): fix template build bugs and consolidate shell quoting (#1442)
Fixes seven template-build correctness bugs across the JS and Python
(sync + async) SDKs, plus a small shell-quoting cleanup. Each fix has
unit/regression coverage, and real end-to-end builds were run against
the API in all three SDK variants.

**Template fixes**
- `getAllFilesInPath` now sorts by full path so the files hash no longer
depends on filesystem traversal order (the JS `sort()` was a no-op on
glob `Path` objects).
- `waitForPort` anchors the port match so port 80 no longer matches
8080.
- The readycmd helpers (`waitForURL`/`waitForFile`/`waitForProcess`) and
the file-op helpers (`remove`/`rename`/`makeDir`/`makeSymlink`) now
shell-quote interpolated values/paths.
- `waitForBuildFinish` keeps fetching logs after a terminal status so
the tail of the build logs (beyond the API's 100-entries-per-call limit)
is no longer dropped.
- COPY instructions now collect one stack trace each, so failed-step
traces stay aligned after `copy()` with multiple sources or
`copyItems()`.
- JS `LogEntry` strips ANSI escape codes in its constructor, matching
the Python SDK.

**Cleanup:** consolidated three duplicate single-quote shell helpers
(`shellQuote`, the new `quoteShellArg`, and git's `shellEscape`) into
one faithful `shlex.quote` port in `utils.ts` — safe values stay
unquoted, keeping generated commands and layer-cache hashes stable.

**Behavior note:** templates with paths/URLs containing spaces or shell
metacharacters now build correctly; plain paths are unchanged, so
existing layer caches are preserved.

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-17 10:57:21 +02:00
github-actions[bot] fef573dc17 [skip ci] Release new versions 2026-06-16 18:36:48 +00:00
Mish Ushakov 7cec36dcb5 fix(python-sdk): drop stream read timeout, enforce command timeout server-side (#1448)
## Summary

Follow-up to #1444 (the `httpcore` → `TimeoutException` mapping, now
merged). That mapping made the flaky timeout deterministic, but the
underlying cause remained: the streaming HTTP `read` timeout was set to
the command `timeout`, so it raced the server's own `deadline_exceeded`
response. This PR removes the read timeout on streaming calls entirely
and relies on the server-side `connect-timeout-ms` header to enforce the
command timeout — matching the JS SDK, which has no per-chunk read
timeout. The race is now structurally impossible rather than mapped
over.

## Usage

```python
cmd = sandbox.commands.run("sleep 10", timeout=2, background=True)
try:
    for _ in cmd:
        pass
except TimeoutException:
    print("command timed out")  # server-side deadline_exceeded, no transport race
```

## Tradeoff

A silently dropped connection (no RST) on a command with `timeout=0`
(disabled) now has no client-side read backstop and relies on keepalive
pings — the same posture as the JS SDK.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 20:23:54 +02:00
Mish Ushakov 5de9bc2354 fix(python-sdk): map httpcore timeouts to TimeoutException to fix flaky test (#1444)
## Summary

The flaky test `test_run_with_too_short_timeout_iterating` failed
intermittently because, when iterating a background command's output,
the Python SDK sets the HTTP stream `read` timeout to the command
`timeout` — so it races the server's own `deadline_exceeded` response.
When the client read timeout won, a raw `httpcore.ReadTimeout` leaked
out instead of a `TimeoutException`. This PR maps
`httpcore.TimeoutException` to `TimeoutException` in
`handle_rpc_exception`, so callers get a consistent timeout error
regardless of which side fires first, plus unit tests for the mapping.
It also adds a JS parity test (JS was never affected — connect-es always
normalizes timeouts into an already-mapped `ConnectError`).

## Usage

```python
cmd = sandbox.commands.run("sleep 10", timeout=2, background=True)
try:
    for _ in cmd:
        pass
except TimeoutException:
    print("command timed out")  # now raised reliably, no raw httpcore.ReadTimeout
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 12:56:09 +02:00
Mish Ushakov 78c200afc8 feat(sdk): allow disabling client-side API key validation (#1360)
## Summary

Allow disabling client-side API key **format** validation. Previously
the SDKs hard-required keys to match the `e2b_<hex>` pattern, which
blocked deployments that issue API keys with a different format. Instead
of a custom-prefix override, this adds a simple on/off toggle.

The default behaviour is unchanged (validation stays **on**).

## Configuration

| Form | JS | Python |
| --- | --- | --- |
| Env var | `E2B_VALIDATE_API_KEY=false` | `E2B_VALIDATE_API_KEY=false`
|
| Connection option | `validateApiKey: false` | `validate_api_key=False`
|

The connection option takes priority over the environment variable.

## Usage

**JavaScript / TypeScript**

```ts
import { Sandbox } from 'e2b'

// Via connection option
const sandbox = await Sandbox.create({
  apiKey: 'custom_key_format',
  validateApiKey: false,
})

// Or via env var: E2B_VALIDATE_API_KEY=false
```

**Python**

```python
from e2b import Sandbox

# Via connection option
sandbox = Sandbox(
    api_key="custom_key_format",
    validate_api_key=False,
)

# Or via env var: E2B_VALIDATE_API_KEY=false
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-16 11:58:55 +02:00
Mish Ushakov e88ae338e8 fix(sdks): handle signed URL expiration edge cases in upload/download URLs (#1429)
## Summary

- Python `upload_url`/`download_url` now raise
`InvalidArgumentException` when `use_signature_expiration` is passed for
an unsecured sandbox, matching the JS SDK (which now throws
`InvalidArgumentError` instead of a plain `Error`).
- A signature expiration of `0` was treated as falsy and silently
produced a never-expiring signed URL; it now produces an immediately
expiring URL in both SDKs.
- Adds unit tests mirrored across both SDKs
(`tests/sandbox/urls.test.ts` ↔ `tests/test_sandbox_urls.py`) plus a
changeset.

## Usage

```python
sbx = Sandbox()  # not secure=True
sbx.download_url("a.txt", use_signature_expiration=120)  # now raises InvalidArgumentException instead of silently ignoring the expiration
```

```ts
const sbx = await Sandbox.create({ secure: true })
await sbx.downloadUrl('a.txt', { useSignatureExpiration: 0 })  // URL now expires immediately instead of never
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-16 11:27:34 +02:00
Mish Ushakov 5ea287b11e fix(sdk): WriteInfo.type enum, tz-aware times, gzip on default upload path (#1437)
## Summary

- Python `write()` / `write_files()` now return `WriteInfo.type` as the
`FileType` enum instead of the raw API string (sync and async; the JS
string union was already correct, and the volumes client already
converts to `VolumeEntryStatType`).
- `EntryInfo.modified_time` is now timezone-aware UTC (protobuf
`ToDatetime()` returns naive datetimes by default), and naive volume
`atime`/`mtime`/`ctime` timestamps are normalized to UTC.
- `gzip=true` uploads now imply the `application/octet-stream` path in
both JS and Python instead of being silently ignored on the default
`multipart/form-data` path; on envd < 0.5.7 the upload falls back to
uncompressed multipart, matching the existing `use_octet_stream`
fallback.
- Adds sandbox-free unit tests for the model conversions, strengthens
write/info integration test assertions, and includes changesets for
`@e2b/python-sdk` and `e2b`.

## Usage examples

```python
info = sandbox.files.write("hello.txt", "hi")
info.type == FileType.FILE          # was the raw string "file"

entry = sandbox.files.get_info("hello.txt")
entry.modified_time.tzinfo          # datetime.timezone.utc (was None)

sandbox.files.write("big.bin", data, gzip=True)  # now actually gzip-compressed
```

## Test plan

- [x] `pytest tests/test_filesystem_models.py` (new unit tests, 5
passed)
- [x] Python sync + async integration tests for `write`, `info`,
`content_encoding` (16 each, passed against live sandboxes)
- [x] JS `write.test.ts` + `contentEncoding.test.ts` (14 passed)
- [x] `pnpm run format`, `pnpm run lint`, `pnpm run typecheck`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-16 11:26:42 +02:00
Mish Ushakov cb061d269b fix(sdk): correct command/PTY stream handling in Python and JS SDKs (#1441)
## Summary

Fixes three command/PTY streaming issues in the Python and JS SDKs:

- **Multibyte UTF-8 corruption (JS + Python sync/async):** stdout/stderr
were decoded per-chunk, so a UTF-8 character split across two stream
chunks turned into replacement characters. Each handle now keeps a
persistent incremental decoder per stream
(`codecs.getincrementaldecoder` in Python, a shared `TextDecoder` with
`{ stream: true }` in JS) and flushes any incomplete trailing bytes to
`�` on the end event, preserving the existing broken-UTF-8 behavior.
- **`commands.list()` optionals (Python):** now returns `None` instead
of `""` for unset proto3-optional `tag` and `cwd` fields, matching the
declared `Optional[str]` types and the JS SDK.
- **Leaked connections (Python):** command/PTY/watch streams are now
closed when stream setup fails, instead of abandoning the generator (and
its pooled HTTP connection) until GC.

## Usage example

```python
# Split multibyte output is now decoded correctly instead of returning "ð\x9f\x98\x80"-style garbage
result = sandbox.commands.run("printf '😀'")
assert result.stdout == "😀"

# Unset fields are None rather than ""
proc = sandbox.commands.list()[0]
assert proc.tag is None  # previously ""
```

## Testing

- New unit tests for incremental/trailing UTF-8 decoding (Python sync +
async, JS).
- Live command/PTY/watch integration suites pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-15 23:03:27 +02:00
Mish Ushakov b52eb3c76d fix: debug-mode Sandbox.connect() and Unset token handling in Python connect() (#1428)
## Description

`Sandbox.connect()` now short-circuits in debug mode instead of calling
the control plane, matching `Sandbox.create()` — fixed in the JS SDK and
both sync/async Python SDKs (static and instance variants). The Python
SDK's `connect()` also previously passed the generated client's `Unset`
sentinel through as the envd/traffic access tokens when they were absent
(non-secure sandboxes), which made `download_url()`/`upload_url()` emit
broken signed URLs; `_cls_connect` now normalizes the response into
`SandboxCreateResponse` with proper `None` values, the same pattern
`_create_sandbox` already uses. Dead `Unset` checks and the now-unused
generated `Sandbox` model import were cleaned up, and unit tests cover
both behaviors in all three implementations. Debug mode is resolved
through `ConnectionConfig`, so the `E2B_DEBUG` env var triggers the
short-circuit in both `connect()` and `create()`, not just an explicit
`debug=True`.

## Usage

```ts
// JS: works fully offline with E2B_DEBUG / debug: true (no control plane call)
const sbx = await Sandbox.connect(sandboxId, { debug: true })
```

```python
# Python: non-secure sandboxes get unsigned URLs again instead of broken signatures
sbx = Sandbox.connect(sandbox_id)
print(sbx.download_url("file.txt"))  # no garbage signature when envd token is absent

# Debug mode skips the control plane, like Sandbox.create()
sbx = Sandbox.connect(sandbox_id, debug=True)
```

## Testing

New unit tests in `tests/sandbox/connect.test.ts`,
`tests/sync/sandbox_sync/test_connect.py`, and
`tests/async/sandbox_async/test_connect.py`; existing connect
integration suites pass against the live API (8/8 sync Python, 8/8 async
Python, 6/6 JS).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-15 21:15:38 +02:00
Mish Ushakov e0ed071443 fix(python-sdk): anchor file-metadata validation regexes with \A/\Z (#1438)
## Summary

Python's `$` regex anchor also matches just before a trailing newline,
so file-metadata keys/values ending in `\n` passed client-side
validation (unlike the JS SDK, where `$` matches only the true end of
string) and then failed deep in the HTTP stack with an opaque "illegal
header value" error. This re-anchors both validation regexes with
`\A`/`\Z` so such inputs are rejected upfront with
`InvalidArgumentException`, matching JS behavior and the existing
convention used for the API-key pattern.

Also adds trailing-newline rejection test cases to the sync/async Python
suites and, for parity of coverage, to the JS SDK suite (JS already
rejected them — no behavior change there).

## Usage example

```python
sandbox.files.write("file.txt", "x", metadata={"author": "mish\n"})
# before: passed validation, then httpcore raised 'Illegal header value'
# after:  raises InvalidArgumentException with a clear message
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-15 12:11:41 -07:00
Mish Ushakov 82add5b4ea fix(sdks): raise typed, actionable errors when sandbox dies mid-request (#1419)
## Problem

When a sandbox is killed (or reaches its end of life) while a request is
in flight, both SDKs surfaced unusable errors:

- **JS**: `SandboxError: 2: [unknown] terminated` — typed, but cryptic
and says nothing about the sandbox being killed.
- **Python**: leaked a completely raw `httpcore.RemoteProtocolError:
<StreamReset stream_id:1, error_code:2, remote_reset:True>`.

This affected the whole envd streaming family (`commands.run`, PTY
sessions, `files.watchDir`/`watch_dir`) and the `files.read`/`write`
HTTP transfers.

The stream-reset signature alone can't distinguish the sandbox dying
from an intermediary (load balancer, network) dropping the connection —
so the SDKs now actively check, and only transform the error when the
sandbox is confirmed gone.

## Fix

**Health-check disambiguation.** When the connection-terminated
signature appears (JS: `ConnectError` `Code.Unknown` + `terminated` or
Undici `TypeError: terminated`; Python: `httpcore`/`httpx`
`RemoteProtocolError`), the SDK probes envd's `/health` endpoint:

- **502 (sandbox confirmed gone)** → `TimeoutError` (JS) /
`TimeoutException` (Python): "The sandbox was killed or reached its end
of life while the request was in flight." This matches how requests to
an *already-dead* sandbox surface today (the 502 / `Code.Unavailable`
mappings raise the timeout error type), so the exception type no longer
depends on whether the sandbox died just before or just during the
request.
- **Anything else** (still running, or probe inconclusive) → the
original error propagates unchanged, exactly as before this PR.

The probe (5s timeout) runs only on the termination signature, never on
the happy path or for other errors. A health-check closure is plumbed
into `Commands`/`Pty`/`Filesystem` and the command/watch handles in JS
and sync/async Python; `Commands`/`Pty` now receive the envd API client
in their constructors (internal signature change).

**Cleanup** (`e2b_connect/client.py`): removed the
`@_retry(RemoteProtocolError, 3)` decorators from
`call_server_stream`/`acall_server_stream`. They never executed —
`inspect.iscoroutinefunction` is false for (async) generator functions,
and calling a generator function doesn't run its body, so the wrapper's
`try/except` could never fire. A *working* mid-stream retry would be
wrong anyway (it would replay already-delivered events). Unary retries
are unchanged.

## Before / after

```ts
const sandbox = await Sandbox.create()
const cmd = await sandbox.commands.run('sleep 60', { background: true })
await sandbox.kill() // e.g. from another process
await cmd.wait()
// before: SandboxError: 2: [unknown] terminated
// after:  TimeoutError: [unknown] terminated: The sandbox was killed or reached
//         its end of life while the request was in flight.
```

```python
sandbox = Sandbox.create()
cmd = sandbox.commands.run("sleep 60", background=True)
sandbox.kill()
cmd.wait()
# before: httpcore.RemoteProtocolError: <StreamReset stream_id:1, error_code:2, remote_reset:True>  (not an e2b type!)
# after:  e2b.exceptions.TimeoutException: <StreamReset ...>: The sandbox was killed
#         or reached its end of life while the request was in flight.
```

If the health probe does not confirm the sandbox is gone (e.g. a load
balancer dropped the connection, or local envd in debug mode), the
original error propagates unchanged — the SDK only makes a claim when it
has verified it.

## Notes

- Not covered: errors raised while consuming a `format: 'stream'` body
**after** `files.read` returns (JS `ReadableStream` consumption happens
in user code). Python is fully covered since httpx buffers non-streaming
responses inside the request call.

## Tests

- Unit: confirmed-kill → `TimeoutError`/`TimeoutException`, raw-error
passthrough for running/unknown/probe-failure, health check skipped for
unrelated errors — 28 Python + 25 JS assertions pass.
- Integration (run against live sandboxes, all passing): start `sleep
60`, kill the sandbox, assert `wait()` raises
`TimeoutError`/`TimeoutException` with the *confirmed* kill message —
JS, sync Python, and async Python.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-15 19:01:06 +00:00
github-actions[bot] a6c801d043 [skip ci] Release new versions 2026-06-15 18:51:55 +00:00
Mish Ushakov e873ee94b6 feat(sdk): add allowNetworkMounts option to filesystem watch (#1420)
Client-side counterpart to
[e2b-dev/infra#2982](https://github.com/e2b-dev/infra/pull/2982): adds
an `allowNetworkMounts`/`allow_network_mounts` option to filesystem
directory watching across the JS and Python (sync + async) SDKs, so
clients can explicitly opt into watching paths on network filesystem
mounts (NFS, CIFS, SMB, FUSE), which envd rejects by default. Events on
network mounts may be unreliable or not delivered at all, hence the
explicit opt-in.

This regenerates the filesystem proto code from the updated spec and
threads the flag through `watchDir`/`watch_dir` (streaming `WatchDir`
and polling `CreateWatcher`). The option requires envd 0.6.4 (shipped by
the infra PR); using it against an older sandbox throws a
`TemplateError`/`TemplateException`. Default behavior is unchanged.

Includes new watch tests for all three SDKs and a minor-bump changeset
for `e2b` and `@e2b/python-sdk`.

> Note: the new tests exercise the flag on a regular directory (a
network mount can't be set up from SDK tests) and require envd 0.6.4, so
this should land with/after the infra deploy. All pre-existing watch
tests pass; the new ones currently fail with the expected
`TemplateError` against the deployed envd.

### Usage

**JavaScript**
```ts
const handle = await sandbox.files.watchDir(
  '/mnt/nfs-share/my-dir',
  (event) => console.log(event.type, event.name),
  { allowNetworkMounts: true }
)
```

**Python (async)**
```python
handle = await sandbox.files.watch_dir(
    "/mnt/nfs-share/my-dir",
    on_event=lambda e: print(e.type, e.name),
    allow_network_mounts=True,
)
```

**Python (sync)**
```python
handle = sandbox.files.watch_dir("/mnt/nfs-share/my-dir", allow_network_mounts=True)
for e in handle.get_new_events():
    print(e.type, e.name)
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-15 15:34:02 +02:00
Mish Ushakov cab59caa0b fix(js-sdk): pass getMetrics start/end as query params (#1427)
## Description

`Sandbox.getMetrics()` in the JS SDK passed the `start` and `end`
options as path parameters instead of query parameters, so openapi-fetch
never serialized them and the requested time range was silently ignored.
They are now sent under `query`, matching the OpenAPI spec; the Python
SDKs already passed them correctly. The metrics tests across JS and
Python (sync/async) now assert that returned metrics fall within the
requested window (with slack for 5s metric-bucket alignment) and that a
window from before the sandbox existed returns no metrics, which would
have caught this regression.

## Usage

```ts
const start = new Date(Date.now() - 60_000)
const metrics = await sandbox.getMetrics({ start, end: new Date() })
// metrics are now actually limited to the requested time range
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-14 00:18:04 -07:00
Mish Ushakov 32880d6e96 fix(python-sdk): key async transport caches by loop object, not id(loop) (#1434)
## Description

The per-event-loop caches for `AsyncHTTPTransport`s and
`httpx.AsyncClient`s (Sandbox API, envd, and volume clients) were keyed
by `id(asyncio.get_running_loop())`, but CPython reuses object ids of
dead loops almost immediately — so sequential loops could inherit a
transport bound to a previous, closed loop and fail. The caches are now
`weakref.WeakKeyDictionary`s keyed by the loop object itself, which
makes stale id collisions impossible and releases entries when their
loop is garbage collected (fixing a leak where dead-loop entries
accumulated forever). Added regression tests covering the
sequential-loop scenario for all three caches.

This pattern no longer breaks:

```python
# e.g. a worker or test harness running repeated event loops
for job in jobs:
    asyncio.run(process_with_sandbox(job))  # each run previously risked
                                            # inheriting a closed loop's transport
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 22:18:20 +02:00
Mish Ushakov 0b0c728fe8 Fix volume SDK issues: transports, timeouts, empty files, eager stream errors (#1431)
Fixes a batch of review findings in the JS and Python volume SDKs,
aligning behavior between the two. Python now caches `AsyncVolume` HTTP
transports per event loop and proxy (sync per thread) instead of a
process-wide singleton, applies the 60s default `request_timeout` to
metadata operations that previously ran with httpx timeouts disabled, no
longer falls back to `E2B_ACCESS_TOKEN` for volume content auth, and no
longer mutates the caller's `headers` dict. JS `Volume.readFile` now
returns empty values instead of `undefined` for empty files, and volume
content requests get the documented 60s default request timeout. All
changes are covered by new mock-based unit tests (no live API needed)
plus changesets for both SDKs.

## Usage examples

```python
volume = await AsyncVolume.connect(volume_id)

# Times out after 60s by default (previously could hang indefinitely)
entries = await volume.list("/")
```

```ts
const volume = await Volume.connect(volumeId)

// Returns an empty Blob / ReadableStream for empty files (previously undefined)
const blob = await volume.readFile('empty.txt', { format: 'blob' })

// Times out after the documented 60s by default; pass 0 to disable
await volume.getInfo('file.txt', { requestTimeoutMs: 0 })
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 19:17:11 +00:00
Weilu JIa 1328d9fe44 fix(python): Retry connections on HTTP/2 API transports (#1425) 2026-06-12 11:17:27 +00:00
github-actions[bot] de47dfd6b1 [skip ci] Release new versions 2026-06-12 00:18:17 +00:00
Matt Brockman 82d6e323fc Use dedicated clients for Python template uploads (#1424) 2026-06-11 17:10:58 -07:00
Matt Brockman 554dc88bd1 Deduplicate sync thread-local client setup (#1423) 2026-06-11 16:05:38 -07:00
github-actions[bot] b9e131ad88 [skip ci] Release new versions 2026-06-11 20:00:01 +00:00
Matt Brockman 44c1e9f575 Fix/python sync thread local envd (#1422)
safer threading handling
2026-06-11 19:39:33 +00:00
Mish Ushakov 1d5259ca1d fix(sdks): transport proxy caching, request timeout, and option handling (#1421)
Fixes a batch of connection-handling bugs found in review, with unit
tests for each and a changeset for both SDKs.

- **Python**: cached HTTP transports are now keyed on the configured
proxy, so clients with different (or no) proxy settings no longer
silently reuse the transport built for the first proxy seen.
- **Python**: `request_timeout` now applies to control-plane API
requests — the underlying httpx client was previously built with no
timeout at all (`request_timeout=0` still disables it).
- **Python**: the server-stream parser no longer stalls or drops the
final envelope when the remaining payload is shorter than the 5-byte
envelope header; also removed the no-op `@_retry` decorators from the
streaming RPC methods to avoid confusion.
- **JS + Python**: an explicit `debug=False` / `debug: false` now
overrides `E2B_DEBUG=true` instead of being ignored.
- **JS**: the RPC logger no longer crashes requests with a `TypeError`
when a response contains protobuf int64 (`bigint`) fields (e.g.
`EntryInfo.size` returned by `files.list()`/`stat()` and `includeEntry`
watch events); they are logged as strings.

## Usage examples

```ts
// JS: logging RPCs whose responses carry int64 fields no longer throws
const sbx = await Sandbox.create({ logger: console })
await sbx.files.list('/')

// JS: force-disable debug mode even when E2B_DEBUG=true is set
const sbx2 = await Sandbox.create({ debug: false })
```

```python
# Python: per-call API timeout is now actually enforced
Sandbox.list(request_timeout=10)

# Python: clients with different proxies get their own transports
Sandbox.create(proxy="http://127.0.0.1:8080")
Sandbox.create()  # no longer routed through the proxy above
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 19:12:47 +00:00
github-actions[bot] d23ad659a4 [skip ci] Release new versions 2026-06-10 17:33:36 +00:00
Mish Ushakov da85b1e33c feat(sdk): add includeEntry option to filesystem watch (#1385)
Client-side counterpart to
[e2b-dev/infra#2930](https://github.com/e2b-dev/infra/pull/2930): adds
an `includeEntry`/`include_entry` option to filesystem directory
watching across the JS and Python (sync + async) SDKs, so each
`FilesystemEvent` can carry the affected entry's `EntryInfo`
(best-effort — unset for remove/rename-away events where the path no
longer exists). This regenerates the filesystem proto code from the
updated spec, threads the flag through `watchDir`/`watch_dir` (streaming
`WatchDir` and polling `CreateWatcher`), maps the new `entry` field onto
the event, and extracts a shared entry-mapping helper reused by
`list`/`getInfo`/`rename`. The option degrades gracefully: older
sandboxes (< envd 0.6.2) ignore it and leave `entry` unset, so there's
no hard version gate. Includes new watch tests for all three SDKs and a
minor-bump changeset for `e2b` and `@e2b/python-sdk`.

> Note: the entry-info tests require envd 0.6.2 (shipped by the infra
PR), so this should land with/after that deploy.

### Usage

**JavaScript**
```ts
const handle = await sandbox.files.watchDir(
  'my-dir',
  (event) => {
    console.log(event.type, event.name, event.entry?.path, event.entry?.type)
  },
  { includeEntry: true }
)
```

**Python (async)**
```python
def on_event(e):
    print(e.type, e.name, e.entry.path if e.entry else None)

handle = await sandbox.files.watch_dir("my-dir", on_event=on_event, include_entry=True)
```

**Python (sync)**
```python
handle = sandbox.files.watch_dir("my-dir", include_entry=True)
for e in handle.get_new_events():
    print(e.type, e.name, e.entry.path if e.entry else None)
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 19:02:09 +02:00
Mish Ushakov 961ffbae84 feat(sdks): expose user-defined file metadata on sandbox.files (#1383)
Adds a `metadata` option to file uploads and surfaces persisted metadata
on every `EntryInfo` / `WriteInfo` returned by `getInfo`, `list`,
`rename`, and write responses, across the JS and Python (sync + async)
SDKs.

Metadata is sent as `X-Metadata-<key>: <value>` request headers and
persisted by envd as `user.e2b.*` extended attributes; the same map is
applied to every file in a multi-file upload. Keys and values must be
printable US-ASCII and keys are lowercased by the sandbox, so they may
differ in case when read back. Requires **envd 0.6.2 or later**.

This syncs the envd OpenAPI spec and filesystem proto with
[infra#2732](https://github.com/e2b-dev/infra/pull/2732) and regenerates
the JS/Python clients.

## Usage

**JavaScript / TypeScript**
```ts
// Single file
const info = await sandbox.files.write('report.txt', 'hello', {
  metadata: { author: 'mish', purpose: 'demo' },
})
console.log(info.metadata) // { author: 'mish', purpose: 'demo' }

// Multiple files (same metadata applied to each)
await sandbox.files.writeFiles(
  [
    { path: 'a.txt', data: 'A' },
    { path: 'b.txt', data: 'B' },
  ],
  { metadata: { source: 'import' } }
)

// Read it back
const stat = await sandbox.files.getInfo('report.txt')
console.log(stat.metadata) // { author: 'mish', purpose: 'demo' }
```

**Python**
```python
# Single file
info = sandbox.files.write("report.txt", "hello", metadata={"author": "mish"})
print(info.metadata)  # {"author": "mish"}

# Multiple files (same metadata applied to each)
sandbox.files.write_files(
    [
        WriteEntry(path="a.txt", data="A"),
        WriteEntry(path="b.txt", data="B"),
    ],
    metadata={"source": "import"},
)

# Read it back
stat = sandbox.files.get_info("report.txt")
print(stat.metadata)  # {"author": "mish"}
```

The async Python API is identical with `await`.

## Tests

Integration tests cover the round-trip across `write` / `getInfo` /
`list` / `rename`, octet-stream uploads, multi-file uploads,
overwrite-clears-stale-metadata, and metadata written directly as
`user.e2b.*` xattrs via `sandbox.commands.run` surfacing in `getInfo`.
They require a sandbox running envd 0.6.2+.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 16:05:34 +00:00
Mish Ushakov 7dc861f899 fix: align behavior and API surface between the JS and Python SDKs (#1411)
Aligns several behavioral and API-surface discrepancies between the JS
and Python SDKs found during a cross-SDK audit. **Python:**
`commands.send_stdin`/`CommandHandle.send_stdin` now accept `bytes`
(plus `request_timeout` on the handle), `git.reset` gets a typed
`GitResetMode` with JS-matching validation, `sandbox_url` is threaded
through `get_api_params` (and the dead `SandboxOpts` key removed), and
`from_image` requires both `username` and `password` when credentials
are given. **JS:** `getFullInfo` was removed in favor of a single
`getInfo` that now includes `sandboxDomain` (matching Python's
`get_info`), `fromImage` requires both credentials, `getBuildStatus`
defaults `logsOffset` to `0`, `getMetrics`/`kill` short-circuit
consistently in debug mode (instance + static), and `requestTimeoutMs:
0` explicitly disables the request timeout. Tests were added on both
sides (git-arg validation, stdin bytes, credential validation,
timeout-0, connection config) and the CLI's `sandbox info` now uses
`getInfo`. See the changeset for the full per-SDK list.

## Usage examples

```ts
// JS: registry credentials now require both fields
Template().fromImage('registry.example.com/img:latest', { username: 'u', password: 'p' })

// JS: getInfo now exposes sandboxDomain (getFullInfo removed)
const info = await Sandbox.getInfo(sandboxId)
console.log(info.sandboxDomain)

// JS: disable the request timeout
await Sandbox.create({ requestTimeoutMs: 0 })
```

```python
# Python: send raw bytes to stdin
sandbox.commands.send_stdin(cmd.pid, b"hello")

# Python: typed git reset mode (validated)
sandbox.git.reset(repo, mode="hard")

# Python: registry credentials require both fields
Template().from_image("registry.example.com/img:latest", username="u", password="p")
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 13:40:22 +00:00
Mish Ushakov f63efeb76d test(sdk): add pty.kill coverage for JS and Python sync/async (#1412)
Adds the previously-missing test coverage for `pty.kill()`, which was
untested across all three SDK implementations despite the rest of the
PTY API (create/connect/sendInput/resize) being well covered.

Each suite gets two tests covering both return paths of `kill()`:
- **Kill a live PTY** — asserts `kill()` returns `true`, then confirms
the process is gone via `kill -0 <pid>` (throws
`ProcessExitError`/`CommandExitException`).
- **Kill a non-existent PID** — asserts `kill()` returns `false`,
matching the documented not-found behavior.

The tests mirror the style of the existing `commands.kill` tests and
were verified to lint cleanly and be discovered by vitest/pytest (full
runs require a live sandbox).

## Files
- `packages/js-sdk/tests/sandbox/pty/kill.test.ts`
- `packages/python-sdk/tests/sync/sandbox_sync/pty/test_pty_kill.py`
- `packages/python-sdk/tests/async/sandbox_async/pty/test_pty_kill.py`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 12:03:27 +02:00
github-actions[bot] a6dca9a31e [skip ci] Release new versions 2026-06-09 17:26:37 +00:00
Mish Ushakov 4e16cffc2f feat(js-sdk): add proxy connection param (#1386)
Adds a `proxy` connection parameter to the JS SDK, mirroring the Python
SDK. When set, requests are routed through the given HTTP proxy via an
undici `ProxyAgent` dispatcher (fetchers are cached per-proxy so
non-proxy traffic is unaffected). It applies to control-plane API
requests, all requests made to the returned sandbox (REST plus
filesystem/commands/pty RPC), and volume requests. Behavior is unchanged
when no proxy is provided, and unit tests cover both the API and envd
fetch paths.

## Usage

```ts
import { Sandbox } from 'e2b'

// Routes API + all sandbox requests through the proxy
const sandbox = await Sandbox.create({
  proxy: 'http://user:pass@127.0.0.1:8080',
})
await sandbox.files.write('/hello.txt', 'world')

// Also works when connecting to an existing sandbox
const sbx = await Sandbox.connect(sandboxId, { proxy: 'http://127.0.0.1:8080' })
```

> Proxying relies on the optional `undici` package and the Node runtime;
in browser/edge runtimes requests use global `fetch`, which has no proxy
support (same as the existing HTTP/2 dispatcher).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 18:29:16 +02:00
github-actions[bot] 26ca87c3f1 [skip ci] Release new versions 2026-06-09 12:34:31 +00:00
Mish Ushakov d86368a11e fix(python-sdk): align sync and async implementations (#1403)
Reconciles divergences found while auditing the sync and async Python
SDK trees, keeping behavior equivalent across both.

- **Parameter ordering:** aligned `_create` and `Commands._start`
signatures to the public API and to each other, and reordered the
`Commands.connect` rpc args (`headers` before `timeout`) to match the
`_start` convention.
- **`pause` return:** the public `pause()` / `beta_pause()` are now
annotated `-> str` and actually return the sandbox ID (matching
`_cls_pause` and the class-method form, which already returned it)
instead of `-> None`; the `:return:` docstrings are restored.
- **Exceptions:** the internal "Body of the request is None" guard in
`sandbox_api` now consistently raises a bare `Exception` (matching the
volume client) instead of mixing `Exception`/`SandboxException` between
sync and async.
- **Misc:** async `Filesystem.write` now passes keyword args; the async
constructor reuses the cached `envd_api_url` property instead of
recomputing the sandbox URL; async pty `resize` gains a `-> None`
annotation.
- **Docstrings:** aligned the deprecation marker and
`get_metrics`/`write_files`/`kill` wording across sync/async, and fixed
a `**seconds**s` typo.

These are alignment/consistency fixes only; the deeper architectural
async-vs-sync splits (streaming-vs-polling `watch_dir`, pty `on_data`,
command output callbacks) are intentional and left untouched.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 14:15:15 +02:00
Mish Ushakov 7296b2c55d fix(python-sdk): drop envd headers from control-plane connect request (#1402)
`Sandbox.connect` was attaching the data-plane envd headers
(`E2b-Sandbox-Id`, `E2b-Sandbox-Port`) to the control-plane `POST
/sandboxes/{id}/connect` call in both the sync and async SDKs. These
headers belong only on data-plane (filesystem/commands/pty) requests, so
this aligns the Python SDK with the JS SDK, which never sends them on
the connect call.

## Usage

No API change — `Sandbox.connect(sandbox_id)` (and the async equivalent)
behaves the same, just without the spurious headers on the control-plane
request.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 12:43:54 +02:00
Mish Ushakov f2550fa999 chore(python-sdk): mark packages as typed (PEP 561) (#1363)
## Summary

Add empty `py.typed` markers to the `e2b` and `e2b_connect` packages so
mypy/Pyright honor the inline annotations on `Sandbox`, `AsyncSandbox`,
and other public APIs instead of treating imports as `Any`. Includes a
patch changeset for `@e2b/python-sdk`.

## Test plan
- [ ] `pip install` the built wheel in a fresh env and confirm `mypy` no
longer reports `e2b` as untyped without `--follow-untyped-imports`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-09 12:36:06 +02:00
Matt Brockman 6c04e31f68 fix(python-sdk): use thread-local API transports (#1399)
makes the sync python python API http transport cache thread-local to
handle unsafe usage of the shared transport under pressure (e.g.
concurrent template builds). uses the same logic that we were using for
envd.

test
`test_sync_api_transport_cache_reuses_within_thread_and_isolates_across_threads`
fails on main, passes on branch.
2026-06-08 12:36:11 +02:00
Mish Ushakov 08012eeb4a feat: add sendStdin/closeStdin to CommandHandle (#1397)
Adds `sendStdin`/`send_stdin` and `closeStdin`/`close_stdin` directly on
the command handle (JS, Python sync, and Python async) so background
commands can be fed stdin and signalled EOF without reaching back to
`sandbox.commands` with the PID. The handle delegates to the existing
`Commands` methods via closures, mirroring how `kill` is wired, and also
adds the previously-missing `close_stdin`/`aclose_stdin` to the Python
`Commands` class (version-gated on `ENVD_ENVD_CLOSE`, matching JS).
PTY-created handles don't support these and raise a clear error, and the
existing PID-based `Commands.sendStdin` methods are untouched, so the
change is fully backward-compatible. Includes handle-based tests across
all three SDKs and a changeset bumping `e2b` and `@e2b/python-sdk` at
patch.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 10:51:39 +02:00
github-actions[bot] c892017cb6 [skip ci] Release new versions 2026-06-06 06:44:16 +00:00
Tomas Valenta 073661a8b5 feat(sdk): add API-only header options (#1395)
## Summary
- Adds `apiHeaders` / `api_headers` for API-only custom headers.
- Deprecates the existing `headers` option in favor of the explicit API
header option.

## Usage
```ts
await Sandbox.create({ apiHeaders: { Authorization: 'Bearer ...' } })
```

```python
sandbox = Sandbox.create(api_headers={"Authorization": "Bearer ..."})
```

## Tests
- Python syntax checks passed for touched files.
- IDE lints and `git diff --check` passed.

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-05 23:25:21 -07:00
Mish Ushakov e7a82ea9eb chore: remove unused dead code across SDK packages (#1388)
Removes internal symbols with zero references, found via knip
(js-sdk/cli) and vulture (python-sdk) and verified with repo-wide greps:
`wait` (js-sdk),
`asSandboxTemplate`/`asHeadline`/`selectOption`/`basicDockerfile` (cli),
and `format_execution_timeout_error` (python-sdk). No public API changes
— only dead, unexported-from-index or unreferenced code is dropped.
`format`, `lint`, and `typecheck` pass for all touched packages, and a
patch changeset is included for the three published packages.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 19:50:13 +02:00
Mish Ushakov 5b2bb941de fix(sdk): consistent rate limit error for envd 429 responses (#1387)
## Summary

The main API client already raised `RateLimitError` (JS) /
`RateLimitException` (Python) for HTTP 429, but the lower-level **envd**
HTTP and RPC layers fell through to a generic sandbox error, so the same
rate-limit condition surfaced as a different type depending on which
request path hit it. This maps envd 429 (and the equivalent gRPC
`ResourceExhausted` code) to the dedicated rate-limit error consistently
across the JS SDK and the Python sync/async SDKs. The JS RPC layer was
also missing the `ResourceExhausted` mapping entirely, which is now
added for parity with Python.

## Changes
- `js-sdk/src/envd/api.ts`, `python-sdk/e2b/envd/api.py` — envd HTTP 429
→ `RateLimitError`/`RateLimitException`
- `js-sdk/src/envd/rpc.ts` — added gRPC `Code.ResourceExhausted` →
`RateLimitError`
- Added unit tests for both the envd HTTP and RPC error mappers in JS
and Python
- Changeset (`e2b`: patch)

## Usage example
```ts
import { Sandbox, RateLimitError } from 'e2b'

try {
  await sandbox.files.write('/tmp/file.txt', 'data')
} catch (err) {
  if (err instanceof RateLimitError) {
    // now reliably caught regardless of which request path was rate limited
  }
}
```

```python
from e2b import RateLimitException

try:
    sandbox.files.write("/tmp/file.txt", "data")
except RateLimitException:
    ...
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 10:44:27 -07:00
dependabot[bot] 33009eb307 chore(deps): bump idna from 3.11 to 3.15 in /packages/python-sdk in the pip group across 1 directory (#1379)
Bumps the pip group with 1 update in the /packages/python-sdk directory:
[idna](https://github.com/kjd/idna).

Updates `idna` from 3.11 to 3.15
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/kjd/idna/blob/master/HISTORY.md">idna's
changelog</a>.</em></p>
<blockquote>
<h2>3.15 (2026-05-12)</h2>
<ul>
<li>Enforce DNS-length cap on individual labels early in
<code>check_label</code>,
short-circuiting contextual-rule processing for oversized input
while staying compatible with UTS 46 usage.</li>
<li>Tidy core helpers: hoist bidi category sets to module-level
frozensets (avoiding per-codepoint list construction), simplify
length checks, and reuse the shared <code>_unicode_dots_re</code> from
<code>idna.core</code> in the codec module.</li>
<li>Use <code>raise ... from err</code> for proper exception chaining
and
switch internal string formatting to f-strings.</li>
<li>Allow <code>flit_core</code> 4.x in the build backend.</li>
<li>Expand the ruff lint set (flake8-bugbear, flake8-simplify,
pyupgrade, perflint) and apply the surfaced fixes; pin lint CI
to Python 3.14.</li>
<li>Add Dependabot configuration for GitHub Actions.</li>
<li>Convert README and HISTORY from reStructuredText to Markdown.</li>
<li>Reference CVE-2026-45409 for the 3.14 advisory in place of the
initial GHSA identifier.</li>
</ul>
<p>Thanks to Felix Yan, Stan Ulbrych, and metsw24-max for
contributions to this release.</p>
<h2>3.14 (2026-05-10)</h2>
<ul>
<li>Removed opportunity to process long inputs into quadratic
time by rejecting oversize inputs up-front. Closes a bypass
of the CVE-2024-3651 mitigation. [CVE-2026-45409]</li>
</ul>
<p>Thanks to Stan Ulbrych for reporting the issue.</p>
<h2>3.13 (2026-04-22)</h2>
<ul>
<li>Correct classification error for codepoint U+A7F1</li>
</ul>
<h2>3.12 (2026-04-21)</h2>
<ul>
<li>Update to Unicode 17.0.0.</li>
<li>Issue a deprecation warning for the transitional argument.</li>
<li>Added lazy-loading to provide some performance improvements.</li>
<li>Removed vestiges of code related to Python 2 support, including
segmentation of data structures specific to Jython.</li>
</ul>
<p>Thanks to Rodrigo Nogueira for contributions to this release.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/kjd/idna/commit/af30a092e158181d0b35ac66dfa813788126bdd8"><code>af30a09</code></a>
Release 3.15</li>
<li><a
href="https://github.com/kjd/idna/commit/30314d4628744ca14cf2b5820564e5127a9f86f2"><code>30314d4</code></a>
Pre-release 3.15rc0</li>
<li><a
href="https://github.com/kjd/idna/commit/05d4b219aa9eddc47371fcbd2000f0301016f3e9"><code>05d4b21</code></a>
Merge pull request <a
href="https://redirect.github.com/kjd/idna/issues/237">#237</a> from
kjd/convert-docs-to-markdown</li>
<li><a
href="https://github.com/kjd/idna/commit/2987fdba1962bbb2358399e0084ba062b98a0bee"><code>2987fdb</code></a>
Convert README and HISTORY from reStructuredText to Markdown</li>
<li><a
href="https://github.com/kjd/idna/commit/59fa8002d514bf4a5ce7b58f67b9ec587d53fa9c"><code>59fa800</code></a>
Merge pull request <a
href="https://redirect.github.com/kjd/idna/issues/236">#236</a> from
kjd/dependabot/github_actions/actions-f3e34333ea</li>
<li><a
href="https://github.com/kjd/idna/commit/def69834ced5d4b3c50439d8b99c4c856ec19ca2"><code>def6983</code></a>
Merge branch 'master' into
dependabot/github_actions/actions-f3e34333ea</li>
<li><a
href="https://github.com/kjd/idna/commit/bbd8004a797185d8c56bb555cd5c88fde05e0631"><code>bbd8004</code></a>
Merge pull request <a
href="https://redirect.github.com/kjd/idna/issues/234">#234</a> from
StanFromIreland/patch-1</li>
<li><a
href="https://github.com/kjd/idna/commit/edd07c05024344a6ccb517414ccb36683aee99fc"><code>edd07c0</code></a>
Bump github/codeql-action from 3.35.2 to 4.35.2 in the actions
group</li>
<li><a
href="https://github.com/kjd/idna/commit/5557db030c11bdec50d62aa5f631d705d33ba123"><code>5557db0</code></a>
Merge branch 'master' into patch-1</li>
<li><a
href="https://github.com/kjd/idna/commit/f11746cf4981d25123ef7830d3ee60f07de8ae3d"><code>f11746c</code></a>
Merge pull request <a
href="https://redirect.github.com/kjd/idna/issues/235">#235</a> from
StanFromIreland/patch-2</li>
<li>Additional commits viewable in <a
href="https://github.com/kjd/idna/compare/v3.11...v3.15">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=idna&package-manager=pip&previous-version=3.11&new-version=3.15)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts page](https://github.com/e2b-dev/E2B/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Mish Ushakov <10400064+mishushakov@users.noreply.github.com>
2026-06-05 06:18:40 -07:00
dependabot[bot] 6e3a469a8c chore(deps-dev): bump urllib3 from 2.6.3 to 2.7.0 in /packages/python-sdk in the pip group across 1 directory (#1324)
Bumps the pip group with 1 update in the /packages/python-sdk directory:
[urllib3](https://github.com/urllib3/urllib3).

Updates `urllib3` from 2.6.3 to 2.7.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/releases">urllib3's
releases</a>.</em></p>
<blockquote>
<h2>2.7.0</h2>
<h2>🚀 urllib3 is fundraising for HTTP/2 support</h2>
<p><a
href="https://sethmlarson.dev/urllib3-is-fundraising-for-http2-support">urllib3
is raising ~$40,000 USD</a> to release HTTP/2 support and ensure
long-term sustainable maintenance of the project after a sharp decline
in financial support. If your company or organization uses Python and
would benefit from HTTP/2 support in Requests, pip, cloud SDKs, and
thousands of other projects <a
href="https://opencollective.com/urllib3">please consider contributing
financially</a> to ensure HTTP/2 support is developed sustainably and
maintained for the long-haul.</p>
<p>Thank you for your support.</p>
<h2>Security</h2>
<p>Addressed high-severity security issues. Impact was limited to
specific use cases detailed in the accompanying advisories; overall user
exposure was estimated to be marginal.</p>
<ul>
<li>
<p>Decompression-bomb safeguards of the streaming API were bypassed:</p>
<ol>
<li>When <code>HTTPResponse.drain_conn()</code> was called after the
response had been read and decompressed partially. (Reported by <a
href="https://github.com/Cycloctane"><code>@​Cycloctane</code></a>)</li>
<li>During the second <code>HTTPResponse.read(amt=N)</code> or
<code>HTTPResponse.stream(amt=N)</code> call when the response was
decompressed using the official <a
href="https://pypi.org/project/brotli/">Brotli</a> library. (Reported by
<a
href="https://github.com/kimkou2024"><code>@​kimkou2024</code></a>)</li>
</ol>
<p>See GHSA-mf9v-mfxr-j63j for details.</p>
</li>
<li>
<p>HTTP pools created using
<code>ProxyManager.connection_from_url</code> did not strip sensitive
headers specified in <code>Retry.remove_headers_on_redirect</code> when
redirecting to a different host. (GHSA-qccp-gfcp-xxvc reported by <a
href="https://github.com/christos-spearbit"><code>@​christos-spearbit</code></a>)</p>
</li>
</ul>
<h2>Deprecations and Removals</h2>
<ul>
<li>Used <code>FutureWarning</code> instead of
<code>DeprecationWarning</code> for better visibility of existing
deprecation notices. Rescheduled the removal of deprecated features to
version 3.0. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3763">urllib3/urllib3#3763</a>)</li>
<li>Removed support for end-of-life Python 3.9. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3720">urllib3/urllib3#3720</a>)</li>
<li>Removed support for end-of-life PyPy3.10. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4979">urllib3/urllib3#4979</a>)</li>
<li>Bumped the minimum supported pyOpenSSL version to 19.0.0. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3777">urllib3/urllib3#3777</a>)</li>
</ul>
<h2>Bugfixes</h2>
<ul>
<li>Fixed a bug where <code>HTTPResponse.read(amt=None)</code> was
ignoring decompressed data buffered from previous partial reads. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3636">urllib3/urllib3#3636</a>)</li>
<li>Fixed a bug where <code>HTTPResponse.read()</code> could cache only
part of the response after a partial read when
<code>cache_content=True</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4967">urllib3/urllib3#4967</a>)</li>
<li>Fixed <code>HTTPResponse.stream()</code> and
<code>HTTPResponse.read_chunked()</code> to handle <code>amt=0</code>.
(<a
href="https://redirect.github.com/urllib3/urllib3/issues/3793">urllib3/urllib3#3793</a>)</li>
<li>Updated <code>_TYPE_BODY</code> type alias to include missing
<code>Iterable[str]</code>, matching the documented and runtime behavior
of chunked request bodies. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3798">urllib3/urllib3#3798</a>)</li>
<li>Fixed <code>LocationParseError</code> when paths resembling
schemeless URIs were passed to
<code>HTTPConnectionPool.urlopen()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3352">urllib3/urllib3#3352</a>)</li>
<li>Fixed <code>BaseHTTPResponse.readinto()</code> type annotation to
accept <code>memoryview</code> in addition to <code>bytearray</code>,
matching the <code>io.RawIOBase.readinto</code> contract and enabling
use with <code>io.BufferedReader</code> without type errors. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3764">urllib3/urllib3#3764</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/blob/main/CHANGES.rst">urllib3's
changelog</a>.</em></p>
<blockquote>
<h1>2.7.0 (2026-05-07)</h1>
<h2>Security</h2>
<p>Addressed high-severity security issues.
Impact was limited to specific use cases detailed in the accompanying
advisories; overall user exposure was estimated to be marginal.</p>
<ul>
<li>
<p>Decompression-bomb safeguards of the streaming API were bypassed:</p>
<ol>
<li>When <code>HTTPResponse.drain_conn()</code> was called after the
response had been
read and decompressed partially.</li>
<li>During the second <code>HTTPResponse.read(amt=N)</code> or
<code>HTTPResponse.stream(amt=N)</code> call when the response was
decompressed
using the official <code>Brotli
&lt;https://pypi.org/project/brotli/&gt;</code>__ library.</li>
</ol>
<p>See <code>GHSA-mf9v-mfxr-j63j
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-mf9v-mfxr-j63j&gt;</code>__
for details.</p>
</li>
<li>
<p>HTTP pools created using
<code>ProxyManager.connection_from_url</code> did not strip
sensitive headers specified in
<code>Retry.remove_headers_on_redirect</code> when
redirecting to a different host.
(<code>GHSA-qccp-gfcp-xxvc
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-qccp-gfcp-xxvc&gt;</code>__)</p>
</li>
</ul>
<h2>Deprecations and Removals</h2>
<ul>
<li>Used <code>FutureWarning</code> instead of
<code>DeprecationWarning</code> for better
visibility of existing deprecation notices. Rescheduled the removal of
deprecated features to version 3.0.
(<code>[#3763](https://github.com/urllib3/urllib3/issues/3763)
&lt;https://github.com/urllib3/urllib3/issues/3763&gt;</code>__)</li>
<li>Removed support for end-of-life Python 3.9.
(<code>[#3720](https://github.com/urllib3/urllib3/issues/3720)
&lt;https://github.com/urllib3/urllib3/issues/3720&gt;</code>__)</li>
<li>Removed support for end-of-life PyPy3.10.
(<code>[#4979](https://github.com/urllib3/urllib3/issues/4979)
&lt;https://github.com/urllib3/urllib3/issues/4979&gt;</code>__)</li>
<li>Bumped the minimum supported pyOpenSSL version to 19.0.0.
(<code>[#3777](https://github.com/urllib3/urllib3/issues/3777)
&lt;https://github.com/urllib3/urllib3/issues/3777&gt;</code>__)</li>
</ul>
<h2>Bugfixes</h2>
<ul>
<li>Fixed a bug where <code>HTTPResponse.read(amt=None)</code> was
ignoring decompressed
data buffered from previous partial reads.
(<code>[#3636](https://github.com/urllib3/urllib3/issues/3636)
&lt;https://github.com/urllib3/urllib3/issues/3636&gt;</code>__)</li>
<li>Fixed a bug where <code>HTTPResponse.read()</code> could cache only
part of the
response after a partial read when <code>cache_content=True</code>.</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/urllib3/urllib3/commit/9a950b92d999f906b6020bb2d1076ee56cddd5d2"><code>9a950b9</code></a>
Release 2.7.0</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/5ec0de499b9166ca71c65ab04f2a7e4eb0d66fcc"><code>5ec0de4</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/2bdcc44d1e163fb5cc48a8662425e35e15adfe6a"><code>2bdcc44</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/f45b0df09d8620ac6ed0491eb9362c8c87b7bc2c"><code>f45b0df</code></a>
Fix a misleading example for <code>ProxyManager</code> (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4970">#4970</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/577193ca029872384f82c133449e0935f6d8a64b"><code>577193c</code></a>
Switch to nightly PyPy3.11 in CI for now (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4984">#4984</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/e90af45bb006c3a452a3a21644a2681523f5c7fc"><code>e90af45</code></a>
Avoid infinite loop in <code>HTTPResponse.read_chunked</code> when
<code>amt=0</code> (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4974">#4974</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/67ed74fdaec6659a6534621ec8e3aaaa6f976210"><code>67ed74f</code></a>
Bump dev dependencies (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4972">#4972</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/3abd481097b54d87b574ac7ea593c3f40938a84d"><code>3abd481</code></a>
Upgrade mypy to version 1.20.2 (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4978">#4978</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/2b8725dfcac4f21d4d93cc0cc3a64a33af08f890"><code>2b8725d</code></a>
Drop support for EOL PyPy3.10 (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4979">#4979</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/2944b2a0a6c573f5548a39cfd17196f98ee21b33"><code>2944b2a</code></a>
Upgrade <code>setup-chrome</code> and <code>setup-firefox</code> to fix
warnings (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4973">#4973</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/urllib3/urllib3/compare/2.6.3...2.7.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=urllib3&package-manager=pip&previous-version=2.6.3&new-version=2.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts page](https://github.com/e2b-dev/E2B/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jakub Novák <jakub@e2b.dev>
2026-06-01 18:57:09 +02:00
github-actions[bot] e113618db0 [skip ci] Release new versions 2026-05-29 23:46:06 +00:00
Matt Brockman 4b9cc043dc Fix/python envd stable transport (#1368) 2026-05-29 16:39:30 -07:00