SDK Beta - Migration Guide

The following guide shows how to migrate your code from the current Core SDKs (e2b) and Code Interpreter SDKs (@e2b/code-interpreter/e2b-code-interpreter) to the beta versions.

The latest beta versions you should install can be found in NPM/PyPi release history:

Table of contents

Core Sandbox SDK changes

These changes affect both the e2b Core SDKs and Code Interpreter SDKs (@e2b/code-interpreter/e2b-code-interpreter) because the Code Interpreter uses the Core SDK.

Creating sandbox

When creating a sandbox you now specify the sandbox timeout — how long the sandbox will exist. If you don't specify the timeout the sandbox will be closed after 5 minutes.

You also no longer call the .close() method when you are done with the sandbox. Sandbox will be automatically closed and killed after the timeout.

You can use .kill() to kill the sandbox immediately if you are sure you won't need it anymore.

import Sandbox from 'e2b'

// Before
// const sandbox = await Sandbox.create()
// await sandbox.close()

// Now
const sandbox = await Sandbox.create({ timeoutMs: 300_000 })

If you need to use a custom sandbox template you pass the template as the first parameter:

import Sandbox from 'e2b'

// Before
// const sandbox = await Sandbox.create({ template: 'template-name-or-id' })
// await sandbox.close()

// Now
const sandbox = await Sandbox.create('template-name-or-id', {
	timeoutMs: 300_000,
})

Modifying sandbox timeout

If you need to change how long the sandbox should stay alive after it was created, you can use .setTimeout()/.set_timeout() method. It will modify the timeout of the sandbox.

import Sandbox from 'e2b'

// Before
// const sandbox = await Sandbox.create()
// await sandbox.keepAlive(600_000)

// Now
const sandbox = await Sandbox.create({ timeoutMs: 300_000 })
await sandbox.setTimeout(600_000)

Reconnecting

When connection to an existing sandbox use .connect()/.connect() method instead of .reconnect()/.reconnect().

Instead of using .keepAlive()/.keep_alive() method to prevent the sandbox from closing until you reconnect use .setTimeout()/.set_timeout() method. Because the timeout is set when the sandbox is created, you may not need to set the timeout when reconnecting at all now.

import Sandbox from 'e2b'

// Before
// const sandbox = await Sandbox.create()
// await sandbox.keepAlive(600_000)
// await sandbox.close()

// const existingSandbox = await Sandbox.reconnect(sandbox.id)

// Now
const sandbox = await Sandbox.create({ timeoutMs: 600_000 })

const existingSandbox = await Sandbox.connect(sandbox.sandboxId)

Uploading data and creating files in sandbox

Use .files.write() method to upload files to the sandbox.

The method accepts path in the sandbox as the first argument and the data as the second argument.

import Sandbox from 'e2b'

// Before
// const content = fs.readFileSync('/local/path')
// await sandbox.uploadFile(content, '/path/in/sandbox')

// Now
const content = fs.readFileSync('/local/path')
await sandbox.files.write('/path/in/sandbox', content)

Downloading files and reading files in sandbox

Use .files.read() method to download files from the sandbox.

The method accepts path in the sandbox as the first argument and optional format as the second argument.

import Sandbox from 'e2b'

// Before
//const content = await sandbox.downloadFile('/path/in/sandbox')

// Now
const content = await sandbox.files.read('/path/in/sandbox')

Running processes

You execute processes by calling .commands.run() method. By default, the method waits for the command to finish.

You can specify the timeout for the command execution by passing timeoutMs/timeout option. The default timeout is 60 seconds.

If the command fails with a non-zero exit a ProcessExitError/ProcessExitException is raised and you can catch and inspect the error for more info.

import Sandbox from 'e2b'

// Before
// const sandbox = await Sandbox.create()
// const result = await sandbox.process.startAndWait({
// 	cmd: 'echo "Hello, world!"',
// 	onStderr: (msg) => console.log(msg.line),
// 	onStdout: (msg) => console.log(msg.line),
// })

// Now
const result = await sandbox.commands.run('echo "Hello, World!"', {
	onStderr(output) { console.log(output) },
	onStdout(output) { console.log(output) },
	timeoutMs: 60_000,
})

If you want to run the command in the background use background: true/background=True option. You can then use .wait() method to wait for the command to finish.

import Sandbox from 'e2b'

// Before
// const sandbox = await Sandbox.create()
// const process = await sandbox.process.start({
// 	cmd: 'sleep 10; echo "Hello, world!"',
// 	onStderr: (msg) => console.log(msg.line),
// 	onStdout: (msg) => console.log(msg.line),
// })

// const result = await process.wait()

// Now
const command = await sandbox.commands.run('sleep 10; echo "Hello, world!"', {
	onStderr(output) { console.log(output) },
	onStdout(output) { console.log(output) },
	background: true,
})

const result = await command.wait()

Watching for files' changes

import Sandbox from 'e2b'

// Before
// const sandbox = await Sandbox.create()
// const watcher = sandbox.filesystem.watchDir('/path/in/sandbox')
// watcher.addEventListener((event) => console.log(event))
// await watcher.start()

// Now
const sandbox = await Sandbox.create()
await sandbox.files.watch('/path/in/sandbox', (event) => console.log(event))

Accessing sandbox ID

The id property on the sandbox/code interpreter instance is now named sandboxId/sandbox_id.

import Sandbox from 'e2b'

// Before
// const sandboxId = await sandbox.id

// Now
const sandboxId = await sandbox.sandboxId

Getting sandbox upload URL

The .fileURL/.file_url() is now .uploadURL/.upload_url() method that takes an optional argument that specifies the path in the sandbox where the file will be uploaded.

If the path is not specified the file will be uploaded to the home dir — /home/user.

import Sandbox from 'e2b'

// Before
// const url = await sandbox.fileURL

// Now
const url = await sandbox.uploadUrl('/path/in/sandbox')

Configuring sandbox cwd

Previously you could set the sandbox working directory by passing cwd option when creating the sandbox. Right now this is not supported because it leads to subtle bugs especially when reconnecting to an existing sandbox.

If you need this feature please reach out to us on Discord or GitHub so we can prioritize it.

Timeouts

There are now two types of timeouts that you can pass as parameters:

  1. request_timeout/requestTimeoutMs sets how long the operation should wait for connection/processing. This is useful for ensuring that none of the sandbox operations hang indefinitely.
  2. timeout/timeoutMs which is used for setting the maximum length of long-running operations like executing code, running processes, or the sandbox itself.

Code Interpreter SDK changes

All the previously mentioned changes to the Core SDK also apply to the Code Interpreter SDK. Apart from them, the changes to the Code Interpreter SDK are very minimal:

Executing code

When executing code via JS/TS Code Interpreter SDK you now pass the timeoutMs option to the execCell method instead of timeout.

The default timeout for the code execution is now 300 seconds.

import CodeInterpreter from '@e2b/code-interpreter'

// Before
// const sandbox = await CodeInterpreter.create()
// const execution = await sandbox.notebook.execCell('print("Hello, world!")', {
//   timeout: 2000,
// })
// await sandbox.close()

// Now
const sandbox = await CodeInterpreter.create({ timeoutMs: 300_000 })
const execution = await sandbox.notebook.execCell('print("Hello, world!")', {
  timeoutMs: 2000,
})

Custom template

If you are using a custom template for the Code Interpreter you need to rebuild it.

You can rebuild the template by either calling

e2b template build -c "/root/.jupyter/start-up.sh"

if you use the E2B Docker image as base in your e2b.Dockerfile

FROM e2bdev/code-interpreter:latest

# You custom Dockerfile content here

Or if you are using custom base you need to copy all files excluding the e2b.toml from beta template to the directory with your template and then run e2b template build -c "/root/.jupyter/start-up.sh".

Python Async

Python Core SDK and Code Interpter SDK now support async.

If you need to use async import AsyncSandbox/AsyncCodeInterpreter instead of Sandbox/CodeInterpreter.

# Sync
# from e2b import Sandbox
# sandbox = Sandbox()

# from e2b_code_interpreter import CodeInterpreter
# sandbox = CodeInterpreter()

# Async
from e2b import AsyncSandbox
from e2b_code_interpreter import AsyncCodeInterpreter

sandbox = await AsyncSandbox.create()
sandbox = await AsyncCodeInterpreter.create()

The async versions of methods for watching for files' changes and running commands in the background are slightly different:

Watching for files' changes in async Python SDK

from e2b import Sandbox

# Sync
# sandbox = Sandbox()
# watcher = sandbox.files.watch("/path/in/sandbox")

# for event in watcher:
#     print(event)

# Async
sandbox = await AsyncSandbox.create()

await sandbox.files.watch("/path/in/sandbox", lambda event: print(event))

Running background commands in async Python SDK

from e2b import Sandbox

# Sync
# sandbox = Sandbox()
# command = sandbox.commands.run(
# 	cmd='echo "Hello, World!"',
# 	background=True,
# )

# result = command.wait(
# 	on_stderr=lambda output: print(output),
# 	on_stdout=lambda output: print(output),
# )

# Async
sandbox = await AsyncSandbox.create()
command = await sandbox.commands.run(
	cmd='echo "Hello, World!"',
	on_stderr=lambda output: print(output),
	on_stdout=lambda output: print(output),
	background=True,
)

result = await command.wait()