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:
- JavaScript & TypeScript
- Latest release with rc tag for
e2b
- Latest release with rc tag for
@e2b/code-interpreter
- Latest release with rc tag for
- Python
- Latest release with PRE-RELEASE for
e2b
- Latest release with PRE-RELEASE for
e2b-code-interpreter
- Latest release with PRE-RELEASE for
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.
If you are using a custom template you need to rebuild it by calling e2b template build
in the directory with the template.
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:
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.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"
.
Check of the Code Interpreter custom template page for more info.
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()