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