## Summary
- Resolved 43 type diagnostics reported by ty (Astral's Python type
checker)
- Fixed Self type issues on class singletons
- Added explicit type annotations for shadowed attributes
- Replaced None with UNSET for auto-generated API parameters
- Fixed method signature alignment for protocol matching
- Added targeted type: ignore suppressions for pattern-based limitations
All checks pass: ty check, ruff format, ruff check.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Mostly typing/CI changes, but some adjustments affect sandbox
connect/pause overload dispatch and API response/parameter handling
(`UNSET` vs `None`), which could alter edge-case runtime behavior.
>
> **Overview**
> Fixes Python SDK static typing issues for Astral’s `ty` checker and
wires typechecking into CI.
>
> Adds a new `Typecheck` GitHub Action plus workspace `typecheck`
scripts (TS packages via `tsc`, Python SDK via `make typecheck` running
`ty`), and publishes a patch changeset for `@e2b/python-sdk`.
>
> Across the Python SDK, adjusts type annotations and overloads (e.g.,
`Self`/singleton typing, `connect` overloads, optional
`user`/token/domain handling), tightens API model parsing with
`cast`/`Optional` checks and `UNSET` usage, and adds a few targeted `ty`
ignore comments in tests/protocols to silence checker limitations.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f66402847c40cee7e44e1aaa7caa97e271ba9978. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
## Summary
- Fixes `ty` type checker reporting `error[no-matching-overload]` when
calling `Sandbox.kill()` (and all other methods using the
`class_method_variant` pattern)
- Single 2-line change: make `class_method_variant` inherit from
`Generic[T]` instead of `object`
## Problem
The `class_method_variant` descriptor uses `cast(T, self)` to tell type
checkers that the decorator preserves the original function's type.
Without `Generic[T]`, `T` is only a method-level TypeVar — `ty` doesn't
trust the cast and fails to resolve overloads at call sites. `mypy` and
`pyright` are more lenient and accept it either way.
Affected methods (both `Sandbox` and `AsyncSandbox`): `kill`, `connect`,
`set_timeout`, `get_info`, `get_metrics`, `beta_pause`.
## Fix
Adding `Generic[T]` makes `T` a class-level type parameter, so `ty` can
track the type binding through the descriptor
(`class_method_variant[(self, **opts) -> bool]`). The cast then makes
sense to all three type checkers.
## Verification
Tested with a consumer repro (`sandbox.kill()`) against:
| Type Checker | Before | After |
|---|---|---|
| ty 0.0.15 | `error[no-matching-overload]` | All checks passed |
| mypy 1.19.1 | All checks passed | All checks passed |
| pyright 1.1.408 | All checks passed | All checks passed |
## Test plan
- [x] Verified `ty check` passes on consumer-side repro
- [x] Verified `mypy` and `pyright` still pass (no regressions)
- [x] Verified Python syntax is valid
- [x] No runtime behavior change (`Generic[T]` only affects type-level
metadata)
Add path validation to the copy method in both JS and Python SDKs to
ensure source paths are always relative and don't escape the context
directory.
This prevents:
- Absolute paths like /absolute/whatever (Unix) or C:\whatever (Windows)
- Path traversal attacks like ../whatever or ./foo/../../../bar
The validation works cross-platform using Node's
path.isAbsolute/normalize and Python's os.path.isabs/normpath plus
PureWindowsPath for detecting Windows paths on Unix.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Changes behavior of `copy`/`copy_items` to throw earlier for
previously-accepted absolute or escaping paths, which could break some
consumers; logic is localized and well-covered by tests.
>
> **Overview**
> Prevents path traversal in template `copy` operations by validating
`src` is *relative* and does not escape the context directory (rejects
absolute paths and `..`-based escapes) in both the JS and Python SDKs.
>
> Updates `copyItems`/`copy_items` error handling to preserve the
caller’s stack trace when validation fails, adds unit coverage for the
new path validator plus new stack-trace tests for absolute-path
failures, and ships as patch releases via a changeset.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c1a8eb978e3fd99fa829d571e811bb7ee18cd40b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Fixes issue with missing `restore` and `reset` functionality on the
async git sandboxes.
Consolidate shared git helpers by moving remote URL argument
construction and
parsing into the git utilities package. Sync and async git modules now
reuse
the same builders where possible, with tests to ensure no drift.
---------
Co-authored-by: Filip Brebera <filip@bxxf.dev>
# Sandbox Git Commands
Adds Git support to the sandbox class. This allows the sandbox to manage
git via standard clone, checkout, branch, add, pull, and push commands
without needing to use commands.run. The API mirrors common Git
workflows while handling sandbox-specific concerns like auth injection
and safe remote handling.
**Python example**
```python
from e2b import Sandbox
sandbox = Sandbox.create()
repo_path = '/home/user/my-repo'
# Optional: set author for commits
sandbox.git.configure_user('Your Name', 'you@example.com')
# Clone or init
sandbox.git.clone('https://github.com/org/repo.git', path=repo_path)
# or
sandbox.git.init(repo_path, initial_branch='main')
# Make a change
sandbox.files.write(f'{repo_path}/README.md', '# Hello\n')
# Commit
sandbox.git.add(repo_path, files=['README.md'])
sandbox.git.commit(repo_path, message='Initial commit')
# Branching
sandbox.git.create_branch(repo_path, 'feature1')
# or
sandbox.git.checkout_branch(repo_path, 'main')
# Push
sandbox.git.remote_add(repo_path, 'origin', 'https://github.com/org/repo.git', overwrite=True)
sandbox.git.push(repo_path, remote='origin', branch='main', set_upstream=True)
```
**JavaScript / TypeScript example**
```ts
import { Sandbox } from 'e2b'
const sandbox = await Sandbox.create()
const repoPath = '/home/user/my-repo'
await sandbox.git.configureUser('Your Name', 'you@example.com')
await sandbox.git.clone('https://github.com/org/repo.git', { path: repoPath })
// or
await sandbox.git.init(repoPath, { initialBranch: 'main' })
await sandbox.files.write(`${repoPath}/README.md`, '# Hello\n')
await sandbox.git.add(repoPath, { files: ['README.md'] })
await sandbox.git.commit(repoPath, { message: 'Initial commit' })
await sandbox.git.createBranch(repoPath, 'feature1')
await sandbox.git.checkoutBranch(repoPath, 'main')
await sandbox.git.remoteAdd(repoPath, 'origin', 'https://github.com/org/repo.git', {
overwrite: true,
})
await sandbox.git.push(repoPath, { remote: 'origin', branch: 'main', setUpstream: true })
```
**Main commands**
- `clone`: Clone a repo into the sandbox. Supports `branch`, `depth`,
optional `username` + `password` for private repos, and
`dangerously_store_credentials` / `dangerouslyStoreCredentials` to keep
credentials in the remote URL.
- `init`: Initialize a new repo. Supports `initial_branch` /
`initialBranch` and `bare`.
- `status`: Get parsed `git status --porcelain -b` info.
- `branches`: List branches and current branch.
- `create_branch` / `createBranch`: Create and check out a new branch.
- `checkout_branch` / `checkoutBranch`: Switch to an existing branch.
- `delete_branch` / `deleteBranch`: Delete a branch. Supports `force`.
- `add`: Stage files. Supports explicit files or `all`.
- `commit`: Create a commit. Supports author override and `allow_empty`.
- `reset` / `reset`: Reset `HEAD` (supports modes like `soft`, `mixed`,
`hard`, etc.) and optional paths.
- `restore` / `restore`: Restore files or unstage changes (`worktree` /
`staged`) from a source ref.
- `pull`: Pull from a remote. Supports `remote`, `branch`, and optional
auth.
- `push`: Push to a remote. Supports `remote`, `branch`, `set_upstream`,
and optional auth.
- `remote_add` / `remoteAdd`: Add a remote. Supports `overwrite` and
`fetch`.
- `remote_get` / `remoteGet`: Read a remote URL.
- `set_config` / `setConfig`: Set a git config value. Supports `scope`
(`global`, `local`, `system`), and `path` for local scope.
- `get_config` / `getConfig`: Read a git config value. Supports the same
`scope` options and returns `None` / `undefined` if unset.
- `dangerously_authenticate` / `dangerouslyAuthenticate`: Persist
credentials via the git credential helper (global).
- `configure_user` / `configureUser`: Set default `user.name` and
`user.email` for commits.
- `create_github_repo` (Python only): Create a GitHub repo from inside
the sandbox and optionally add it as a remote.
**Status shape**
- `status` returns a `GitStatus` with `current_branch` /
`currentBranch`, `upstream`, `ahead`, `behind`, `detached`, and
`file_status` / `fileStatus`.
- `file_status` entries include `name`, `status`, `index_status` /
`indexStatus`, `working_tree_status` / `workingTreeStatus`, `staged`,
and optional `renamed_from` / `renamedFrom`.
- Convenience helpers include: `is_clean` / `isClean`, `has_changes` /
`hasChanges`, `has_staged` / `hasStaged`, `has_untracked` /
`hasUntracked`, `has_conflicts` / `hasConflicts`, plus counts
(`total_count` / `totalCount`, `staged_count` / `stagedCount`,
`unstaged_count` / `unstagedCount`, `untracked_count` /
`untrackedCount`, `conflict_count` / `conflictCount`). In Python these
are properties on the `GitStatus` object; in JS they are fields on the
returned object.
**Notes**
- For private HTTPS remotes, pass `username` + `password` (token) on
`clone`, `pull`, or `push`.
- Use `remote_add` / `remoteAdd` with `overwrite=True` to update an
existing remote URL and `fetch=True` to fetch after.
- Use `dangerously_authenticate` / `dangerouslyAuthenticate` only when
you want to persist credentials globally on the sandbox.
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Optimizes file uploads in both JS and Python SDKs to avoid unnecessary
reads and add broader input support.
>
> - JS SDK: `Filesystem.write`/`writeFiles` now build a single
`FormData` using `toBlob` (new util) to pass
`string`/`ArrayBuffer`/`Blob`/`ReadableStream` without pre-reading;
updated tests add `ReadableStream` coverage
> - Python SDK (sync/async): `write_files` accepts `str`/`bytes`
directly, reads `TextIOBase`, and passes `IOBase` (binary) streams
through without reading; new tests cover `BytesIO` and `StringIO`
> - Changeset: patch bumps for `@e2b/python-sdk` and `e2b`
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
45516e31fa8ba8b678824a6c1adc217287a8effe. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Aligns metrics APIs to use Unix seconds (no milliseconds) for
`start`/`end` across SDKs.
>
> - **JS SDK**: `SandboxMetricsOpts` `start`/`end` now `Date` only;
convert to seconds before calling `GET /sandboxes/{sandboxID}/metrics`.
> - **Python SDK (async/sync)**: send `int(timestamp())` for
`start`/`end` instead of milliseconds.
> - **Tests**: JS and Python tests now pass `start`/`end` and validate
non-empty results.
> - **Changesets**: patch notes for `e2b` and `@e2b/python-sdk`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
7c59f8023fc0de9a5eda7ffd4c588057c7465f3e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
small follow-up to #1068
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Aligns alias existence error handling across SDKs to use
template-specific errors.
>
> - JS: `checkAliasExists` now passes `TemplateError` to
`handleApiError` and imports `TemplateError` in `buildApi.ts`
> - Python: `check_alias_exists` uses `TemplateException` in both async
and sync `build_api.py`
> - Adds changeset for patch releases of `@e2b/python-sdk` and `e2b`
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0624c03207d0ee09b2fc838e204f6232cba5c748. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Integration tests will fail until the feature is deployed in E2B Cloud
production.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Enables checking template alias availability from both SDKs.
>
> - JS: Implements `checkAliasExists` in `template/buildApi.ts`, exposes
`Template.aliasExists` in `template/index.ts`, adds `AliasExistsOptions`
type and tests
> - Python: Adds `Template.alias_exists` and
`AsyncTemplate.alias_exists` wired to generated
`get_templates_aliases_{alias}` client; includes sync/async tests
> - API: Regenerates schemas/clients to include `GET
/templates/aliases/{alias}`, template build logs endpoint and
parameters, and supporting models (e.g., `TemplateAliasResponse`)
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
4e577fd77888478ac83b66db7537cd2355ea050b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Adds support for parsing ownership on file copy operations in
Dockerfile-based templates.
>
> - JS: Update `dockerfileParser.ts` to treat `COPY/ADD` as
`ModifiableInstruction`, parse `--chown` via `instruction.getFlags()`,
and pass `user` to `templateBuilder.copy(src, dest, { user })`
> - Python: Update `_handle_copy_instruction` in `dockerfile_parser.py`
to extract `--chown=<user[:group]>` and pass `user` to
`template_builder.copy(src, dest, user=user)`
> - Tests: Add JS and Python (sync/async) tests verifying `COPY --chown`
parsing and argument propagation
> - Changeset: Patch releases for `@e2b/python-sdk` and `e2b`
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
9f3b151be18288bdcc41eaf37157b5d4572f0abf. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Summary
- Fixes garbled Unicode and box-drawing character rendering when running
tmux inside E2B sandboxes
- Adds `LANG=C.UTF-8` and `LC_ALL=C.UTF-8` environment variable defaults
to PTY creation in both JS/TS and Python SDKs
## Problem
When running applications like Claude Code inside tmux in an E2B
sandbox, Unicode characters and box-drawing glyphs render incorrectly:
**Before (broken):**
- Box-drawing characters appear as broken dashes
- Text alignment is garbled
- The Claude mascot renders as `------` instead of proper pixel art
**After (fixed):**
- Proper Unicode rendering
- Correct box-drawing characters
- Properly aligned text
## Root Cause
The PTY session was created with `TERM=xterm-256color` but without UTF-8
locale settings. Running `locale` in the sandbox showed:
```
LANG=
LC_CTYPE="POSIX"
LC_ALL=
```
tmux requires UTF-8 locale settings to properly render Unicode
characters. Without them, it falls back to ASCII-only rendering.
## Solution
Set `LANG` and `LC_ALL` to `C.UTF-8` by default when creating PTY
sessions. This locale is:
- Available on most modern Linux distributions
- Provides UTF-8 character encoding
- Portable and doesn't require specific locale packages
The fix uses `setdefault` (Python) / nullish coalescing (JS) to allow
users to override these values if needed.
## Files Changed
| File | Change |
|------|--------|
| `packages/js-sdk/src/sandbox/commands/pty.ts` | Add LANG and LC_ALL
defaults |
| `packages/python-sdk/e2b/sandbox_async/commands/pty.py` | Add LANG and
LC_ALL defaults |
| `packages/python-sdk/e2b/sandbox_sync/commands/pty.py` | Add LANG and
LC_ALL defaults |
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Fix tmux Unicode rendering by enforcing UTF-8 locale in PTYs**
>
> - In PTY creation (JS `pty.ts`, Python async/sync `pty.py`), default
`LANG` and `LC_ALL` to `C.UTF-8`; set `TERM` only if not already
provided
> - Adds changeset entry documenting the patch
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a914027d39568da2c9b022cb25e6f9b4e9aab91c. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Add a note to the template environment variables that they exist only
during template build, so users don't get confused.
---------
Co-authored-by: Mish <10400064+mishushakov@users.noreply.github.com>
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Introduce `connect` methods to attach to running PTY sessions across
JS and Python SDKs, with tests and default timeout handling.
>
> - **SDKs**:
> - **JS (`packages/js-sdk/src/sandbox/commands/pty.ts`)**:
> - Add `Pty.connect(pid, opts?)` to attach to running PTYs; accepts
`PtyConnectOpts` with `onData`, `timeoutMs`, and `requestTimeoutMs`.
> - Factor default PTY connection timeout via
`defaultPtyConnectionTimeout` and apply to `create`/`connect` calls.
> - **Python**:
> - Async: Add `AsyncSandbox.pty.connect(pid, on_data, timeout?,
request_timeout?)` in `e2b/sandbox_async/commands/pty.py`.
> - Sync: Add `sandbox.pty.connect(pid, timeout?, request_timeout?)` in
`e2b/sandbox_sync/commands/pty.py`.
> - **Tests**:
> - JS: `packages/js-sdk/tests/sandbox/pty/ptyConnect.test.ts` validates
connect/reconnect and output handling.
> - Python: async and sync tests under
`packages/python-sdk/tests/.../pty/test_pty_connect.py` verify
reconnection and exit codes.
> - **Release**:
> - Changeset: minor version bumps for `@e2b/python-sdk` and `e2b`; note
“added option to connect to a running pty session”.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
539c4f518606544dfcef253df5bde49354fe7903. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Mish <10400064+mishushakov@users.noreply.github.com>
What was happening is that the following snippet:
```dockerfile
CMD ["sleep", "20"]
```
Was incorrectly converted to:
```
sleep, 20
```
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Fixes parsing of Dockerfile CMD/ENTRYPOINT array syntax to a proper
start command and updates tests accordingly.
>
> - **Python SDK**:
> - `e2b/template/dockerfile_parser.py`: Parse CMD/ENTRYPOINT JSON array
(e.g., `["sleep", "20"]`) into a space-joined command (`sleep 20`) and
set as `start_cmd`.
> - **Tests**:
> - JS SDK and Python (sync/async): Add ENTRYPOINT case and assert
`startCmd`/`_start_cmd` equals `sleep 20`.
> - **Release**:
> - Changeset: patch bump for `@e2b/python-sdk`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ed257ab11e618ece3e5fe70f232a3265fd857ad4. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Add Windows to CI matrices and make JS/Python utils and tests
cross-platform via path handling updates.
>
> - **CI**:
> - Add Windows to test matrices in `cli_tests.yml`, `js_sdk_tests.yml`,
`python_sdk_tests.yml`; set bash shell/workdirs; disable fail-fast for
some jobs.
> - Python CI runs `pytest -n 4` via Poetry.
> - **JS SDK**:
> - Path normalization for globbing (`normalizePath`) and use of
`Path.relativePosix()` in hashing and tar creation in
`src/template/utils.ts`.
> - **Python SDK**:
> - Add `normalize_path` and use forward-slash glob patterns in
`e2b/template/utils.py`.
> - **Tests**:
> - Make stack trace parsing robust to Windows paths; use `basename` in
file assertions; adjust Python tar tests tempdir fixture handling.
> - **Changeset**: add patch note for windows-related fixes.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1b8dbe4a1af642dbcb86500837e93f7998b223f6. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Joseph Lombrozo <joe.lombrozo@e2b.dev>
Fixes issue https://github.com/e2b-dev/E2B/issues/1032
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Preserve Dockerfile USER/WORKDIR when provided and only apply E2B
defaults if absent, with tests and CLI fixtures updated accordingly.
>
> - **Dockerfile parsing (SDKs)**:
> - **JS (`packages/js-sdk/src/template/dockerfileParser.ts`)**: Track
`USER`/`WORKDIR` usage and only set E2B defaults (`user`, `/home/user`)
if not specified; keep Docker defaults (`root`, `/`) initially.
> - **Python
(`packages/python-sdk/e2b/template/dockerfile_parser.py`)**: Same
behavior—preserve explicit `USER`/`WORKDIR`, fallback to defaults only
when absent.
> - **Tests**:
> - **JS**: Add tests for default vs. custom `USER`/`WORKDIR` in
`fromMethods.test.ts`.
> - **Python (async/sync)**: Add analogous tests in
`test_from_methods.py`.
> - **CLI template fixtures**:
> - Update expected outputs to remove redundant
`.set_user('user')`/`.set_workdir('/home/user')` when already specified;
minor ordering tweak for `.setStartCmd` in TS fixture.
> - **Changeset**:
> - Minor version bumps for `@e2b/python-sdk` and `e2b`; note: keep
Docker `WORKDIR` and `USER` if specified.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1ce66362501932308292cef87b5d8a73012ee5f2. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
- removed machine, os, processor, release default headers (these do not
occur in the JS version)
- particularly, "processor" header was causing issues on Windows due to
incorrect formatting/escape.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Removes unnecessary default headers from the Python SDK API client and
adds a patch changeset.
>
> - **Python SDK**:
> - Trim `default_headers` in `packages/python-sdk/e2b/api/metadata.py`
by removing `machine`, `os`, `processor`, and `release`.
> - **Release**:
> - Add changeset to publish a patch for `@e2b/python-sdk`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
9a5ef769ee2eb0b9a05649c20a00dfd507984931. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This takes some shortcuts in order to keep backwards compatibility.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Reuses a singleton httpx transport/client across the SDK, introduces a
generic retry decorator for connect calls, and refactors code/tests to
use the shared clients and fixtures.
>
> - **SDK (transport/client reuse)**
> - Add global `limits` (configurable via `E2B_*` env vars) and switch
`ApiClient` to accept `transport` instead of `limits`.
> - Introduce `e2b.api.client_async/client_sync` with `get_transport()`
(singleton) and `get_api_client()`; update `Sandbox`/`AsyncSandbox`,
paginators, and sandbox APIs to use them.
> - Remove per-class `_limits` from `SandboxBase`/`TemplateBase`; merge
extra headers correctly; pass `E2b-Sandbox-Port` as string.
> - Template build flows (sync/async) now reuse the API client's
underlying httpx client for file uploads.
> - **Connect client** (`e2b_connect/client.py`)
> - Add `_retry` decorator and apply to unary/server-stream methods;
simplify reconnection logic; minor typing/headers cleanups.
> - **Tests**
> - Add retry unit tests; introduce
`sandbox_factory`/`async_sandbox_factory` and a session `event_loop`;
refactor tests to use factories and shared transports; adjust tar
archive expectations.
> - **Misc**
> - Add `.editorconfig`, CLI `.envrc`, and changeset entries.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1d359231b63dc21b6c8d797886f7d6a77c9ed6b7. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Tomas Valenta <valenta.and.thomas@gmail.com>
Co-authored-by: Mish <10400064+mishushakov@users.noreply.github.com>
This requires [infra#1448](https://github.com/e2b-dev/infra/pull/1448)
first.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Adds support to override the sandbox API URL (E2B_SANDBOX_URL) across
JS/Python SDKs, centralizes sandbox host/url logic with headers, and
updates CI to build the SDK before CLI.
>
> - **SDKs (JS & Python)**
> - Add `sandboxUrl` support in `ConnectionConfig` (env var
`E2B_SANDBOX_URL`), with new helpers `getSandboxUrl`/`getHost` and
shared `envdPort`.
> - Refactor sandbox initialization to use
`ConnectionConfig.getSandboxUrl(...)` and `getHost(...)`.
> - Always attach sandbox headers `E2b-Sandbox-Id` and
`E2b-Sandbox-Port` to sandbox and connect requests.
> - Python: thread `sandbox_url` through opts; update async/sync connect
calls to pass headers; minor fix to default `headers=None` in
`e2b_connect.client.Client` stream prep.
> - **CI**
> - Build `packages/js-sdk` before `packages/cli`; set step
`working-directory` for build/test.
> - **Dependencies**
> - Point `e2b` dependency in lockfile to local `../js-sdk` link.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
5dc58171af6c170f8640f49d736dbe9c571f2b21. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Mish <10400064+mishushakov@users.noreply.github.com>
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Ensure file uploads honor ignore patterns (incl. .dockerignore),
refactor file discovery/tar streaming in JS/Python SDKs, and add
comprehensive tests.
>
> - **File upload behavior**:
> - JS/TS and Python uploads now pass `ignorePatterns` (merged from
`fileIgnorePatterns` and `.dockerignore`) to tar creation, ensuring
ignored files aren’t uploaded.
> - **Refactor/Utilities**:
> - Rename `getAllFilesForFilesHash` -> `getAllFilesInPath` with
optional directory inclusion in both SDKs.
> - Implement `tar_file_stream` (JS and Python) to build archives from
`getAllFilesInPath`, with `noDirRecurse` and symlink control.
> - Hashing functions updated to use `getAllFilesInPath`.
> - Type tweak: allow `None` in Python `stack_traces` during build wait.
> - **Integration**:
> - JS `uploadFile` and Python async/sync `upload_file` now use tar
streaming with ignore patterns; JS `Template` wires ignore patterns into
uploads.
> - **Tests**:
> - Add extensive tests for `getAllFilesInPath` and `tar_file_stream` in
JS and Python, covering ignore patterns, directories, sorting, and
symlinks.
> - Remove obsolete tests relying on old function names.
> - **Meta**:
> - Changeset entries for `@e2b/python-sdk` and `e2b` (patch).
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2f83444f9006393f33e8c346bec1998b3a06044d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Currently, when you provide a simple folder pattern like `folder/` to
copy() it will not check folders contents for changes (only the folder
metadata itself) which leads to stale caches.
This fix appends ** pattern when no pattern is specified for recursive
hash computation.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Ensure folder COPY patterns hash contents recursively to fix cache
invalidation, adding a shared file-gathering helper, tests, and a Python
glob dependency.
>
> - **Template hashing (JS + Python SDKs)**:
> - Add `getAllFilesForFilesHash`
(`packages/js-sdk/src/template/utils.ts`) and
`get_all_files_for_files_hash`
(`packages/python-sdk/e2b/template/utils.py`) to collect directories and
nested files using glob patterns and ignores.
> - Update `calculateFilesHash`/`calculate_files_hash` to use the new
helpers, hashing recursive paths, metadata, and file contents; handle
symlinks consistently.
> - **Tests**:
> - Add comprehensive tests for recursive matching, ignore patterns,
sorting, empty dirs, symlinks in
`packages/js-sdk/tests/.../getAllFilesForFilesHash.test.ts` and Python
async/sync tests under
`packages/python-sdk/tests/.../test_get_all_files_for_files_hash.py`.
> - **Dependencies**:
> - Add `wcmatch` in `packages/python-sdk/pyproject.toml` for advanced
globbing.
> - **Release**:
> - Patch bump via `.changeset/green-mice-watch.md`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d495427d86ad4e4d5a280567baa63df40a3271fb. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Jakub Dobry <jakub.dobry8@gmail.com>
Current env var syntax won't be anymore supported by Docker and is
currently blocking local development.
```
3 warnings found (use docker --debug to expand):
- LegacyKeyValueFormat: "ENV key=value" should be used instead of legacy "ENV key value" format (line 2)
```
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Use "ENV key=value" in generated Dockerfiles and add tests; minor
devcontainer path string cast.
>
> - **Template/Dockerfile generation**:
> - **JS SDK (`packages/js-sdk/src/template/index.ts`)**: Handle `ENV`
instructions and output as `ENV key=value ...`.
> - **Python SDK (`packages/python-sdk/e2b/template/main.py`)**: Same
`ENV` formatting; also cast `devcontainer_directory` to `str` in
devcontainer start command.
> - **Tests**:
> - **JS**: Add `toDockerfile` test covering `ENV` output.
> - **Python (sync/async)**: Add tests for `ENV` output in generated
Dockerfiles.
> - **Changeset**: Patch releases for `@e2b/python-sdk` and `e2b`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
4a9c504167dd8069551724d83bfa66f0859c1bd4. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Use new connect API for JS/Python SDKs to connect and only extend
(never shorten) running sandbox timeouts, with updated types/docs and
tests.
>
> - **SDKs**:
> - **JS**:
> - Replace `resume`/`setTimeout` flow with `SandboxApi.connectSandbox`
calling `POST /sandboxes/{sandboxID}/connect`.
> - Update `Sandbox.connect` (static/instance) to use returned
`sandboxDomain`, `envdAccessToken`, `envdVersion`.
> - Redefine `SandboxConnectOpts` to include `timeoutMs` that only
extends existing timeout.
> - **Python (async/sync)**:
> - Introduce `_cls_connect` using `post_sandboxes_sandbox_id_connect`
with `ConnectSandbox`; return `Sandbox` model.
> - Update `connect` methods to use API response for
domain/token/version; remove extra info fetch.
> - Docstrings clarify timeout only extends for running sandboxes.
> - **Tests**:
> - Add cases ensuring connect does not shorten timeout and does extend
when longer (JS, async Python, sync Python).
> - Preserve error on connecting to non-running sandbox.
> - **Meta**:
> - Changeset: minor releases for `@e2b/python-sdk`, `e2b`, and
`@e2b/cli`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e76b07990cb4c05e51ba1c51fb5cc7bbd44b991b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Adds `fromBunImage` and `bunInstall` to JS/Python SDKs, and extends
`npmInstall` with a `dev` flag, with tests across sync/async suites.
>
> - **Template APIs**:
> - Add `fromBunImage` to start from `oven/bun:<variant>` in
`packages/js-sdk/src/template/index.ts` and
`packages/python-sdk/e2b/template/main.py`.
> - Add `bunInstall(packages, { g, dev })` in both SDKs.
> - Extend `npmInstall` to accept `{ dev: boolean }` in both SDKs.
> - **Types/Docs**:
> - Update `packages/js-sdk/src/template/types.ts` to declare
`fromBunImage`, `bunInstall`, and `npmInstall` `dev` option.
> - **Tests**:
> - Add tests for `fromBunImage` and `bunInstall` and update
`npmInstall` (global/dev) in JS (`packages/js-sdk/tests/...`) and Python
sync/async (`packages/python-sdk/tests/...`).
> - **Changeset**:
> - Minor releases for `@e2b/python-sdk` and `e2b`
(`.changeset/silly-lions-buy.md`).
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b6461d015743d38ba014d724167d2ca256cf7951. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
for building type-safe wrappers around .setStartCmd/.setReadyCmd
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Expose `ReadyCmd` via JS (`packages/js-sdk/src/index.ts`) and Python
(`e2b/__init__.py`) SDK entrypoints, with patch version bumps.
>
> - **SDK Exports**:
> - **JS**: Re-exports `ReadyCmd` from `./template/readycmd` in
`packages/js-sdk/src/index.ts`.
> - **Python**: Exposes `ReadyCmd` in `e2b/__init__.py` imports and
`__all__`.
> - **Versioning**:
> - `.changeset/early-trainers-repeat.md`: Patch bumps for
`@e2b/python-sdk` and `e2b`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ff91a3e3578be8db6ea7644ee6717f1bd18b0165. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Adds a force option to makeSymlink that passes -f to ln, with
typings/docs and tests across JS and Python SDKs.
>
> - **Template symlink enhancement**
> - **JS SDK (`packages/js-sdk`)**:
> - `makeSymlink(src, dest, options)` now accepts `{ user?: string;
force?: boolean }` and appends `-f` when `force` is true in
`src/template/index.ts`.
> - Types updated in `src/template/types.ts`, including example usage
with `{ force: true }`.
> - Tests added in `tests/template/methods/makeSymlink.test.ts` (regular
and forced).
> - **Python SDK (`packages/python-sdk`)**:
> - `make_symlink(src, dest, user=None, force=False)` now supports
`force` and appends `-f` when true in `e2b/template/main.py`.
> - Docstring examples updated to include `force=True`.
> - Tests added for async and sync in
`tests/async/template_async/methods/test_make_symlink.py` and
`tests/sync/template_sync/methods/test_make_symlink.py`.
> - **Release**:
> - Changeset added for patch releases of `@e2b/python-sdk` and `e2b`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
6c5bbf9edfc7234b703046f387d11b8f10a002ab. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This was causing some unexpected issues if users were trying to
apt-install some packages that needed recommended dependencies.
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Adds an option to `aptInstall`/`apt_install` to toggle
`--no-install-recommends`, updates typings/docs, and adds tests for both
modes.
>
> - **Template APIs**:
> - **JS SDK (`packages/js-sdk`)**:
> - `aptInstall` now accepts `options?: { noInstallRecommends?: boolean
}` and conditionally includes `--no-install-recommends`.
> - Types updated in `src/template/types.ts` with example usage.
> - **Python SDK (`packages/python-sdk`)**:
> - `apt_install` now accepts `no_install_recommends: bool = False` and
conditionally includes `--no-install-recommends`.
> - **Tests**:
> - JS: Add `aptInstall` tests (with and without `noInstallRecommends`);
refactor `npmInstall` tests to use `buildTemplateTest` helper.
> - Python: Add async and sync tests for `apt_install` with and without
`no_install_recommends`.
> - **Changeset**:
> - Patch bumps for `@e2b/python-sdk` and `e2b` with note on making
`--no-install-recommends` optional.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3963b7daca73f1cfb99f405b09fbfb86c40c4b4f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
The "lts" tag was unavailable on Docker Hub
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Switch default Ubuntu image tag from 'lts' to 'latest' across
JS/Python SDKs and expand/refactor template tests and test config.
>
> - **SDKs**:
> - **Ubuntu default**: Change `fromUbuntuImage`/`from_ubuntu_image`
default variant from `'lts'` to `'latest'` in
`packages/js-sdk/src/template/index.ts` and
`packages/python-sdk/e2b/template/main.py`; update TS docs in
`packages/js-sdk/src/template/types.ts`.
> - **Tests**:
> - **JS**: Refactor template tests to use `buildTemplateTest`, add
`tests/template/methods/fromMethods.test.ts`, adjust npm/pip/runCmd
tests (include user install with `g: false`), and remove per-test
timeouts where not needed.
> - **Python (async/sync)**: Add comprehensive tests for from* methods,
npm/pip installs (including user installs), and runCmd behaviors; switch
to shared build fixtures.
> - **Vitest config**: Exclude `tests/template/**` from the main suite
and include all template tests in a dedicated project in
`vitest.workspace.mts`.
> - **Changeset**:
> - Patch bumps for `@e2b/python-sdk` and `e2b`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0bf3a7c15122d28cbc99b8faa44e7e217f634377. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
(no tests as nothin was breaking)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Adds an optional `user` parameter to fs-related template methods and
`gitClone`, with tests for running commands as specific users.
>
> - **SDKs**:
> - **JS (`packages/js-sdk`)**:
> - Add `user` option to `TemplateBuilder` methods: `remove`, `rename`,
`makeDir`, `makeSymlink`, and `gitClone`; pass through to `runCmd`.
> - Update type defs and examples in `src/template/types.ts`.
> - **Python (`packages/python-sdk`)**:
> - Add `user` arg to `TemplateBuilder` methods: `remove`, `rename`,
`make_dir`, `make_symlink`, and `git_clone`; forward to `run_cmd`.
> - Update docstrings/examples.
> - **Tests**:
> - JS: add `runCmd` tests for default, specific `user`, and invalid
user in `packages/js-sdk/tests/template/methods/runCmd.test.ts`.
> - Python: add async and sync `run_cmd` tests (default, specific
`user`, invalid user) in
`packages/python-sdk/tests/async/.../test_run_cmd.py` and
`packages/python-sdk/tests/sync/.../test_run_cmd.py`.
> - **Release**:
> - Add changeset (`.changeset/warm-seals-design.md`) marking patch
bumps for `@e2b/python-sdk` and `e2b`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b0cbedc1d5c136367155c5646859842bd666b0d9. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This adds (experimantal) support to add arbitrary MCP server from
Github.
```python
sbx = await AsyncSandbox.beta_create(timeout=600, mcp={
"github/modelcontextprotocol/servers": {
"install_cmd": "npm install",
"run_cmd": "sudo npx -y @modelcontextprotocol/server-filesystem /root",
},
})
```
or in TS with better typing:
```typescript
const sandbox = await Sandbox.betaCreate({
mcp: {
duckduckgo: {},
'github/modelcontextprotocol/servers': {
installCmd: 'npm install',
runCmd: `sudo npx -y @modelcontextprotocol/server-filesystem /root`,
},
},
timeoutMs: 600_000,
});
```
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Adds beta support to launch custom MCP servers (including
GitHub-defined ones) and updates MCP schemas/types; also switches
default MCP template to `mcp-gateway`.
>
> - **SDK (JS & Python)**:
> - Add beta support for `mcp` config, including dynamic GitHub-based
servers with custom `runCmd/installCmd/envs` and automatic `mcp-gateway`
startup with token.
> - Send `UNSET`/omit when `mcp` not provided to avoid API noise.
> - Change default MCP template from `mcp-gateway-v0-2` to
`mcp-gateway`.
> - **Types/Schema**:
> - Extend `McpServer` typings (JS `mcp.d.ts`, Python type hints) to
include many servers and descriptive metadata.
> - Introduce GitHub MCP types (TS `GitHubMcpServer`, Python
`GitHubMcpServerConfig`) and export in SDK surfaces.
> - Regenerate and enrich `spec/mcp-server.json` with
titles/descriptions and new server entries.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f3139b8fc2f1246c72734d8048ba277a13e3949d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This will help for local development
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Add support to override the API base URL via `api_url` parameter or
`E2B_API_URL` env var with clear precedence.
>
> - **Python SDK**:
> - **ConnectionConfig**:
> - Add `api_url` parameter and `_api_url()` env lookup (`E2B_API_URL`).
> - Resolve `api_url` in order: constructor arg > `E2B_API_URL` >
`debug` localhost or `https://api.<domain>`.
> - **API Params**:
> - Include `api_url` in `ApiParams` and propagate via `get_api_params`.
> - **Tests** (`packages/python-sdk/tests/test_connection_config.py`):
> - Verify default, arg override, env override, and precedence.
> - **Changeset**: Patch release for `@e2b/python-sdk`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
9be6d4e85bb0ad8ea52ad61c77530ac72f231c54. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Fix Dockerfile generation to properly render `RUN` and `COPY`
instructions using only relevant args, and add patch changesets.
>
> - **Template to Dockerfile generation**:
> - JS (`packages/js-sdk/src/template/index.ts`): Special-case `RUN` and
`COPY` so Dockerfile emits `RUN <cmd>` and `COPY <src> <dest>` instead
of joining all args.
> - Python (`packages/python-sdk/e2b/template/main.py`): Same
special-casing for `RUN` and `COPY` during Dockerfile rendering.
> - **Release**:
> - Changeset: patch bumps for `@e2b/python-sdk` and `e2b` with note
"fix RUN and COPY handling in to_dockerfile".
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
04b2dbbda34f0845f3d4ec9963cc478b7b7b7f01. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Previously the gateway was just fire and forget which lead to a race
condition when you immediately tried to access the mcp server, changed
the template to launch a daemon with healthcheck.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Start MCP gateway synchronously with error checks and bump default MCP
template to `mcp-gateway-v0-2` across JS and Python SDKs.
>
> - **MCP Gateway startup**:
> - JS (`packages/js-sdk/src/sandbox/index.ts`): Start `mcp-gateway`
without background mode; validate exit code and throw on failure.
> - Python Async (`packages/python-sdk/e2b/sandbox_async/main.py`):
Await `mcp-gateway` start, remove background/timeout flags; raise on
non-zero exit.
> - Python Sync (`packages/python-sdk/e2b/sandbox_sync/main.py`): Run
`mcp-gateway` synchronously; check exit code and raise on failure.
> - **Defaults**:
> - Update `default_mcp_template` from `mcp-gateway-v0-1` to
`mcp-gateway-v0-2` in JS and Python SDKs.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
79e431c78bf384c970a5b1fede55071116a089c5. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Adds `mcp` config support for sandbox creation across API, JS, and
Python SDKs, and updates timeout tests to use explicit request timeouts.
>
> - **API/OpenAPI**:
> - Add `McpConfig` schema and `mcp` field to `NewSandbox` in
`spec/openapi.yml` and generated TS `schema.gen.ts`.
> - **JS SDK**:
> - `SandboxApi.createSandbox` sends `mcp` in POST body
(`packages/js-sdk/src/sandbox/sandboxApi.ts`).
> - Types updated to include `components["schemas"]["McpConfig"]`.
> - **Python SDK**:
> - Extend `NewSandbox` model and sandbox create flow to accept/pass
`mcp`; async/sync APIs propagate `mcp` to POST `/sandboxes`.
> - **Tests**:
> - Increase `is_running` request timeouts in timeout tests to reduce
flakiness (JS and Python).
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
04ad4e6d4947e33523b74aba2f703fa1e9c05e72. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Global installs for pip/npm now run as root; pip gains an option to
install per-user instead.
>
> - **Template SDKs**:
> - **JavaScript (`packages/js-sdk/src/template`)**:
> - `pipInstall` now supports `options: { g?: boolean }` (default
`true`); when `g` is `true`, runs as `root`, when `false`, adds `--user`
and runs as current user.
> - `npmInstall` runs as `root` when `options.g` is `true`.
> - **Python (`packages/python-sdk/e2b/template/main.py`)**:
> - `pip_install` now accepts `g: bool = True`; when `True`, runs as
`root`, when `False`, adds `--user` and runs as current user.
> - `npm_install` runs as `root` when `g` is `True`.
> - **Changeset**: patch bump for `@e2b/python-sdk` and `e2b` with note:
install global packages as sudo.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
6be5ba211f7d200d50ffca50c1751d455b3e2cfa. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->