Skip to content

Conversation

@djeebus
Copy link
Contributor

@djeebus djeebus commented Nov 6, 2025

This requires infra#1448 first.


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.

Written by Cursor Bugbot for commit 5dc5817. This will update automatically on new commits. Configure here.

@changeset-bot
Copy link

changeset-bot bot commented Nov 6, 2025

🦋 Changeset detected

Latest commit: 5dc5817

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
e2b Patch
@e2b/python-sdk Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Envd API URL Not Passed During Sandbox Reconnect

The _cls_connect method doesn't pass envd_api_url when creating the sandbox instance. When reconnecting to an existing sandbox, the envd_api_url will always default to the computed value instead of allowing users to override it. The method should accept an envd_api_url parameter and pass it to the cls() constructor call on line 672.

packages/python-sdk/e2b/sandbox_async/main.py#L648-L677

@classmethod
async def _cls_connect(
cls,
sandbox_id: str,
timeout: Optional[int] = None,
**opts: Unpack[ApiParams],
) -> Self:
await SandboxApi._cls_resume(
sandbox_id=sandbox_id,
timeout=timeout,
**opts,
)
response = await SandboxApi._cls_get_info(sandbox_id, **opts)
sandbox_headers = {}
envd_access_token = response._envd_access_token
if envd_access_token is not None and not isinstance(envd_access_token, Unset):
sandbox_headers["X-Access-Token"] = envd_access_token
connection_config = ConnectionConfig(
extra_sandbox_headers=sandbox_headers,
**opts,
)
return cls(
sandbox_id=response.sandbox_id,
sandbox_domain=response.sandbox_domain,
envd_version=Version(response.envd_version),
envd_access_token=envd_access_token,

Fix in Cursor Fix in Web


Bug: Envd API URL Not Propagated During Sandbox Reconnect

The _cls_connect method doesn't pass envd_api_url when creating the sandbox instance. When reconnecting to an existing sandbox, the envd_api_url will always default to the computed value instead of allowing users to override it. The method should accept an envd_api_url parameter and pass it to the cls() constructor call on line 672.

packages/python-sdk/e2b/sandbox_sync/main.py#L649-L677

@classmethod
def _cls_connect(
cls,
sandbox_id: str,
timeout: Optional[int] = None,
**opts: Unpack[ApiParams],
) -> Self:
SandboxApi._cls_resume(sandbox_id, timeout, **opts)
response = cls._cls_get_info(sandbox_id, **opts)
sandbox_headers = {}
envd_access_token = response._envd_access_token
if envd_access_token is not None and not isinstance(envd_access_token, Unset):
sandbox_headers["X-Access-Token"] = envd_access_token
connection_config = ConnectionConfig(
extra_sandbox_headers=sandbox_headers,
**opts,
)
return cls(
sandbox_id=sandbox_id,
sandbox_domain=response.sandbox_domain,
connection_config=connection_config,
envd_version=Version(response.envd_version),
envd_access_token=envd_access_token,
)

Fix in Cursor Fix in Web


Bug: Beta_create ignores envd_api_url parameter

The beta_create method doesn't accept envd_api_url as a parameter and doesn't pass it to the _create method call on line 587. This means users cannot override the envd API URL when using beta_create, unlike the regular create method which does support this parameter.

packages/python-sdk/e2b/sandbox_async/main.py#L561-L605

sandbox = await cls._create(
template=template,
timeout=timeout,
auto_pause=auto_pause,
metadata=metadata,
envs=envs,
secure=secure,
allow_internet_access=allow_internet_access,
mcp=mcp,
**opts,
)
if mcp is not None:
token = str(uuid.uuid4())
sandbox._mcp_token = token
res = await sandbox.commands.run(
f"mcp-gateway --config '{json.dumps(mcp)}'",
user="root",
envs={"GATEWAY_ACCESS_TOKEN": token},
)
if res.exit_code != 0:
raise Exception(f"Failed to start MCP gateway: {res.stderr}")
return sandbox
@overload
async def beta_pause(
self,
**opts: Unpack[ApiParams],
) -> None:
"""
[BETA] This feature is in beta and may change in the future.
Pause the sandbox.
:return: Sandbox ID that can be used to resume the sandbox
"""
...
@overload
@staticmethod
async def beta_pause(
sandbox_id: str,
**opts: Unpack[ApiParams],

Fix in Cursor Fix in Web


Bug: Beta_create Fails to Override API URL Parameter

The beta_create method doesn't accept envd_api_url as a parameter and doesn't pass it to the _create method call on line 587. This means users cannot override the envd API URL when using beta_create, unlike the regular create method which does support this parameter.

packages/python-sdk/e2b/sandbox_sync/main.py#L561-L605

if not template and mcp is not None:
template = cls.default_mcp_template
elif not template:
template = cls.default_template
sandbox = cls._create(
template=template,
auto_pause=auto_pause,
timeout=timeout,
metadata=metadata,
envs=envs,
secure=secure,
allow_internet_access=allow_internet_access,
mcp=mcp,
**opts,
)
if mcp is not None:
token = str(uuid.uuid4())
sandbox._mcp_token = token
res = sandbox.commands.run(
f"mcp-gateway --config '{json.dumps(mcp)}'",
user="root",
envs={"GATEWAY_ACCESS_TOKEN": token},
)
if res.exit_code != 0:
raise Exception(f"Failed to start MCP gateway: {res.stderr}")
return sandbox
@overload
def beta_pause(
self,
**opts: Unpack[ApiParams],
) -> None:
"""
[BETA] This feature is in beta and may change in the future.
Pause the sandbox.
"""
...
@overload

Fix in Cursor Fix in Web


Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 737 to 739
envd_version=envd_version,
envd_access_token=envd_access_token,
connection_config=connection_config,

Choose a reason for hiding this comment

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

P1 Badge Connect path cannot use custom envd API URL

The new envd_api_url parameter and routing headers are wired only through _create, but _cls_connect still builds its ConnectionConfig with only the optional access token. When a sandbox is created with a custom envd endpoint (or when the endpoint requires the X-Sandbox-ID/X-Sandbox-Port headers added here) and the user later reconnects via AsyncSandbox.connect(...), the reconnecting instance has no way to supply the same URL or headers, so subsequent file/command requests go to the default domain and will fail for sandboxes behind the custom load balancer. _cls_connect needs to accept and forward envd_api_url and the extra headers as well to make the override usable for reconnections.

Useful? React with 👍 / 👎.

return cls(
sandbox_id=sandbox_id,
sandbox_domain=sandbox_domain,
envd_version=envd_version,

Choose a reason for hiding this comment

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

P1 Badge Synchronous reconnect ignores envd API override

As in the async variant, the sync _create path now accepts envd_api_url and adds the X-Sandbox-ID/X-Sandbox-Port headers, but _cls_connect still constructs a sandbox using only the default host and no new headers. Reconnecting to a sandbox that was created through a custom envd API (or where the load balancer depends on those headers) will therefore hit the wrong endpoint or be rejected. _cls_connect should expose an envd_api_url parameter and include the same headers so reconnections behave consistently.

Useful? React with 👍 / 👎.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: API URL not honored by beta_create method

The beta_create method does not accept or pass the envd_api_url parameter to _create(), even though _create() now accepts this parameter (line 689). This means users cannot override the envd API URL when using beta_create, creating an inconsistency with the regular create method which does support this parameter.

packages/python-sdk/e2b/sandbox_sync/main.py#L547-L590

:param template: Sandbox template name or ID
:param timeout: Timeout for the sandbox in **seconds**, default to 300 seconds. The maximum time a sandbox can be kept alive is 24 hours (86_400 seconds) for Pro users and 1 hour (3_600 seconds) for Hobby users.
:param auto_pause: Automatically pause the sandbox after the timeout expires. Defaults to `False`.
:param metadata: Custom metadata for the sandbox
:param envs: Custom environment variables for the sandbox
:param secure: Envd is secured with access token and cannot be used without it, defaults to `True`.
:param allow_internet_access: Allow sandbox to access the internet, defaults to `True`.
:param mcp: MCP server to enable in the sandbox
:return: A Sandbox instance for the new sandbox
Use this method instead of using the constructor to create a new sandbox.
"""
if not template and mcp is not None:
template = cls.default_mcp_template
elif not template:
template = cls.default_template
sandbox = cls._create(
template=template,
auto_pause=auto_pause,
timeout=timeout,
metadata=metadata,
envs=envs,
secure=secure,
allow_internet_access=allow_internet_access,
mcp=mcp,
**opts,
)
if mcp is not None:
token = str(uuid.uuid4())
sandbox._mcp_token = token
res = sandbox.commands.run(
f"mcp-gateway --config '{json.dumps(mcp)}'",
user="root",
envs={"GATEWAY_ACCESS_TOKEN": token},
)
if res.exit_code != 0:
raise Exception(f"Failed to start MCP gateway: {res.stderr}")

Fix in Cursor Fix in Web


Bug: beta_create ignores envd_api_url parameter

The beta_create method does not accept or pass the envd_api_url parameter to _create(), even though _create() now accepts this parameter (line 692). This means users cannot override the envd API URL when using beta_create, creating an inconsistency with the regular create method which does support this parameter.

packages/python-sdk/e2b/sandbox_async/main.py#L544-L587

:param auto_pause: Automatically pause the sandbox after the timeout expires. Defaults to `False`.
:param metadata: Custom metadata for the sandbox
:param envs: Custom environment variables for the sandbox
:param secure: Envd is secured with access token and cannot be used without it, defaults to `True`.
:param allow_internet_access: Allow sandbox to access the internet, defaults to `True`.
:param mcp: MCP server to enable in the sandbox
:return: A Sandbox instance for the new sandbox
Use this method instead of using the constructor to create a new sandbox.
"""
if not template and mcp is not None:
template = cls.default_mcp_template
elif not template:
template = cls.default_template
sandbox = await cls._create(
template=template,
timeout=timeout,
auto_pause=auto_pause,
metadata=metadata,
envs=envs,
secure=secure,
allow_internet_access=allow_internet_access,
mcp=mcp,
**opts,
)
if mcp is not None:
token = str(uuid.uuid4())
sandbox._mcp_token = token
res = await sandbox.commands.run(
f"mcp-gateway --config '{json.dumps(mcp)}'",
user="root",
envs={"GATEWAY_ACCESS_TOKEN": token},
)
if res.exit_code != 0:
raise Exception(f"Failed to start MCP gateway: {res.stderr}")
return sandbox
@overload

Fix in Cursor Fix in Web


Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Inconsistent beta_create with envd_api_url parameter

The beta_create method doesn't accept the envd_api_url parameter that was added to the create method and _create internal method. This creates an inconsistency where users can override the envd API URL with create() but not with beta_create(), even though both methods call the same _create() internal method that now supports this parameter.

packages/python-sdk/e2b/sandbox_async/main.py#L544-L577

:param auto_pause: Automatically pause the sandbox after the timeout expires. Defaults to `False`.
:param metadata: Custom metadata for the sandbox
:param envs: Custom environment variables for the sandbox
:param secure: Envd is secured with access token and cannot be used without it, defaults to `True`.
:param allow_internet_access: Allow sandbox to access the internet, defaults to `True`.
:param mcp: MCP server to enable in the sandbox
:return: A Sandbox instance for the new sandbox
Use this method instead of using the constructor to create a new sandbox.
"""
if not template and mcp is not None:
template = cls.default_mcp_template
elif not template:
template = cls.default_template
sandbox = await cls._create(
template=template,
timeout=timeout,
auto_pause=auto_pause,
metadata=metadata,
envs=envs,
secure=secure,
allow_internet_access=allow_internet_access,
mcp=mcp,
**opts,
)
if mcp is not None:
token = str(uuid.uuid4())
sandbox._mcp_token = token
res = await sandbox.commands.run(

Fix in Cursor Fix in Web


Bug: API URL parameter missing in beta_create signature

The beta_create method doesn't accept the envd_api_url parameter that was added to the create method and _create internal method. This creates an inconsistency where users can override the envd API URL with create() but not with beta_create(), even though both methods call the same _create() internal method that now supports this parameter.

packages/python-sdk/e2b/sandbox_sync/main.py#L513-L546

"Metrics are not supported in this version of the sandbox, please rebuild your template."
)
if self._envd_version < Version("0.2.4"):
logger.warning(
"Disk metrics are not supported in this version of the sandbox, please rebuild the template to get disk metrics."
)
return SandboxApi._cls_get_metrics(
sandbox_id=self.sandbox_id,
start=start,
end=end,
**self.connection_config.get_api_params(**opts),
)
@classmethod
def beta_create(
cls,
template: Optional[str] = None,
timeout: Optional[int] = None,
auto_pause: bool = False,
metadata: Optional[Dict[str, str]] = None,
envs: Optional[Dict[str, str]] = None,
secure: bool = True,
allow_internet_access: bool = True,
mcp: Optional[McpServer] = None,
**opts: Unpack[ApiParams],
) -> Self:
"""
[BETA] This feature is in beta and may change in the future.
Create a new sandbox.
By default, the sandbox is created from the default `base` sandbox template.

Fix in Cursor Fix in Web


Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Sandbox connection header inconsistency

The _cls_connect method doesn't add E2b-Sandbox-Id and E2b-Sandbox-Port headers to sandbox_headers before creating the ConnectionConfig, unlike the _create method which adds these headers. This inconsistency means sandboxes connected via connect() will be missing these headers that are present when using create(), potentially causing issues if the infrastructure expects them.

packages/python-sdk/e2b/sandbox_async/main.py#L646-L675

@classmethod
async def _cls_connect(
cls,
sandbox_id: str,
timeout: Optional[int] = None,
**opts: Unpack[ApiParams],
) -> Self:
await SandboxApi._cls_resume(
sandbox_id=sandbox_id,
timeout=timeout,
**opts,
)
response = await SandboxApi._cls_get_info(sandbox_id, **opts)
sandbox_headers = {}
envd_access_token = response._envd_access_token
if envd_access_token is not None and not isinstance(envd_access_token, Unset):
sandbox_headers["X-Access-Token"] = envd_access_token
connection_config = ConnectionConfig(
extra_sandbox_headers=sandbox_headers,
**opts,
)
return cls(
sandbox_id=response.sandbox_id,
sandbox_domain=response.sandbox_domain,
envd_version=Version(response.envd_version),
envd_access_token=envd_access_token,

Fix in Cursor Fix in Web


Bug: Inconsistent Sandbox Header Handling

The _cls_connect method doesn't add E2b-Sandbox-Id and E2b-Sandbox-Port headers to sandbox_headers before creating the ConnectionConfig, unlike the _create method which adds these headers. This inconsistency means sandboxes connected via connect() will be missing these headers that are present when using create(), potentially causing issues if the infrastructure expects them.

packages/python-sdk/e2b/sandbox_sync/main.py#L647-L676

@classmethod
def _cls_connect(
cls,
sandbox_id: str,
timeout: Optional[int] = None,
**opts: Unpack[ApiParams],
) -> Self:
SandboxApi._cls_resume(sandbox_id, timeout, **opts)
response = cls._cls_get_info(sandbox_id, **opts)
sandbox_headers = {}
envd_access_token = response._envd_access_token
if envd_access_token is not None and not isinstance(envd_access_token, Unset):
sandbox_headers["X-Access-Token"] = envd_access_token
connection_config = ConnectionConfig(
extra_sandbox_headers=sandbox_headers,
**opts,
)
return cls(
sandbox_id=sandbox_id,
sandbox_domain=response.sandbox_domain,
connection_config=connection_config,
envd_version=Version(response.envd_version),
envd_access_token=envd_access_token,
)
@classmethod

Fix in Cursor Fix in Web


Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Sandbox URL override feature fails.

The constructor doesn't assign opts?.sandboxUrl to a class property, but getSandboxUrl() method references this.sandboxUrl on line 131. This causes the sandbox URL override feature to not work since the property is always undefined.

packages/js-sdk/src/connectionConfig.ts#L83-L97

constructor(opts?: ConnectionOpts) {
this.apiKey = opts?.apiKey || ConnectionConfig.apiKey
this.debug = opts?.debug || ConnectionConfig.debug
this.domain = opts?.domain || ConnectionConfig.domain
this.accessToken = opts?.accessToken || ConnectionConfig.accessToken
this.requestTimeoutMs = opts?.requestTimeoutMs ?? REQUEST_TIMEOUT_MS
this.logger = opts?.logger
this.headers = opts?.headers || {}
this.headers['User-Agent'] = `e2b-js-sdk/${version}`
this.apiUrl =
opts?.apiUrl ||
ConnectionConfig.apiUrl ||
(this.debug ? 'http://localhost:3000' : `https://api.${this.domain}`)

Fix in Cursor Fix in Web


Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Sandbox URL: Programmatic Override Silently Ignored

The sandboxUrl option in ConnectionOpts is documented and exposed but never stored or used in the ConnectionConfig constructor. When users pass sandboxUrl in options, it gets silently ignored because getSandboxUrl only checks the static environment variable getter, not an instance field. This breaks the ability to override the sandbox URL programmatically.

packages/js-sdk/src/connectionConfig.ts#L84-L99

readonly headers?: Record<string, string>
constructor(opts?: ConnectionOpts) {
this.apiKey = opts?.apiKey || ConnectionConfig.apiKey
this.debug = opts?.debug || ConnectionConfig.debug
this.domain = opts?.domain || ConnectionConfig.domain
this.accessToken = opts?.accessToken || ConnectionConfig.accessToken
this.requestTimeoutMs = opts?.requestTimeoutMs ?? REQUEST_TIMEOUT_MS
this.logger = opts?.logger
this.headers = opts?.headers || {}
this.headers['User-Agent'] = `e2b-js-sdk/${version}`
this.apiUrl =
opts?.apiUrl ||
ConnectionConfig.apiUrl ||
(this.debug ? 'http://localhost:3000' : `https://api.${this.domain}`)

Fix in Cursor Fix in Web


Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Sandbox URL option is ineffective.

The ConnectionConfig constructor doesn't store or use the sandboxUrl option from opts, even though ConnectionOpts interface includes it and getSandboxUrl method exists. This means passing sandboxUrl via options has no effect, unlike the Python SDK which correctly handles this parameter. The constructor should store opts?.sandboxUrl and getSandboxUrl should check it before falling back to the environment variable.

packages/js-sdk/src/connectionConfig.ts#L85-L99

constructor(opts?: ConnectionOpts) {
this.apiKey = opts?.apiKey || ConnectionConfig.apiKey
this.debug = opts?.debug || ConnectionConfig.debug
this.domain = opts?.domain || ConnectionConfig.domain
this.accessToken = opts?.accessToken || ConnectionConfig.accessToken
this.requestTimeoutMs = opts?.requestTimeoutMs ?? REQUEST_TIMEOUT_MS
this.logger = opts?.logger
this.headers = opts?.headers || {}
this.headers['User-Agent'] = `e2b-js-sdk/${version}`
this.apiUrl =
opts?.apiUrl ||
ConnectionConfig.apiUrl ||
(this.debug ? 'http://localhost:3000' : `https://api.${this.domain}`)

Fix in Cursor Fix in Web


Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Inconsistent Sandbox Connection Headers

The _cls_connect method doesn't set the E2b-Sandbox-Id and E2b-Sandbox-Port headers that are required for sandbox communication. These headers are set in the _create method but missing here, causing inconsistent behavior when connecting to existing sandboxes versus creating new ones.

packages/python-sdk/e2b/sandbox_sync/main.py#L650-L676

@classmethod
def _cls_connect(
cls,
sandbox_id: str,
timeout: Optional[int] = None,
**opts: Unpack[ApiParams],
) -> Self:
sandbox = SandboxApi._cls_connect(sandbox_id, timeout, **opts)
sandbox_headers = {}
envd_access_token = sandbox.envd_access_token
if envd_access_token is not None and not isinstance(envd_access_token, Unset):
sandbox_headers["X-Access-Token"] = envd_access_token
connection_config = ConnectionConfig(
extra_sandbox_headers=sandbox_headers,
**opts,
)
return cls(
sandbox_id=sandbox_id,
sandbox_domain=sandbox.domain,
connection_config=connection_config,
envd_version=Version(sandbox.envd_version),
envd_access_token=envd_access_token,
)

Fix in Cursor Fix in Web


Bug: Sandbox Connectivity Header Mismatch

The _cls_connect method doesn't set the E2b-Sandbox-Id and E2b-Sandbox-Port headers that are required for sandbox communication. These headers are set in the _create method but missing here, causing inconsistent behavior when connecting to existing sandboxes versus creating new ones.

packages/python-sdk/e2b/sandbox_async/main.py#L649-L675

@classmethod
async def _cls_connect(
cls,
sandbox_id: str,
timeout: Optional[int] = None,
**opts: Unpack[ApiParams],
) -> Self:
sandbox = await SandboxApi._cls_connect(
sandbox_id=sandbox_id,
timeout=timeout,
**opts,
)
sandbox_headers = {}
envd_access_token = sandbox.envd_access_token
if envd_access_token is not None and not isinstance(envd_access_token, Unset):
sandbox_headers["X-Access-Token"] = envd_access_token
connection_config = ConnectionConfig(
extra_sandbox_headers=sandbox_headers,
**opts,
)
return cls(
sandbox_id=sandbox.sandbox_id,
sandbox_domain=sandbox.domain,
envd_version=Version(sandbox.envd_version),

Fix in Cursor Fix in Web


Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Reconnected Sandboxes Lose Identification

The _cls_connect method doesn't set the E2b-Sandbox-Id and E2b-Sandbox-Port headers that are required for sandbox communication. These headers are properly set in the _create method but missing here, causing reconnected sandboxes to lack necessary identification headers when making requests to the sandbox API.

packages/python-sdk/e2b/sandbox_sync/main.py#L650-L677

@classmethod
def _cls_connect(
cls,
sandbox_id: str,
timeout: Optional[int] = None,
**opts: Unpack[ApiParams],
) -> Self:
sandbox = SandboxApi._cls_connect(sandbox_id, timeout, **opts)
sandbox_headers = {}
envd_access_token = sandbox.envd_access_token
if envd_access_token is not None and not isinstance(envd_access_token, Unset):
sandbox_headers["X-Access-Token"] = envd_access_token
connection_config = ConnectionConfig(
extra_sandbox_headers=sandbox_headers,
**opts,
)
return cls(
sandbox_id=sandbox_id,
sandbox_domain=sandbox.domain,
connection_config=connection_config,
envd_version=Version(sandbox.envd_version),
envd_access_token=envd_access_token,
)
@classmethod

Fix in Cursor Fix in Web


Bug: Reconnected sandboxes lose their identity.

The _cls_connect method doesn't set the E2b-Sandbox-Id and E2b-Sandbox-Port headers that are required for sandbox communication. These headers are properly set in the _create method but missing here, causing reconnected sandboxes to lack necessary identification headers when making requests to the sandbox API.

packages/python-sdk/e2b/sandbox_async/main.py#L651-L678

@classmethod
async def _cls_connect(
cls,
sandbox_id: str,
timeout: Optional[int] = None,
**opts: Unpack[ApiParams],
) -> Self:
sandbox = await SandboxApi._cls_connect(
sandbox_id=sandbox_id,
timeout=timeout,
**opts,
)
sandbox_headers = {}
envd_access_token = sandbox.envd_access_token
if envd_access_token is not None and not isinstance(envd_access_token, Unset):
sandbox_headers["X-Access-Token"] = envd_access_token
connection_config = ConnectionConfig(
extra_sandbox_headers=sandbox_headers,
**opts,
)
return cls(
sandbox_id=sandbox.sandbox_id,
sandbox_domain=sandbox.domain,
envd_version=Version(sandbox.envd_version),
envd_access_token=envd_access_token,

Fix in Cursor Fix in Web


Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Missing Dependency Breaks CLI Functionality

The e2b dependency was removed from the CLI package dependencies, but the CLI code extensively imports and uses e2b throughout multiple files (api.ts, sandbox commands, template commands, auth commands). This will cause the CLI package to fail at runtime when trying to import e2b.

packages/cli/package.json#L88-L89

"dockerfile-ast": "^0.6.1",
"handlebars": "^4.7.8",

Fix in Cursor Fix in Web


@djeebus djeebus force-pushed the support-local-envd-dev branch from e95a9c7 to 8131eb4 Compare November 11, 2025 01:29
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Inconsistent Sandbox Header Handling

The _cls_connect method doesn't set the E2b-Sandbox-Id and E2b-Sandbox-Port headers that are set in the _create method. This creates an inconsistency where sandboxes created via create() have these headers but sandboxes connected via connect() don't, potentially causing different behavior or failures when the backend expects these headers.

packages/python-sdk/e2b/sandbox_async/main.py#L655-L677

timeout: Optional[int] = None,
**opts: Unpack[ApiParams],
) -> Self:
sandbox = await SandboxApi._cls_connect(
sandbox_id=sandbox_id,
timeout=timeout,
**opts,
)
sandbox_headers = {}
envd_access_token = sandbox.envd_access_token
if envd_access_token is not None and not isinstance(envd_access_token, Unset):
sandbox_headers["X-Access-Token"] = envd_access_token
connection_config = ConnectionConfig(
extra_sandbox_headers=sandbox_headers,
**opts,
)
return cls(
sandbox_id=sandbox.sandbox_id,
sandbox_domain=sandbox.domain,
envd_version=Version(sandbox.envd_version),

Fix in Cursor Fix in Web


Bug: Mismatched Sandbox Connection Headers

The _cls_connect method doesn't set the E2b-Sandbox-Id and E2b-Sandbox-Port headers that are set in the _create method. This creates an inconsistency where sandboxes created via create() have these headers but sandboxes connected via connect() don't, potentially causing different behavior or failures when the backend expects these headers.

packages/python-sdk/e2b/sandbox_sync/main.py#L650-L672

@classmethod
def _cls_connect(
cls,
sandbox_id: str,
timeout: Optional[int] = None,
**opts: Unpack[ApiParams],
) -> Self:
sandbox = SandboxApi._cls_connect(sandbox_id, timeout, **opts)
sandbox_headers = {}
envd_access_token = sandbox.envd_access_token
if envd_access_token is not None and not isinstance(envd_access_token, Unset):
sandbox_headers["X-Access-Token"] = envd_access_token
connection_config = ConnectionConfig(
extra_sandbox_headers=sandbox_headers,
**opts,
)
return cls(
sandbox_id=sandbox_id,
sandbox_domain=sandbox.domain,
connection_config=connection_config,

Fix in Cursor Fix in Web


Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Sandbox Connection Headers: Inconsistency Bug

The _cls_connect method is missing the E2b-Sandbox-Id and E2b-Sandbox-Port headers that are added in the _create method. When connecting to an existing sandbox, these headers won't be sent, causing inconsistent behavior compared to newly created sandboxes. The headers should be added to sandbox_headers before creating the ConnectionConfig.

packages/python-sdk/e2b/sandbox_async/main.py#L655-L677

timeout: Optional[int] = None,
**opts: Unpack[ApiParams],
) -> Self:
sandbox = await SandboxApi._cls_connect(
sandbox_id=sandbox_id,
timeout=timeout,
**opts,
)
sandbox_headers = {}
envd_access_token = sandbox.envd_access_token
if envd_access_token is not None and not isinstance(envd_access_token, Unset):
sandbox_headers["X-Access-Token"] = envd_access_token
connection_config = ConnectionConfig(
extra_sandbox_headers=sandbox_headers,
**opts,
)
return cls(
sandbox_id=sandbox.sandbox_id,
sandbox_domain=sandbox.domain,
envd_version=Version(sandbox.envd_version),

Fix in Cursor Fix in Web


Bug: Sandbox Connection Header Inconsistency

The _cls_connect method is missing the E2b-Sandbox-Id and E2b-Sandbox-Port headers that are added in the _create method. When connecting to an existing sandbox, these headers won't be sent, causing inconsistent behavior compared to newly created sandboxes. The headers should be added to sandbox_headers before creating the ConnectionConfig.

packages/python-sdk/e2b/sandbox_sync/main.py#L650-L672

@classmethod
def _cls_connect(
cls,
sandbox_id: str,
timeout: Optional[int] = None,
**opts: Unpack[ApiParams],
) -> Self:
sandbox = SandboxApi._cls_connect(sandbox_id, timeout, **opts)
sandbox_headers = {}
envd_access_token = sandbox.envd_access_token
if envd_access_token is not None and not isinstance(envd_access_token, Unset):
sandbox_headers["X-Access-Token"] = envd_access_token
connection_config = ConnectionConfig(
extra_sandbox_headers=sandbox_headers,
**opts,
)
return cls(
sandbox_id=sandbox_id,
sandbox_domain=sandbox.domain,
connection_config=connection_config,

Fix in Cursor Fix in Web


@djeebus djeebus merged commit bbeff74 into main Nov 14, 2025
8 checks passed
@djeebus djeebus deleted the support-local-envd-dev branch November 14, 2025 18:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants