Skip to content

SDK V2 release #142

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Aug 22, 2025
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
6 changes: 6 additions & 0 deletions .changeset/new-kings-sleep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@e2b/code-interpreter-python': major
'@e2b/code-interpreter': major
---

SDK v2
5 changes: 5 additions & 0 deletions .changeset/strange-donkeys-clean.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@e2b/code-interpreter-template': minor
---

Propagate access token
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Python
```py
from e2b_code_interpreter import Sandbox

with Sandbox() as sandbox:
with Sandbox.create() as sandbox:
sandbox.run_code("x = 1")
execution = sandbox.run_code("x+=1; x")
print(execution.text) # outputs 2
Expand Down
2 changes: 1 addition & 1 deletion js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
"vm"
],
"dependencies": {
"e2b": "^1.4.0"
"e2b": "^2.0.1"
},
"engines": {
"node": ">=18"
Expand Down
140 changes: 86 additions & 54 deletions js/src/sandbox.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import { Sandbox as BaseSandbox, InvalidArgumentError } from 'e2b'

import { Result, Execution, OutputMessage, parseOutput, extractError, ExecutionError } from './messaging'
import { formatExecutionTimeoutError, formatRequestTimeoutError, readLines } from "./utils";
import {
Result,
Execution,
OutputMessage,
parseOutput,
extractError,
ExecutionError,
} from './messaging'
import {
formatExecutionTimeoutError,
formatRequestTimeoutError,
readLines,
} from './utils'
import { JUPYTER_PORT, DEFAULT_TIMEOUT_MS } from './consts'

/**
Expand Down Expand Up @@ -29,37 +40,37 @@ export interface RunCodeOpts {
/**
* Callback for handling stdout messages.
*/
onStdout?: (output: OutputMessage) => (Promise<any> | any),
onStdout?: (output: OutputMessage) => Promise<any> | any
/**
* Callback for handling stderr messages.
*/
onStderr?: (output: OutputMessage) => (Promise<any> | any),
onStderr?: (output: OutputMessage) => Promise<any> | any
/**
* Callback for handling the final execution result.
*/
onResult?: (data: Result) => (Promise<any> | any),
onResult?: (data: Result) => Promise<any> | any
/**
* Callback for handling the `ExecutionError` object.
*/
onError?: (error: ExecutionError) => (Promise<any> | any),
onError?: (error: ExecutionError) => Promise<any> | any
/**
* Custom environment variables for code execution.
*
*
* @default {}
*/
envs?: Record<string, string>,
envs?: Record<string, string>
/**
* Timeout for the code execution in **milliseconds**.
*
*
* @default 60_000 // 60 seconds
*/
timeoutMs?: number,
timeoutMs?: number
/**
* Timeout for the request in **milliseconds**.
*
*
* @default 30_000 // 30 seconds
*/
requestTimeoutMs?: number,
requestTimeoutMs?: number
}

/**
Expand All @@ -68,22 +79,22 @@ export interface RunCodeOpts {
export interface CreateCodeContextOpts {
/**
* Working directory for the context.
*
*
* @default /home/user
*/
cwd?: string,
cwd?: string
/**
* Language for the context.
*
*
* @default python
*/
language?: string,
language?: string
/**
* Timeout for the request in **milliseconds**.
*
*
* @default 30_000 // 30 seconds
*/
requestTimeoutMs?: number,
requestTimeoutMs?: number
}

/**
Expand All @@ -108,65 +119,66 @@ export interface CreateCodeContextOpts {
* ```
*/
export class Sandbox extends BaseSandbox {
protected static override readonly defaultTemplate: string = 'code-interpreter-v1'
protected static override readonly defaultTemplate: string =
'code-interpreter-v1'

/**
* Run the code as Python.
*
*
* Specify the `language` or `context` option to run the code as a different language or in a different `Context`.
*
*
* You can reference previously defined variables, imports, and functions in the code.
*
* @param code code to execute.
* @param opts options for executing the code.
*
*
* @returns `Execution` result object.
*/
async runCode(
code: string,
opts?: RunCodeOpts & {
/**
* Language to use for code execution.
*
*
* If not defined, the default Python context is used.
*/
language?: 'python',
},
language?: 'python'
}
): Promise<Execution>
/**
* Run the code for the specified language.
*
*
* Specify the `language` or `context` option to run the code as a different language or in a different `Context`.
* If no language is specified, Python is used.
*
*
* You can reference previously defined variables, imports, and functions in the code.
*
* @param code code to execute.
* @param opts options for executing the code.
*
*
* @returns `Execution` result object.
*/
async runCode(
code: string,
opts?: RunCodeOpts & {
/**
* Language to use for code execution.
*
*
* If not defined, the default Python context is used.
*/
language?: string,
},
language?: string
}
): Promise<Execution>
/**
* Runs the code in the specified context, if not specified, the default context is used.
*
*
* Specify the `language` or `context` option to run the code as a different language or in a different `Context`.
*
*
* You can reference previously defined variables, imports, and functions in the code.
*
* @param code code to execute.
* @param opts options for executing the code
*
*
* @returns `Execution` result object
*/
async runCode(
Expand All @@ -175,35 +187,44 @@ export class Sandbox extends BaseSandbox {
/**
* Context to run the code in.
*/
context?: Context,
},
context?: Context
}
): Promise<Execution>
async runCode(
code: string,
opts?: RunCodeOpts & {
language?: string,
context?: Context,
},
language?: string
context?: Context
}
): Promise<Execution> {
if (opts?.context && opts?.language) {
throw new InvalidArgumentError("You can provide context or language, but not both at the same time.")
throw new InvalidArgumentError(
'You can provide context or language, but not both at the same time.'
)
}

const controller = new AbortController()

const requestTimeout = opts?.requestTimeoutMs ?? this.connectionConfig.requestTimeoutMs
const requestTimeout =
opts?.requestTimeoutMs ?? this.connectionConfig.requestTimeoutMs

const reqTimer = requestTimeout ? setTimeout(() => {
controller.abort()
}, requestTimeout)
const reqTimer = requestTimeout
? setTimeout(() => {
controller.abort()
}, requestTimeout)
: undefined

const headers: Record<string, string> = {
'Content-Type': 'application/json',
}
if (this.envdAccessToken) {
headers['X-Access-Token'] = this.envdAccessToken
}

try {
const res = await fetch(`${this.jupyterUrl}/execute`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
headers,
body: JSON.stringify({
code,
context_id: opts?.context?.id,
Expand All @@ -220,7 +241,9 @@ export class Sandbox extends BaseSandbox {
}

if (!res.body) {
throw new Error(`Not response body: ${res.statusText} ${await res?.text()}`)
throw new Error(
`Not response body: ${res.statusText} ${await res?.text()}`
)
}

clearTimeout(reqTimer)
Expand All @@ -229,16 +252,22 @@ export class Sandbox extends BaseSandbox {

const bodyTimer = bodyTimeout
? setTimeout(() => {
controller.abort()
}, bodyTimeout)
controller.abort()
}, bodyTimeout)
: undefined

const execution = new Execution()


try {
for await (const chunk of readLines(res.body)) {
await parseOutput(execution, chunk, opts?.onStdout, opts?.onStderr, opts?.onResult, opts?.onError)
await parseOutput(
execution,
chunk,
opts?.onStdout,
opts?.onStderr,
opts?.onResult,
opts?.onError
)
}
} catch (error) {
throw formatExecutionTimeoutError(error)
Expand All @@ -256,7 +285,7 @@ export class Sandbox extends BaseSandbox {
* Creates a new context to run code in.
*
* @param opts options for creating the context.
*
*
* @returns context object.
*/
async createCodeContext(opts?: CreateCodeContextOpts): Promise<Context> {
Expand All @@ -265,6 +294,7 @@ export class Sandbox extends BaseSandbox {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...this.connectionConfig.headers,
},
body: JSON.stringify({
language: opts?.language,
Expand All @@ -286,6 +316,8 @@ export class Sandbox extends BaseSandbox {
}

protected get jupyterUrl(): string {
return `${this.connectionConfig.debug ? 'http' : 'https'}://${this.getHost(JUPYTER_PORT)}`
return `${this.connectionConfig.debug ? 'http' : 'https'}://${this.getHost(
JUPYTER_PORT
)}`
}
}
Loading