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