Skip to content

feat(sdk): add E2B client to the downstream SDK packages - #1772

Closed
devin-ai-integration[bot] wants to merge 3 commits into
mainfrom
devin/1787757299-downstream-e2b-client
Closed

feat(sdk): add E2B client to the downstream SDK packages#1772
devin-ai-integration[bot] wants to merge 3 commits into
mainfrom
devin/1787757299-downstream-e2b-client

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds an E2B client to the four downstream SDKs (@e2b/code-interpreter, @e2b/desktop, e2b-code-interpreter, e2b-desktop), so the API key and domain can be bound explicitly instead of coming from the environment:

import { E2B } from '@e2b/code-interpreter'

const sbx = await new E2B({ apiKey, domain }).Sandbox.create()
const execution = await sbx.runCode('x = 1; x += 1; x')
from e2b_desktop import E2B

desktop = E2B(api_key=..., domain=...).Sandbox.create()
desktop.stream.start()

Per-call options still win, explicit undefined / None doesn't erase the bound config, clients are isolated from each other and from the env-configured top-level exports, and client.Sandbox.create() returns an instance of the package's own Sandbox (so runCode / run_code, contexts, and the desktop screen/mouse/keyboard/stream APIs are all there).

Binding lives on the resource classes now

Instead of every package generating bound subclasses itself (the previous _bind helper / inline class extends Sandbox { boundOpts }), the binding is a single internal factory on the resource classes, in the core SDK:

// connectionConfig.ts — internal, hidden from the docs
class ClientFactory {
  static withOpts<T>(this: T, opts?: Omit<ConnectionOpts, 'signal'>): T
}

// TemplateBase overrides it to keep the bound class callable as a factory
static override withOpts<T>(this: T, opts?): CallableTemplate<T & typeof TemplateBase>
class ClientFactory:
    @classmethod
    def _with_params(cls, **api_params: Unpack[ApiParams]) -> Type[Self]: ...

Every client — core and downstream — is now just:

this.Sandbox = Sandbox.withOpts(opts)   // the package's own Sandbox
this.Volume = Volume.withOpts(opts)
this.Template = Template.withOpts(opts) // still callable: client.Template()
this.Secret = Secret.withOpts(opts)
self.Sandbox = Sandbox._with_params(**opts)
self.AsyncSandbox = AsyncSandbox._with_params(**opts)
...

Consequences worth noting:

  • The downstream clients no longer instantiate a core E2B under the hood to get Volume/Template/Secret, and callableTemplate stays internal (TemplateBase.withOpts wraps the bound class itself).
  • Binding is now idempotent/composable: X.withOpts(a).withOpts(b) keeps a where b doesn't override it (covered by a new test in both core suites), and signal is still dropped so it can only be passed per call.
  • The bound options are a real snapshot: the header maps are copied too, so apiHeaders / api_headers mutated after the client is constructed no longer leak into its requests (fixed once in the shared factory, for every client).
  • Both helpers are internal (@internal @hidden @hide / :meta private:), so no new public surface — but the downstream packages call them across the package boundary, hence the patch bumps for e2b/@e2b/python-sdk and the raised e2b>= floors in the two Python packages.

Tests mirroring the core client suites were added for all four packages (offline, against a local API server; the desktop suites stub the envd-only parts of create), plus READMEs and a minor changeset.

Link to Devin session: https://app.devin.ai/sessions/ec1af68649fd4880a1cb27cb51d819e9
Requested by: @mishushakov

Co-Authored-By: mish@e2b.dev <mish@e2b.dev>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@cla-bot cla-bot Bot added the cla-signed label Aug 26, 2026
@changeset-bot

changeset-bot Bot commented Aug 26, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 59fb825

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

This PR includes changesets to release 6 packages
Name Type
@e2b/code-interpreter Minor
@e2b/code-interpreter-python Minor
@e2b/desktop Minor
@e2b/desktop-python Minor
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

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Checked cross-language parity, API shape and naming, typing, configuration precedence/immutability, flat package exports, and public documentation. Found 6 TASTE.md violations: four T-51 shallow configuration snapshots and two T-54 mixed value/type re-exports. All findings are attached to changed lines.

Comment thread packages/code-interpreter-js/src/client.ts Outdated
Comment thread packages/desktop-js/src/client.ts Outdated
Comment thread packages/code-interpreter-python/e2b_code_interpreter/client.py Outdated
Comment thread packages/desktop-python/e2b_desktop/client.py Outdated
Comment thread packages/code-interpreter-js/src/index.ts
Comment thread packages/desktop-js/src/index.ts
@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Package Artifacts

Built from 693807c. Download artifacts from this workflow run.

JS SDK (e2b@2.46.1-devin-1787757299-downstream-e2b-client.0):

npm install ./e2b-2.46.1-devin-1787757299-downstream-e2b-client.0.tgz

CLI (@e2b/cli@2.18.1-devin-1787757299-downstream-e2b-client.0):

npm install ./e2b-cli-2.18.1-devin-1787757299-downstream-e2b-client.0.tgz

Code Interpreter JS SDK (@e2b/code-interpreter@2.7.2-devin-1787757299-downstream-e2b-client.0):

npm install ./e2b-code-interpreter-2.7.2-devin-1787757299-downstream-e2b-client.0.tgz

Desktop JS SDK (@e2b/desktop@2.3.3-devin-1787757299-downstream-e2b-client.0):

npm install ./e2b-desktop-2.3.3-devin-1787757299-downstream-e2b-client.0.tgz

Python SDK (e2b==2.46.0+devin.1787757299.downstream.e2b.client):

pip install ./e2b-2.46.0+devin.1787757299.downstream.e2b.client-py3-none-any.whl

Code Interpreter Python SDK (e2b-code-interpreter==2.9.1+devin.1787757299.downstream.e2b.client):

pip install ./e2b_code_interpreter-2.9.1+devin.1787757299.downstream.e2b.client-py3-none-any.whl

Desktop Python SDK (e2b-desktop==2.4.3+devin.1787757299.downstream.e2b.client):

pip install ./e2b_desktop-2.4.3+devin.1787757299.downstream.e2b.client-py3-none-any.whl

Co-Authored-By: mish@e2b.dev <mish@e2b.dev>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Fixed centrally in 59fb825: binding now happens in the core ClientFactory.withOpts / _with_params, which copies headers/apiHeaders (api_headers) as well, so all four clients get the snapshot. Covered by new tests in both core client suites.

3 similar comments
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Fixed centrally in 59fb825: binding now happens in the core ClientFactory.withOpts / _with_params, which copies headers/apiHeaders (api_headers) as well, so all four clients get the snapshot. Covered by new tests in both core client suites.

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Fixed centrally in 59fb825: binding now happens in the core ClientFactory.withOpts / _with_params, which copies headers/apiHeaders (api_headers) as well, so all four clients get the snapshot. Covered by new tests in both core client suites.

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Fixed centrally in 59fb825: binding now happens in the core ClientFactory.withOpts / _with_params, which copies headers/apiHeaders (api_headers) as well, so all four clients get the snapshot. Covered by new tests in both core client suites.

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Not changing this: packages/js-sdk/src/index.ts already exports the core client the same way (export { E2B, type E2BClientOpts } from './client'), so the downstream entry points match the existing convention.

1 similar comment
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Not changing this: packages/js-sdk/src/index.ts already exports the core client the same way (export { E2B, type E2BClientOpts } from './client'), so the downstream entry points match the existing convention.

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Split for easier review: the core binding factory + Code Interpreter clients are in #1783, and the Desktop clients are stacked on top in #1784.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant