@mastra/e2b-desktop 0.0.0 → 0.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md ADDED
@@ -0,0 +1,30 @@
1
+ Portions of this software are licensed as follows:
2
+
3
+ - All content that resides under any directory named "ee/" within this
4
+ repository, including but not limited to:
5
+ - `packages/core/src/auth/ee/`
6
+ - `packages/server/src/server/auth/ee/`
7
+ is licensed under the license defined in `ee/LICENSE`.
8
+
9
+ - All third-party components incorporated into the Mastra Software are
10
+ licensed under the original license provided by the owner of the
11
+ applicable component.
12
+
13
+ - Content outside of the above-mentioned directories or restrictions is
14
+ available under the "Apache License 2.0" as defined below.
15
+
16
+ # Apache License 2.0
17
+
18
+ Copyright (c) 2025 Kepler Software, Inc.
19
+
20
+ Licensed under the Apache License, Version 2.0 (the "License");
21
+ you may not use this file except in compliance with the License.
22
+ You may obtain a copy of the License at
23
+
24
+ http://www.apache.org/licenses/LICENSE-2.0
25
+
26
+ Unless required by applicable law or agreed to in writing, software
27
+ distributed under the License is distributed on an "AS IS" BASIS,
28
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29
+ See the License for the specific language governing permissions and
30
+ limitations under the License.
package/dist/index.cjs ADDED
@@ -0,0 +1,285 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let _e2b_desktop = require("@e2b/desktop");
3
+ let _mastra_core_workspace = require("@mastra/core/workspace");
4
+ let _mastra_e2b = require("@mastra/e2b");
5
+ //#region src/sandbox/index.ts
6
+ /**
7
+ * E2B Desktop Sandbox Provider
8
+ *
9
+ * An E2B sandbox running a full Linux desktop environment with computer-use
10
+ * (screenshot, mouse, keyboard) control. Extends `@mastra/e2b`'s `E2BSandbox`
11
+ * the same way `@e2b/desktop`'s SDK `Sandbox` extends `e2b`'s: everything the
12
+ * base provider supports (command execution, processes, file upload,
13
+ * reconnection) works against the same desktop VM.
14
+ *
15
+ * @see https://github.com/e2b-dev/desktop
16
+ */
17
+ /**
18
+ * E2B-hosted desktop template (`@e2b/desktop`'s default). Used when no
19
+ * explicit `template` option is provided — unlike the base provider, no
20
+ * template build is required.
21
+ */
22
+ const DEFAULT_DESKTOP_TEMPLATE = "desktop";
23
+ /**
24
+ * E2B Desktop sandbox provider for Mastra workspaces.
25
+ *
26
+ * Features:
27
+ * - Everything from `E2BSandbox` (commands, processes, file upload, pause/resume)
28
+ * - `computer` capability: screenshot, mouse, and keyboard control — when
29
+ * used in a `Workspace`, agents automatically get the
30
+ * `mastra_workspace_computer_*` tools
31
+ * - Live desktop view via an authenticated noVNC stream URL
32
+ *
33
+ * @example Basic usage
34
+ * ```typescript
35
+ * import { Agent } from '@mastra/core/agent';
36
+ * import { Workspace } from '@mastra/core/workspace';
37
+ * import { E2BDesktopSandbox } from '@mastra/e2b-desktop';
38
+ *
39
+ * const sandbox = new E2BDesktopSandbox({ resolution: [1280, 720] });
40
+ * const agent = new Agent({
41
+ * // file + shell + computer tools are all emitted automatically
42
+ * workspace: new Workspace({ sandbox }),
43
+ * // ...
44
+ * });
45
+ * ```
46
+ *
47
+ * @example Direct desktop control
48
+ * ```typescript
49
+ * const sandbox = new E2BDesktopSandbox();
50
+ * await sandbox.start();
51
+ * await sandbox.computer.leftClick(100, 200);
52
+ * const { data } = await sandbox.computer.screenshot();
53
+ * const viewerUrl = await sandbox.computer.streamUrl();
54
+ * ```
55
+ */
56
+ var E2BDesktopSandbox = class E2BDesktopSandbox extends _mastra_e2b.E2BSandbox {
57
+ name = "E2BDesktopSandbox";
58
+ provider = "e2b-desktop";
59
+ resolution;
60
+ dpi;
61
+ _desktopConstructorOptions;
62
+ /** Stream startup memo, keyed by SDK sandbox ID so a fresh VM restarts it. */
63
+ _streamStarted = null;
64
+ constructor(options = {}) {
65
+ super(options);
66
+ this.resolution = options.resolution;
67
+ this.dpi = options.dpi;
68
+ this._desktopConstructorOptions = { ...options };
69
+ }
70
+ /**
71
+ * Computer-use (desktop) capability: screenshot, mouse, and keyboard
72
+ * control of the sandbox's desktop, backed by `@e2b/desktop`.
73
+ * Operations start the sandbox automatically if it is not running.
74
+ */
75
+ computer = {
76
+ screenshot: async () => {
77
+ return {
78
+ data: await this.withDesktop((desktop) => desktop.screenshot()),
79
+ mediaType: "image/png"
80
+ };
81
+ },
82
+ leftClick: async (x, y) => {
83
+ await this.withDesktop((desktop) => desktop.leftClick(x, y));
84
+ },
85
+ rightClick: async (x, y) => {
86
+ await this.withDesktop((desktop) => desktop.rightClick(x, y));
87
+ },
88
+ doubleClick: async (x, y) => {
89
+ await this.withDesktop((desktop) => desktop.doubleClick(x, y));
90
+ },
91
+ moveMouse: async (x, y) => {
92
+ await this.withDesktop((desktop) => desktop.moveMouse(x, y));
93
+ },
94
+ drag: async (from, to) => {
95
+ await this.withDesktop((desktop) => desktop.drag([from.x, from.y], [to.x, to.y]));
96
+ },
97
+ scroll: async (direction, amount) => {
98
+ await this.withDesktop((desktop) => desktop.scroll(direction, amount));
99
+ },
100
+ type: async (text) => {
101
+ await this.withDesktop((desktop) => desktop.write(text));
102
+ },
103
+ press: async (key) => {
104
+ await this.withDesktop((desktop) => desktop.press(key));
105
+ },
106
+ getScreenSize: async () => {
107
+ return this.withDesktop((desktop) => desktop.getScreenSize());
108
+ },
109
+ getCursorPosition: async () => {
110
+ return this.withDesktop((desktop) => desktop.getCursorPosition());
111
+ },
112
+ streamUrl: async () => {
113
+ try {
114
+ return await this.withDesktop(async (desktop) => {
115
+ await this.ensureStreamStarted(desktop);
116
+ try {
117
+ return desktop.stream.getUrl({ authKey: desktop.stream.getAuthKey() });
118
+ } catch {
119
+ return desktop.stream.getUrl();
120
+ }
121
+ });
122
+ } catch {
123
+ return null;
124
+ }
125
+ }
126
+ };
127
+ /**
128
+ * Get the underlying `@e2b/desktop` Sandbox instance for direct access to
129
+ * desktop APIs not exposed through the abstraction (e.g. `launch()`,
130
+ * `open()`, window helpers, custom stream control).
131
+ *
132
+ * @throws {SandboxNotReadyError} If the sandbox has not been started
133
+ *
134
+ * @example Launch an application
135
+ * ```typescript
136
+ * await sandbox.start();
137
+ * await sandbox.desktop.launch('xfce4-terminal');
138
+ * await sandbox.desktop.open('https://mastra.ai');
139
+ * ```
140
+ */
141
+ get desktop() {
142
+ if (!this._sandbox) throw new _mastra_core_workspace.SandboxNotReadyError(this.id);
143
+ return this._sandbox;
144
+ }
145
+ /**
146
+ * Construct a sibling `E2BDesktopSandbox` that inherits this sandbox's
147
+ * configuration with per-instance overrides. See `E2BSandbox.clone`.
148
+ */
149
+ clone(options = {}) {
150
+ const { id: _id, ...base } = this._desktopConstructorOptions;
151
+ return new E2BDesktopSandbox({
152
+ ...base,
153
+ ...options.id !== void 0 && { id: options.id },
154
+ ...options.env !== void 0 && { env: options.env },
155
+ ...options.idleTimeoutMinutes !== void 0 && { timeout: options.idleTimeoutMinutes * 6e4 }
156
+ });
157
+ }
158
+ /** Create a `@e2b/desktop` SDK sandbox (with desktop display options). */
159
+ async createSdkSandbox(templateId, opts) {
160
+ return _e2b_desktop.Sandbox.create(templateId, {
161
+ ...opts,
162
+ ...this.resolution && { resolution: this.resolution },
163
+ ...this.dpi !== void 0 && { dpi: this.dpi }
164
+ });
165
+ }
166
+ /** Connect to an existing `@e2b/desktop` SDK sandbox. */
167
+ async connectSdkSandbox(sandboxId, opts) {
168
+ return _e2b_desktop.Sandbox.connect(sandboxId, opts);
169
+ }
170
+ /**
171
+ * Resolve the template: without an explicit `template` option, use the
172
+ * E2B-hosted desktop template (no build needed). Explicit templates go
173
+ * through the base provider's resolution (ID, builder, or customizer).
174
+ */
175
+ async resolveTemplate() {
176
+ if (this._resolvedTemplateId) return this._resolvedTemplateId;
177
+ if (!this.templateSpec) {
178
+ this._resolvedTemplateId = DEFAULT_DESKTOP_TEMPLATE;
179
+ return this._resolvedTemplateId;
180
+ }
181
+ return super.resolveTemplate();
182
+ }
183
+ /**
184
+ * The default desktop template is E2B-hosted — there is nothing to build.
185
+ * (Only reached from the template-not-found retry path in `start()`.)
186
+ */
187
+ async buildDefaultTemplate() {
188
+ this._resolvedTemplateId = DEFAULT_DESKTOP_TEMPLATE;
189
+ return this._resolvedTemplateId;
190
+ }
191
+ /** Ensure the sandbox is running, then run a desktop SDK operation. */
192
+ async withDesktop(fn) {
193
+ await this.ensureRunning();
194
+ return this.retryOnDead(() => fn(this.desktop));
195
+ }
196
+ /**
197
+ * Ensure the VNC stream is running (authenticated), memoized per SDK
198
+ * sandbox so a resumed/recreated VM restarts it. A stream already started
199
+ * externally (via the `desktop` escape hatch) is left untouched.
200
+ */
201
+ async ensureStreamStarted(desktop) {
202
+ if (this._streamStarted?.sandboxId !== desktop.sandboxId) {
203
+ const promise = desktop.stream.start({ requireAuth: true }).catch((error) => {
204
+ if (String(error).includes("already running")) return;
205
+ this._streamStarted = null;
206
+ throw error;
207
+ });
208
+ this._streamStarted = {
209
+ sandboxId: desktop.sandboxId,
210
+ promise
211
+ };
212
+ }
213
+ return this._streamStarted.promise;
214
+ }
215
+ };
216
+ //#endregion
217
+ //#region src/provider.ts
218
+ const e2bDesktopSandboxProvider = {
219
+ id: "e2b-desktop",
220
+ name: "E2B Desktop Sandbox",
221
+ description: "Cloud desktop (computer-use) sandbox powered by E2B",
222
+ configSchema: {
223
+ type: "object",
224
+ properties: {
225
+ template: {
226
+ type: "string",
227
+ description: "Sandbox template ID (defaults to the E2B desktop template)"
228
+ },
229
+ timeout: {
230
+ type: "number",
231
+ description: "Execution timeout in milliseconds",
232
+ default: 3e5
233
+ },
234
+ env: {
235
+ type: "object",
236
+ description: "Environment variables",
237
+ additionalProperties: { type: "string" }
238
+ },
239
+ metadata: {
240
+ type: "object",
241
+ description: "Custom metadata",
242
+ additionalProperties: true
243
+ },
244
+ resolution: {
245
+ type: "array",
246
+ description: "Desktop resolution as [width, height] in pixels",
247
+ items: { type: "number" },
248
+ minItems: 2,
249
+ maxItems: 2
250
+ },
251
+ dpi: {
252
+ type: "number",
253
+ description: "Desktop display DPI"
254
+ },
255
+ domain: {
256
+ type: "string",
257
+ description: "Domain for self-hosted E2B"
258
+ },
259
+ apiUrl: {
260
+ type: "string",
261
+ description: "API URL for self-hosted E2B"
262
+ },
263
+ apiKey: {
264
+ type: "string",
265
+ description: "E2B API key"
266
+ },
267
+ accessToken: {
268
+ type: "string",
269
+ description: "E2B access token"
270
+ }
271
+ }
272
+ },
273
+ createSandbox: (config) => {
274
+ const { resolution, ...rest } = config;
275
+ return new E2BDesktopSandbox({
276
+ ...rest,
277
+ ...resolution && { resolution: [resolution[0], resolution[1]] }
278
+ });
279
+ }
280
+ };
281
+ //#endregion
282
+ exports.E2BDesktopSandbox = E2BDesktopSandbox;
283
+ exports.e2bDesktopSandboxProvider = e2bDesktopSandboxProvider;
284
+
285
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["E2BSandbox","SandboxNotReadyError","E2BDesktopSdkSandbox"],"sources":["../src/sandbox/index.ts","../src/provider.ts"],"sourcesContent":["/**\n * E2B Desktop Sandbox Provider\n *\n * An E2B sandbox running a full Linux desktop environment with computer-use\n * (screenshot, mouse, keyboard) control. Extends `@mastra/e2b`'s `E2BSandbox`\n * the same way `@e2b/desktop`'s SDK `Sandbox` extends `e2b`'s: everything the\n * base provider supports (command execution, processes, file upload,\n * reconnection) works against the same desktop VM.\n *\n * @see https://github.com/e2b-dev/desktop\n */\n\nimport { Sandbox as E2BDesktopSdkSandbox } from '@e2b/desktop';\nimport type { SandboxCloneOptions, SandboxComputer } from '@mastra/core/workspace';\nimport { SandboxNotReadyError } from '@mastra/core/workspace';\nimport { E2BSandbox } from '@mastra/e2b';\nimport type { E2BSandboxOptions } from '@mastra/e2b';\nimport type { Sandbox, SandboxConnectOpts, SandboxOpts } from 'e2b';\n\n/**\n * E2B-hosted desktop template (`@e2b/desktop`'s default). Used when no\n * explicit `template` option is provided — unlike the base provider, no\n * template build is required.\n */\nconst DEFAULT_DESKTOP_TEMPLATE = 'desktop';\n\n// =============================================================================\n// E2B Desktop Sandbox Options\n// =============================================================================\n\n/**\n * E2B Desktop sandbox provider configuration.\n *\n * Inherits all `E2BSandboxOptions` (credentials, timeout, env, metadata,\n * network, template, instructions). When no `template` is provided, the\n * E2B-hosted `desktop` template is used instead of the base provider's\n * mountable template.\n */\nexport interface E2BDesktopSandboxOptions extends E2BSandboxOptions {\n /**\n * Desktop display resolution as `[width, height]` in pixels.\n * Applies to newly created sandboxes only.\n */\n resolution?: [number, number];\n /**\n * Desktop display DPI.\n * Applies to newly created sandboxes only.\n */\n dpi?: number;\n}\n\n// =============================================================================\n// E2B Desktop Sandbox Implementation\n// =============================================================================\n\n/**\n * E2B Desktop sandbox provider for Mastra workspaces.\n *\n * Features:\n * - Everything from `E2BSandbox` (commands, processes, file upload, pause/resume)\n * - `computer` capability: screenshot, mouse, and keyboard control — when\n * used in a `Workspace`, agents automatically get the\n * `mastra_workspace_computer_*` tools\n * - Live desktop view via an authenticated noVNC stream URL\n *\n * @example Basic usage\n * ```typescript\n * import { Agent } from '@mastra/core/agent';\n * import { Workspace } from '@mastra/core/workspace';\n * import { E2BDesktopSandbox } from '@mastra/e2b-desktop';\n *\n * const sandbox = new E2BDesktopSandbox({ resolution: [1280, 720] });\n * const agent = new Agent({\n * // file + shell + computer tools are all emitted automatically\n * workspace: new Workspace({ sandbox }),\n * // ...\n * });\n * ```\n *\n * @example Direct desktop control\n * ```typescript\n * const sandbox = new E2BDesktopSandbox();\n * await sandbox.start();\n * await sandbox.computer.leftClick(100, 200);\n * const { data } = await sandbox.computer.screenshot();\n * const viewerUrl = await sandbox.computer.streamUrl();\n * ```\n */\nexport class E2BDesktopSandbox extends E2BSandbox {\n override readonly name: string = 'E2BDesktopSandbox';\n override readonly provider: string = 'e2b-desktop';\n\n private readonly resolution?: [number, number];\n private readonly dpi?: number;\n private readonly _desktopConstructorOptions: E2BDesktopSandboxOptions;\n\n /** Stream startup memo, keyed by SDK sandbox ID so a fresh VM restarts it. */\n private _streamStarted: { sandboxId: string; promise: Promise<void> } | null = null;\n\n constructor(options: E2BDesktopSandboxOptions = {}) {\n super(options);\n this.resolution = options.resolution;\n this.dpi = options.dpi;\n this._desktopConstructorOptions = { ...options };\n }\n\n /**\n * Computer-use (desktop) capability: screenshot, mouse, and keyboard\n * control of the sandbox's desktop, backed by `@e2b/desktop`.\n * Operations start the sandbox automatically if it is not running.\n */\n override readonly computer: SandboxComputer = {\n screenshot: async () => {\n const data = await this.withDesktop(desktop => desktop.screenshot());\n return { data, mediaType: 'image/png' as const };\n },\n leftClick: async (x, y) => {\n await this.withDesktop(desktop => desktop.leftClick(x, y));\n },\n rightClick: async (x, y) => {\n await this.withDesktop(desktop => desktop.rightClick(x, y));\n },\n doubleClick: async (x, y) => {\n await this.withDesktop(desktop => desktop.doubleClick(x, y));\n },\n moveMouse: async (x, y) => {\n await this.withDesktop(desktop => desktop.moveMouse(x, y));\n },\n drag: async (from, to) => {\n await this.withDesktop(desktop => desktop.drag([from.x, from.y], [to.x, to.y]));\n },\n scroll: async (direction, amount) => {\n await this.withDesktop(desktop => desktop.scroll(direction, amount));\n },\n type: async text => {\n await this.withDesktop(desktop => desktop.write(text));\n },\n press: async key => {\n await this.withDesktop(desktop => desktop.press(key));\n },\n getScreenSize: async () => {\n return this.withDesktop(desktop => desktop.getScreenSize());\n },\n getCursorPosition: async () => {\n return this.withDesktop(desktop => desktop.getCursorPosition());\n },\n streamUrl: async () => {\n try {\n return await this.withDesktop(async desktop => {\n await this.ensureStreamStarted(desktop);\n try {\n return desktop.stream.getUrl({ authKey: desktop.stream.getAuthKey() });\n } catch {\n // Stream was started externally without auth — return the plain URL.\n return desktop.stream.getUrl();\n }\n });\n } catch {\n return null;\n }\n },\n };\n\n /**\n * Get the underlying `@e2b/desktop` Sandbox instance for direct access to\n * desktop APIs not exposed through the abstraction (e.g. `launch()`,\n * `open()`, window helpers, custom stream control).\n *\n * @throws {SandboxNotReadyError} If the sandbox has not been started\n *\n * @example Launch an application\n * ```typescript\n * await sandbox.start();\n * await sandbox.desktop.launch('xfce4-terminal');\n * await sandbox.desktop.open('https://mastra.ai');\n * ```\n */\n get desktop(): E2BDesktopSdkSandbox {\n if (!this._sandbox) {\n throw new SandboxNotReadyError(this.id);\n }\n // Safe: the factory hooks below guarantee the SDK sandbox is a desktop sandbox.\n return this._sandbox as E2BDesktopSdkSandbox;\n }\n\n /**\n * Construct a sibling `E2BDesktopSandbox` that inherits this sandbox's\n * configuration with per-instance overrides. See `E2BSandbox.clone`.\n */\n override clone(options: SandboxCloneOptions = {}): E2BDesktopSandbox {\n const { id: _id, ...base } = this._desktopConstructorOptions;\n return new E2BDesktopSandbox({\n ...base,\n ...(options.id !== undefined && { id: options.id }),\n ...(options.env !== undefined && { env: options.env }),\n ...(options.idleTimeoutMinutes !== undefined && { timeout: options.idleTimeoutMinutes * 60_000 }),\n });\n }\n\n // ---------------------------------------------------------------------------\n // SDK Factory Hooks\n // ---------------------------------------------------------------------------\n\n /** Create a `@e2b/desktop` SDK sandbox (with desktop display options). */\n protected override async createSdkSandbox(templateId: string, opts: SandboxOpts): Promise<Sandbox> {\n return E2BDesktopSdkSandbox.create(templateId, {\n ...opts,\n ...(this.resolution && { resolution: this.resolution }),\n ...(this.dpi !== undefined && { dpi: this.dpi }),\n });\n }\n\n /** Connect to an existing `@e2b/desktop` SDK sandbox. */\n protected override async connectSdkSandbox(sandboxId: string, opts: SandboxConnectOpts): Promise<Sandbox> {\n return E2BDesktopSdkSandbox.connect(sandboxId, opts);\n }\n\n // ---------------------------------------------------------------------------\n // Template Resolution\n // ---------------------------------------------------------------------------\n\n /**\n * Resolve the template: without an explicit `template` option, use the\n * E2B-hosted desktop template (no build needed). Explicit templates go\n * through the base provider's resolution (ID, builder, or customizer).\n */\n protected override async resolveTemplate(): Promise<string> {\n if (this._resolvedTemplateId) {\n return this._resolvedTemplateId;\n }\n if (!this.templateSpec) {\n this._resolvedTemplateId = DEFAULT_DESKTOP_TEMPLATE;\n return this._resolvedTemplateId;\n }\n return super.resolveTemplate();\n }\n\n /**\n * The default desktop template is E2B-hosted — there is nothing to build.\n * (Only reached from the template-not-found retry path in `start()`.)\n */\n protected override async buildDefaultTemplate(): Promise<string> {\n this._resolvedTemplateId = DEFAULT_DESKTOP_TEMPLATE;\n return this._resolvedTemplateId;\n }\n\n // ---------------------------------------------------------------------------\n // Internal Helpers\n // ---------------------------------------------------------------------------\n\n /** Ensure the sandbox is running, then run a desktop SDK operation. */\n private async withDesktop<T>(fn: (desktop: E2BDesktopSdkSandbox) => Promise<T>): Promise<T> {\n await this.ensureRunning();\n return this.retryOnDead(() => fn(this.desktop));\n }\n\n /**\n * Ensure the VNC stream is running (authenticated), memoized per SDK\n * sandbox so a resumed/recreated VM restarts it. A stream already started\n * externally (via the `desktop` escape hatch) is left untouched.\n */\n private async ensureStreamStarted(desktop: E2BDesktopSdkSandbox): Promise<void> {\n if (this._streamStarted?.sandboxId !== desktop.sandboxId) {\n const promise = desktop.stream.start({ requireAuth: true }).catch((error: unknown) => {\n if (String(error).includes('already running')) {\n return;\n }\n this._streamStarted = null;\n throw error;\n });\n this._streamStarted = { sandboxId: desktop.sandboxId, promise };\n }\n return this._streamStarted.promise;\n }\n}\n","/**\n * E2B Desktop sandbox provider descriptor for MastraEditor.\n *\n * @example\n * ```typescript\n * import { e2bDesktopSandboxProvider } from '@mastra/e2b-desktop';\n *\n * const editor = new MastraEditor({\n * sandboxes: [e2bDesktopSandboxProvider],\n * });\n * ```\n */\nimport type { SandboxProvider } from '@mastra/core/editor';\nimport { E2BDesktopSandbox } from './sandbox';\n\n/**\n * Serializable subset of E2BDesktopSandboxOptions for editor storage.\n * Non-serializable options (TemplateBuilder callbacks, runtime objects) are excluded.\n */\ninterface E2BDesktopProviderConfig {\n template?: string;\n timeout?: number;\n env?: Record<string, string>;\n metadata?: Record<string, unknown>;\n resolution?: [number, number];\n dpi?: number;\n domain?: string;\n apiUrl?: string;\n apiKey?: string;\n accessToken?: string;\n}\n\nexport const e2bDesktopSandboxProvider: SandboxProvider<E2BDesktopProviderConfig> = {\n id: 'e2b-desktop',\n name: 'E2B Desktop Sandbox',\n description: 'Cloud desktop (computer-use) sandbox powered by E2B',\n configSchema: {\n type: 'object',\n properties: {\n template: { type: 'string', description: 'Sandbox template ID (defaults to the E2B desktop template)' },\n timeout: { type: 'number', description: 'Execution timeout in milliseconds', default: 300000 },\n env: {\n type: 'object',\n description: 'Environment variables',\n additionalProperties: { type: 'string' },\n },\n metadata: {\n type: 'object',\n description: 'Custom metadata',\n additionalProperties: true,\n },\n resolution: {\n type: 'array',\n description: 'Desktop resolution as [width, height] in pixels',\n items: { type: 'number' },\n minItems: 2,\n maxItems: 2,\n },\n dpi: { type: 'number', description: 'Desktop display DPI' },\n domain: { type: 'string', description: 'Domain for self-hosted E2B' },\n apiUrl: { type: 'string', description: 'API URL for self-hosted E2B' },\n apiKey: { type: 'string', description: 'E2B API key' },\n accessToken: { type: 'string', description: 'E2B access token' },\n },\n },\n createSandbox: config => {\n const { resolution, ...rest } = config;\n return new E2BDesktopSandbox({\n ...rest,\n ...(resolution && { resolution: [resolution[0]!, resolution[1]!] }),\n });\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAwBA,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgEjC,IAAa,oBAAb,MAAa,0BAA0BA,YAAAA,WAAW;CAChD,OAAiC;CACjC,WAAqC;CAErC;CACA;CACA;;CAGA,iBAA+E;CAE/E,YAAY,UAAoC,CAAC,GAAG;EAClD,MAAM,OAAO;EACb,KAAK,aAAa,QAAQ;EAC1B,KAAK,MAAM,QAAQ;EACnB,KAAK,6BAA6B,EAAE,GAAG,QAAQ;CACjD;;;;;;CAOA,WAA8C;EAC5C,YAAY,YAAY;GAEtB,OAAO;IAAE,MAAA,MADU,KAAK,aAAY,YAAW,QAAQ,WAAW,CAAC;IACpD,WAAW;GAAqB;EACjD;EACA,WAAW,OAAO,GAAG,MAAM;GACzB,MAAM,KAAK,aAAY,YAAW,QAAQ,UAAU,GAAG,CAAC,CAAC;EAC3D;EACA,YAAY,OAAO,GAAG,MAAM;GAC1B,MAAM,KAAK,aAAY,YAAW,QAAQ,WAAW,GAAG,CAAC,CAAC;EAC5D;EACA,aAAa,OAAO,GAAG,MAAM;GAC3B,MAAM,KAAK,aAAY,YAAW,QAAQ,YAAY,GAAG,CAAC,CAAC;EAC7D;EACA,WAAW,OAAO,GAAG,MAAM;GACzB,MAAM,KAAK,aAAY,YAAW,QAAQ,UAAU,GAAG,CAAC,CAAC;EAC3D;EACA,MAAM,OAAO,MAAM,OAAO;GACxB,MAAM,KAAK,aAAY,YAAW,QAAQ,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC;EAChF;EACA,QAAQ,OAAO,WAAW,WAAW;GACnC,MAAM,KAAK,aAAY,YAAW,QAAQ,OAAO,WAAW,MAAM,CAAC;EACrE;EACA,MAAM,OAAM,SAAQ;GAClB,MAAM,KAAK,aAAY,YAAW,QAAQ,MAAM,IAAI,CAAC;EACvD;EACA,OAAO,OAAM,QAAO;GAClB,MAAM,KAAK,aAAY,YAAW,QAAQ,MAAM,GAAG,CAAC;EACtD;EACA,eAAe,YAAY;GACzB,OAAO,KAAK,aAAY,YAAW,QAAQ,cAAc,CAAC;EAC5D;EACA,mBAAmB,YAAY;GAC7B,OAAO,KAAK,aAAY,YAAW,QAAQ,kBAAkB,CAAC;EAChE;EACA,WAAW,YAAY;GACrB,IAAI;IACF,OAAO,MAAM,KAAK,YAAY,OAAM,YAAW;KAC7C,MAAM,KAAK,oBAAoB,OAAO;KACtC,IAAI;MACF,OAAO,QAAQ,OAAO,OAAO,EAAE,SAAS,QAAQ,OAAO,WAAW,EAAE,CAAC;KACvE,QAAQ;MAEN,OAAO,QAAQ,OAAO,OAAO;KAC/B;IACF,CAAC;GACH,QAAQ;IACN,OAAO;GACT;EACF;CACF;;;;;;;;;;;;;;;CAgBA,IAAI,UAAgC;EAClC,IAAI,CAAC,KAAK,UACR,MAAM,IAAIC,uBAAAA,qBAAqB,KAAK,EAAE;EAGxC,OAAO,KAAK;CACd;;;;;CAMA,MAAe,UAA+B,CAAC,GAAsB;EACnE,MAAM,EAAE,IAAI,KAAK,GAAG,SAAS,KAAK;EAClC,OAAO,IAAI,kBAAkB;GAC3B,GAAG;GACH,GAAI,QAAQ,OAAO,KAAA,KAAa,EAAE,IAAI,QAAQ,GAAG;GACjD,GAAI,QAAQ,QAAQ,KAAA,KAAa,EAAE,KAAK,QAAQ,IAAI;GACpD,GAAI,QAAQ,uBAAuB,KAAA,KAAa,EAAE,SAAS,QAAQ,qBAAqB,IAAO;EACjG,CAAC;CACH;;CAOA,MAAyB,iBAAiB,YAAoB,MAAqC;EACjG,OAAOC,aAAAA,QAAqB,OAAO,YAAY;GAC7C,GAAG;GACH,GAAI,KAAK,cAAc,EAAE,YAAY,KAAK,WAAW;GACrD,GAAI,KAAK,QAAQ,KAAA,KAAa,EAAE,KAAK,KAAK,IAAI;EAChD,CAAC;CACH;;CAGA,MAAyB,kBAAkB,WAAmB,MAA4C;EACxG,OAAOA,aAAAA,QAAqB,QAAQ,WAAW,IAAI;CACrD;;;;;;CAWA,MAAyB,kBAAmC;EAC1D,IAAI,KAAK,qBACP,OAAO,KAAK;EAEd,IAAI,CAAC,KAAK,cAAc;GACtB,KAAK,sBAAsB;GAC3B,OAAO,KAAK;EACd;EACA,OAAO,MAAM,gBAAgB;CAC/B;;;;;CAMA,MAAyB,uBAAwC;EAC/D,KAAK,sBAAsB;EAC3B,OAAO,KAAK;CACd;;CAOA,MAAc,YAAe,IAA+D;EAC1F,MAAM,KAAK,cAAc;EACzB,OAAO,KAAK,kBAAkB,GAAG,KAAK,OAAO,CAAC;CAChD;;;;;;CAOA,MAAc,oBAAoB,SAA8C;EAC9E,IAAI,KAAK,gBAAgB,cAAc,QAAQ,WAAW;GACxD,MAAM,UAAU,QAAQ,OAAO,MAAM,EAAE,aAAa,KAAK,CAAC,CAAC,CAAC,OAAO,UAAmB;IACpF,IAAI,OAAO,KAAK,CAAC,CAAC,SAAS,iBAAiB,GAC1C;IAEF,KAAK,iBAAiB;IACtB,MAAM;GACR,CAAC;GACD,KAAK,iBAAiB;IAAE,WAAW,QAAQ;IAAW;GAAQ;EAChE;EACA,OAAO,KAAK,eAAe;CAC7B;AACF;;;AClPA,MAAa,4BAAuE;CAClF,IAAI;CACJ,MAAM;CACN,aAAa;CACb,cAAc;EACZ,MAAM;EACN,YAAY;GACV,UAAU;IAAE,MAAM;IAAU,aAAa;GAA6D;GACtG,SAAS;IAAE,MAAM;IAAU,aAAa;IAAqC,SAAS;GAAO;GAC7F,KAAK;IACH,MAAM;IACN,aAAa;IACb,sBAAsB,EAAE,MAAM,SAAS;GACzC;GACA,UAAU;IACR,MAAM;IACN,aAAa;IACb,sBAAsB;GACxB;GACA,YAAY;IACV,MAAM;IACN,aAAa;IACb,OAAO,EAAE,MAAM,SAAS;IACxB,UAAU;IACV,UAAU;GACZ;GACA,KAAK;IAAE,MAAM;IAAU,aAAa;GAAsB;GAC1D,QAAQ;IAAE,MAAM;IAAU,aAAa;GAA6B;GACpE,QAAQ;IAAE,MAAM;IAAU,aAAa;GAA8B;GACrE,QAAQ;IAAE,MAAM;IAAU,aAAa;GAAc;GACrD,aAAa;IAAE,MAAM;IAAU,aAAa;GAAmB;EACjE;CACF;CACA,gBAAe,WAAU;EACvB,MAAM,EAAE,YAAY,GAAG,SAAS;EAChC,OAAO,IAAI,kBAAkB;GAC3B,GAAG;GACH,GAAI,cAAc,EAAE,YAAY,CAAC,WAAW,IAAK,WAAW,EAAG,EAAE;EACnE,CAAC;CACH;AACF"}
@@ -0,0 +1,3 @@
1
+ export { E2BDesktopSandbox, type E2BDesktopSandboxOptions } from './sandbox/index.js';
2
+ export { e2bDesktopSandboxProvider } from './provider.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAC7E,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,283 @@
1
+ import { Sandbox } from "@e2b/desktop";
2
+ import { SandboxNotReadyError } from "@mastra/core/workspace";
3
+ import { E2BSandbox } from "@mastra/e2b";
4
+ //#region src/sandbox/index.ts
5
+ /**
6
+ * E2B Desktop Sandbox Provider
7
+ *
8
+ * An E2B sandbox running a full Linux desktop environment with computer-use
9
+ * (screenshot, mouse, keyboard) control. Extends `@mastra/e2b`'s `E2BSandbox`
10
+ * the same way `@e2b/desktop`'s SDK `Sandbox` extends `e2b`'s: everything the
11
+ * base provider supports (command execution, processes, file upload,
12
+ * reconnection) works against the same desktop VM.
13
+ *
14
+ * @see https://github.com/e2b-dev/desktop
15
+ */
16
+ /**
17
+ * E2B-hosted desktop template (`@e2b/desktop`'s default). Used when no
18
+ * explicit `template` option is provided — unlike the base provider, no
19
+ * template build is required.
20
+ */
21
+ const DEFAULT_DESKTOP_TEMPLATE = "desktop";
22
+ /**
23
+ * E2B Desktop sandbox provider for Mastra workspaces.
24
+ *
25
+ * Features:
26
+ * - Everything from `E2BSandbox` (commands, processes, file upload, pause/resume)
27
+ * - `computer` capability: screenshot, mouse, and keyboard control — when
28
+ * used in a `Workspace`, agents automatically get the
29
+ * `mastra_workspace_computer_*` tools
30
+ * - Live desktop view via an authenticated noVNC stream URL
31
+ *
32
+ * @example Basic usage
33
+ * ```typescript
34
+ * import { Agent } from '@mastra/core/agent';
35
+ * import { Workspace } from '@mastra/core/workspace';
36
+ * import { E2BDesktopSandbox } from '@mastra/e2b-desktop';
37
+ *
38
+ * const sandbox = new E2BDesktopSandbox({ resolution: [1280, 720] });
39
+ * const agent = new Agent({
40
+ * // file + shell + computer tools are all emitted automatically
41
+ * workspace: new Workspace({ sandbox }),
42
+ * // ...
43
+ * });
44
+ * ```
45
+ *
46
+ * @example Direct desktop control
47
+ * ```typescript
48
+ * const sandbox = new E2BDesktopSandbox();
49
+ * await sandbox.start();
50
+ * await sandbox.computer.leftClick(100, 200);
51
+ * const { data } = await sandbox.computer.screenshot();
52
+ * const viewerUrl = await sandbox.computer.streamUrl();
53
+ * ```
54
+ */
55
+ var E2BDesktopSandbox = class E2BDesktopSandbox extends E2BSandbox {
56
+ name = "E2BDesktopSandbox";
57
+ provider = "e2b-desktop";
58
+ resolution;
59
+ dpi;
60
+ _desktopConstructorOptions;
61
+ /** Stream startup memo, keyed by SDK sandbox ID so a fresh VM restarts it. */
62
+ _streamStarted = null;
63
+ constructor(options = {}) {
64
+ super(options);
65
+ this.resolution = options.resolution;
66
+ this.dpi = options.dpi;
67
+ this._desktopConstructorOptions = { ...options };
68
+ }
69
+ /**
70
+ * Computer-use (desktop) capability: screenshot, mouse, and keyboard
71
+ * control of the sandbox's desktop, backed by `@e2b/desktop`.
72
+ * Operations start the sandbox automatically if it is not running.
73
+ */
74
+ computer = {
75
+ screenshot: async () => {
76
+ return {
77
+ data: await this.withDesktop((desktop) => desktop.screenshot()),
78
+ mediaType: "image/png"
79
+ };
80
+ },
81
+ leftClick: async (x, y) => {
82
+ await this.withDesktop((desktop) => desktop.leftClick(x, y));
83
+ },
84
+ rightClick: async (x, y) => {
85
+ await this.withDesktop((desktop) => desktop.rightClick(x, y));
86
+ },
87
+ doubleClick: async (x, y) => {
88
+ await this.withDesktop((desktop) => desktop.doubleClick(x, y));
89
+ },
90
+ moveMouse: async (x, y) => {
91
+ await this.withDesktop((desktop) => desktop.moveMouse(x, y));
92
+ },
93
+ drag: async (from, to) => {
94
+ await this.withDesktop((desktop) => desktop.drag([from.x, from.y], [to.x, to.y]));
95
+ },
96
+ scroll: async (direction, amount) => {
97
+ await this.withDesktop((desktop) => desktop.scroll(direction, amount));
98
+ },
99
+ type: async (text) => {
100
+ await this.withDesktop((desktop) => desktop.write(text));
101
+ },
102
+ press: async (key) => {
103
+ await this.withDesktop((desktop) => desktop.press(key));
104
+ },
105
+ getScreenSize: async () => {
106
+ return this.withDesktop((desktop) => desktop.getScreenSize());
107
+ },
108
+ getCursorPosition: async () => {
109
+ return this.withDesktop((desktop) => desktop.getCursorPosition());
110
+ },
111
+ streamUrl: async () => {
112
+ try {
113
+ return await this.withDesktop(async (desktop) => {
114
+ await this.ensureStreamStarted(desktop);
115
+ try {
116
+ return desktop.stream.getUrl({ authKey: desktop.stream.getAuthKey() });
117
+ } catch {
118
+ return desktop.stream.getUrl();
119
+ }
120
+ });
121
+ } catch {
122
+ return null;
123
+ }
124
+ }
125
+ };
126
+ /**
127
+ * Get the underlying `@e2b/desktop` Sandbox instance for direct access to
128
+ * desktop APIs not exposed through the abstraction (e.g. `launch()`,
129
+ * `open()`, window helpers, custom stream control).
130
+ *
131
+ * @throws {SandboxNotReadyError} If the sandbox has not been started
132
+ *
133
+ * @example Launch an application
134
+ * ```typescript
135
+ * await sandbox.start();
136
+ * await sandbox.desktop.launch('xfce4-terminal');
137
+ * await sandbox.desktop.open('https://mastra.ai');
138
+ * ```
139
+ */
140
+ get desktop() {
141
+ if (!this._sandbox) throw new SandboxNotReadyError(this.id);
142
+ return this._sandbox;
143
+ }
144
+ /**
145
+ * Construct a sibling `E2BDesktopSandbox` that inherits this sandbox's
146
+ * configuration with per-instance overrides. See `E2BSandbox.clone`.
147
+ */
148
+ clone(options = {}) {
149
+ const { id: _id, ...base } = this._desktopConstructorOptions;
150
+ return new E2BDesktopSandbox({
151
+ ...base,
152
+ ...options.id !== void 0 && { id: options.id },
153
+ ...options.env !== void 0 && { env: options.env },
154
+ ...options.idleTimeoutMinutes !== void 0 && { timeout: options.idleTimeoutMinutes * 6e4 }
155
+ });
156
+ }
157
+ /** Create a `@e2b/desktop` SDK sandbox (with desktop display options). */
158
+ async createSdkSandbox(templateId, opts) {
159
+ return Sandbox.create(templateId, {
160
+ ...opts,
161
+ ...this.resolution && { resolution: this.resolution },
162
+ ...this.dpi !== void 0 && { dpi: this.dpi }
163
+ });
164
+ }
165
+ /** Connect to an existing `@e2b/desktop` SDK sandbox. */
166
+ async connectSdkSandbox(sandboxId, opts) {
167
+ return Sandbox.connect(sandboxId, opts);
168
+ }
169
+ /**
170
+ * Resolve the template: without an explicit `template` option, use the
171
+ * E2B-hosted desktop template (no build needed). Explicit templates go
172
+ * through the base provider's resolution (ID, builder, or customizer).
173
+ */
174
+ async resolveTemplate() {
175
+ if (this._resolvedTemplateId) return this._resolvedTemplateId;
176
+ if (!this.templateSpec) {
177
+ this._resolvedTemplateId = DEFAULT_DESKTOP_TEMPLATE;
178
+ return this._resolvedTemplateId;
179
+ }
180
+ return super.resolveTemplate();
181
+ }
182
+ /**
183
+ * The default desktop template is E2B-hosted — there is nothing to build.
184
+ * (Only reached from the template-not-found retry path in `start()`.)
185
+ */
186
+ async buildDefaultTemplate() {
187
+ this._resolvedTemplateId = DEFAULT_DESKTOP_TEMPLATE;
188
+ return this._resolvedTemplateId;
189
+ }
190
+ /** Ensure the sandbox is running, then run a desktop SDK operation. */
191
+ async withDesktop(fn) {
192
+ await this.ensureRunning();
193
+ return this.retryOnDead(() => fn(this.desktop));
194
+ }
195
+ /**
196
+ * Ensure the VNC stream is running (authenticated), memoized per SDK
197
+ * sandbox so a resumed/recreated VM restarts it. A stream already started
198
+ * externally (via the `desktop` escape hatch) is left untouched.
199
+ */
200
+ async ensureStreamStarted(desktop) {
201
+ if (this._streamStarted?.sandboxId !== desktop.sandboxId) {
202
+ const promise = desktop.stream.start({ requireAuth: true }).catch((error) => {
203
+ if (String(error).includes("already running")) return;
204
+ this._streamStarted = null;
205
+ throw error;
206
+ });
207
+ this._streamStarted = {
208
+ sandboxId: desktop.sandboxId,
209
+ promise
210
+ };
211
+ }
212
+ return this._streamStarted.promise;
213
+ }
214
+ };
215
+ //#endregion
216
+ //#region src/provider.ts
217
+ const e2bDesktopSandboxProvider = {
218
+ id: "e2b-desktop",
219
+ name: "E2B Desktop Sandbox",
220
+ description: "Cloud desktop (computer-use) sandbox powered by E2B",
221
+ configSchema: {
222
+ type: "object",
223
+ properties: {
224
+ template: {
225
+ type: "string",
226
+ description: "Sandbox template ID (defaults to the E2B desktop template)"
227
+ },
228
+ timeout: {
229
+ type: "number",
230
+ description: "Execution timeout in milliseconds",
231
+ default: 3e5
232
+ },
233
+ env: {
234
+ type: "object",
235
+ description: "Environment variables",
236
+ additionalProperties: { type: "string" }
237
+ },
238
+ metadata: {
239
+ type: "object",
240
+ description: "Custom metadata",
241
+ additionalProperties: true
242
+ },
243
+ resolution: {
244
+ type: "array",
245
+ description: "Desktop resolution as [width, height] in pixels",
246
+ items: { type: "number" },
247
+ minItems: 2,
248
+ maxItems: 2
249
+ },
250
+ dpi: {
251
+ type: "number",
252
+ description: "Desktop display DPI"
253
+ },
254
+ domain: {
255
+ type: "string",
256
+ description: "Domain for self-hosted E2B"
257
+ },
258
+ apiUrl: {
259
+ type: "string",
260
+ description: "API URL for self-hosted E2B"
261
+ },
262
+ apiKey: {
263
+ type: "string",
264
+ description: "E2B API key"
265
+ },
266
+ accessToken: {
267
+ type: "string",
268
+ description: "E2B access token"
269
+ }
270
+ }
271
+ },
272
+ createSandbox: (config) => {
273
+ const { resolution, ...rest } = config;
274
+ return new E2BDesktopSandbox({
275
+ ...rest,
276
+ ...resolution && { resolution: [resolution[0], resolution[1]] }
277
+ });
278
+ }
279
+ };
280
+ //#endregion
281
+ export { E2BDesktopSandbox, e2bDesktopSandboxProvider };
282
+
283
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["E2BDesktopSdkSandbox"],"sources":["../src/sandbox/index.ts","../src/provider.ts"],"sourcesContent":["/**\n * E2B Desktop Sandbox Provider\n *\n * An E2B sandbox running a full Linux desktop environment with computer-use\n * (screenshot, mouse, keyboard) control. Extends `@mastra/e2b`'s `E2BSandbox`\n * the same way `@e2b/desktop`'s SDK `Sandbox` extends `e2b`'s: everything the\n * base provider supports (command execution, processes, file upload,\n * reconnection) works against the same desktop VM.\n *\n * @see https://github.com/e2b-dev/desktop\n */\n\nimport { Sandbox as E2BDesktopSdkSandbox } from '@e2b/desktop';\nimport type { SandboxCloneOptions, SandboxComputer } from '@mastra/core/workspace';\nimport { SandboxNotReadyError } from '@mastra/core/workspace';\nimport { E2BSandbox } from '@mastra/e2b';\nimport type { E2BSandboxOptions } from '@mastra/e2b';\nimport type { Sandbox, SandboxConnectOpts, SandboxOpts } from 'e2b';\n\n/**\n * E2B-hosted desktop template (`@e2b/desktop`'s default). Used when no\n * explicit `template` option is provided — unlike the base provider, no\n * template build is required.\n */\nconst DEFAULT_DESKTOP_TEMPLATE = 'desktop';\n\n// =============================================================================\n// E2B Desktop Sandbox Options\n// =============================================================================\n\n/**\n * E2B Desktop sandbox provider configuration.\n *\n * Inherits all `E2BSandboxOptions` (credentials, timeout, env, metadata,\n * network, template, instructions). When no `template` is provided, the\n * E2B-hosted `desktop` template is used instead of the base provider's\n * mountable template.\n */\nexport interface E2BDesktopSandboxOptions extends E2BSandboxOptions {\n /**\n * Desktop display resolution as `[width, height]` in pixels.\n * Applies to newly created sandboxes only.\n */\n resolution?: [number, number];\n /**\n * Desktop display DPI.\n * Applies to newly created sandboxes only.\n */\n dpi?: number;\n}\n\n// =============================================================================\n// E2B Desktop Sandbox Implementation\n// =============================================================================\n\n/**\n * E2B Desktop sandbox provider for Mastra workspaces.\n *\n * Features:\n * - Everything from `E2BSandbox` (commands, processes, file upload, pause/resume)\n * - `computer` capability: screenshot, mouse, and keyboard control — when\n * used in a `Workspace`, agents automatically get the\n * `mastra_workspace_computer_*` tools\n * - Live desktop view via an authenticated noVNC stream URL\n *\n * @example Basic usage\n * ```typescript\n * import { Agent } from '@mastra/core/agent';\n * import { Workspace } from '@mastra/core/workspace';\n * import { E2BDesktopSandbox } from '@mastra/e2b-desktop';\n *\n * const sandbox = new E2BDesktopSandbox({ resolution: [1280, 720] });\n * const agent = new Agent({\n * // file + shell + computer tools are all emitted automatically\n * workspace: new Workspace({ sandbox }),\n * // ...\n * });\n * ```\n *\n * @example Direct desktop control\n * ```typescript\n * const sandbox = new E2BDesktopSandbox();\n * await sandbox.start();\n * await sandbox.computer.leftClick(100, 200);\n * const { data } = await sandbox.computer.screenshot();\n * const viewerUrl = await sandbox.computer.streamUrl();\n * ```\n */\nexport class E2BDesktopSandbox extends E2BSandbox {\n override readonly name: string = 'E2BDesktopSandbox';\n override readonly provider: string = 'e2b-desktop';\n\n private readonly resolution?: [number, number];\n private readonly dpi?: number;\n private readonly _desktopConstructorOptions: E2BDesktopSandboxOptions;\n\n /** Stream startup memo, keyed by SDK sandbox ID so a fresh VM restarts it. */\n private _streamStarted: { sandboxId: string; promise: Promise<void> } | null = null;\n\n constructor(options: E2BDesktopSandboxOptions = {}) {\n super(options);\n this.resolution = options.resolution;\n this.dpi = options.dpi;\n this._desktopConstructorOptions = { ...options };\n }\n\n /**\n * Computer-use (desktop) capability: screenshot, mouse, and keyboard\n * control of the sandbox's desktop, backed by `@e2b/desktop`.\n * Operations start the sandbox automatically if it is not running.\n */\n override readonly computer: SandboxComputer = {\n screenshot: async () => {\n const data = await this.withDesktop(desktop => desktop.screenshot());\n return { data, mediaType: 'image/png' as const };\n },\n leftClick: async (x, y) => {\n await this.withDesktop(desktop => desktop.leftClick(x, y));\n },\n rightClick: async (x, y) => {\n await this.withDesktop(desktop => desktop.rightClick(x, y));\n },\n doubleClick: async (x, y) => {\n await this.withDesktop(desktop => desktop.doubleClick(x, y));\n },\n moveMouse: async (x, y) => {\n await this.withDesktop(desktop => desktop.moveMouse(x, y));\n },\n drag: async (from, to) => {\n await this.withDesktop(desktop => desktop.drag([from.x, from.y], [to.x, to.y]));\n },\n scroll: async (direction, amount) => {\n await this.withDesktop(desktop => desktop.scroll(direction, amount));\n },\n type: async text => {\n await this.withDesktop(desktop => desktop.write(text));\n },\n press: async key => {\n await this.withDesktop(desktop => desktop.press(key));\n },\n getScreenSize: async () => {\n return this.withDesktop(desktop => desktop.getScreenSize());\n },\n getCursorPosition: async () => {\n return this.withDesktop(desktop => desktop.getCursorPosition());\n },\n streamUrl: async () => {\n try {\n return await this.withDesktop(async desktop => {\n await this.ensureStreamStarted(desktop);\n try {\n return desktop.stream.getUrl({ authKey: desktop.stream.getAuthKey() });\n } catch {\n // Stream was started externally without auth — return the plain URL.\n return desktop.stream.getUrl();\n }\n });\n } catch {\n return null;\n }\n },\n };\n\n /**\n * Get the underlying `@e2b/desktop` Sandbox instance for direct access to\n * desktop APIs not exposed through the abstraction (e.g. `launch()`,\n * `open()`, window helpers, custom stream control).\n *\n * @throws {SandboxNotReadyError} If the sandbox has not been started\n *\n * @example Launch an application\n * ```typescript\n * await sandbox.start();\n * await sandbox.desktop.launch('xfce4-terminal');\n * await sandbox.desktop.open('https://mastra.ai');\n * ```\n */\n get desktop(): E2BDesktopSdkSandbox {\n if (!this._sandbox) {\n throw new SandboxNotReadyError(this.id);\n }\n // Safe: the factory hooks below guarantee the SDK sandbox is a desktop sandbox.\n return this._sandbox as E2BDesktopSdkSandbox;\n }\n\n /**\n * Construct a sibling `E2BDesktopSandbox` that inherits this sandbox's\n * configuration with per-instance overrides. See `E2BSandbox.clone`.\n */\n override clone(options: SandboxCloneOptions = {}): E2BDesktopSandbox {\n const { id: _id, ...base } = this._desktopConstructorOptions;\n return new E2BDesktopSandbox({\n ...base,\n ...(options.id !== undefined && { id: options.id }),\n ...(options.env !== undefined && { env: options.env }),\n ...(options.idleTimeoutMinutes !== undefined && { timeout: options.idleTimeoutMinutes * 60_000 }),\n });\n }\n\n // ---------------------------------------------------------------------------\n // SDK Factory Hooks\n // ---------------------------------------------------------------------------\n\n /** Create a `@e2b/desktop` SDK sandbox (with desktop display options). */\n protected override async createSdkSandbox(templateId: string, opts: SandboxOpts): Promise<Sandbox> {\n return E2BDesktopSdkSandbox.create(templateId, {\n ...opts,\n ...(this.resolution && { resolution: this.resolution }),\n ...(this.dpi !== undefined && { dpi: this.dpi }),\n });\n }\n\n /** Connect to an existing `@e2b/desktop` SDK sandbox. */\n protected override async connectSdkSandbox(sandboxId: string, opts: SandboxConnectOpts): Promise<Sandbox> {\n return E2BDesktopSdkSandbox.connect(sandboxId, opts);\n }\n\n // ---------------------------------------------------------------------------\n // Template Resolution\n // ---------------------------------------------------------------------------\n\n /**\n * Resolve the template: without an explicit `template` option, use the\n * E2B-hosted desktop template (no build needed). Explicit templates go\n * through the base provider's resolution (ID, builder, or customizer).\n */\n protected override async resolveTemplate(): Promise<string> {\n if (this._resolvedTemplateId) {\n return this._resolvedTemplateId;\n }\n if (!this.templateSpec) {\n this._resolvedTemplateId = DEFAULT_DESKTOP_TEMPLATE;\n return this._resolvedTemplateId;\n }\n return super.resolveTemplate();\n }\n\n /**\n * The default desktop template is E2B-hosted — there is nothing to build.\n * (Only reached from the template-not-found retry path in `start()`.)\n */\n protected override async buildDefaultTemplate(): Promise<string> {\n this._resolvedTemplateId = DEFAULT_DESKTOP_TEMPLATE;\n return this._resolvedTemplateId;\n }\n\n // ---------------------------------------------------------------------------\n // Internal Helpers\n // ---------------------------------------------------------------------------\n\n /** Ensure the sandbox is running, then run a desktop SDK operation. */\n private async withDesktop<T>(fn: (desktop: E2BDesktopSdkSandbox) => Promise<T>): Promise<T> {\n await this.ensureRunning();\n return this.retryOnDead(() => fn(this.desktop));\n }\n\n /**\n * Ensure the VNC stream is running (authenticated), memoized per SDK\n * sandbox so a resumed/recreated VM restarts it. A stream already started\n * externally (via the `desktop` escape hatch) is left untouched.\n */\n private async ensureStreamStarted(desktop: E2BDesktopSdkSandbox): Promise<void> {\n if (this._streamStarted?.sandboxId !== desktop.sandboxId) {\n const promise = desktop.stream.start({ requireAuth: true }).catch((error: unknown) => {\n if (String(error).includes('already running')) {\n return;\n }\n this._streamStarted = null;\n throw error;\n });\n this._streamStarted = { sandboxId: desktop.sandboxId, promise };\n }\n return this._streamStarted.promise;\n }\n}\n","/**\n * E2B Desktop sandbox provider descriptor for MastraEditor.\n *\n * @example\n * ```typescript\n * import { e2bDesktopSandboxProvider } from '@mastra/e2b-desktop';\n *\n * const editor = new MastraEditor({\n * sandboxes: [e2bDesktopSandboxProvider],\n * });\n * ```\n */\nimport type { SandboxProvider } from '@mastra/core/editor';\nimport { E2BDesktopSandbox } from './sandbox';\n\n/**\n * Serializable subset of E2BDesktopSandboxOptions for editor storage.\n * Non-serializable options (TemplateBuilder callbacks, runtime objects) are excluded.\n */\ninterface E2BDesktopProviderConfig {\n template?: string;\n timeout?: number;\n env?: Record<string, string>;\n metadata?: Record<string, unknown>;\n resolution?: [number, number];\n dpi?: number;\n domain?: string;\n apiUrl?: string;\n apiKey?: string;\n accessToken?: string;\n}\n\nexport const e2bDesktopSandboxProvider: SandboxProvider<E2BDesktopProviderConfig> = {\n id: 'e2b-desktop',\n name: 'E2B Desktop Sandbox',\n description: 'Cloud desktop (computer-use) sandbox powered by E2B',\n configSchema: {\n type: 'object',\n properties: {\n template: { type: 'string', description: 'Sandbox template ID (defaults to the E2B desktop template)' },\n timeout: { type: 'number', description: 'Execution timeout in milliseconds', default: 300000 },\n env: {\n type: 'object',\n description: 'Environment variables',\n additionalProperties: { type: 'string' },\n },\n metadata: {\n type: 'object',\n description: 'Custom metadata',\n additionalProperties: true,\n },\n resolution: {\n type: 'array',\n description: 'Desktop resolution as [width, height] in pixels',\n items: { type: 'number' },\n minItems: 2,\n maxItems: 2,\n },\n dpi: { type: 'number', description: 'Desktop display DPI' },\n domain: { type: 'string', description: 'Domain for self-hosted E2B' },\n apiUrl: { type: 'string', description: 'API URL for self-hosted E2B' },\n apiKey: { type: 'string', description: 'E2B API key' },\n accessToken: { type: 'string', description: 'E2B access token' },\n },\n },\n createSandbox: config => {\n const { resolution, ...rest } = config;\n return new E2BDesktopSandbox({\n ...rest,\n ...(resolution && { resolution: [resolution[0]!, resolution[1]!] }),\n });\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAwBA,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgEjC,IAAa,oBAAb,MAAa,0BAA0B,WAAW;CAChD,OAAiC;CACjC,WAAqC;CAErC;CACA;CACA;;CAGA,iBAA+E;CAE/E,YAAY,UAAoC,CAAC,GAAG;EAClD,MAAM,OAAO;EACb,KAAK,aAAa,QAAQ;EAC1B,KAAK,MAAM,QAAQ;EACnB,KAAK,6BAA6B,EAAE,GAAG,QAAQ;CACjD;;;;;;CAOA,WAA8C;EAC5C,YAAY,YAAY;GAEtB,OAAO;IAAE,MAAA,MADU,KAAK,aAAY,YAAW,QAAQ,WAAW,CAAC;IACpD,WAAW;GAAqB;EACjD;EACA,WAAW,OAAO,GAAG,MAAM;GACzB,MAAM,KAAK,aAAY,YAAW,QAAQ,UAAU,GAAG,CAAC,CAAC;EAC3D;EACA,YAAY,OAAO,GAAG,MAAM;GAC1B,MAAM,KAAK,aAAY,YAAW,QAAQ,WAAW,GAAG,CAAC,CAAC;EAC5D;EACA,aAAa,OAAO,GAAG,MAAM;GAC3B,MAAM,KAAK,aAAY,YAAW,QAAQ,YAAY,GAAG,CAAC,CAAC;EAC7D;EACA,WAAW,OAAO,GAAG,MAAM;GACzB,MAAM,KAAK,aAAY,YAAW,QAAQ,UAAU,GAAG,CAAC,CAAC;EAC3D;EACA,MAAM,OAAO,MAAM,OAAO;GACxB,MAAM,KAAK,aAAY,YAAW,QAAQ,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC;EAChF;EACA,QAAQ,OAAO,WAAW,WAAW;GACnC,MAAM,KAAK,aAAY,YAAW,QAAQ,OAAO,WAAW,MAAM,CAAC;EACrE;EACA,MAAM,OAAM,SAAQ;GAClB,MAAM,KAAK,aAAY,YAAW,QAAQ,MAAM,IAAI,CAAC;EACvD;EACA,OAAO,OAAM,QAAO;GAClB,MAAM,KAAK,aAAY,YAAW,QAAQ,MAAM,GAAG,CAAC;EACtD;EACA,eAAe,YAAY;GACzB,OAAO,KAAK,aAAY,YAAW,QAAQ,cAAc,CAAC;EAC5D;EACA,mBAAmB,YAAY;GAC7B,OAAO,KAAK,aAAY,YAAW,QAAQ,kBAAkB,CAAC;EAChE;EACA,WAAW,YAAY;GACrB,IAAI;IACF,OAAO,MAAM,KAAK,YAAY,OAAM,YAAW;KAC7C,MAAM,KAAK,oBAAoB,OAAO;KACtC,IAAI;MACF,OAAO,QAAQ,OAAO,OAAO,EAAE,SAAS,QAAQ,OAAO,WAAW,EAAE,CAAC;KACvE,QAAQ;MAEN,OAAO,QAAQ,OAAO,OAAO;KAC/B;IACF,CAAC;GACH,QAAQ;IACN,OAAO;GACT;EACF;CACF;;;;;;;;;;;;;;;CAgBA,IAAI,UAAgC;EAClC,IAAI,CAAC,KAAK,UACR,MAAM,IAAI,qBAAqB,KAAK,EAAE;EAGxC,OAAO,KAAK;CACd;;;;;CAMA,MAAe,UAA+B,CAAC,GAAsB;EACnE,MAAM,EAAE,IAAI,KAAK,GAAG,SAAS,KAAK;EAClC,OAAO,IAAI,kBAAkB;GAC3B,GAAG;GACH,GAAI,QAAQ,OAAO,KAAA,KAAa,EAAE,IAAI,QAAQ,GAAG;GACjD,GAAI,QAAQ,QAAQ,KAAA,KAAa,EAAE,KAAK,QAAQ,IAAI;GACpD,GAAI,QAAQ,uBAAuB,KAAA,KAAa,EAAE,SAAS,QAAQ,qBAAqB,IAAO;EACjG,CAAC;CACH;;CAOA,MAAyB,iBAAiB,YAAoB,MAAqC;EACjG,OAAOA,QAAqB,OAAO,YAAY;GAC7C,GAAG;GACH,GAAI,KAAK,cAAc,EAAE,YAAY,KAAK,WAAW;GACrD,GAAI,KAAK,QAAQ,KAAA,KAAa,EAAE,KAAK,KAAK,IAAI;EAChD,CAAC;CACH;;CAGA,MAAyB,kBAAkB,WAAmB,MAA4C;EACxG,OAAOA,QAAqB,QAAQ,WAAW,IAAI;CACrD;;;;;;CAWA,MAAyB,kBAAmC;EAC1D,IAAI,KAAK,qBACP,OAAO,KAAK;EAEd,IAAI,CAAC,KAAK,cAAc;GACtB,KAAK,sBAAsB;GAC3B,OAAO,KAAK;EACd;EACA,OAAO,MAAM,gBAAgB;CAC/B;;;;;CAMA,MAAyB,uBAAwC;EAC/D,KAAK,sBAAsB;EAC3B,OAAO,KAAK;CACd;;CAOA,MAAc,YAAe,IAA+D;EAC1F,MAAM,KAAK,cAAc;EACzB,OAAO,KAAK,kBAAkB,GAAG,KAAK,OAAO,CAAC;CAChD;;;;;;CAOA,MAAc,oBAAoB,SAA8C;EAC9E,IAAI,KAAK,gBAAgB,cAAc,QAAQ,WAAW;GACxD,MAAM,UAAU,QAAQ,OAAO,MAAM,EAAE,aAAa,KAAK,CAAC,CAAC,CAAC,OAAO,UAAmB;IACpF,IAAI,OAAO,KAAK,CAAC,CAAC,SAAS,iBAAiB,GAC1C;IAEF,KAAK,iBAAiB;IACtB,MAAM;GACR,CAAC;GACD,KAAK,iBAAiB;IAAE,WAAW,QAAQ;IAAW;GAAQ;EAChE;EACA,OAAO,KAAK,eAAe;CAC7B;AACF;;;AClPA,MAAa,4BAAuE;CAClF,IAAI;CACJ,MAAM;CACN,aAAa;CACb,cAAc;EACZ,MAAM;EACN,YAAY;GACV,UAAU;IAAE,MAAM;IAAU,aAAa;GAA6D;GACtG,SAAS;IAAE,MAAM;IAAU,aAAa;IAAqC,SAAS;GAAO;GAC7F,KAAK;IACH,MAAM;IACN,aAAa;IACb,sBAAsB,EAAE,MAAM,SAAS;GACzC;GACA,UAAU;IACR,MAAM;IACN,aAAa;IACb,sBAAsB;GACxB;GACA,YAAY;IACV,MAAM;IACN,aAAa;IACb,OAAO,EAAE,MAAM,SAAS;IACxB,UAAU;IACV,UAAU;GACZ;GACA,KAAK;IAAE,MAAM;IAAU,aAAa;GAAsB;GAC1D,QAAQ;IAAE,MAAM;IAAU,aAAa;GAA6B;GACpE,QAAQ;IAAE,MAAM;IAAU,aAAa;GAA8B;GACrE,QAAQ;IAAE,MAAM;IAAU,aAAa;GAAc;GACrD,aAAa;IAAE,MAAM;IAAU,aAAa;GAAmB;EACjE;CACF;CACA,gBAAe,WAAU;EACvB,MAAM,EAAE,YAAY,GAAG,SAAS;EAChC,OAAO,IAAI,kBAAkB;GAC3B,GAAG;GACH,GAAI,cAAc,EAAE,YAAY,CAAC,WAAW,IAAK,WAAW,EAAG,EAAE;EACnE,CAAC;CACH;AACF"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * E2B Desktop sandbox provider descriptor for MastraEditor.
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * import { e2bDesktopSandboxProvider } from '@mastra/e2b-desktop';
7
+ *
8
+ * const editor = new MastraEditor({
9
+ * sandboxes: [e2bDesktopSandboxProvider],
10
+ * });
11
+ * ```
12
+ */
13
+ import type { SandboxProvider } from '@mastra/core/editor';
14
+ /**
15
+ * Serializable subset of E2BDesktopSandboxOptions for editor storage.
16
+ * Non-serializable options (TemplateBuilder callbacks, runtime objects) are excluded.
17
+ */
18
+ interface E2BDesktopProviderConfig {
19
+ template?: string;
20
+ timeout?: number;
21
+ env?: Record<string, string>;
22
+ metadata?: Record<string, unknown>;
23
+ resolution?: [number, number];
24
+ dpi?: number;
25
+ domain?: string;
26
+ apiUrl?: string;
27
+ apiKey?: string;
28
+ accessToken?: string;
29
+ }
30
+ export declare const e2bDesktopSandboxProvider: SandboxProvider<E2BDesktopProviderConfig>;
31
+ export {};
32
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAG3D;;;GAGG;AACH,UAAU,wBAAwB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,yBAAyB,EAAE,eAAe,CAAC,wBAAwB,CAwC/E,CAAC"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * E2B Desktop Sandbox Provider
3
+ *
4
+ * An E2B sandbox running a full Linux desktop environment with computer-use
5
+ * (screenshot, mouse, keyboard) control. Extends `@mastra/e2b`'s `E2BSandbox`
6
+ * the same way `@e2b/desktop`'s SDK `Sandbox` extends `e2b`'s: everything the
7
+ * base provider supports (command execution, processes, file upload,
8
+ * reconnection) works against the same desktop VM.
9
+ *
10
+ * @see https://github.com/e2b-dev/desktop
11
+ */
12
+ import { Sandbox as E2BDesktopSdkSandbox } from '@e2b/desktop';
13
+ import type { SandboxCloneOptions, SandboxComputer } from '@mastra/core/workspace';
14
+ import { E2BSandbox } from '@mastra/e2b';
15
+ import type { E2BSandboxOptions } from '@mastra/e2b';
16
+ import type { Sandbox, SandboxConnectOpts, SandboxOpts } from 'e2b';
17
+ /**
18
+ * E2B Desktop sandbox provider configuration.
19
+ *
20
+ * Inherits all `E2BSandboxOptions` (credentials, timeout, env, metadata,
21
+ * network, template, instructions). When no `template` is provided, the
22
+ * E2B-hosted `desktop` template is used instead of the base provider's
23
+ * mountable template.
24
+ */
25
+ export interface E2BDesktopSandboxOptions extends E2BSandboxOptions {
26
+ /**
27
+ * Desktop display resolution as `[width, height]` in pixels.
28
+ * Applies to newly created sandboxes only.
29
+ */
30
+ resolution?: [number, number];
31
+ /**
32
+ * Desktop display DPI.
33
+ * Applies to newly created sandboxes only.
34
+ */
35
+ dpi?: number;
36
+ }
37
+ /**
38
+ * E2B Desktop sandbox provider for Mastra workspaces.
39
+ *
40
+ * Features:
41
+ * - Everything from `E2BSandbox` (commands, processes, file upload, pause/resume)
42
+ * - `computer` capability: screenshot, mouse, and keyboard control — when
43
+ * used in a `Workspace`, agents automatically get the
44
+ * `mastra_workspace_computer_*` tools
45
+ * - Live desktop view via an authenticated noVNC stream URL
46
+ *
47
+ * @example Basic usage
48
+ * ```typescript
49
+ * import { Agent } from '@mastra/core/agent';
50
+ * import { Workspace } from '@mastra/core/workspace';
51
+ * import { E2BDesktopSandbox } from '@mastra/e2b-desktop';
52
+ *
53
+ * const sandbox = new E2BDesktopSandbox({ resolution: [1280, 720] });
54
+ * const agent = new Agent({
55
+ * // file + shell + computer tools are all emitted automatically
56
+ * workspace: new Workspace({ sandbox }),
57
+ * // ...
58
+ * });
59
+ * ```
60
+ *
61
+ * @example Direct desktop control
62
+ * ```typescript
63
+ * const sandbox = new E2BDesktopSandbox();
64
+ * await sandbox.start();
65
+ * await sandbox.computer.leftClick(100, 200);
66
+ * const { data } = await sandbox.computer.screenshot();
67
+ * const viewerUrl = await sandbox.computer.streamUrl();
68
+ * ```
69
+ */
70
+ export declare class E2BDesktopSandbox extends E2BSandbox {
71
+ readonly name: string;
72
+ readonly provider: string;
73
+ private readonly resolution?;
74
+ private readonly dpi?;
75
+ private readonly _desktopConstructorOptions;
76
+ /** Stream startup memo, keyed by SDK sandbox ID so a fresh VM restarts it. */
77
+ private _streamStarted;
78
+ constructor(options?: E2BDesktopSandboxOptions);
79
+ /**
80
+ * Computer-use (desktop) capability: screenshot, mouse, and keyboard
81
+ * control of the sandbox's desktop, backed by `@e2b/desktop`.
82
+ * Operations start the sandbox automatically if it is not running.
83
+ */
84
+ readonly computer: SandboxComputer;
85
+ /**
86
+ * Get the underlying `@e2b/desktop` Sandbox instance for direct access to
87
+ * desktop APIs not exposed through the abstraction (e.g. `launch()`,
88
+ * `open()`, window helpers, custom stream control).
89
+ *
90
+ * @throws {SandboxNotReadyError} If the sandbox has not been started
91
+ *
92
+ * @example Launch an application
93
+ * ```typescript
94
+ * await sandbox.start();
95
+ * await sandbox.desktop.launch('xfce4-terminal');
96
+ * await sandbox.desktop.open('https://mastra.ai');
97
+ * ```
98
+ */
99
+ get desktop(): E2BDesktopSdkSandbox;
100
+ /**
101
+ * Construct a sibling `E2BDesktopSandbox` that inherits this sandbox's
102
+ * configuration with per-instance overrides. See `E2BSandbox.clone`.
103
+ */
104
+ clone(options?: SandboxCloneOptions): E2BDesktopSandbox;
105
+ /** Create a `@e2b/desktop` SDK sandbox (with desktop display options). */
106
+ protected createSdkSandbox(templateId: string, opts: SandboxOpts): Promise<Sandbox>;
107
+ /** Connect to an existing `@e2b/desktop` SDK sandbox. */
108
+ protected connectSdkSandbox(sandboxId: string, opts: SandboxConnectOpts): Promise<Sandbox>;
109
+ /**
110
+ * Resolve the template: without an explicit `template` option, use the
111
+ * E2B-hosted desktop template (no build needed). Explicit templates go
112
+ * through the base provider's resolution (ID, builder, or customizer).
113
+ */
114
+ protected resolveTemplate(): Promise<string>;
115
+ /**
116
+ * The default desktop template is E2B-hosted — there is nothing to build.
117
+ * (Only reached from the template-not-found retry path in `start()`.)
118
+ */
119
+ protected buildDefaultTemplate(): Promise<string>;
120
+ /** Ensure the sandbox is running, then run a desktop SDK operation. */
121
+ private withDesktop;
122
+ /**
123
+ * Ensure the VNC stream is running (authenticated), memoized per SDK
124
+ * sandbox so a resumed/recreated VM restarts it. A stream already started
125
+ * externally (via the `desktop` escape hatch) is left untouched.
126
+ */
127
+ private ensureStreamStarted;
128
+ }
129
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sandbox/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEnF,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AAapE;;;;;;;GAOG;AACH,MAAM,WAAW,wBAAyB,SAAQ,iBAAiB;IACjE;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,qBAAa,iBAAkB,SAAQ,UAAU;IAC/C,SAAkB,IAAI,EAAE,MAAM,CAAuB;IACrD,SAAkB,QAAQ,EAAE,MAAM,CAAiB;IAEnD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAmB;IAC/C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAA2B;IAEtE,8EAA8E;IAC9E,OAAO,CAAC,cAAc,CAA8D;gBAExE,OAAO,GAAE,wBAA6B;IAOlD;;;;OAIG;IACH,SAAkB,QAAQ,EAAE,eAAe,CAkDzC;IAEF;;;;;;;;;;;;;OAaG;IACH,IAAI,OAAO,IAAI,oBAAoB,CAMlC;IAED;;;OAGG;IACM,KAAK,CAAC,OAAO,GAAE,mBAAwB,GAAG,iBAAiB;IAcpE,0EAA0E;cACjD,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAQlG,yDAAyD;cAChC,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IAQzG;;;;OAIG;cACsB,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;IAW3D;;;OAGG;cACsB,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;IAShE,uEAAuE;YACzD,WAAW;IAKzB;;;;OAIG;YACW,mBAAmB;CAalC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/e2b-desktop",
3
- "version": "0.0.0",
3
+ "version": "0.1.0-alpha.0",
4
4
  "description": "E2B Desktop (computer-use) sandbox provider for Mastra workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -18,36 +18,25 @@
18
18
  },
19
19
  "./package.json": "./package.json"
20
20
  },
21
- "scripts": {
22
- "build": "tsdown --silent --config tsdown.config.ts",
23
- "build:lib": "pnpm build",
24
- "build:watch": "pnpm build --watch",
25
- "test:unit": "vitest run --exclude '**/*.integration.test.ts'",
26
- "test:watch": "vitest watch",
27
- "test": "vitest run ./src/**/*.integration.test.ts",
28
- "test:cloud": "pnpm test",
29
- "lint": "oxlint . && eslint .",
30
- "lint:fix": "oxlint --fix . && eslint --fix ."
31
- },
32
21
  "license": "Apache-2.0",
33
22
  "dependencies": {
34
23
  "@e2b/desktop": "^2.3.1",
35
- "@mastra/e2b": "workspace:^",
36
- "e2b": "^2.36.0"
24
+ "e2b": "^2.36.0",
25
+ "@mastra/e2b": "^0.10.0-alpha.5"
37
26
  },
38
27
  "devDependencies": {
39
- "@internal/lint": "workspace:*",
40
- "@internal/types-builder": "workspace:*",
41
- "@internal/workspace-test-utils": "workspace:*",
42
- "@mastra/core": "workspace:*",
43
28
  "@types/node": "22.20.1",
44
- "@vitest/coverage-v8": "catalog:",
45
- "@vitest/ui": "catalog:",
29
+ "@vitest/coverage-v8": "4.1.10",
30
+ "@vitest/ui": "4.1.10",
46
31
  "dotenv": "^17.4.2",
47
32
  "eslint": "^10.7.0",
48
33
  "tsdown": "0.22.9",
49
- "typescript": "catalog:",
50
- "vitest": "catalog:"
34
+ "typescript": "^6.0.3",
35
+ "vitest": "4.1.10",
36
+ "@internal/types-builder": "0.0.100",
37
+ "@internal/lint": "0.0.125",
38
+ "@internal/workspace-test-utils": "0.0.69",
39
+ "@mastra/core": "1.62.0-alpha.12"
51
40
  },
52
41
  "peerDependencies": {
53
42
  "@mastra/core": ">=1.60.0-0 <2.0.0-0"
@@ -67,5 +56,16 @@
67
56
  },
68
57
  "engines": {
69
58
  "node": ">=22.13.0"
59
+ },
60
+ "scripts": {
61
+ "build": "tsdown --silent --config tsdown.config.ts",
62
+ "build:lib": "pnpm build",
63
+ "build:watch": "pnpm build --watch",
64
+ "test:unit": "vitest run --exclude '**/*.integration.test.ts'",
65
+ "test:watch": "vitest watch",
66
+ "test": "vitest run ./src/**/*.integration.test.ts",
67
+ "test:cloud": "pnpm test",
68
+ "lint": "oxlint . && eslint .",
69
+ "lint:fix": "oxlint --fix . && eslint --fix ."
70
70
  }
71
- }
71
+ }