computesdk 1.1.1 → 1.2.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,45 +20,29 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
- SandboxManager: () => SandboxManager,
23
+ CommandExitError: () => CommandExitError,
24
24
  compute: () => compute,
25
25
  createProvider: () => createProvider,
26
- handleComputeRequest: () => handleComputeRequest
26
+ handleComputeRequest: () => handleComputeRequest,
27
+ isCommandExitError: () => isCommandExitError
27
28
  });
28
29
  module.exports = __toCommonJS(index_exports);
29
30
 
30
- // src/sandbox.ts
31
- var SandboxManager = class {
32
- /**
33
- * Create a sandbox from a provider
34
- */
35
- async create(provider, options) {
36
- return await provider.sandbox.create(options);
37
- }
38
- /**
39
- * Get an existing sandbox by ID from a provider
40
- */
41
- async getById(provider, sandboxId) {
42
- return await provider.sandbox.getById(sandboxId);
43
- }
44
- /**
45
- * List all active sandboxes from a provider
46
- */
47
- async list(provider) {
48
- return await provider.sandbox.list();
49
- }
50
- /**
51
- * Destroy a sandbox via a provider
52
- */
53
- async destroy(provider, sandboxId) {
54
- return await provider.sandbox.destroy(sandboxId);
31
+ // src/types/sandbox.ts
32
+ var CommandExitError = class extends Error {
33
+ constructor(result) {
34
+ super(`Command exited with code ${result.exitCode}`);
35
+ this.result = result;
36
+ this.name = "CommandExitError";
55
37
  }
56
38
  };
39
+ function isCommandExitError(error) {
40
+ return typeof error === "object" && error !== null && "name" in error && error.name === "CommandExitError" && "result" in error;
41
+ }
57
42
 
58
43
  // src/compute.ts
59
44
  var ComputeManager = class {
60
45
  constructor() {
61
- this.sandboxManager = new SandboxManager();
62
46
  this.config = null;
63
47
  this.sandbox = {
64
48
  /**
@@ -74,16 +58,16 @@ var ComputeManager = class {
74
58
  * provider: e2b({ apiKey: 'your-key' })
75
59
  * })
76
60
  *
77
- * // With default provider (both forms work)
78
- * compute.setConfig({ provider: e2b({ apiKey: 'your-key' }) })
79
- * const sandbox1 = await compute.sandbox.create({})
80
- * const sandbox2 = await compute.sandbox.create()
61
+ * // With default provider (both forms work)
62
+ * compute.setConfig({ defaultProvider: e2b({ apiKey: 'your-key' }) })
63
+ * const sandbox1 = await compute.sandbox.create({})
64
+ * const sandbox2 = await compute.sandbox.create()
81
65
  * ```
82
66
  */
83
67
  create: async (params) => {
84
68
  const provider = params && "provider" in params && params.provider ? params.provider : this.getDefaultProvider();
85
69
  const options = params?.options;
86
- return await this.sandboxManager.create(provider, options);
70
+ return await provider.sandbox.create(options);
87
71
  },
88
72
  /**
89
73
  * Get an existing sandbox by ID from a provider (or default provider if configured)
@@ -91,12 +75,12 @@ var ComputeManager = class {
91
75
  getById: async (providerOrSandboxId, sandboxId) => {
92
76
  if (typeof providerOrSandboxId === "string") {
93
77
  const provider = this.getDefaultProvider();
94
- return await this.sandboxManager.getById(provider, providerOrSandboxId);
78
+ return await provider.sandbox.getById(providerOrSandboxId);
95
79
  } else {
96
80
  if (!sandboxId) {
97
81
  throw new Error("sandboxId is required when provider is specified");
98
82
  }
99
- return await this.sandboxManager.getById(providerOrSandboxId, sandboxId);
83
+ return await providerOrSandboxId.sandbox.getById(sandboxId);
100
84
  }
101
85
  },
102
86
  /**
@@ -104,7 +88,7 @@ var ComputeManager = class {
104
88
  */
105
89
  list: async (provider) => {
106
90
  const actualProvider = provider || this.getDefaultProvider();
107
- return await this.sandboxManager.list(actualProvider);
91
+ return await actualProvider.sandbox.list();
108
92
  },
109
93
  /**
110
94
  * Destroy a sandbox via a provider (or default provider if configured)
@@ -112,12 +96,12 @@ var ComputeManager = class {
112
96
  destroy: async (providerOrSandboxId, sandboxId) => {
113
97
  if (typeof providerOrSandboxId === "string") {
114
98
  const provider = this.getDefaultProvider();
115
- return await this.sandboxManager.destroy(provider, providerOrSandboxId);
99
+ return await provider.sandbox.destroy(providerOrSandboxId);
116
100
  } else {
117
101
  if (!sandboxId) {
118
102
  throw new Error("sandboxId is required when provider is specified");
119
103
  }
120
- return await this.sandboxManager.destroy(providerOrSandboxId, sandboxId);
104
+ return await providerOrSandboxId.sandbox.destroy(sandboxId);
121
105
  }
122
106
  }
123
107
  };
@@ -126,7 +110,17 @@ var ComputeManager = class {
126
110
  * Set default configuration
127
111
  */
128
112
  setConfig(config) {
129
- this.config = config;
113
+ if (!config.defaultProvider && !config.provider) {
114
+ throw new Error("Either defaultProvider or provider must be specified in setConfig");
115
+ }
116
+ if (config.defaultProvider && config.provider) {
117
+ console.warn("Both defaultProvider and provider specified in setConfig. Using defaultProvider. The provider key is deprecated, please use defaultProvider instead.");
118
+ }
119
+ const actualProvider = config.defaultProvider || config.provider;
120
+ this.config = {
121
+ provider: actualProvider,
122
+ defaultProvider: actualProvider
123
+ };
130
124
  }
131
125
  /**
132
126
  * Get current configuration
@@ -146,7 +140,7 @@ var ComputeManager = class {
146
140
  getDefaultProvider() {
147
141
  if (!this.config?.provider) {
148
142
  throw new Error(
149
- "No default provider configured. Either call compute.setConfig({ provider }) or pass provider explicitly."
143
+ "No default provider configured. Either call compute.setConfig({ defaultProvider }) or pass provider explicitly."
150
144
  );
151
145
  }
152
146
  return this.config.provider;
@@ -155,567 +149,281 @@ var ComputeManager = class {
155
149
  // blob = new BlobManager();
156
150
  // database = new DatabaseManager();
157
151
  // git = new GitManager();
158
- /**
159
- * Get the sandbox manager (useful for testing)
160
- */
161
- getSandboxManager() {
162
- return this.sandboxManager;
163
- }
164
152
  };
165
153
  var compute = new ComputeManager();
166
154
 
167
155
  // src/request-handler.ts
168
- async function handleComputeRequest(params) {
169
- const { request, provider } = params;
156
+ async function executeAction(body, provider) {
170
157
  try {
171
- const getSandbox = async (sandboxId) => {
172
- if (sandboxId) {
173
- const existingSandbox = await compute.sandbox.getById(provider, sandboxId);
174
- if (!existingSandbox) {
175
- throw new Error(`Sandbox with ID ${sandboxId} not found`);
176
- }
177
- return existingSandbox;
178
- } else {
179
- return await compute.sandbox.create({
180
- provider,
181
- options: request.options || { runtime: "python" }
182
- });
158
+ const { action, sandboxId } = body;
159
+ if (action === "compute.sandbox.create") {
160
+ const sandbox2 = await compute.sandbox.create({
161
+ provider,
162
+ options: body.options || { runtime: "python" }
163
+ });
164
+ return {
165
+ success: true,
166
+ sandboxId: sandbox2.sandboxId,
167
+ provider: provider.name
168
+ };
169
+ }
170
+ if (action === "compute.sandbox.list") {
171
+ const sandboxes = await compute.sandbox.list(provider);
172
+ return {
173
+ success: true,
174
+ sandboxId: "",
175
+ provider: provider.name,
176
+ sandboxes: sandboxes.map((sb) => ({
177
+ sandboxId: sb.sandboxId,
178
+ provider: sb.provider
179
+ }))
180
+ };
181
+ }
182
+ if (action === "compute.sandbox.destroy") {
183
+ if (!sandboxId) {
184
+ throw new Error("sandboxId is required for destroy action");
183
185
  }
186
+ await compute.sandbox.destroy(provider, sandboxId);
187
+ return {
188
+ success: true,
189
+ sandboxId,
190
+ provider: provider.name
191
+ };
192
+ }
193
+ if (!sandboxId) {
194
+ throw new Error("sandboxId is required for this action");
195
+ }
196
+ const sandbox = await compute.sandbox.getById(provider, sandboxId);
197
+ if (!sandbox) {
198
+ throw new Error(`Sandbox ${sandboxId} not found`);
199
+ }
200
+ if (action === "compute.sandbox.getInfo") {
201
+ const result = await sandbox.getInfo();
202
+ return {
203
+ success: true,
204
+ sandboxId,
205
+ provider: provider.name,
206
+ info: {
207
+ id: result.id,
208
+ provider: result.provider,
209
+ runtime: result.runtime,
210
+ status: result.status,
211
+ createdAt: result.createdAt.toISOString(),
212
+ timeout: result.timeout,
213
+ metadata: result.metadata
214
+ }
215
+ };
216
+ }
217
+ if (action === "compute.sandbox.runCode") {
218
+ if (!body.code) throw new Error("code is required");
219
+ const result = await sandbox.runCode(body.code, body.runtime);
220
+ return {
221
+ success: true,
222
+ sandboxId,
223
+ provider: provider.name,
224
+ result: {
225
+ stdout: result.stdout,
226
+ stderr: result.stderr,
227
+ exitCode: result.exitCode,
228
+ executionTime: result.executionTime
229
+ }
230
+ };
231
+ }
232
+ if (action === "compute.sandbox.runCommand") {
233
+ if (!body.command) throw new Error("command is required");
234
+ const result = await sandbox.runCommand(body.command, body.args);
235
+ return {
236
+ success: true,
237
+ 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
+ if (action === "compute.sandbox.filesystem.readFile") {
248
+ if (!body.path) throw new Error("path is required");
249
+ const result = await sandbox.filesystem.readFile(body.path);
250
+ return {
251
+ success: true,
252
+ sandboxId,
253
+ provider: provider.name,
254
+ fileContent: result
255
+ };
256
+ }
257
+ if (action === "compute.sandbox.filesystem.writeFile") {
258
+ if (!body.path) throw new Error("path is required");
259
+ if (body.content === void 0) throw new Error("content is required");
260
+ await sandbox.filesystem.writeFile(body.path, body.content);
261
+ return { success: true, sandboxId, provider: provider.name };
262
+ }
263
+ if (action === "compute.sandbox.filesystem.mkdir") {
264
+ if (!body.path) throw new Error("path is required");
265
+ await sandbox.filesystem.mkdir(body.path);
266
+ return { success: true, sandboxId, provider: provider.name };
267
+ }
268
+ if (action === "compute.sandbox.filesystem.readdir") {
269
+ if (!body.path) throw new Error("path is required");
270
+ const result = await sandbox.filesystem.readdir(body.path);
271
+ return {
272
+ success: true,
273
+ sandboxId,
274
+ provider: provider.name,
275
+ files: result.map((entry) => ({
276
+ name: entry.name,
277
+ path: entry.path,
278
+ isDirectory: entry.isDirectory,
279
+ size: entry.size,
280
+ lastModified: entry.lastModified.toISOString()
281
+ }))
282
+ };
283
+ }
284
+ if (action === "compute.sandbox.filesystem.exists") {
285
+ if (!body.path) throw new Error("path is required");
286
+ const result = await sandbox.filesystem.exists(body.path);
287
+ return {
288
+ success: true,
289
+ sandboxId,
290
+ provider: provider.name,
291
+ exists: result
292
+ };
293
+ }
294
+ if (action === "compute.sandbox.filesystem.remove") {
295
+ if (!body.path) throw new Error("path is required");
296
+ await sandbox.filesystem.remove(body.path);
297
+ return { success: true, sandboxId, provider: provider.name };
298
+ }
299
+ throw new Error(`Unknown action: ${action}`);
300
+ } catch (error) {
301
+ return {
302
+ success: false,
303
+ error: error instanceof Error ? error.message : "Unknown error occurred",
304
+ sandboxId: body.sandboxId || "",
305
+ provider: provider.name
184
306
  };
185
- switch (request.action) {
186
- // Sandbox operations
187
- case "compute.sandbox.create": {
188
- const sandbox = await compute.sandbox.create({
189
- provider,
190
- options: request.options || { runtime: "python" }
191
- });
192
- return {
193
- success: true,
194
- sandboxId: sandbox.sandboxId,
195
- provider: provider.name
196
- };
197
- }
198
- case "compute.sandbox.destroy": {
199
- if (!request.sandboxId) {
200
- return {
201
- success: false,
202
- error: "Sandbox ID is required for destroy action",
203
- sandboxId: "",
204
- provider: provider.name
205
- };
206
- }
207
- await compute.sandbox.destroy(provider, request.sandboxId);
208
- return {
209
- success: true,
210
- sandboxId: request.sandboxId,
211
- provider: provider.name
212
- };
213
- }
214
- case "compute.sandbox.getInfo": {
215
- if (!request.sandboxId) {
216
- return {
217
- success: false,
218
- error: "Sandbox ID is required for getInfo action",
219
- sandboxId: "",
220
- provider: provider.name
221
- };
222
- }
223
- const sandbox = await getSandbox(request.sandboxId);
224
- const info = await sandbox.getInfo();
225
- return {
226
- success: true,
227
- sandboxId: request.sandboxId,
228
- provider: provider.name,
229
- info: {
230
- id: info.id,
231
- provider: info.provider,
232
- runtime: info.runtime,
233
- status: info.status,
234
- createdAt: info.createdAt.toISOString(),
235
- timeout: info.timeout,
236
- metadata: info.metadata
237
- }
238
- };
239
- }
240
- case "compute.sandbox.list": {
241
- const sandboxes = await compute.sandbox.list(provider);
242
- return {
243
- success: true,
307
+ }
308
+ }
309
+ async function handleComputeRequest(paramsOrRequestOrBody, provider) {
310
+ if (typeof paramsOrRequestOrBody === "object" && "request" in paramsOrRequestOrBody && "provider" in paramsOrRequestOrBody) {
311
+ const params = paramsOrRequestOrBody;
312
+ return await executeAction(params.request, params.provider);
313
+ }
314
+ if (!provider) {
315
+ throw new Error("Provider is required when not using object-style API");
316
+ }
317
+ const requestOrBody = paramsOrRequestOrBody;
318
+ try {
319
+ let body;
320
+ if (requestOrBody instanceof Request) {
321
+ if (requestOrBody.method !== "POST") {
322
+ return Response.json({
323
+ success: false,
324
+ error: "Only POST requests are supported",
244
325
  sandboxId: "",
245
- provider: provider.name,
246
- sandboxes: sandboxes.map((sandbox) => ({
247
- sandboxId: sandbox.sandboxId,
248
- provider: sandbox.provider
249
- }))
250
- };
251
- }
252
- // Code execution
253
- case "compute.sandbox.runCode": {
254
- if (!request.code) {
255
- return {
256
- success: false,
257
- error: "Code is required for runCode action",
258
- sandboxId: request.sandboxId || "",
259
- provider: provider.name
260
- };
261
- }
262
- const sandbox = await getSandbox(request.sandboxId);
263
- const result = await sandbox.runCode(request.code, request.runtime);
264
- return {
265
- success: true,
266
- sandboxId: sandbox.sandboxId,
267
- provider: provider.name,
268
- result: {
269
- stdout: result.stdout,
270
- stderr: result.stderr,
271
- exitCode: result.exitCode,
272
- executionTime: result.executionTime
273
- }
274
- };
275
- }
276
- case "compute.sandbox.runCommand": {
277
- if (!request.command) {
278
- return {
279
- success: false,
280
- error: "Command is required for runCommand action",
281
- sandboxId: request.sandboxId || "",
282
- provider: provider.name
283
- };
284
- }
285
- const sandbox = await getSandbox(request.sandboxId);
286
- const result = await sandbox.runCommand(request.command, request.args);
287
- return {
288
- success: true,
289
- sandboxId: sandbox.sandboxId,
290
- provider: provider.name,
291
- result: {
292
- stdout: result.stdout,
293
- stderr: result.stderr,
294
- exitCode: result.exitCode,
295
- executionTime: result.executionTime
296
- }
297
- };
298
- }
299
- // Filesystem operations
300
- case "compute.sandbox.filesystem.readFile": {
301
- if (!request.sandboxId) {
302
- return {
303
- success: false,
304
- error: "Sandbox ID is required for filesystem operations",
305
- sandboxId: "",
306
- provider: provider.name
307
- };
308
- }
309
- if (!request.path) {
310
- return {
311
- success: false,
312
- error: "File path is required for readFile action",
313
- sandboxId: request.sandboxId,
314
- provider: provider.name
315
- };
316
- }
317
- const sandbox = await getSandbox(request.sandboxId);
318
- const content = await sandbox.filesystem.readFile(request.path);
319
- return {
320
- success: true,
321
- sandboxId: request.sandboxId,
322
- provider: provider.name,
323
- fileContent: content
324
- };
325
- }
326
- case "compute.sandbox.filesystem.writeFile": {
327
- if (!request.sandboxId) {
328
- return {
329
- success: false,
330
- error: "Sandbox ID is required for filesystem operations",
331
- sandboxId: "",
332
- provider: provider.name
333
- };
334
- }
335
- if (!request.path) {
336
- return {
337
- success: false,
338
- error: "File path is required for writeFile action",
339
- sandboxId: request.sandboxId,
340
- provider: provider.name
341
- };
342
- }
343
- if (request.content === void 0) {
344
- return {
345
- success: false,
346
- error: "File content is required for writeFile action",
347
- sandboxId: request.sandboxId,
348
- provider: provider.name
349
- };
350
- }
351
- const sandbox = await getSandbox(request.sandboxId);
352
- await sandbox.filesystem.writeFile(request.path, request.content);
353
- return {
354
- success: true,
355
- sandboxId: request.sandboxId,
356
- provider: provider.name
357
- };
358
- }
359
- case "compute.sandbox.filesystem.mkdir": {
360
- if (!request.sandboxId) {
361
- return {
362
- success: false,
363
- error: "Sandbox ID is required for filesystem operations",
364
- sandboxId: "",
365
- provider: provider.name
366
- };
367
- }
368
- if (!request.path) {
369
- return {
370
- success: false,
371
- error: "Directory path is required for mkdir action",
372
- sandboxId: request.sandboxId,
373
- provider: provider.name
374
- };
375
- }
376
- const sandbox = await getSandbox(request.sandboxId);
377
- await sandbox.filesystem.mkdir(request.path);
378
- return {
379
- success: true,
380
- sandboxId: request.sandboxId,
381
- provider: provider.name
382
- };
383
- }
384
- case "compute.sandbox.filesystem.readdir": {
385
- if (!request.sandboxId) {
386
- return {
387
- success: false,
388
- error: "Sandbox ID is required for filesystem operations",
389
- sandboxId: "",
390
- provider: provider.name
391
- };
392
- }
393
- if (!request.path) {
394
- return {
395
- success: false,
396
- error: "Directory path is required for readdir action",
397
- sandboxId: request.sandboxId,
398
- provider: provider.name
399
- };
400
- }
401
- const sandbox = await getSandbox(request.sandboxId);
402
- const entries = await sandbox.filesystem.readdir(request.path);
403
- return {
404
- success: true,
405
- sandboxId: request.sandboxId,
406
- provider: provider.name,
407
- files: entries.map((entry) => ({
408
- name: entry.name,
409
- path: entry.path,
410
- isDirectory: entry.isDirectory,
411
- size: entry.size,
412
- lastModified: entry.lastModified.toISOString()
413
- }))
414
- };
415
- }
416
- case "compute.sandbox.filesystem.exists": {
417
- if (!request.sandboxId) {
418
- return {
419
- success: false,
420
- error: "Sandbox ID is required for filesystem operations",
421
- sandboxId: "",
422
- provider: provider.name
423
- };
424
- }
425
- if (!request.path) {
426
- return {
427
- success: false,
428
- error: "Path is required for exists action",
429
- sandboxId: request.sandboxId,
430
- provider: provider.name
431
- };
432
- }
433
- const sandbox = await getSandbox(request.sandboxId);
434
- const exists = await sandbox.filesystem.exists(request.path);
435
- return {
436
- success: true,
437
- sandboxId: request.sandboxId,
438
- provider: provider.name,
439
- exists
440
- };
441
- }
442
- case "compute.sandbox.filesystem.remove": {
443
- if (!request.sandboxId) {
444
- return {
445
- success: false,
446
- error: "Sandbox ID is required for filesystem operations",
447
- sandboxId: "",
448
- provider: provider.name
449
- };
450
- }
451
- if (!request.path) {
452
- return {
453
- success: false,
454
- error: "Path is required for remove action",
455
- sandboxId: request.sandboxId,
456
- provider: provider.name
457
- };
458
- }
459
- const sandbox = await getSandbox(request.sandboxId);
460
- await sandbox.filesystem.remove(request.path);
461
- return {
462
- success: true,
463
- sandboxId: request.sandboxId,
464
326
  provider: provider.name
465
- };
327
+ }, { status: 405 });
466
328
  }
467
- // Terminal operations
468
- case "compute.sandbox.terminal.create": {
469
- if (!request.sandboxId) {
470
- return {
471
- success: false,
472
- error: "Sandbox ID is required for terminal operations",
473
- sandboxId: "",
474
- provider: provider.name
475
- };
476
- }
477
- const sandbox = await getSandbox(request.sandboxId);
478
- const terminal = await sandbox.terminal.create(request.terminalOptions);
479
- return {
480
- success: true,
481
- sandboxId: request.sandboxId,
482
- provider: provider.name,
483
- terminal: {
484
- pid: terminal.pid,
485
- command: terminal.command,
486
- status: terminal.status,
487
- cols: terminal.cols,
488
- rows: terminal.rows
489
- }
490
- };
491
- }
492
- case "compute.sandbox.terminal.list": {
493
- if (!request.sandboxId) {
494
- return {
495
- success: false,
496
- error: "Sandbox ID is required for terminal operations",
497
- sandboxId: "",
498
- provider: provider.name
499
- };
500
- }
501
- const sandbox = await getSandbox(request.sandboxId);
502
- const terminals = await sandbox.terminal.list();
503
- return {
504
- success: true,
505
- sandboxId: request.sandboxId,
506
- provider: provider.name,
507
- terminals: terminals.map((terminal) => ({
508
- pid: terminal.pid,
509
- command: terminal.command,
510
- status: terminal.status,
511
- cols: terminal.cols,
512
- rows: terminal.rows
513
- }))
514
- };
515
- }
516
- case "compute.sandbox.terminal.getById": {
517
- if (!request.sandboxId) {
518
- return {
519
- success: false,
520
- error: "Sandbox ID is required for terminal operations",
521
- sandboxId: "",
522
- provider: provider.name
523
- };
524
- }
525
- if (!request.terminalId) {
526
- return {
527
- success: false,
528
- error: "Terminal ID is required for getById action",
529
- sandboxId: request.sandboxId,
530
- provider: provider.name
531
- };
532
- }
533
- const sandbox = await getSandbox(request.sandboxId);
534
- const terminal = await sandbox.terminal.getById(request.terminalId);
535
- if (!terminal) {
536
- return {
537
- success: false,
538
- error: `Terminal with ID ${request.terminalId} not found`,
539
- sandboxId: request.sandboxId,
540
- provider: provider.name
541
- };
542
- }
543
- return {
544
- success: true,
545
- sandboxId: request.sandboxId,
546
- provider: provider.name,
547
- terminal: {
548
- pid: terminal.pid,
549
- command: terminal.command,
550
- status: terminal.status,
551
- cols: terminal.cols,
552
- rows: terminal.rows
553
- }
554
- };
555
- }
556
- case "compute.sandbox.terminal.destroy": {
557
- if (!request.sandboxId) {
558
- return {
559
- success: false,
560
- error: "Sandbox ID is required for terminal operations",
561
- sandboxId: "",
562
- provider: provider.name
563
- };
564
- }
565
- if (!request.terminalId) {
566
- return {
567
- success: false,
568
- error: "Terminal ID is required for destroy action",
569
- sandboxId: request.sandboxId,
570
- provider: provider.name
571
- };
572
- }
573
- const sandbox = await getSandbox(request.sandboxId);
574
- await sandbox.terminal.destroy(request.terminalId);
575
- return {
576
- success: true,
577
- sandboxId: request.sandboxId,
578
- provider: provider.name
579
- };
580
- }
581
- // Terminal I/O operations
582
- case "compute.sandbox.terminal.write": {
583
- if (!request.sandboxId) {
584
- return {
585
- success: false,
586
- error: "Sandbox ID is required for terminal operations",
587
- sandboxId: "",
588
- provider: provider.name
589
- };
590
- }
591
- if (!request.terminalId) {
592
- return {
593
- success: false,
594
- error: "Terminal ID is required for write action",
595
- sandboxId: request.sandboxId,
596
- provider: provider.name
597
- };
598
- }
599
- if (!request.data) {
600
- return {
601
- success: false,
602
- error: "Data is required for write action",
603
- sandboxId: request.sandboxId,
604
- provider: provider.name
605
- };
606
- }
607
- const sandbox = await getSandbox(request.sandboxId);
608
- const terminal = await sandbox.terminal.getById(request.terminalId);
609
- if (!terminal) {
610
- return {
611
- success: false,
612
- error: `Terminal with ID ${request.terminalId} not found`,
613
- sandboxId: request.sandboxId,
614
- provider: provider.name
615
- };
616
- }
617
- await terminal.write(request.data);
618
- return {
619
- success: true,
620
- sandboxId: request.sandboxId,
621
- provider: provider.name
622
- };
623
- }
624
- case "compute.sandbox.terminal.resize": {
625
- if (!request.sandboxId) {
626
- return {
627
- success: false,
628
- error: "Sandbox ID is required for terminal operations",
629
- sandboxId: "",
630
- provider: provider.name
631
- };
632
- }
633
- if (!request.terminalId) {
634
- return {
635
- success: false,
636
- error: "Terminal ID is required for resize action",
637
- sandboxId: request.sandboxId,
638
- provider: provider.name
639
- };
640
- }
641
- if (!request.cols || !request.rows) {
642
- return {
643
- success: false,
644
- error: "Cols and rows are required for resize action",
645
- sandboxId: request.sandboxId,
646
- provider: provider.name
647
- };
648
- }
649
- const sandbox = await getSandbox(request.sandboxId);
650
- const terminal = await sandbox.terminal.getById(request.terminalId);
651
- if (!terminal) {
652
- return {
653
- success: false,
654
- error: `Terminal with ID ${request.terminalId} not found`,
655
- sandboxId: request.sandboxId,
656
- provider: provider.name
657
- };
658
- }
659
- await terminal.resize(request.cols, request.rows);
660
- return {
661
- success: true,
662
- sandboxId: request.sandboxId,
663
- provider: provider.name
664
- };
665
- }
666
- case "compute.sandbox.terminal.kill": {
667
- if (!request.sandboxId) {
668
- return {
669
- success: false,
670
- error: "Sandbox ID is required for terminal operations",
671
- sandboxId: "",
672
- provider: provider.name
673
- };
674
- }
675
- if (!request.terminalId) {
676
- return {
677
- success: false,
678
- error: "Terminal ID is required for kill action",
679
- sandboxId: request.sandboxId,
680
- provider: provider.name
681
- };
682
- }
683
- const sandbox = await getSandbox(request.sandboxId);
684
- const terminal = await sandbox.terminal.getById(request.terminalId);
685
- if (!terminal) {
686
- return {
687
- success: false,
688
- error: `Terminal with ID ${request.terminalId} not found`,
689
- sandboxId: request.sandboxId,
690
- provider: provider.name
691
- };
692
- }
693
- await terminal.kill();
694
- return {
695
- success: true,
696
- sandboxId: request.sandboxId,
697
- provider: provider.name
698
- };
699
- }
700
- default:
701
- return {
329
+ try {
330
+ body = await requestOrBody.json();
331
+ } catch (parseError) {
332
+ return Response.json({
702
333
  success: false,
703
- error: `Unknown action: ${request.action}`,
704
- sandboxId: request.sandboxId || "",
334
+ error: "Invalid JSON in request body",
335
+ sandboxId: "",
705
336
  provider: provider.name
706
- };
337
+ }, { status: 400 });
338
+ }
339
+ } else {
340
+ body = requestOrBody;
707
341
  }
342
+ const result = await executeAction(body, provider);
343
+ return Response.json(result, {
344
+ status: result.success ? 200 : 500
345
+ });
708
346
  } catch (error) {
709
- return {
347
+ return Response.json({
710
348
  success: false,
711
- error: error instanceof Error ? error.message : "Unknown error occurred",
712
- sandboxId: request.sandboxId || "",
349
+ error: error instanceof Error ? error.message : "Request handling failed",
350
+ sandboxId: "",
713
351
  provider: provider.name
714
- };
352
+ }, { status: 500 });
715
353
  }
716
354
  }
717
355
 
718
356
  // src/factory.ts
357
+ var defaultFilesystemMethods = {
358
+ readFile: async (sandbox, path, runCommand) => {
359
+ const result = await runCommand(sandbox, "cat", [path]);
360
+ if (result.exitCode !== 0) {
361
+ throw new Error(`Failed to read file ${path}: ${result.stderr}`);
362
+ }
363
+ return result.stdout.replace(/\n$/, "");
364
+ },
365
+ writeFile: async (sandbox, path, content, runCommand) => {
366
+ const result = await runCommand(sandbox, "sh", ["-c", `echo ${JSON.stringify(content)} > ${JSON.stringify(path)}`]);
367
+ if (result.exitCode !== 0) {
368
+ throw new Error(`Failed to write file ${path}: ${result.stderr}`);
369
+ }
370
+ },
371
+ mkdir: async (sandbox, path, runCommand) => {
372
+ const result = await runCommand(sandbox, "mkdir", ["-p", path]);
373
+ if (result.exitCode !== 0) {
374
+ throw new Error(`Failed to create directory ${path}: ${result.stderr}`);
375
+ }
376
+ },
377
+ readdir: async (sandbox, path, runCommand) => {
378
+ let result = await runCommand(sandbox, "ls", ["-la", path]);
379
+ let hasDetailedOutput = true;
380
+ if (result.exitCode !== 0) {
381
+ result = await runCommand(sandbox, "ls", ["-l", path]);
382
+ }
383
+ if (result.exitCode !== 0) {
384
+ result = await runCommand(sandbox, "ls", [path]);
385
+ hasDetailedOutput = false;
386
+ }
387
+ if (result.exitCode !== 0) {
388
+ throw new Error(`Failed to list directory ${path}: ${result.stderr}`);
389
+ }
390
+ const lines = (result.stdout || "").split("\n").filter((line) => line.trim() && !line.startsWith("total"));
391
+ return lines.map((line) => {
392
+ if (hasDetailedOutput && line.includes(" ")) {
393
+ const parts = line.trim().split(/\s+/);
394
+ const name = parts[parts.length - 1];
395
+ const isDirectory = line.startsWith("d");
396
+ return {
397
+ name,
398
+ path: `${path}/${name}`,
399
+ isDirectory,
400
+ size: parseInt(parts[4]) || 0,
401
+ lastModified: /* @__PURE__ */ new Date()
402
+ };
403
+ } else {
404
+ const name = line.trim();
405
+ return {
406
+ name,
407
+ path: `${path}/${name}`,
408
+ isDirectory: false,
409
+ // Can't determine from simple ls
410
+ size: 0,
411
+ lastModified: /* @__PURE__ */ new Date()
412
+ };
413
+ }
414
+ });
415
+ },
416
+ exists: async (sandbox, path, runCommand) => {
417
+ const result = await runCommand(sandbox, "test", ["-e", path]);
418
+ return result.exitCode === 0;
419
+ },
420
+ remove: async (sandbox, path, runCommand) => {
421
+ const result = await runCommand(sandbox, "rm", ["-rf", path]);
422
+ if (result.exitCode !== 0) {
423
+ throw new Error(`Failed to remove ${path}: ${result.stderr}`);
424
+ }
425
+ }
426
+ };
719
427
  var UnsupportedFileSystem = class {
720
428
  constructor(providerName) {
721
429
  this.providerName = providerName;
@@ -739,155 +447,46 @@ var UnsupportedFileSystem = class {
739
447
  throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
740
448
  }
741
449
  };
742
- var UnsupportedTerminal = class {
743
- constructor(providerName) {
744
- this.providerName = providerName;
745
- }
746
- async create(_options) {
747
- throw new Error(`Terminal operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
748
- }
749
- async getById(_terminalId) {
750
- throw new Error(`Terminal operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
751
- }
752
- async list() {
753
- throw new Error(`Terminal operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
754
- }
755
- async destroy(_terminalId) {
756
- throw new Error(`Terminal operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
757
- }
758
- };
759
450
  var SupportedFileSystem = class {
760
- constructor(sandbox, methods) {
451
+ constructor(sandbox, methods, allMethods) {
761
452
  this.sandbox = sandbox;
762
453
  this.methods = methods;
454
+ this.allMethods = allMethods;
763
455
  }
764
456
  async readFile(path) {
765
- return this.methods.readFile(this.sandbox, path);
457
+ return this.methods.readFile(this.sandbox, path, this.allMethods.runCommand);
766
458
  }
767
459
  async writeFile(path, content) {
768
- return this.methods.writeFile(this.sandbox, path, content);
460
+ return this.methods.writeFile(this.sandbox, path, content, this.allMethods.runCommand);
769
461
  }
770
462
  async mkdir(path) {
771
- return this.methods.mkdir(this.sandbox, path);
463
+ return this.methods.mkdir(this.sandbox, path, this.allMethods.runCommand);
772
464
  }
773
465
  async readdir(path) {
774
- return this.methods.readdir(this.sandbox, path);
466
+ return this.methods.readdir(this.sandbox, path, this.allMethods.runCommand);
775
467
  }
776
468
  async exists(path) {
777
- return this.methods.exists(this.sandbox, path);
469
+ return this.methods.exists(this.sandbox, path, this.allMethods.runCommand);
778
470
  }
779
471
  async remove(path) {
780
- return this.methods.remove(this.sandbox, path);
781
- }
782
- };
783
- var GeneratedTerminalSession = class {
784
- constructor(terminal, sandbox, methods, terminalId, command, cols = 80, rows = 24) {
785
- this.terminal = terminal;
786
- this.sandbox = sandbox;
787
- this.methods = methods;
788
- this.pid = parseInt(terminalId);
789
- this.command = command;
790
- this.status = "running";
791
- this.cols = cols;
792
- this.rows = rows;
793
- }
794
- async write(data) {
795
- return this.methods.write(this.sandbox, this.terminal, data);
796
- }
797
- async resize(cols, rows) {
798
- return this.methods.resize(this.sandbox, this.terminal, cols, rows);
799
- }
800
- async kill() {
801
- return this.methods.kill(this.sandbox, this.terminal);
802
- }
803
- };
804
- var SupportedTerminal = class {
805
- constructor(sandbox, methods) {
806
- this.sandbox = sandbox;
807
- this.methods = methods;
808
- }
809
- async create(options) {
810
- let terminalSession;
811
- const createOptions = {
812
- ...options,
813
- onData: (data) => {
814
- if (terminalSession?.onData) {
815
- terminalSession.onData(data);
816
- }
817
- },
818
- onExit: (exitCode) => {
819
- if (terminalSession?.onExit) {
820
- terminalSession.onExit(exitCode);
821
- }
822
- }
823
- };
824
- const result = await this.methods.create(this.sandbox, createOptions);
825
- terminalSession = new GeneratedTerminalSession(
826
- result.terminal,
827
- this.sandbox,
828
- this.methods,
829
- result.terminalId,
830
- options?.command || "bash",
831
- options?.cols || 80,
832
- options?.rows || 24
833
- );
834
- terminalSession.onData = options?.onData;
835
- terminalSession.onExit = options?.onExit;
836
- return terminalSession;
837
- }
838
- async getById(terminalId) {
839
- const result = await this.methods.getById(this.sandbox, terminalId);
840
- if (!result) return null;
841
- return new GeneratedTerminalSession(
842
- result.terminal,
843
- this.sandbox,
844
- this.methods,
845
- result.terminalId,
846
- "bash",
847
- // Default command for existing terminals
848
- 80,
849
- // Default cols
850
- 24
851
- // Default rows
852
- );
853
- }
854
- async list() {
855
- const results = await this.methods.list(this.sandbox);
856
- return results.map((result) => new GeneratedTerminalSession(
857
- result.terminal,
858
- this.sandbox,
859
- this.methods,
860
- result.terminalId,
861
- "bash",
862
- // Default command
863
- 80,
864
- // Default cols
865
- 24
866
- // Default rows
867
- ));
868
- }
869
- async destroy(terminalId) {
870
- return this.methods.destroy(this.sandbox, terminalId);
472
+ return this.methods.remove(this.sandbox, path, this.allMethods.runCommand);
871
473
  }
872
474
  };
873
475
  var GeneratedSandbox = class {
874
- constructor(sandbox, sandboxId, providerName, methods, config, destroyMethod) {
476
+ constructor(sandbox, sandboxId, providerName, methods, config, destroyMethod, providerInstance) {
875
477
  this.sandbox = sandbox;
876
478
  this.methods = methods;
877
479
  this.config = config;
878
480
  this.destroyMethod = destroyMethod;
481
+ this.providerInstance = providerInstance;
879
482
  this.sandboxId = sandboxId;
880
483
  this.provider = providerName;
484
+ this.instance = sandbox;
881
485
  if (methods.filesystem) {
882
- this.filesystem = new SupportedFileSystem(sandbox, methods.filesystem);
486
+ this.filesystem = new SupportedFileSystem(sandbox, methods.filesystem, methods);
883
487
  } else {
884
488
  this.filesystem = new UnsupportedFileSystem(providerName);
885
489
  }
886
- if (methods.terminal) {
887
- this.terminal = new SupportedTerminal(sandbox, methods.terminal);
888
- } else {
889
- this.terminal = new UnsupportedTerminal(providerName);
890
- }
891
490
  }
892
491
  async runCode(code, runtime) {
893
492
  return await this.methods.runCode(this.sandbox, code, runtime, this.config);
@@ -898,6 +497,12 @@ var GeneratedSandbox = class {
898
497
  async getInfo() {
899
498
  return await this.methods.getInfo(this.sandbox);
900
499
  }
500
+ async getUrl(options) {
501
+ return await this.methods.getUrl(this.sandbox, options);
502
+ }
503
+ getProvider() {
504
+ return this.providerInstance;
505
+ }
901
506
  async kill() {
902
507
  await this.destroy();
903
508
  }
@@ -906,10 +511,11 @@ var GeneratedSandbox = class {
906
511
  }
907
512
  };
908
513
  var GeneratedSandboxManager = class {
909
- constructor(config, providerName, methods) {
514
+ constructor(config, providerName, methods, providerInstance) {
910
515
  this.config = config;
911
516
  this.providerName = providerName;
912
517
  this.methods = methods;
518
+ this.providerInstance = providerInstance;
913
519
  this.activeSandboxes = /* @__PURE__ */ new Map();
914
520
  }
915
521
  async create(options) {
@@ -920,7 +526,8 @@ var GeneratedSandboxManager = class {
920
526
  this.providerName,
921
527
  this.methods,
922
528
  this.config,
923
- this.methods.destroy
529
+ this.methods.destroy,
530
+ this.providerInstance
924
531
  );
925
532
  this.activeSandboxes.set(result.sandboxId, sandbox);
926
533
  return sandbox;
@@ -940,7 +547,8 @@ var GeneratedSandboxManager = class {
940
547
  this.providerName,
941
548
  this.methods,
942
549
  this.config,
943
- this.methods.destroy
550
+ this.methods.destroy,
551
+ this.providerInstance
944
552
  );
945
553
  this.activeSandboxes.set(result.sandboxId, sandbox);
946
554
  return sandbox;
@@ -957,7 +565,8 @@ var GeneratedSandboxManager = class {
957
565
  this.providerName,
958
566
  this.methods,
959
567
  this.config,
960
- this.methods.destroy
568
+ this.methods.destroy,
569
+ this.providerInstance
961
570
  );
962
571
  this.activeSandboxes.set(result.sandboxId, sandbox);
963
572
  }
@@ -976,20 +585,25 @@ var GeneratedProvider = class {
976
585
  this.sandbox = new GeneratedSandboxManager(
977
586
  config,
978
587
  providerConfig.name,
979
- providerConfig.methods.sandbox
588
+ providerConfig.methods.sandbox,
589
+ this
980
590
  );
981
591
  }
982
592
  };
983
593
  function createProvider(providerConfig) {
594
+ if (!providerConfig.methods.sandbox.filesystem) {
595
+ providerConfig.methods.sandbox.filesystem = defaultFilesystemMethods;
596
+ }
984
597
  return (config) => {
985
598
  return new GeneratedProvider(config, providerConfig);
986
599
  };
987
600
  }
988
601
  // Annotate the CommonJS export names for ESM import in node:
989
602
  0 && (module.exports = {
990
- SandboxManager,
603
+ CommandExitError,
991
604
  compute,
992
605
  createProvider,
993
- handleComputeRequest
606
+ handleComputeRequest,
607
+ isCommandExitError
994
608
  });
995
609
  //# sourceMappingURL=index.js.map