computesdk 1.1.0 → 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,15 +58,16 @@ var ComputeManager = class {
74
58
  * provider: e2b({ apiKey: 'your-key' })
75
59
  * })
76
60
  *
77
- * // With default provider
78
- * compute.setConfig({ provider: e2b({ apiKey: 'your-key' }) })
79
- * const sandbox = 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()
80
65
  * ```
81
66
  */
82
67
  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);
68
+ const provider = params && "provider" in params && params.provider ? params.provider : this.getDefaultProvider();
69
+ const options = params?.options;
70
+ return await provider.sandbox.create(options);
86
71
  },
87
72
  /**
88
73
  * Get an existing sandbox by ID from a provider (or default provider if configured)
@@ -90,12 +75,12 @@ var ComputeManager = class {
90
75
  getById: async (providerOrSandboxId, sandboxId) => {
91
76
  if (typeof providerOrSandboxId === "string") {
92
77
  const provider = this.getDefaultProvider();
93
- return await this.sandboxManager.getById(provider, providerOrSandboxId);
78
+ return await provider.sandbox.getById(providerOrSandboxId);
94
79
  } else {
95
80
  if (!sandboxId) {
96
81
  throw new Error("sandboxId is required when provider is specified");
97
82
  }
98
- return await this.sandboxManager.getById(providerOrSandboxId, sandboxId);
83
+ return await providerOrSandboxId.sandbox.getById(sandboxId);
99
84
  }
100
85
  },
101
86
  /**
@@ -103,7 +88,7 @@ var ComputeManager = class {
103
88
  */
104
89
  list: async (provider) => {
105
90
  const actualProvider = provider || this.getDefaultProvider();
106
- return await this.sandboxManager.list(actualProvider);
91
+ return await actualProvider.sandbox.list();
107
92
  },
108
93
  /**
109
94
  * Destroy a sandbox via a provider (or default provider if configured)
@@ -111,12 +96,12 @@ var ComputeManager = class {
111
96
  destroy: async (providerOrSandboxId, sandboxId) => {
112
97
  if (typeof providerOrSandboxId === "string") {
113
98
  const provider = this.getDefaultProvider();
114
- return await this.sandboxManager.destroy(provider, providerOrSandboxId);
99
+ return await provider.sandbox.destroy(providerOrSandboxId);
115
100
  } else {
116
101
  if (!sandboxId) {
117
102
  throw new Error("sandboxId is required when provider is specified");
118
103
  }
119
- return await this.sandboxManager.destroy(providerOrSandboxId, sandboxId);
104
+ return await providerOrSandboxId.sandbox.destroy(sandboxId);
120
105
  }
121
106
  }
122
107
  };
@@ -125,7 +110,17 @@ var ComputeManager = class {
125
110
  * Set default configuration
126
111
  */
127
112
  setConfig(config) {
128
- 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
+ };
129
124
  }
130
125
  /**
131
126
  * Get current configuration
@@ -145,7 +140,7 @@ var ComputeManager = class {
145
140
  getDefaultProvider() {
146
141
  if (!this.config?.provider) {
147
142
  throw new Error(
148
- "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."
149
144
  );
150
145
  }
151
146
  return this.config.provider;
@@ -154,567 +149,281 @@ var ComputeManager = class {
154
149
  // blob = new BlobManager();
155
150
  // database = new DatabaseManager();
156
151
  // git = new GitManager();
157
- /**
158
- * Get the sandbox manager (useful for testing)
159
- */
160
- getSandboxManager() {
161
- return this.sandboxManager;
162
- }
163
152
  };
164
153
  var compute = new ComputeManager();
165
154
 
166
155
  // src/request-handler.ts
167
- async function handleComputeRequest(params) {
168
- const { request, provider } = params;
156
+ async function executeAction(body, provider) {
169
157
  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
- });
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");
182
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
183
306
  };
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,
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",
243
325
  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
326
  provider: provider.name
464
- };
327
+ }, { status: 405 });
465
328
  }
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 {
329
+ try {
330
+ body = await requestOrBody.json();
331
+ } catch (parseError) {
332
+ return Response.json({
701
333
  success: false,
702
- error: `Unknown action: ${request.action}`,
703
- sandboxId: request.sandboxId || "",
334
+ error: "Invalid JSON in request body",
335
+ sandboxId: "",
704
336
  provider: provider.name
705
- };
337
+ }, { status: 400 });
338
+ }
339
+ } else {
340
+ body = requestOrBody;
706
341
  }
342
+ const result = await executeAction(body, provider);
343
+ return Response.json(result, {
344
+ status: result.success ? 200 : 500
345
+ });
707
346
  } catch (error) {
708
- return {
347
+ return Response.json({
709
348
  success: false,
710
- error: error instanceof Error ? error.message : "Unknown error occurred",
711
- sandboxId: request.sandboxId || "",
349
+ error: error instanceof Error ? error.message : "Request handling failed",
350
+ sandboxId: "",
712
351
  provider: provider.name
713
- };
352
+ }, { status: 500 });
714
353
  }
715
354
  }
716
355
 
717
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
+ };
718
427
  var UnsupportedFileSystem = class {
719
428
  constructor(providerName) {
720
429
  this.providerName = providerName;
@@ -738,155 +447,46 @@ var UnsupportedFileSystem = class {
738
447
  throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
739
448
  }
740
449
  };
741
- var UnsupportedTerminal = class {
742
- constructor(providerName) {
743
- this.providerName = providerName;
744
- }
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.`);
747
- }
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.`);
750
- }
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.`);
753
- }
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.`);
756
- }
757
- };
758
450
  var SupportedFileSystem = class {
759
- constructor(sandbox, methods) {
451
+ constructor(sandbox, methods, allMethods) {
760
452
  this.sandbox = sandbox;
761
453
  this.methods = methods;
454
+ this.allMethods = allMethods;
762
455
  }
763
456
  async readFile(path) {
764
- return this.methods.readFile(this.sandbox, path);
457
+ return this.methods.readFile(this.sandbox, path, this.allMethods.runCommand);
765
458
  }
766
459
  async writeFile(path, content) {
767
- return this.methods.writeFile(this.sandbox, path, content);
460
+ return this.methods.writeFile(this.sandbox, path, content, this.allMethods.runCommand);
768
461
  }
769
462
  async mkdir(path) {
770
- return this.methods.mkdir(this.sandbox, path);
463
+ return this.methods.mkdir(this.sandbox, path, this.allMethods.runCommand);
771
464
  }
772
465
  async readdir(path) {
773
- return this.methods.readdir(this.sandbox, path);
466
+ return this.methods.readdir(this.sandbox, path, this.allMethods.runCommand);
774
467
  }
775
468
  async exists(path) {
776
- return this.methods.exists(this.sandbox, path);
469
+ return this.methods.exists(this.sandbox, path, this.allMethods.runCommand);
777
470
  }
778
471
  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
- }
821
- }
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;
836
- }
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);
472
+ return this.methods.remove(this.sandbox, path, this.allMethods.runCommand);
870
473
  }
871
474
  };
872
475
  var GeneratedSandbox = class {
873
- constructor(sandbox, sandboxId, providerName, methods, config, destroyMethod) {
476
+ constructor(sandbox, sandboxId, providerName, methods, config, destroyMethod, providerInstance) {
874
477
  this.sandbox = sandbox;
875
478
  this.methods = methods;
876
479
  this.config = config;
877
480
  this.destroyMethod = destroyMethod;
481
+ this.providerInstance = providerInstance;
878
482
  this.sandboxId = sandboxId;
879
483
  this.provider = providerName;
484
+ this.instance = sandbox;
880
485
  if (methods.filesystem) {
881
- this.filesystem = new SupportedFileSystem(sandbox, methods.filesystem);
486
+ this.filesystem = new SupportedFileSystem(sandbox, methods.filesystem, methods);
882
487
  } else {
883
488
  this.filesystem = new UnsupportedFileSystem(providerName);
884
489
  }
885
- if (methods.terminal) {
886
- this.terminal = new SupportedTerminal(sandbox, methods.terminal);
887
- } else {
888
- this.terminal = new UnsupportedTerminal(providerName);
889
- }
890
490
  }
891
491
  async runCode(code, runtime) {
892
492
  return await this.methods.runCode(this.sandbox, code, runtime, this.config);
@@ -897,6 +497,12 @@ var GeneratedSandbox = class {
897
497
  async getInfo() {
898
498
  return await this.methods.getInfo(this.sandbox);
899
499
  }
500
+ async getUrl(options) {
501
+ return await this.methods.getUrl(this.sandbox, options);
502
+ }
503
+ getProvider() {
504
+ return this.providerInstance;
505
+ }
900
506
  async kill() {
901
507
  await this.destroy();
902
508
  }
@@ -905,10 +511,11 @@ var GeneratedSandbox = class {
905
511
  }
906
512
  };
907
513
  var GeneratedSandboxManager = class {
908
- constructor(config, providerName, methods) {
514
+ constructor(config, providerName, methods, providerInstance) {
909
515
  this.config = config;
910
516
  this.providerName = providerName;
911
517
  this.methods = methods;
518
+ this.providerInstance = providerInstance;
912
519
  this.activeSandboxes = /* @__PURE__ */ new Map();
913
520
  }
914
521
  async create(options) {
@@ -919,7 +526,8 @@ var GeneratedSandboxManager = class {
919
526
  this.providerName,
920
527
  this.methods,
921
528
  this.config,
922
- this.methods.destroy
529
+ this.methods.destroy,
530
+ this.providerInstance
923
531
  );
924
532
  this.activeSandboxes.set(result.sandboxId, sandbox);
925
533
  return sandbox;
@@ -939,7 +547,8 @@ var GeneratedSandboxManager = class {
939
547
  this.providerName,
940
548
  this.methods,
941
549
  this.config,
942
- this.methods.destroy
550
+ this.methods.destroy,
551
+ this.providerInstance
943
552
  );
944
553
  this.activeSandboxes.set(result.sandboxId, sandbox);
945
554
  return sandbox;
@@ -956,7 +565,8 @@ var GeneratedSandboxManager = class {
956
565
  this.providerName,
957
566
  this.methods,
958
567
  this.config,
959
- this.methods.destroy
568
+ this.methods.destroy,
569
+ this.providerInstance
960
570
  );
961
571
  this.activeSandboxes.set(result.sandboxId, sandbox);
962
572
  }
@@ -975,20 +585,25 @@ var GeneratedProvider = class {
975
585
  this.sandbox = new GeneratedSandboxManager(
976
586
  config,
977
587
  providerConfig.name,
978
- providerConfig.methods.sandbox
588
+ providerConfig.methods.sandbox,
589
+ this
979
590
  );
980
591
  }
981
592
  };
982
593
  function createProvider(providerConfig) {
594
+ if (!providerConfig.methods.sandbox.filesystem) {
595
+ providerConfig.methods.sandbox.filesystem = defaultFilesystemMethods;
596
+ }
983
597
  return (config) => {
984
598
  return new GeneratedProvider(config, providerConfig);
985
599
  };
986
600
  }
987
601
  // Annotate the CommonJS export names for ESM import in node:
988
602
  0 && (module.exports = {
989
- SandboxManager,
603
+ CommandExitError,
990
604
  compute,
991
605
  createProvider,
992
- handleComputeRequest
606
+ handleComputeRequest,
607
+ isCommandExitError
993
608
  });
994
609
  //# sourceMappingURL=index.js.map