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