Skip to content

Commit 50a7cb3

Browse files
authored
Release SDK v2 (#118)
* Prep for SDK v2 release * Add changeset * Bump e2b * Secure `True` by default * Setup display * Add annotation * Update readmes
1 parent 89bd971 commit 50a7cb3

16 files changed

Lines changed: 447 additions & 243 deletions

File tree

.changeset/thirty-sheep-begin.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@e2b/desktop-python': major
3+
'@e2b/desktop': major
4+
---
5+
6+
SDK v2

README.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ npm install @e2b/desktop
5656
from e2b_desktop import Sandbox
5757

5858
# Create a new desktop sandbox
59-
desktop = Sandbox()
59+
desktop = Sandbox.create()
6060

6161
# Launch an application
6262
desktop.launch('google-chrome') # or vscode, firefox, etc.
@@ -122,7 +122,7 @@ console.log('Stream URL:', desktop.stream.getUrl({ authKey }))
122122

123123
```python
124124
from e2b_desktop import Sandbox
125-
desktop = Sandbox()
125+
desktop = Sandbox.create()
126126

127127
# Start the stream
128128
desktop.stream.start()
@@ -167,7 +167,7 @@ await desktop.stream.stop()
167167

168168
```python
169169
from e2b_desktop import Sandbox
170-
desktop = Sandbox()
170+
desktop = Sandbox.create()
171171

172172
# Start the stream
173173
desktop.stream.start(
@@ -220,7 +220,7 @@ await desktop.stream.stop()
220220

221221
```python
222222
from e2b_desktop import Sandbox
223-
desktop = Sandbox()
223+
desktop = Sandbox.create()
224224

225225
# Get current (active) window ID
226226
window_id = desktop.get_current_window_id()
@@ -261,7 +261,7 @@ await desktop.stream.stop()
261261

262262
```python
263263
from e2b_desktop import Sandbox
264-
desktop = Sandbox()
264+
desktop = Sandbox.create()
265265

266266
desktop.double_click()
267267
desktop.left_click()
@@ -304,7 +304,7 @@ await desktop.mouseRelease('left') // Release the mouse button
304304

305305
```python
306306
from e2b_desktop import Sandbox
307-
desktop = Sandbox()
307+
desktop = Sandbox.create()
308308

309309
# Write text at the current cursor position with customizable typing speed
310310
desktop.write("Hello, world!") # Default: chunk_size=25, delay_in_ms=75
@@ -341,7 +341,7 @@ await desktop.press(['ctrl', 'c']) // Key combination
341341

342342
```python
343343
from e2b_desktop import Sandbox
344-
desktop = Sandbox()
344+
desktop = Sandbox.create()
345345

346346
# Get current (active) window ID
347347
window_id = desktop.get_current_window_id()
@@ -376,7 +376,7 @@ const title = await desktop.getWindowTitle(windowId)
376376

377377
```python
378378
from e2b_desktop import Sandbox
379-
desktop = Sandbox()
379+
desktop = Sandbox.create()
380380

381381
# Take a screenshot and save it as "screenshot.png" locally
382382
image = desktop.screenshot()
@@ -402,7 +402,7 @@ fs.writeFileSync('screenshot.png', image)
402402

403403
```python
404404
from e2b_desktop import Sandbox
405-
desktop = Sandbox()
405+
desktop = Sandbox.create()
406406

407407
# Open file with default application
408408
desktop.files.write("/home/user/index.js", "console.log('hello')") # First create the file
@@ -427,7 +427,7 @@ await desktop.open('/home/user/index.js') // Then open it
427427

428428
```python
429429
from e2b_desktop import Sandbox
430-
desktop = Sandbox()
430+
desktop = Sandbox.create()
431431

432432
# Launch the application
433433
desktop.launch('google-chrome')
@@ -450,7 +450,7 @@ await desktop.launch('google-chrome')
450450

451451
```python
452452
from e2b_desktop import Sandbox
453-
desktop = Sandbox()
453+
desktop = Sandbox.create()
454454

455455
# Run any bash command
456456
out = desktop.commands.run("ls -la /home/user")
@@ -475,7 +475,7 @@ console.log(out)
475475

476476
```python
477477
from e2b_desktop import Sandbox
478-
desktop = Sandbox()
478+
desktop = Sandbox.create()
479479

480480
desktop.wait(1000) # Wait for 1 second
481481
```

examples/basic-python/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def check_queue():
4444

4545
def main():
4646
print("> Starting desktop sandbox...")
47-
desktop = Sandbox()
47+
desktop = Sandbox.create()
4848
print(" - Desktop Sandbox started, ID:", desktop.sandbox_id)
4949

5050
width, height = desktop.get_screen_size()

examples/streaming-apps-python/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pip install e2b-desktop
3131
from e2b_desktop import Sandbox
3232

3333
# Create a new desktop sandbox
34-
desktop = Sandbox()
34+
desktop = Sandbox.create()
3535
print('Desktop sandbox created', desktop.sandbox_id)
3636

3737
# Launch an application

packages/js-sdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,6 @@
6262
"vitest": "^3.0.5"
6363
},
6464
"dependencies": {
65-
"e2b": "^1.4.0"
65+
"e2b": "^2.0.0"
6666
}
6767
}

packages/js-sdk/src/sandbox.ts

Lines changed: 109 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import {
22
Sandbox as SandboxBase,
33
SandboxOpts as SandboxOptsBase,
4+
SandboxBetaCreateOpts as SandboxBetaCreateOptsBase,
45
CommandHandle,
56
CommandResult,
67
CommandExitError,
7-
ConnectionConfig,
88
TimeoutError,
99
} from 'e2b'
1010

@@ -116,6 +116,31 @@ export interface SandboxOpts extends SandboxOptsBase {
116116
display?: string
117117
}
118118

119+
/**
120+
* Configuration options for the Sandbox environment.
121+
* @interface SandboxOpts
122+
* @extends {SandboxOptsBase}
123+
*/
124+
export interface SandboxBetaCreateOpts extends SandboxBetaCreateOptsBase {
125+
/**
126+
* The screen resolution in pixels, specified as [width, height].
127+
* @type {[number, number]}
128+
*/
129+
resolution?: [number, number]
130+
131+
/**
132+
* Dots per inch (DPI) setting for the display.
133+
* @type {number}
134+
*/
135+
dpi?: number
136+
137+
/**
138+
* Display identifier.
139+
* @type {string}
140+
*/
141+
display?: string
142+
}
143+
119144
export class Sandbox extends SandboxBase {
120145
protected static override readonly defaultTemplate: string = 'desktop'
121146
private lastXfce4Pid: number | null = null
@@ -138,6 +163,7 @@ export class Sandbox extends SandboxBase {
138163
) {
139164
super(opts)
140165
}
166+
141167
/**
142168
* Create a new sandbox from the default `desktop` sandbox template.
143169
*
@@ -184,8 +210,6 @@ export class Sandbox extends SandboxBase {
184210
? { template: templateOrOpts, sandboxOpts: opts }
185211
: { template: this.defaultTemplate, sandboxOpts: templateOrOpts }
186212

187-
const config = new ConnectionConfig(sandboxOpts)
188-
189213
// Add DISPLAY environment variable if not already set
190214
const display = opts?.display || ':0'
191215
const sandboxOptsWithDisplay = {
@@ -196,46 +220,70 @@ export class Sandbox extends SandboxBase {
196220
},
197221
}
198222

199-
let sbx
200-
if (config.debug) {
201-
sbx = new this({
202-
sandboxId: 'desktop',
203-
...sandboxOptsWithDisplay,
204-
...config,
205-
}) as InstanceType<S>
206-
} else {
207-
const sandbox = await this.createSandbox(
208-
template,
209-
sandboxOptsWithDisplay?.timeoutMs ?? this.defaultSandboxTimeoutMs,
210-
sandboxOptsWithDisplay
211-
)
212-
sbx = new this({
213-
...sandbox,
214-
...sandboxOptsWithDisplay,
215-
...config,
216-
}) as InstanceType<S>
217-
}
223+
const sbx = await super.create(template, sandboxOptsWithDisplay) as InstanceType<S>
224+
await sbx._start(display, sandboxOptsWithDisplay)
218225

219-
sbx.display = display
220-
sbx.lastXfce4Pid = null
221-
sbx.stream = new VNCServer(sbx)
226+
return sbx
227+
}
222228

223-
const [width, height] = sandboxOpts?.resolution ?? [1024, 768]
224-
await sbx.commands.run(
225-
`Xvfb ${sbx.display} -ac -screen 0 ${width}x${height}x24 ` +
226-
`-retro -dpi ${sandboxOpts?.dpi ?? 96} -nolisten tcp -nolisten unix`,
227-
{ background: true, timeoutMs: 0 }
228-
)
229+
/**
230+
* Create a new sandbox from the default `desktop` sandbox template.
231+
*
232+
* @param opts connection options.
233+
*
234+
* @returns sandbox instance for the new sandbox.
235+
*
236+
* @example
237+
* ```ts
238+
* const sandbox = await Sandbox.create()
239+
* ```
240+
* @constructs Sandbox
241+
*/
242+
static async betaCreate<S extends typeof Sandbox>(
243+
this: S,
244+
opts?: SandboxBetaCreateOpts
245+
): Promise<InstanceType<S>>
246+
/**
247+
* Create a new sandbox from the specified sandbox template.
248+
*
249+
* @param template sandbox template name or ID.
250+
* @param opts connection options.
251+
*
252+
* @returns sandbox instance for the new sandbox.
253+
*
254+
* @example
255+
* ```ts
256+
* const sandbox = await Sandbox.create('<template-name-or-id>')
257+
* ```
258+
* @constructs Sandbox
259+
*/
260+
static async betaCreate<S extends typeof Sandbox>(
261+
this: S,
262+
template: string,
263+
opts?: SandboxBetaCreateOpts
264+
): Promise<InstanceType<S>>
265+
static async betaCreate<S extends typeof Sandbox>(
266+
this: S,
267+
templateOrOpts?: SandboxBetaCreateOpts | string,
268+
opts?: SandboxOpts
269+
): Promise<InstanceType<S>> {
270+
const { template, sandboxOpts } =
271+
typeof templateOrOpts === 'string'
272+
? { template: templateOrOpts, sandboxOpts: opts }
273+
: { template: this.defaultTemplate, sandboxOpts: templateOrOpts }
229274

230-
let hasStarted = await sbx.waitAndVerify(
231-
`xdpyinfo -display ${sbx.display}`,
232-
(r: CommandResult) => r.exitCode === 0
233-
)
234-
if (!hasStarted) {
235-
throw new TimeoutError('Could not start Xvfb')
275+
// Add DISPLAY environment variable if not already set
276+
const display = opts?.display || ':0'
277+
const sandboxOptsWithDisplay = {
278+
...sandboxOpts,
279+
envs: {
280+
...sandboxOpts?.envs,
281+
DISPLAY: display,
282+
},
236283
}
237284

238-
await sbx.startXfce4()
285+
const sbx = await super.betaCreate(template, sandboxOptsWithDisplay) as InstanceType<S>
286+
await sbx._start(display, sandboxOptsWithDisplay)
239287

240288
return sbx
241289
}
@@ -593,6 +641,29 @@ export class Sandbox extends SandboxBase {
593641
timeoutMs: 0,
594642
})
595643
}
644+
645+
protected async _start(display:string, opts?: SandboxOpts): Promise<void> {
646+
this.display = display
647+
this.lastXfce4Pid = null
648+
this.stream = new VNCServer(this)
649+
650+
const [width, height] = opts?.resolution ?? [1024, 768]
651+
await this.commands.run(
652+
`Xvfb ${display} -ac -screen 0 ${width}x${height}x24 ` +
653+
`-retro -dpi ${opts?.dpi ?? 96} -nolisten tcp -nolisten unix`,
654+
{ background: true, timeoutMs: 0 }
655+
)
656+
657+
let hasStarted = await this.waitAndVerify(
658+
`xdpyinfo -display ${display}`,
659+
(r: CommandResult) => r.exitCode === 0
660+
)
661+
if (!hasStarted) {
662+
throw new TimeoutError('Could not start Xvfb')
663+
}
664+
665+
await this.startXfce4()
666+
}
596667
}
597668

598669
interface VNCServerOptions {

0 commit comments

Comments
 (0)