computesdk 1.0.2 → 1.1.1

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/dist/index.mjs CHANGED
@@ -1,494 +1,965 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
- // src/errors.ts
9
- var ComputeError = class extends Error {
1
+ // src/sandbox.ts
2
+ var SandboxManager = class {
10
3
  /**
11
- * Create a new ComputeError
12
- *
13
- * @param message Error message
14
- * @param provider Provider identifier
15
- * @param sandboxId Optional sandbox identifier
4
+ * Create a sandbox from a provider
16
5
  */
17
- constructor(message, provider, sandboxId) {
18
- super(message);
19
- this.name = this.constructor.name;
20
- this.provider = provider;
21
- this.sandboxId = sandboxId;
22
- Object.setPrototypeOf(this, new.target.prototype);
6
+ async create(provider, options) {
7
+ return await provider.sandbox.create(options);
23
8
  }
24
- };
25
- var ExecutionError = class extends ComputeError {
26
9
  /**
27
- * Create a new ExecutionError
28
- *
29
- * @param message Error message
30
- * @param provider Provider identifier
31
- * @param exitCode Exit code from the execution
32
- * @param sandboxId Optional sandbox identifier
10
+ * Get an existing sandbox by ID from a provider
33
11
  */
34
- constructor(message, provider, exitCode, sandboxId) {
35
- super(message, provider, sandboxId);
36
- /** Error code */
37
- this.code = "EXECUTION_ERROR";
38
- /** Execution errors are generally not retryable */
39
- this.isRetryable = false;
40
- this.exitCode = exitCode;
12
+ async getById(provider, sandboxId) {
13
+ return await provider.sandbox.getById(sandboxId);
41
14
  }
42
- };
43
- var TimeoutError = class extends ComputeError {
44
15
  /**
45
- * Create a new TimeoutError
46
- *
47
- * @param message Error message
48
- * @param provider Provider identifier
49
- * @param timeoutMs Timeout duration in milliseconds
50
- * @param sandboxId Optional sandbox identifier
16
+ * List all active sandboxes from a provider
51
17
  */
52
- constructor(message, provider, timeoutMs, sandboxId) {
53
- super(message, provider, sandboxId);
54
- /** Error code */
55
- this.code = "TIMEOUT_ERROR";
56
- /** Timeout errors may be retryable with a longer timeout */
57
- this.isRetryable = true;
58
- this.timeoutMs = timeoutMs;
18
+ async list(provider) {
19
+ return await provider.sandbox.list();
59
20
  }
60
- };
61
- var ProviderError = class extends ComputeError {
62
21
  /**
63
- * Create a new ProviderError
64
- *
65
- * @param message Error message
66
- * @param provider Provider identifier
67
- * @param originalError Optional original error from the provider
68
- * @param sandboxId Optional sandbox identifier
22
+ * Destroy a sandbox via a provider
69
23
  */
70
- constructor(message, provider, originalError, sandboxId) {
71
- super(message, provider, sandboxId);
72
- /** Error code */
73
- this.code = "PROVIDER_ERROR";
74
- /** Provider errors may be retryable */
75
- this.isRetryable = true;
76
- this.originalError = originalError;
24
+ async destroy(provider, sandboxId) {
25
+ return await provider.sandbox.destroy(sandboxId);
77
26
  }
78
27
  };
79
- var ConfigurationError = class extends ComputeError {
28
+
29
+ // src/compute.ts
30
+ var ComputeManager = class {
31
+ constructor() {
32
+ this.sandboxManager = new SandboxManager();
33
+ this.config = null;
34
+ this.sandbox = {
35
+ /**
36
+ * Create a sandbox from a provider (or default provider if configured)
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * import { e2b } from '@computesdk/e2b'
41
+ * import { compute } from 'computesdk'
42
+ *
43
+ * // With explicit provider
44
+ * const sandbox = await compute.sandbox.create({
45
+ * provider: e2b({ apiKey: 'your-key' })
46
+ * })
47
+ *
48
+ * // With default provider (both forms work)
49
+ * compute.setConfig({ provider: e2b({ apiKey: 'your-key' }) })
50
+ * const sandbox1 = await compute.sandbox.create({})
51
+ * const sandbox2 = await compute.sandbox.create()
52
+ * ```
53
+ */
54
+ create: async (params) => {
55
+ const provider = params && "provider" in params && params.provider ? params.provider : this.getDefaultProvider();
56
+ const options = params?.options;
57
+ return await this.sandboxManager.create(provider, options);
58
+ },
59
+ /**
60
+ * Get an existing sandbox by ID from a provider (or default provider if configured)
61
+ */
62
+ getById: async (providerOrSandboxId, sandboxId) => {
63
+ if (typeof providerOrSandboxId === "string") {
64
+ const provider = this.getDefaultProvider();
65
+ return await this.sandboxManager.getById(provider, providerOrSandboxId);
66
+ } else {
67
+ if (!sandboxId) {
68
+ throw new Error("sandboxId is required when provider is specified");
69
+ }
70
+ return await this.sandboxManager.getById(providerOrSandboxId, sandboxId);
71
+ }
72
+ },
73
+ /**
74
+ * List all active sandboxes from a provider (or default provider if configured)
75
+ */
76
+ list: async (provider) => {
77
+ const actualProvider = provider || this.getDefaultProvider();
78
+ return await this.sandboxManager.list(actualProvider);
79
+ },
80
+ /**
81
+ * Destroy a sandbox via a provider (or default provider if configured)
82
+ */
83
+ destroy: async (providerOrSandboxId, sandboxId) => {
84
+ if (typeof providerOrSandboxId === "string") {
85
+ const provider = this.getDefaultProvider();
86
+ return await this.sandboxManager.destroy(provider, providerOrSandboxId);
87
+ } else {
88
+ if (!sandboxId) {
89
+ throw new Error("sandboxId is required when provider is specified");
90
+ }
91
+ return await this.sandboxManager.destroy(providerOrSandboxId, sandboxId);
92
+ }
93
+ }
94
+ };
95
+ }
80
96
  /**
81
- * Create a new ConfigurationError
82
- *
83
- * @param message Error message
84
- * @param provider Provider identifier
85
- * @param sandboxId Optional sandbox identifier
97
+ * Set default configuration
86
98
  */
87
- constructor(message, provider, sandboxId) {
88
- super(message, provider, sandboxId);
89
- /** Error code */
90
- this.code = "CONFIGURATION_ERROR";
91
- /** Configuration errors are not retryable without changes */
92
- this.isRetryable = false;
99
+ setConfig(config) {
100
+ this.config = config;
93
101
  }
94
- };
95
- var AuthenticationError = class extends ComputeError {
96
102
  /**
97
- * Create a new AuthenticationError
98
- *
99
- * @param message Error message
100
- * @param provider Provider identifier
101
- * @param sandboxId Optional sandbox identifier
103
+ * Get current configuration
102
104
  */
103
- constructor(message, provider, sandboxId) {
104
- super(message, provider, sandboxId);
105
- /** Error code */
106
- this.code = "AUTHENTICATION_ERROR";
107
- /** Authentication errors are not retryable without new credentials */
108
- this.isRetryable = false;
105
+ getConfig() {
106
+ return this.config;
107
+ }
108
+ /**
109
+ * Clear current configuration
110
+ */
111
+ clearConfig() {
112
+ this.config = null;
109
113
  }
110
- };
111
- var ProviderUnavailableError = class extends ComputeError {
112
114
  /**
113
- * Create a new ProviderUnavailableError
114
- *
115
- * @param message Error message
116
- * @param provider Provider identifier
117
- * @param sandboxId Optional sandbox identifier
115
+ * Get the default provider, throwing if not configured
118
116
  */
119
- constructor(message, provider, sandboxId) {
120
- super(message, provider, sandboxId);
121
- /** Error code */
122
- this.code = "PROVIDER_UNAVAILABLE";
123
- /** Provider unavailability may be temporary */
124
- this.isRetryable = true;
117
+ getDefaultProvider() {
118
+ if (!this.config?.provider) {
119
+ throw new Error(
120
+ "No default provider configured. Either call compute.setConfig({ provider }) or pass provider explicitly."
121
+ );
122
+ }
123
+ return this.config.provider;
124
+ }
125
+ // Future: compute.blob.*, compute.database.*, compute.git.* will be added here
126
+ // blob = new BlobManager();
127
+ // database = new DatabaseManager();
128
+ // git = new GitManager();
129
+ /**
130
+ * Get the sandbox manager (useful for testing)
131
+ */
132
+ getSandboxManager() {
133
+ return this.sandboxManager;
125
134
  }
126
135
  };
136
+ var compute = new ComputeManager();
127
137
 
128
- // src/config.ts
129
- var DEFAULT_TIMEOUT = 3e5;
130
- var ENV_KEYS = {
131
- E2B: "E2B_API_KEY",
132
- VERCEL: "VERCEL_TOKEN",
133
- CLOUDFLARE: "CLOUDFLARE_API_TOKEN",
134
- FLY: "FLY_API_TOKEN"
135
- };
136
- function isCloudflareWorkers() {
137
- return typeof DurableObject !== "undefined" && typeof WebSocketPair !== "undefined" && typeof caches !== "undefined";
138
+ // src/request-handler.ts
139
+ async function handleComputeRequest(params) {
140
+ const { request, provider } = params;
141
+ try {
142
+ const getSandbox = async (sandboxId) => {
143
+ if (sandboxId) {
144
+ const existingSandbox = await compute.sandbox.getById(provider, sandboxId);
145
+ if (!existingSandbox) {
146
+ throw new Error(`Sandbox with ID ${sandboxId} not found`);
147
+ }
148
+ return existingSandbox;
149
+ } else {
150
+ return await compute.sandbox.create({
151
+ provider,
152
+ options: request.options || { runtime: "python" }
153
+ });
154
+ }
155
+ };
156
+ switch (request.action) {
157
+ // Sandbox operations
158
+ case "compute.sandbox.create": {
159
+ const sandbox = await compute.sandbox.create({
160
+ provider,
161
+ options: request.options || { runtime: "python" }
162
+ });
163
+ return {
164
+ success: true,
165
+ sandboxId: sandbox.sandboxId,
166
+ provider: provider.name
167
+ };
168
+ }
169
+ case "compute.sandbox.destroy": {
170
+ if (!request.sandboxId) {
171
+ return {
172
+ success: false,
173
+ error: "Sandbox ID is required for destroy action",
174
+ sandboxId: "",
175
+ provider: provider.name
176
+ };
177
+ }
178
+ await compute.sandbox.destroy(provider, request.sandboxId);
179
+ return {
180
+ success: true,
181
+ sandboxId: request.sandboxId,
182
+ provider: provider.name
183
+ };
184
+ }
185
+ case "compute.sandbox.getInfo": {
186
+ if (!request.sandboxId) {
187
+ return {
188
+ success: false,
189
+ error: "Sandbox ID is required for getInfo action",
190
+ sandboxId: "",
191
+ provider: provider.name
192
+ };
193
+ }
194
+ const sandbox = await getSandbox(request.sandboxId);
195
+ const info = await sandbox.getInfo();
196
+ return {
197
+ success: true,
198
+ sandboxId: request.sandboxId,
199
+ provider: provider.name,
200
+ info: {
201
+ id: info.id,
202
+ provider: info.provider,
203
+ runtime: info.runtime,
204
+ status: info.status,
205
+ createdAt: info.createdAt.toISOString(),
206
+ timeout: info.timeout,
207
+ metadata: info.metadata
208
+ }
209
+ };
210
+ }
211
+ case "compute.sandbox.list": {
212
+ const sandboxes = await compute.sandbox.list(provider);
213
+ return {
214
+ success: true,
215
+ sandboxId: "",
216
+ provider: provider.name,
217
+ sandboxes: sandboxes.map((sandbox) => ({
218
+ sandboxId: sandbox.sandboxId,
219
+ provider: sandbox.provider
220
+ }))
221
+ };
222
+ }
223
+ // Code execution
224
+ case "compute.sandbox.runCode": {
225
+ if (!request.code) {
226
+ return {
227
+ success: false,
228
+ error: "Code is required for runCode action",
229
+ sandboxId: request.sandboxId || "",
230
+ provider: provider.name
231
+ };
232
+ }
233
+ const sandbox = await getSandbox(request.sandboxId);
234
+ const result = await sandbox.runCode(request.code, request.runtime);
235
+ return {
236
+ success: true,
237
+ sandboxId: sandbox.sandboxId,
238
+ provider: provider.name,
239
+ result: {
240
+ stdout: result.stdout,
241
+ stderr: result.stderr,
242
+ exitCode: result.exitCode,
243
+ executionTime: result.executionTime
244
+ }
245
+ };
246
+ }
247
+ case "compute.sandbox.runCommand": {
248
+ if (!request.command) {
249
+ return {
250
+ success: false,
251
+ error: "Command is required for runCommand action",
252
+ sandboxId: request.sandboxId || "",
253
+ provider: provider.name
254
+ };
255
+ }
256
+ const sandbox = await getSandbox(request.sandboxId);
257
+ const result = await sandbox.runCommand(request.command, request.args);
258
+ return {
259
+ success: true,
260
+ sandboxId: sandbox.sandboxId,
261
+ provider: provider.name,
262
+ result: {
263
+ stdout: result.stdout,
264
+ stderr: result.stderr,
265
+ exitCode: result.exitCode,
266
+ executionTime: result.executionTime
267
+ }
268
+ };
269
+ }
270
+ // Filesystem operations
271
+ case "compute.sandbox.filesystem.readFile": {
272
+ if (!request.sandboxId) {
273
+ return {
274
+ success: false,
275
+ error: "Sandbox ID is required for filesystem operations",
276
+ sandboxId: "",
277
+ provider: provider.name
278
+ };
279
+ }
280
+ if (!request.path) {
281
+ return {
282
+ success: false,
283
+ error: "File path is required for readFile action",
284
+ sandboxId: request.sandboxId,
285
+ provider: provider.name
286
+ };
287
+ }
288
+ const sandbox = await getSandbox(request.sandboxId);
289
+ const content = await sandbox.filesystem.readFile(request.path);
290
+ return {
291
+ success: true,
292
+ sandboxId: request.sandboxId,
293
+ provider: provider.name,
294
+ fileContent: content
295
+ };
296
+ }
297
+ case "compute.sandbox.filesystem.writeFile": {
298
+ if (!request.sandboxId) {
299
+ return {
300
+ success: false,
301
+ error: "Sandbox ID is required for filesystem operations",
302
+ sandboxId: "",
303
+ provider: provider.name
304
+ };
305
+ }
306
+ if (!request.path) {
307
+ return {
308
+ success: false,
309
+ error: "File path is required for writeFile action",
310
+ sandboxId: request.sandboxId,
311
+ provider: provider.name
312
+ };
313
+ }
314
+ if (request.content === void 0) {
315
+ return {
316
+ success: false,
317
+ error: "File content is required for writeFile action",
318
+ sandboxId: request.sandboxId,
319
+ provider: provider.name
320
+ };
321
+ }
322
+ const sandbox = await getSandbox(request.sandboxId);
323
+ await sandbox.filesystem.writeFile(request.path, request.content);
324
+ return {
325
+ success: true,
326
+ sandboxId: request.sandboxId,
327
+ provider: provider.name
328
+ };
329
+ }
330
+ case "compute.sandbox.filesystem.mkdir": {
331
+ if (!request.sandboxId) {
332
+ return {
333
+ success: false,
334
+ error: "Sandbox ID is required for filesystem operations",
335
+ sandboxId: "",
336
+ provider: provider.name
337
+ };
338
+ }
339
+ if (!request.path) {
340
+ return {
341
+ success: false,
342
+ error: "Directory path is required for mkdir action",
343
+ sandboxId: request.sandboxId,
344
+ provider: provider.name
345
+ };
346
+ }
347
+ const sandbox = await getSandbox(request.sandboxId);
348
+ await sandbox.filesystem.mkdir(request.path);
349
+ return {
350
+ success: true,
351
+ sandboxId: request.sandboxId,
352
+ provider: provider.name
353
+ };
354
+ }
355
+ case "compute.sandbox.filesystem.readdir": {
356
+ if (!request.sandboxId) {
357
+ return {
358
+ success: false,
359
+ error: "Sandbox ID is required for filesystem operations",
360
+ sandboxId: "",
361
+ provider: provider.name
362
+ };
363
+ }
364
+ if (!request.path) {
365
+ return {
366
+ success: false,
367
+ error: "Directory path is required for readdir action",
368
+ sandboxId: request.sandboxId,
369
+ provider: provider.name
370
+ };
371
+ }
372
+ const sandbox = await getSandbox(request.sandboxId);
373
+ const entries = await sandbox.filesystem.readdir(request.path);
374
+ return {
375
+ success: true,
376
+ sandboxId: request.sandboxId,
377
+ provider: provider.name,
378
+ files: entries.map((entry) => ({
379
+ name: entry.name,
380
+ path: entry.path,
381
+ isDirectory: entry.isDirectory,
382
+ size: entry.size,
383
+ lastModified: entry.lastModified.toISOString()
384
+ }))
385
+ };
386
+ }
387
+ case "compute.sandbox.filesystem.exists": {
388
+ if (!request.sandboxId) {
389
+ return {
390
+ success: false,
391
+ error: "Sandbox ID is required for filesystem operations",
392
+ sandboxId: "",
393
+ provider: provider.name
394
+ };
395
+ }
396
+ if (!request.path) {
397
+ return {
398
+ success: false,
399
+ error: "Path is required for exists action",
400
+ sandboxId: request.sandboxId,
401
+ provider: provider.name
402
+ };
403
+ }
404
+ const sandbox = await getSandbox(request.sandboxId);
405
+ const exists = await sandbox.filesystem.exists(request.path);
406
+ return {
407
+ success: true,
408
+ sandboxId: request.sandboxId,
409
+ provider: provider.name,
410
+ exists
411
+ };
412
+ }
413
+ case "compute.sandbox.filesystem.remove": {
414
+ if (!request.sandboxId) {
415
+ return {
416
+ success: false,
417
+ error: "Sandbox ID is required for filesystem operations",
418
+ sandboxId: "",
419
+ provider: provider.name
420
+ };
421
+ }
422
+ if (!request.path) {
423
+ return {
424
+ success: false,
425
+ error: "Path is required for remove action",
426
+ sandboxId: request.sandboxId,
427
+ provider: provider.name
428
+ };
429
+ }
430
+ const sandbox = await getSandbox(request.sandboxId);
431
+ await sandbox.filesystem.remove(request.path);
432
+ return {
433
+ success: true,
434
+ sandboxId: request.sandboxId,
435
+ provider: provider.name
436
+ };
437
+ }
438
+ // Terminal operations
439
+ case "compute.sandbox.terminal.create": {
440
+ if (!request.sandboxId) {
441
+ return {
442
+ success: false,
443
+ error: "Sandbox ID is required for terminal operations",
444
+ sandboxId: "",
445
+ provider: provider.name
446
+ };
447
+ }
448
+ const sandbox = await getSandbox(request.sandboxId);
449
+ const terminal = await sandbox.terminal.create(request.terminalOptions);
450
+ return {
451
+ success: true,
452
+ sandboxId: request.sandboxId,
453
+ provider: provider.name,
454
+ terminal: {
455
+ pid: terminal.pid,
456
+ command: terminal.command,
457
+ status: terminal.status,
458
+ cols: terminal.cols,
459
+ rows: terminal.rows
460
+ }
461
+ };
462
+ }
463
+ case "compute.sandbox.terminal.list": {
464
+ if (!request.sandboxId) {
465
+ return {
466
+ success: false,
467
+ error: "Sandbox ID is required for terminal operations",
468
+ sandboxId: "",
469
+ provider: provider.name
470
+ };
471
+ }
472
+ const sandbox = await getSandbox(request.sandboxId);
473
+ const terminals = await sandbox.terminal.list();
474
+ return {
475
+ success: true,
476
+ sandboxId: request.sandboxId,
477
+ provider: provider.name,
478
+ terminals: terminals.map((terminal) => ({
479
+ pid: terminal.pid,
480
+ command: terminal.command,
481
+ status: terminal.status,
482
+ cols: terminal.cols,
483
+ rows: terminal.rows
484
+ }))
485
+ };
486
+ }
487
+ case "compute.sandbox.terminal.getById": {
488
+ if (!request.sandboxId) {
489
+ return {
490
+ success: false,
491
+ error: "Sandbox ID is required for terminal operations",
492
+ sandboxId: "",
493
+ provider: provider.name
494
+ };
495
+ }
496
+ if (!request.terminalId) {
497
+ return {
498
+ success: false,
499
+ error: "Terminal ID is required for getById action",
500
+ sandboxId: request.sandboxId,
501
+ provider: provider.name
502
+ };
503
+ }
504
+ const sandbox = await getSandbox(request.sandboxId);
505
+ const terminal = await sandbox.terminal.getById(request.terminalId);
506
+ if (!terminal) {
507
+ return {
508
+ success: false,
509
+ error: `Terminal with ID ${request.terminalId} not found`,
510
+ sandboxId: request.sandboxId,
511
+ provider: provider.name
512
+ };
513
+ }
514
+ return {
515
+ success: true,
516
+ sandboxId: request.sandboxId,
517
+ provider: provider.name,
518
+ terminal: {
519
+ pid: terminal.pid,
520
+ command: terminal.command,
521
+ status: terminal.status,
522
+ cols: terminal.cols,
523
+ rows: terminal.rows
524
+ }
525
+ };
526
+ }
527
+ case "compute.sandbox.terminal.destroy": {
528
+ if (!request.sandboxId) {
529
+ return {
530
+ success: false,
531
+ error: "Sandbox ID is required for terminal operations",
532
+ sandboxId: "",
533
+ provider: provider.name
534
+ };
535
+ }
536
+ if (!request.terminalId) {
537
+ return {
538
+ success: false,
539
+ error: "Terminal ID is required for destroy action",
540
+ sandboxId: request.sandboxId,
541
+ provider: provider.name
542
+ };
543
+ }
544
+ const sandbox = await getSandbox(request.sandboxId);
545
+ await sandbox.terminal.destroy(request.terminalId);
546
+ return {
547
+ success: true,
548
+ sandboxId: request.sandboxId,
549
+ provider: provider.name
550
+ };
551
+ }
552
+ // Terminal I/O operations
553
+ case "compute.sandbox.terminal.write": {
554
+ if (!request.sandboxId) {
555
+ return {
556
+ success: false,
557
+ error: "Sandbox ID is required for terminal operations",
558
+ sandboxId: "",
559
+ provider: provider.name
560
+ };
561
+ }
562
+ if (!request.terminalId) {
563
+ return {
564
+ success: false,
565
+ error: "Terminal ID is required for write action",
566
+ sandboxId: request.sandboxId,
567
+ provider: provider.name
568
+ };
569
+ }
570
+ if (!request.data) {
571
+ return {
572
+ success: false,
573
+ error: "Data is required for write action",
574
+ sandboxId: request.sandboxId,
575
+ provider: provider.name
576
+ };
577
+ }
578
+ const sandbox = await getSandbox(request.sandboxId);
579
+ const terminal = await sandbox.terminal.getById(request.terminalId);
580
+ if (!terminal) {
581
+ return {
582
+ success: false,
583
+ error: `Terminal with ID ${request.terminalId} not found`,
584
+ sandboxId: request.sandboxId,
585
+ provider: provider.name
586
+ };
587
+ }
588
+ await terminal.write(request.data);
589
+ return {
590
+ success: true,
591
+ sandboxId: request.sandboxId,
592
+ provider: provider.name
593
+ };
594
+ }
595
+ case "compute.sandbox.terminal.resize": {
596
+ if (!request.sandboxId) {
597
+ return {
598
+ success: false,
599
+ error: "Sandbox ID is required for terminal operations",
600
+ sandboxId: "",
601
+ provider: provider.name
602
+ };
603
+ }
604
+ if (!request.terminalId) {
605
+ return {
606
+ success: false,
607
+ error: "Terminal ID is required for resize action",
608
+ sandboxId: request.sandboxId,
609
+ provider: provider.name
610
+ };
611
+ }
612
+ if (!request.cols || !request.rows) {
613
+ return {
614
+ success: false,
615
+ error: "Cols and rows are required for resize action",
616
+ sandboxId: request.sandboxId,
617
+ provider: provider.name
618
+ };
619
+ }
620
+ const sandbox = await getSandbox(request.sandboxId);
621
+ const terminal = await sandbox.terminal.getById(request.terminalId);
622
+ if (!terminal) {
623
+ return {
624
+ success: false,
625
+ error: `Terminal with ID ${request.terminalId} not found`,
626
+ sandboxId: request.sandboxId,
627
+ provider: provider.name
628
+ };
629
+ }
630
+ await terminal.resize(request.cols, request.rows);
631
+ return {
632
+ success: true,
633
+ sandboxId: request.sandboxId,
634
+ provider: provider.name
635
+ };
636
+ }
637
+ case "compute.sandbox.terminal.kill": {
638
+ if (!request.sandboxId) {
639
+ return {
640
+ success: false,
641
+ error: "Sandbox ID is required for terminal operations",
642
+ sandboxId: "",
643
+ provider: provider.name
644
+ };
645
+ }
646
+ if (!request.terminalId) {
647
+ return {
648
+ success: false,
649
+ error: "Terminal ID is required for kill action",
650
+ sandboxId: request.sandboxId,
651
+ provider: provider.name
652
+ };
653
+ }
654
+ const sandbox = await getSandbox(request.sandboxId);
655
+ const terminal = await sandbox.terminal.getById(request.terminalId);
656
+ if (!terminal) {
657
+ return {
658
+ success: false,
659
+ error: `Terminal with ID ${request.terminalId} not found`,
660
+ sandboxId: request.sandboxId,
661
+ provider: provider.name
662
+ };
663
+ }
664
+ await terminal.kill();
665
+ return {
666
+ success: true,
667
+ sandboxId: request.sandboxId,
668
+ provider: provider.name
669
+ };
670
+ }
671
+ default:
672
+ return {
673
+ success: false,
674
+ error: `Unknown action: ${request.action}`,
675
+ sandboxId: request.sandboxId || "",
676
+ provider: provider.name
677
+ };
678
+ }
679
+ } catch (error) {
680
+ return {
681
+ success: false,
682
+ error: error instanceof Error ? error.message : "Unknown error occurred",
683
+ sandboxId: request.sandboxId || "",
684
+ provider: provider.name
685
+ };
686
+ }
138
687
  }
139
- function detectAvailableProviders() {
140
- const available = [];
141
- if (process.env[ENV_KEYS.E2B]) {
142
- available.push("e2b");
688
+
689
+ // src/factory.ts
690
+ var UnsupportedFileSystem = class {
691
+ constructor(providerName) {
692
+ this.providerName = providerName;
143
693
  }
144
- if (process.env[ENV_KEYS.VERCEL]) {
145
- available.push("vercel");
694
+ async readFile(_path) {
695
+ throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
146
696
  }
147
- if (isCloudflareWorkers() || process.env[ENV_KEYS.CLOUDFLARE]) {
148
- available.push("cloudflare");
697
+ async writeFile(_path, _content) {
698
+ throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
149
699
  }
150
- if (process.env[ENV_KEYS.FLY]) {
151
- available.push("fly");
700
+ async mkdir(_path) {
701
+ throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
152
702
  }
153
- return available;
154
- }
155
- function autoSelectProvider() {
156
- const available = detectAvailableProviders();
157
- return available.length > 0 ? available[0] : void 0;
158
- }
159
- function normalizeContainerConfig(container) {
160
- if (!container) {
161
- return void 0;
703
+ async readdir(_path) {
704
+ throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
162
705
  }
163
- if (typeof container === "string") {
164
- return { image: container };
706
+ async exists(_path) {
707
+ throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
165
708
  }
166
- if (!container.image) {
167
- throw new ConfigurationError("Container configuration must include an image", "config");
709
+ async remove(_path) {
710
+ throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
168
711
  }
169
- return container;
170
- }
171
- function getDefaultRuntime(provider, runtime) {
172
- if (runtime) {
173
- return runtime;
174
- }
175
- switch (provider) {
176
- case "e2b":
177
- return "python";
178
- case "vercel":
179
- return "node";
180
- case "cloudflare":
181
- case "fly":
182
- throw new ConfigurationError(
183
- `Container-based provider '${provider}' requires explicit runtime or container configuration`,
184
- provider
185
- );
186
- default:
187
- return "node";
712
+ };
713
+ var UnsupportedTerminal = class {
714
+ constructor(providerName) {
715
+ this.providerName = providerName;
188
716
  }
189
- }
190
- function validateProviderApiKey(provider) {
191
- let envKey;
192
- switch (provider) {
193
- case "e2b":
194
- envKey = ENV_KEYS.E2B;
195
- break;
196
- case "vercel":
197
- envKey = ENV_KEYS.VERCEL;
198
- break;
199
- case "cloudflare":
200
- if (isCloudflareWorkers()) {
201
- return;
202
- }
203
- envKey = ENV_KEYS.CLOUDFLARE;
204
- break;
205
- case "fly":
206
- envKey = ENV_KEYS.FLY;
207
- break;
208
- case "auto":
209
- return;
210
- // Will be handled by auto-selection
211
- default:
212
- throw new ConfigurationError(`Unknown provider: ${provider}`, "config");
213
- }
214
- if (!process.env[envKey]) {
215
- const available = detectAvailableProviders();
216
- const suggestions = available.length > 0 ? `Available providers: ${available.join(", ")}` : `No provider API keys found. Set ${Object.values(ENV_KEYS).join(" or ")} environment variables.`;
217
- throw new ConfigurationError(
218
- `Missing API key for provider '${provider}'. ${suggestions}`,
219
- provider
220
- );
717
+ async create(_options) {
718
+ throw new Error(`Terminal operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
221
719
  }
222
- }
223
- function normalizeSandboxConfig(config) {
224
- const normalized = {
225
- provider: config?.provider || "auto",
226
- timeout: config?.timeout || DEFAULT_TIMEOUT
227
- };
228
- if (normalized.provider === "auto") {
229
- const autoProvider = autoSelectProvider();
230
- if (!autoProvider) {
231
- throw new ConfigurationError(
232
- `No provider API keys found. Set one of the following environment variables: ${Object.values(ENV_KEYS).join(", ")}`,
233
- "config"
234
- );
235
- }
236
- normalized.provider = autoProvider;
237
- } else {
238
- validateProviderApiKey(normalized.provider);
720
+ async getById(_terminalId) {
721
+ throw new Error(`Terminal operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
239
722
  }
240
- if (config?.runtime) {
241
- normalized.runtime = config.runtime;
242
- } else if (!config?.container) {
243
- normalized.runtime = getDefaultRuntime(normalized.provider);
723
+ async list() {
724
+ throw new Error(`Terminal operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
244
725
  }
245
- if (config?.container) {
246
- normalized.container = normalizeContainerConfig(config.container);
726
+ async destroy(_terminalId) {
727
+ throw new Error(`Terminal operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
247
728
  }
248
- return normalized;
249
- }
250
-
251
- // src/utils.ts
252
- async function executeSandbox(params) {
253
- return await params.sandbox.execute(params.code, params.runtime);
254
- }
255
- async function retry(fn, maxRetries = 3, baseDelay = 1e3) {
256
- let lastError;
257
- for (let i = 0; i < maxRetries; i++) {
258
- try {
259
- return await fn();
260
- } catch (error) {
261
- lastError = error instanceof Error ? error : new Error(String(error));
262
- if (i === maxRetries - 1) {
263
- throw lastError;
729
+ };
730
+ var SupportedFileSystem = class {
731
+ constructor(sandbox, methods) {
732
+ this.sandbox = sandbox;
733
+ this.methods = methods;
734
+ }
735
+ async readFile(path) {
736
+ return this.methods.readFile(this.sandbox, path);
737
+ }
738
+ async writeFile(path, content) {
739
+ return this.methods.writeFile(this.sandbox, path, content);
740
+ }
741
+ async mkdir(path) {
742
+ return this.methods.mkdir(this.sandbox, path);
743
+ }
744
+ async readdir(path) {
745
+ return this.methods.readdir(this.sandbox, path);
746
+ }
747
+ async exists(path) {
748
+ return this.methods.exists(this.sandbox, path);
749
+ }
750
+ async remove(path) {
751
+ return this.methods.remove(this.sandbox, path);
752
+ }
753
+ };
754
+ var GeneratedTerminalSession = class {
755
+ constructor(terminal, sandbox, methods, terminalId, command, cols = 80, rows = 24) {
756
+ this.terminal = terminal;
757
+ this.sandbox = sandbox;
758
+ this.methods = methods;
759
+ this.pid = parseInt(terminalId);
760
+ this.command = command;
761
+ this.status = "running";
762
+ this.cols = cols;
763
+ this.rows = rows;
764
+ }
765
+ async write(data) {
766
+ return this.methods.write(this.sandbox, this.terminal, data);
767
+ }
768
+ async resize(cols, rows) {
769
+ return this.methods.resize(this.sandbox, this.terminal, cols, rows);
770
+ }
771
+ async kill() {
772
+ return this.methods.kill(this.sandbox, this.terminal);
773
+ }
774
+ };
775
+ var SupportedTerminal = class {
776
+ constructor(sandbox, methods) {
777
+ this.sandbox = sandbox;
778
+ this.methods = methods;
779
+ }
780
+ async create(options) {
781
+ let terminalSession;
782
+ const createOptions = {
783
+ ...options,
784
+ onData: (data) => {
785
+ if (terminalSession?.onData) {
786
+ terminalSession.onData(data);
787
+ }
788
+ },
789
+ onExit: (exitCode) => {
790
+ if (terminalSession?.onExit) {
791
+ terminalSession.onExit(exitCode);
792
+ }
264
793
  }
265
- const delay = baseDelay * Math.pow(2, i);
266
- await new Promise((resolve) => setTimeout(resolve, delay));
267
- }
794
+ };
795
+ const result = await this.methods.create(this.sandbox, createOptions);
796
+ terminalSession = new GeneratedTerminalSession(
797
+ result.terminal,
798
+ this.sandbox,
799
+ this.methods,
800
+ result.terminalId,
801
+ options?.command || "bash",
802
+ options?.cols || 80,
803
+ options?.rows || 24
804
+ );
805
+ terminalSession.onData = options?.onData;
806
+ terminalSession.onExit = options?.onExit;
807
+ return terminalSession;
268
808
  }
269
- throw lastError;
270
- }
271
-
272
- // src/registry.ts
273
- function createComputeRegistry(providers) {
274
- if (!providers || Object.keys(providers).length === 0) {
275
- throw new ConfigurationError("Provider registry requires at least one provider", "registry");
276
- }
277
- function sandbox(id) {
278
- const parts = id.split(":");
279
- if (parts.length < 1) {
280
- throw new ConfigurationError(`Invalid sandbox ID format: ${id}`, "registry");
281
- }
282
- const providerName = parts[0];
283
- const providerFactory = providers[providerName];
284
- if (!providerFactory) {
285
- const availableProviders = Object.keys(providers).join(", ");
286
- throw new ConfigurationError(
287
- `Provider '${providerName}' not found in registry. Available providers: ${availableProviders}`,
288
- "registry"
289
- );
809
+ async getById(terminalId) {
810
+ const result = await this.methods.getById(this.sandbox, terminalId);
811
+ if (!result) return null;
812
+ return new GeneratedTerminalSession(
813
+ result.terminal,
814
+ this.sandbox,
815
+ this.methods,
816
+ result.terminalId,
817
+ "bash",
818
+ // Default command for existing terminals
819
+ 80,
820
+ // Default cols
821
+ 24
822
+ // Default rows
823
+ );
824
+ }
825
+ async list() {
826
+ const results = await this.methods.list(this.sandbox);
827
+ return results.map((result) => new GeneratedTerminalSession(
828
+ result.terminal,
829
+ this.sandbox,
830
+ this.methods,
831
+ result.terminalId,
832
+ "bash",
833
+ // Default command
834
+ 80,
835
+ // Default cols
836
+ 24
837
+ // Default rows
838
+ ));
839
+ }
840
+ async destroy(terminalId) {
841
+ return this.methods.destroy(this.sandbox, terminalId);
842
+ }
843
+ };
844
+ var GeneratedSandbox = class {
845
+ constructor(sandbox, sandboxId, providerName, methods, config, destroyMethod) {
846
+ this.sandbox = sandbox;
847
+ this.methods = methods;
848
+ this.config = config;
849
+ this.destroyMethod = destroyMethod;
850
+ this.sandboxId = sandboxId;
851
+ this.provider = providerName;
852
+ if (methods.filesystem) {
853
+ this.filesystem = new SupportedFileSystem(sandbox, methods.filesystem);
854
+ } else {
855
+ this.filesystem = new UnsupportedFileSystem(providerName);
290
856
  }
291
- if (parts.length === 1) {
292
- return providerFactory();
293
- } else if (parts.length === 2) {
294
- const runtimeOrImage = parts[1];
295
- if (isRuntime(runtimeOrImage)) {
296
- return providerFactory({ runtime: runtimeOrImage });
297
- }
298
- return providerFactory({ container: { image: runtimeOrImage } });
857
+ if (methods.terminal) {
858
+ this.terminal = new SupportedTerminal(sandbox, methods.terminal);
299
859
  } else {
300
- const containerImage = parts.slice(1).join(":");
301
- return providerFactory({ container: { image: containerImage } });
860
+ this.terminal = new UnsupportedTerminal(providerName);
302
861
  }
303
862
  }
304
- return { sandbox };
305
- }
306
- function isRuntime(value) {
307
- return ["node", "python"].includes(value);
308
- }
309
-
310
- // src/providers/base.ts
311
- import { v4 as uuidv4 } from "uuid";
312
- var BaseProvider = class {
313
- /**
314
- * Create a new base provider
315
- *
316
- * @param provider Provider identifier
317
- * @param timeout Execution timeout in milliseconds
318
- */
319
- constructor(provider, timeout) {
320
- /** Specification version */
321
- this.specificationVersion = "v1";
322
- this.provider = provider;
323
- this.sandboxId = uuidv4();
324
- this.timeout = timeout;
863
+ async runCode(code, runtime) {
864
+ return await this.methods.runCode(this.sandbox, code, runtime, this.config);
325
865
  }
326
- /**
327
- * Execute code in the sandbox
328
- *
329
- * @param code Code to execute
330
- * @param runtime Optional runtime to use
331
- * @returns Execution result
332
- */
333
- async execute(code, runtime) {
334
- const startTime = Date.now();
335
- try {
336
- const timeoutPromise = new Promise((_, reject) => {
337
- setTimeout(() => {
338
- reject(new TimeoutError(
339
- `Execution timed out after ${this.timeout}ms`,
340
- this.provider,
341
- this.timeout,
342
- this.sandboxId
343
- ));
344
- }, this.timeout);
345
- });
346
- const result = await Promise.race([
347
- this.doExecute(code, runtime),
348
- timeoutPromise
349
- ]);
350
- const executionTime = Date.now() - startTime;
351
- return {
352
- ...result,
353
- executionTime,
354
- sandboxId: this.sandboxId,
355
- provider: this.provider
356
- };
357
- } catch (error) {
358
- if (error instanceof Error && error.name.includes("Error") && "code" in error) {
359
- throw error;
360
- }
361
- throw new ProviderError(
362
- `Execution failed: ${error instanceof Error ? error.message : String(error)}`,
363
- this.provider,
364
- error instanceof Error ? error : void 0,
365
- this.sandboxId
366
- );
367
- }
866
+ async runCommand(command, args) {
867
+ return await this.methods.runCommand(this.sandbox, command, args);
868
+ }
869
+ async getInfo() {
870
+ return await this.methods.getInfo(this.sandbox);
368
871
  }
369
- /**
370
- * Kill the sandbox
371
- *
372
- * @returns Promise that resolves when the sandbox is killed
373
- */
374
872
  async kill() {
375
- try {
376
- await this.doKill();
377
- } catch (error) {
378
- throw new ProviderError(
379
- `Failed to kill sandbox: ${error instanceof Error ? error.message : String(error)}`,
380
- this.provider,
381
- error instanceof Error ? error : void 0,
382
- this.sandboxId
383
- );
384
- }
873
+ await this.destroy();
385
874
  }
386
- /**
387
- * Get information about the sandbox
388
- *
389
- * @returns Sandbox information
390
- */
391
- async getInfo() {
392
- try {
393
- return await this.doGetInfo();
394
- } catch (error) {
395
- throw new ProviderError(
396
- `Failed to get sandbox info: ${error instanceof Error ? error.message : String(error)}`,
397
- this.provider,
398
- error instanceof Error ? error : void 0,
399
- this.sandboxId
400
- );
401
- }
875
+ async destroy() {
876
+ await this.destroyMethod(this.config, this.sandboxId);
402
877
  }
403
878
  };
404
-
405
- // src/sdk.ts
406
- var ComputeSDK = class {
407
- /**
408
- * Create a new sandbox with the specified configuration
409
- *
410
- * @param config Optional sandbox configuration
411
- * @returns Configured sandbox instance
412
- */
413
- static createSandbox(config) {
414
- const normalizedConfig = normalizeSandboxConfig(config);
415
- const providerName = normalizedConfig.provider;
416
- try {
417
- const providerPackage = `@computesdk/${providerName}`;
418
- const provider = __require(providerPackage);
419
- const factory = provider[providerName];
420
- if (!factory) {
421
- throw new ConfigurationError(
422
- `Provider package ${providerPackage} does not export a '${providerName}' function`,
423
- "sdk"
424
- );
425
- }
426
- if (providerName === "cloudflare") {
427
- throw new ConfigurationError(
428
- 'Cloudflare provider requires env parameter with Sandbox namespace. Use createSandbox({ provider: "cloudflare", env: yourEnv }) from within a Worker.',
429
- "sdk"
430
- );
431
- } else if (providerName === "fly") {
432
- if (!normalizedConfig.container) {
433
- throw new ConfigurationError(
434
- `${providerName} provider requires container configuration`,
435
- "sdk"
436
- );
437
- }
438
- return factory({ ...normalizedConfig, container: normalizedConfig.container });
439
- } else {
440
- return factory(normalizedConfig);
441
- }
442
- } catch (error) {
443
- if (error instanceof ConfigurationError) {
444
- throw error;
445
- }
446
- if (error.code === "MODULE_NOT_FOUND") {
447
- throw new ConfigurationError(
448
- `Provider '${providerName}' not installed. Run: npm install @computesdk/${providerName}`,
449
- "sdk"
879
+ var GeneratedSandboxManager = class {
880
+ constructor(config, providerName, methods) {
881
+ this.config = config;
882
+ this.providerName = providerName;
883
+ this.methods = methods;
884
+ this.activeSandboxes = /* @__PURE__ */ new Map();
885
+ }
886
+ async create(options) {
887
+ const result = await this.methods.create(this.config, options);
888
+ const sandbox = new GeneratedSandbox(
889
+ result.sandbox,
890
+ result.sandboxId,
891
+ this.providerName,
892
+ this.methods,
893
+ this.config,
894
+ this.methods.destroy
895
+ );
896
+ this.activeSandboxes.set(result.sandboxId, sandbox);
897
+ return sandbox;
898
+ }
899
+ async getById(sandboxId) {
900
+ const existing = this.activeSandboxes.get(sandboxId);
901
+ if (existing) {
902
+ return existing;
903
+ }
904
+ const result = await this.methods.getById(this.config, sandboxId);
905
+ if (!result) {
906
+ return null;
907
+ }
908
+ const sandbox = new GeneratedSandbox(
909
+ result.sandbox,
910
+ result.sandboxId,
911
+ this.providerName,
912
+ this.methods,
913
+ this.config,
914
+ this.methods.destroy
915
+ );
916
+ this.activeSandboxes.set(result.sandboxId, sandbox);
917
+ return sandbox;
918
+ }
919
+ async list() {
920
+ const results = await this.methods.list(this.config);
921
+ const sandboxes = [];
922
+ for (const result of results) {
923
+ let sandbox = this.activeSandboxes.get(result.sandboxId);
924
+ if (!sandbox) {
925
+ sandbox = new GeneratedSandbox(
926
+ result.sandbox,
927
+ result.sandboxId,
928
+ this.providerName,
929
+ this.methods,
930
+ this.config,
931
+ this.methods.destroy
450
932
  );
933
+ this.activeSandboxes.set(result.sandboxId, sandbox);
451
934
  }
452
- throw new ConfigurationError(
453
- `Failed to load provider '${providerName}': ${error.message}`,
454
- "sdk"
455
- );
935
+ sandboxes.push(sandbox);
456
936
  }
937
+ return sandboxes;
457
938
  }
458
- /**
459
- * Detect available providers based on environment variables
460
- *
461
- * @returns Array of available provider types
462
- */
463
- static detectProviders() {
464
- return detectAvailableProviders();
939
+ async destroy(sandboxId) {
940
+ await this.methods.destroy(this.config, sandboxId);
941
+ this.activeSandboxes.delete(sandboxId);
465
942
  }
466
943
  };
467
-
468
- // src/index.ts
469
- var index_default = ComputeSDK;
944
+ var GeneratedProvider = class {
945
+ constructor(config, providerConfig) {
946
+ this.name = providerConfig.name;
947
+ this.sandbox = new GeneratedSandboxManager(
948
+ config,
949
+ providerConfig.name,
950
+ providerConfig.methods.sandbox
951
+ );
952
+ }
953
+ };
954
+ function createProvider(providerConfig) {
955
+ return (config) => {
956
+ return new GeneratedProvider(config, providerConfig);
957
+ };
958
+ }
470
959
  export {
471
- AuthenticationError,
472
- BaseProvider,
473
- ComputeError,
474
- ComputeSDK,
475
- ConfigurationError,
476
- DEFAULT_TIMEOUT,
477
- ENV_KEYS,
478
- ExecutionError,
479
- ProviderError,
480
- ProviderUnavailableError,
481
- TimeoutError,
482
- autoSelectProvider,
483
- createComputeRegistry,
484
- index_default as default,
485
- detectAvailableProviders,
486
- executeSandbox,
487
- getDefaultRuntime,
488
- isCloudflareWorkers,
489
- normalizeContainerConfig,
490
- normalizeSandboxConfig,
491
- retry,
492
- validateProviderApiKey
960
+ SandboxManager,
961
+ compute,
962
+ createProvider,
963
+ handleComputeRequest
493
964
  };
494
965
  //# sourceMappingURL=index.mjs.map