Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/drop-undici7.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'e2b': minor
'@e2b/cli': minor
'@e2b/code-interpreter': minor
'@e2b/desktop': minor
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
---

Require Node.js 22.19.0 or newer and depend on `undici@^8` only (undici 7 is dropped).

- undici 8 respects the server's HTTP/2 `SETTINGS_MAX_CONCURRENT_STREAMS` and opens more connections when one is saturated.
- Breaking: the SDK-level in-flight request cap is removed, along with the `E2B_API_INFLIGHT_REQUESTS`, `E2B_ENVD_INFLIGHT_REQUESTS` and `E2B_ENVD_RPC_INFLIGHT_REQUESTS` env vars. Concurrency is governed by undici's connection pools (`E2B_API_CONNECTIONS`, `E2B_ENVD_RPC_CONNECTIONS`).
2 changes: 1 addition & 1 deletion codegen.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ ENV PATH="/go/bin:${PATH}"
RUN pip install black==26.3.1 e2b-openapi-python-client==0.26.2 datamodel-code-generator==0.64.0 protoc-gen-connectrpc==0.11.1 protoc-gen-py==0.1.1

# Install Node.js (pinned to match .tool-versions)
ENV NODE_VERSION=22.18.0
ENV NODE_VERSION=22.23.3
RUN ARCH=$(uname -m) && \
case "$ARCH" in \
x86_64) NODE_ARCH="x64" ;; \
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,6 @@
"yup": "^1.7.1"
},
"engines": {
"node": ">=22.9.0"
"node": ">=22.19.0"
}
}
2 changes: 1 addition & 1 deletion packages/code-interpreter-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
"vm"
],
"engines": {
"node": ">=22"
"node": ">=22.19.0"
},
"browserslist": [
"defaults"
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"package.json"
],
"engines": {
"node": ">=22"
"node": ">=22.19.0"
},
"browserslist": [
"defaults"
Expand Down
7 changes: 2 additions & 5 deletions packages/js-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,10 @@
"openapi-fetch": "^0.17.0",
"platform": "^1.3.6",
"tar": "^7.5.22",
"undici": "^7.30.0"
},
"optionalDependencies": {
"undici8": "npm:undici@8.11.2"
"undici": "^8.11.2"
},
"engines": {
"node": ">=22"
"node": ">=22.19.0"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Align the CLI's Node floor with the SDK

When the changesets release process updates @e2b/cli's workspace:^ dependency to this new SDK major, the CLI will still advertise Node >=20.18.1 <21 || >=22.9.0, while this dependency rejects every version below 22.19.0. Consequently, installing the current CLI on its documented Node 20 or Node 22.9–22.18 range fails for users with strict engine enforcement (including this repository's pnpm configuration), before the intended global-fetch fallback can run. Update the CLI engine range and changeset/tests as part of this breaking release, or retain a compatible SDK engine range for the fallback path.

Useful? React with 👍 / 👎.

Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
},
"browserslist": [
"defaults"
Expand Down
21 changes: 1 addition & 20 deletions packages/js-sdk/src/api/http2.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import { runtime } from '../utils'
import { DEFAULT_HTTP_VERSION, type HttpVersion } from '../connectionConfig'
import { parseInflightLimitEnv, parsePositiveIntEnv } from './metadata'
import { parsePositiveIntEnv } from './metadata'
import {
buildDispatchedFetch,
createRuntimeFetch,
type UndiciModule,
} from '../undici'

const DEFAULT_API_CONNECTION_LIMIT = 100
// 1000 = ~10 streams per connection (with the 100-conn default).
// Override via env if your workload needs different.
const DEFAULT_API_INFLIGHT_LIMIT = 1000

// Fetchers are cached per proxy and HTTP version so requests without a proxy
// keep sharing a single dispatcher while each distinct proxy URL gets its own.
Expand Down Expand Up @@ -42,7 +39,6 @@ export function createApiFetchForRuntime(
currentRuntime = runtime,
options: {
connectionLimit?: number
inflightLimit?: number
proxy?: string
httpVersion?: HttpVersion
loadUndici?: () => Promise<UndiciModule | undefined>
Expand All @@ -53,7 +49,6 @@ export function createApiFetchForRuntime(
return createRuntimeFetch(currentRuntime, () =>
buildDispatchedFetch({
connections: options.connectionLimit ?? getApiConnectionLimit(),
inflightLimit: options.inflightLimit ?? getApiInflightLimit(),
proxy: options.proxy,
httpVersion: options.httpVersion,
loadUndici: options.loadUndici,
Expand All @@ -67,17 +62,3 @@ export function getApiConnectionLimit(): number {
DEFAULT_API_CONNECTION_LIMIT
)
}

/**
* Returns the configured max number of API requests that can be in flight at
* once, or `0` to disable the cap.
*
* Defaults to `1000` ({@link DEFAULT_API_INFLIGHT_LIMIT}). Override via
* `E2B_API_INFLIGHT_REQUESTS` env var; set to `0` to disable the cap entirely.
*/
export function getApiInflightLimit(): number {
return parseInflightLimitEnv(
'E2B_API_INFLIGHT_REQUESTS',
DEFAULT_API_INFLIGHT_LIMIT
)
}
82 changes: 0 additions & 82 deletions packages/js-sdk/src/api/inflight.ts

This file was deleted.

21 changes: 0 additions & 21 deletions packages/js-sdk/src/api/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,24 +62,3 @@ export function parsePositiveIntEnv(

return parsed
}

/**
* Parse an inflight-limit env var. Returns `0` to disable the cap (documented
* opt-out) or a positive integer to cap concurrency. Throws on non-integer or
* negative values so misconfiguration is surfaced loudly rather than silently
* removing the cap. A return value of `0` is recognized by
* {@link limitConcurrency} as "no cap".
*/
export function parseInflightLimitEnv(
name: string,
defaultValue: number
): number {
const parsed = parseIntEnv(name, defaultValue)
if (parsed < 0) {
throw new Error(
`Invalid ${name}=${parsed}: expected a non-negative integer ` +
'(use 0 to disable the cap).'
)
}
return parsed
}
40 changes: 1 addition & 39 deletions packages/js-sdk/src/envd/http2.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { runtime } from '../utils'
import { DEFAULT_HTTP_VERSION, type HttpVersion } from '../connectionConfig'
import type { FetchOpts } from '../api/http2'
import { parseInflightLimitEnv, parsePositiveIntEnv } from '../api/metadata'
import { parsePositiveIntEnv } from '../api/metadata'
import {
buildDispatchedFetch,
createRuntimeFetch,
Expand All @@ -10,7 +10,6 @@ import {

type EnvdFetchOptions = {
connectionLimit?: number
inflightLimit?: number
proxy?: string
httpVersion?: HttpVersion
loadUndici?: () => Promise<UndiciModule | undefined>
Expand All @@ -22,8 +21,6 @@ const envdFetchers = new Map<string, typeof fetch>()
const envdRpcFetchers = new Map<string, typeof fetch>()
const DEFAULT_ENVD_CONNECTION_LIMIT = 10
const DEFAULT_ENVD_RPC_CONNECTION_LIMIT = 200
const DEFAULT_ENVD_INFLIGHT_LIMIT = 2000
const DEFAULT_ENVD_RPC_INFLIGHT_LIMIT = 2000

export function createEnvdFetchForRuntime(
currentRuntime = runtime,
Expand All @@ -32,7 +29,6 @@ export function createEnvdFetchForRuntime(
return createRuntimeFetch(currentRuntime, () =>
buildDispatchedFetch({
connections: options.connectionLimit ?? DEFAULT_ENVD_CONNECTION_LIMIT,
inflightLimit: options.inflightLimit ?? 0,
proxy: options.proxy,
httpVersion: options.httpVersion,
loadUndici: options.loadUndici,
Expand Down Expand Up @@ -61,7 +57,6 @@ export function createEnvdFetch({
// Keep one origin connection for short envd REST calls. If ALPN falls back
// to h1, this favors connection pressure over per-sandbox throughput.
const envdFetch = createEnvdFetchForRuntime(runtime, {
inflightLimit: getEnvdInflightLimit(),
proxy,
httpVersion,
})
Expand All @@ -83,7 +78,6 @@ export function createEnvdRpcFetch({

const envdRpcFetch = createEnvdFetchForRuntime(runtime, {
connectionLimit: getEnvdRpcConnectionLimit(),
inflightLimit: getEnvdRpcInflightLimit(),
proxy,
httpVersion,
})
Expand All @@ -98,35 +92,3 @@ export function getEnvdRpcConnectionLimit(): number {
DEFAULT_ENVD_RPC_CONNECTION_LIMIT
)
}

/**
* Returns the configured max number of envd REST requests (e.g.
* `files.read`/`files.write`) that can be in flight at once across all
* sandboxes in this SDK process, or `0` to disable the cap.
*
* Defaults to `2000` ({@link DEFAULT_ENVD_INFLIGHT_LIMIT}). Override
* via `E2B_ENVD_INFLIGHT_REQUESTS` env var; set to `0` to disable the cap
* entirely.
*/
export function getEnvdInflightLimit(): number {
return parseInflightLimitEnv(
'E2B_ENVD_INFLIGHT_REQUESTS',
DEFAULT_ENVD_INFLIGHT_LIMIT
)
}

/**
* Returns the configured max number of envd RPC requests that
* can be in flight at once across all sandboxes in this SDK process,
* or `0` to disable the cap.
*
* Defaults to `2000` ({@link DEFAULT_ENVD_RPC_INFLIGHT_LIMIT}). Override
* via `E2B_ENVD_RPC_INFLIGHT_REQUESTS` env var; set to `0` to disable the cap
* entirely.
*/
export function getEnvdRpcInflightLimit(): number {
return parseInflightLimitEnv(
'E2B_ENVD_RPC_INFLIGHT_REQUESTS',
DEFAULT_ENVD_RPC_INFLIGHT_LIMIT
)
}
7 changes: 3 additions & 4 deletions packages/js-sdk/src/template/buildApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,9 @@ async function putFileStream(
): Promise<{ ok: boolean; statusText: string }> {
// Prefer undici's fetch: it honors the explicit Content-Length on stream
// bodies on every runtime, while Deno's native fetch ignores the header and
// falls back to chunked. Where undici isn't resolvable (e.g. bundled apps),
// fall back to the global fetch — Node's and Bun's native fetch also honor
// Content-Length on stream bodies. loadUndici tries undici 8 first and
// falls back to undici 7 where 8 doesn't import (Bun).
// falls back to chunked. Where undici doesn't load (e.g. bundled apps),
// the global fetch is used — Node's and Bun's native fetch also honor
// Content-Length on stream bodies.
const undici = await loadUndici()
const fetchImpl = (undici?.fetch as typeof fetch | undefined) ?? fetch

Expand Down
Loading
Loading