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