computesdk 1.8.8 → 1.9.1

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,228 +1,767 @@
1
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";
2
+ import { Sandbox } from "@computesdk/client";
3
+ import {
4
+ CommandExitError,
5
+ isCommandExitError
6
+ } from "@computesdk/client";
7
+
8
+ // src/constants.ts
9
+ var GATEWAY_URL = "https://gateway.computesdk.com";
10
+ var PROVIDER_PRIORITY = [
11
+ "e2b",
12
+ "railway",
13
+ "daytona",
14
+ "modal",
15
+ "runloop",
16
+ "vercel",
17
+ "cloudflare",
18
+ "codesandbox",
19
+ "blaxel"
20
+ ];
21
+ var PROVIDER_ENV_VARS = {
22
+ e2b: ["E2B_API_KEY"],
23
+ railway: ["RAILWAY_API_KEY", "RAILWAY_PROJECT_ID", "RAILWAY_ENVIRONMENT_ID"],
24
+ daytona: ["DAYTONA_API_KEY"],
25
+ modal: ["MODAL_TOKEN_ID", "MODAL_TOKEN_SECRET"],
26
+ runloop: ["RUNLOOP_API_KEY"],
27
+ vercel: ["VERCEL_TOKEN", "VERCEL_TEAM_ID", "VERCEL_PROJECT_ID"],
28
+ cloudflare: ["CLOUDFLARE_API_TOKEN", "CLOUDFLARE_ACCOUNT_ID"],
29
+ codesandbox: ["CSB_API_KEY"],
30
+ blaxel: ["BL_API_KEY", "BL_WORKSPACE"]
31
+ };
32
+
33
+ // src/providers/gateway.ts
34
+ import { Sandbox as ClientSandbox } from "@computesdk/client";
35
+
36
+ // src/factory.ts
37
+ import { cmd } from "@computesdk/cmd";
38
+ var UnsupportedFileSystem = class {
39
+ constructor(providerName) {
40
+ this.providerName = providerName;
41
+ }
42
+ async readFile(_path) {
43
+ throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
44
+ }
45
+ async writeFile(_path, _content) {
46
+ throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
47
+ }
48
+ async mkdir(_path) {
49
+ throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
50
+ }
51
+ async readdir(_path) {
52
+ throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
53
+ }
54
+ async exists(_path) {
55
+ throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
56
+ }
57
+ async remove(_path) {
58
+ throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
7
59
  }
8
60
  };
9
- function isCommandExitError(error) {
10
- return typeof error === "object" && error !== null && "name" in error && error.name === "CommandExitError" && "result" in error;
61
+ var SupportedFileSystem = class {
62
+ constructor(sandbox, methods, allMethods) {
63
+ this.sandbox = sandbox;
64
+ this.methods = methods;
65
+ this.allMethods = allMethods;
66
+ }
67
+ async readFile(path) {
68
+ return this.methods.readFile(this.sandbox, path, this.allMethods.runCommand);
69
+ }
70
+ async writeFile(path, content) {
71
+ return this.methods.writeFile(this.sandbox, path, content, this.allMethods.runCommand);
72
+ }
73
+ async mkdir(path) {
74
+ return this.methods.mkdir(this.sandbox, path, this.allMethods.runCommand);
75
+ }
76
+ async readdir(path) {
77
+ return this.methods.readdir(this.sandbox, path, this.allMethods.runCommand);
78
+ }
79
+ async exists(path) {
80
+ return this.methods.exists(this.sandbox, path, this.allMethods.runCommand);
81
+ }
82
+ async remove(path) {
83
+ return this.methods.remove(this.sandbox, path, this.allMethods.runCommand);
84
+ }
85
+ };
86
+ var GeneratedSandbox = class {
87
+ constructor(sandbox, sandboxId, providerName, methods, config, destroyMethod, providerInstance) {
88
+ this.sandbox = sandbox;
89
+ this.methods = methods;
90
+ this.config = config;
91
+ this.destroyMethod = destroyMethod;
92
+ this.providerInstance = providerInstance;
93
+ this.sandboxId = sandboxId;
94
+ this.provider = providerName;
95
+ if (methods.filesystem) {
96
+ this.filesystem = new SupportedFileSystem(sandbox, methods.filesystem, methods);
97
+ } else {
98
+ this.filesystem = new UnsupportedFileSystem(providerName);
99
+ }
100
+ }
101
+ getInstance() {
102
+ if (this.methods.getInstance) {
103
+ return this.methods.getInstance(this.sandbox);
104
+ }
105
+ return this.sandbox;
106
+ }
107
+ async runCode(code, runtime) {
108
+ return await this.methods.runCode(this.sandbox, code, runtime, this.config);
109
+ }
110
+ async runCommand(commandOrArray, argsOrOptions, maybeOptions) {
111
+ let command;
112
+ let args;
113
+ let options;
114
+ if (Array.isArray(commandOrArray)) {
115
+ [command, ...args] = commandOrArray;
116
+ options = argsOrOptions;
117
+ } else {
118
+ command = commandOrArray;
119
+ args = Array.isArray(argsOrOptions) ? argsOrOptions : [];
120
+ options = Array.isArray(argsOrOptions) ? maybeOptions : argsOrOptions;
121
+ }
122
+ const baseCommand = args.length > 0 ? [command, ...args] : [command];
123
+ if (options?.cwd || options?.background) {
124
+ const wrappedCommand = cmd(baseCommand, {
125
+ cwd: options.cwd,
126
+ background: options.background
127
+ });
128
+ const [wrappedCmd, ...wrappedArgs] = wrappedCommand;
129
+ return await this.methods.runCommand(this.sandbox, wrappedCmd, wrappedArgs, void 0);
130
+ }
131
+ return await this.methods.runCommand(this.sandbox, command, args, options);
132
+ }
133
+ async getInfo() {
134
+ return await this.methods.getInfo(this.sandbox);
135
+ }
136
+ async getUrl(options) {
137
+ return await this.methods.getUrl(this.sandbox, options);
138
+ }
139
+ getProvider() {
140
+ return this.providerInstance;
141
+ }
142
+ async kill() {
143
+ await this.destroy();
144
+ }
145
+ async destroy() {
146
+ await this.destroyMethod(this.config, this.sandboxId);
147
+ }
148
+ };
149
+ function getEffectiveMode(config, defaultMode) {
150
+ if (config.mode) {
151
+ return config.mode;
152
+ }
153
+ return defaultMode;
11
154
  }
12
-
13
- // src/auth/license.ts
14
- async function authorizeApiKey(apiKey) {
15
- try {
16
- const response = await fetch("https://sandbox.computesdk.com/__api/license/authorize", {
17
- method: "POST",
18
- headers: {
19
- "Content-Type": "application/json"
20
- },
21
- body: JSON.stringify({
22
- key: apiKey,
23
- increment_usage: 1
24
- })
25
- });
26
- if (!response.ok) {
27
- const errorText = await response.text().catch(() => response.statusText);
28
- throw new Error(`License authorization failed (${response.status}): ${errorText}`);
155
+ var GeneratedSandboxManager = class {
156
+ constructor(config, providerName, methods, providerInstance, defaultMode) {
157
+ this.config = config;
158
+ this.providerName = providerName;
159
+ this.methods = methods;
160
+ this.providerInstance = providerInstance;
161
+ this.effectiveMode = getEffectiveMode(config, defaultMode);
162
+ }
163
+ async create(options) {
164
+ const optionsWithDefaults = { runtime: "node", ...options };
165
+ const result = await this.methods.create(this.config, optionsWithDefaults);
166
+ return new GeneratedSandbox(
167
+ result.sandbox,
168
+ result.sandboxId,
169
+ this.providerName,
170
+ this.methods,
171
+ this.config,
172
+ this.methods.destroy,
173
+ this.providerInstance
174
+ );
175
+ }
176
+ async getById(sandboxId) {
177
+ const result = await this.methods.getById(this.config, sandboxId);
178
+ if (!result) {
179
+ return null;
29
180
  }
30
- const data = await response.json();
31
- if (!data.access_token) {
32
- throw new Error("No access token received from license server");
181
+ return new GeneratedSandbox(
182
+ result.sandbox,
183
+ result.sandboxId,
184
+ this.providerName,
185
+ this.methods,
186
+ this.config,
187
+ this.methods.destroy,
188
+ this.providerInstance
189
+ );
190
+ }
191
+ async list() {
192
+ const results = await this.methods.list(this.config);
193
+ return results.map((result) => new GeneratedSandbox(
194
+ result.sandbox,
195
+ result.sandboxId,
196
+ this.providerName,
197
+ this.methods,
198
+ this.config,
199
+ this.methods.destroy,
200
+ this.providerInstance
201
+ ));
202
+ }
203
+ async destroy(sandboxId) {
204
+ await this.methods.destroy(this.config, sandboxId);
205
+ }
206
+ };
207
+ var GeneratedTemplateManager = class {
208
+ constructor(config, methods) {
209
+ this.config = config;
210
+ this.methods = methods;
211
+ }
212
+ async create(options) {
213
+ return await this.methods.create(this.config, options);
214
+ }
215
+ async list(options) {
216
+ return await this.methods.list(this.config, options);
217
+ }
218
+ async delete(templateId) {
219
+ return await this.methods.delete(this.config, templateId);
220
+ }
221
+ };
222
+ var GeneratedSnapshotManager = class {
223
+ constructor(config, methods) {
224
+ this.config = config;
225
+ this.methods = methods;
226
+ }
227
+ async create(sandboxId, options) {
228
+ return await this.methods.create(this.config, sandboxId, options);
229
+ }
230
+ async list(options) {
231
+ return await this.methods.list(this.config, options);
232
+ }
233
+ async delete(snapshotId) {
234
+ return await this.methods.delete(this.config, snapshotId);
235
+ }
236
+ };
237
+ var GeneratedProvider = class {
238
+ constructor(config, providerConfig) {
239
+ this.name = providerConfig.name;
240
+ this.sandbox = new GeneratedSandboxManager(
241
+ config,
242
+ providerConfig.name,
243
+ providerConfig.methods.sandbox,
244
+ this,
245
+ providerConfig.defaultMode ?? "gateway"
246
+ );
247
+ if (providerConfig.methods.template) {
248
+ this.template = new GeneratedTemplateManager(config, providerConfig.methods.template);
33
249
  }
34
- if (!data.sandbox_url) {
35
- throw new Error("No sandbox_url received from license server");
250
+ if (providerConfig.methods.snapshot) {
251
+ this.snapshot = new GeneratedSnapshotManager(config, providerConfig.methods.snapshot);
36
252
  }
37
- if (!data.preview_url) {
38
- throw new Error("No preview_url received from license server");
253
+ }
254
+ getSupportedRuntimes() {
255
+ return ["node", "python"];
256
+ }
257
+ };
258
+ function createProvider(providerConfig) {
259
+ return (config) => {
260
+ return new GeneratedProvider(config, providerConfig);
261
+ };
262
+ }
263
+
264
+ // src/compute-daemon/lifecycle.ts
265
+ async function waitForComputeReady(client, options = {}) {
266
+ const maxRetries = options.maxRetries ?? 30;
267
+ const initialDelayMs = options.initialDelayMs ?? 500;
268
+ const maxDelayMs = options.maxDelayMs ?? 5e3;
269
+ const backoffFactor = options.backoffFactor ?? 1.5;
270
+ let lastError = null;
271
+ let currentDelay = initialDelayMs;
272
+ for (let i = 0; i < maxRetries; i++) {
273
+ try {
274
+ await client.health();
275
+ if (process.env.COMPUTESDK_DEBUG) {
276
+ console.log(`[Lifecycle] Sandbox ready after ${i + 1} attempt${i === 0 ? "" : "s"}`);
277
+ }
278
+ return;
279
+ } catch (error) {
280
+ lastError = error instanceof Error ? error : new Error(String(error));
281
+ if (i === maxRetries - 1) {
282
+ throw new Error(
283
+ `Sandbox failed to become ready after ${maxRetries} attempts.
284
+ Last error: ${lastError.message}
285
+
286
+ Possible causes:
287
+ 1. Sandbox failed to start (check provider dashboard for errors)
288
+ 2. Network connectivity issues between your app and the sandbox
289
+ 3. Sandbox is taking longer than expected to initialize
290
+ 4. Invalid sandbox URL or authentication credentials
291
+
292
+ Troubleshooting:
293
+ - Check sandbox logs in your provider dashboard
294
+ - Verify your network connection
295
+ - Try increasing maxRetries if initialization is slow
296
+ - Enable debug mode: export COMPUTESDK_DEBUG=1`
297
+ );
298
+ }
299
+ await new Promise((resolve) => setTimeout(resolve, currentDelay));
300
+ currentDelay = Math.min(currentDelay * backoffFactor, maxDelayMs);
39
301
  }
40
- return {
41
- access_token: data.access_token,
42
- sandbox_url: data.sandbox_url,
43
- preview_url: data.preview_url
44
- };
45
- } catch (error) {
46
- if (error instanceof Error && error.message.includes("License authorization failed")) {
47
- throw error;
302
+ }
303
+ }
304
+
305
+ // src/utils.ts
306
+ function calculateBackoff(attempt, baseDelay = 1e3, jitterMax = 100) {
307
+ return baseDelay * Math.pow(2, attempt) + Math.random() * jitterMax;
308
+ }
309
+
310
+ // src/providers/gateway.ts
311
+ import { Sandbox as Sandbox2 } from "@computesdk/client";
312
+ var DEFAULT_GATEWAY_URL = "https://gateway.computesdk.com";
313
+ var DEFAULT_REQUEST_TIMEOUT = 3e4;
314
+ var DEFAULT_MAX_RETRIES = 3;
315
+ var DEFAULT_RETRY_DELAY = 1e3;
316
+ var DEFAULT_RETRYABLE_STATUSES = [408, 429, 502, 503, 504];
317
+ var hasWarnedAboutMissingToken = false;
318
+ var GatewayError = class extends Error {
319
+ constructor(message, statusCode, provider, sandboxId, requestId) {
320
+ super(message);
321
+ this.statusCode = statusCode;
322
+ this.provider = provider;
323
+ this.sandboxId = sandboxId;
324
+ this.requestId = requestId;
325
+ this.name = "GatewayError";
326
+ }
327
+ };
328
+ async function gatewayFetch(url, config, options = {}) {
329
+ const timeout = config.requestTimeout ?? DEFAULT_REQUEST_TIMEOUT;
330
+ const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
331
+ const retryDelay = config.retryDelay ?? DEFAULT_RETRY_DELAY;
332
+ const retryableStatuses = config.retryableStatuses ?? DEFAULT_RETRYABLE_STATUSES;
333
+ let lastError = null;
334
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
335
+ const startTime = Date.now();
336
+ const controller = new AbortController();
337
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
338
+ try {
339
+ const response = await fetch(url, {
340
+ ...options,
341
+ signal: controller.signal,
342
+ headers: {
343
+ "Content-Type": "application/json",
344
+ "X-ComputeSDK-API-Key": config.apiKey,
345
+ "X-Provider": config.provider,
346
+ ...config.providerHeaders || {},
347
+ ...options.headers
348
+ }
349
+ });
350
+ clearTimeout(timeoutId);
351
+ const duration = Date.now() - startTime;
352
+ if (process.env.COMPUTESDK_DEBUG) {
353
+ console.log(`[Gateway] ${options.method || "GET"} ${url} - ${response.status} (${duration}ms)`);
354
+ }
355
+ if (!response.ok) {
356
+ if (response.status === 404) {
357
+ return { success: false };
358
+ }
359
+ const errorText = await response.text().catch(() => response.statusText);
360
+ const requestId = response.headers.get("x-request-id");
361
+ const isRetryable = retryableStatuses.includes(response.status);
362
+ const shouldRetry = isRetryable && attempt < maxRetries;
363
+ if (shouldRetry) {
364
+ const delay = calculateBackoff(attempt, retryDelay);
365
+ if (process.env.COMPUTESDK_DEBUG) {
366
+ console.log(`[Gateway] Retry ${attempt + 1}/${maxRetries} after ${delay.toFixed(0)}ms (status: ${response.status})...`);
367
+ }
368
+ await new Promise((resolve) => setTimeout(resolve, delay));
369
+ continue;
370
+ }
371
+ let errorMessage = `Gateway API error: ${errorText}`;
372
+ if (response.status === 401) {
373
+ errorMessage = `Invalid ComputeSDK API key.
374
+
375
+ Check your COMPUTESDK_API_KEY environment variable.
376
+ Get your key at: https://computesdk.com/dashboard`;
377
+ } else if (response.status === 403) {
378
+ errorMessage = `Access forbidden. Your API key may not have permission to use provider "${config.provider}".
379
+
380
+ Visit https://computesdk.com/dashboard to check your plan.`;
381
+ } else if (response.status === 429) {
382
+ errorMessage = `Rate limit exceeded. Please try again in a moment.
383
+
384
+ If this persists, visit https://computesdk.com/dashboard to upgrade your plan.`;
385
+ } else if (response.status >= 500) {
386
+ errorMessage = `Gateway server error (${response.status}). This is temporary - please try again.
387
+
388
+ If this persists, check status at https://status.computesdk.com`;
389
+ }
390
+ throw new GatewayError(
391
+ errorMessage,
392
+ response.status,
393
+ config.provider,
394
+ void 0,
395
+ requestId || void 0
396
+ );
397
+ }
398
+ return response.json();
399
+ } catch (error) {
400
+ clearTimeout(timeoutId);
401
+ if (error instanceof GatewayError) {
402
+ lastError = error;
403
+ throw error;
404
+ }
405
+ if (error instanceof Error && error.name === "AbortError") {
406
+ const timeoutError = new GatewayError(
407
+ `Request timed out after ${timeout}ms.
408
+
409
+ The gateway may be experiencing high load or network issues.
410
+ Check your connection and try again.`,
411
+ 408,
412
+ config.provider
413
+ );
414
+ if (attempt < maxRetries) {
415
+ const delay = calculateBackoff(attempt, retryDelay);
416
+ if (process.env.COMPUTESDK_DEBUG) {
417
+ console.log(`[Gateway] Retry ${attempt + 1}/${maxRetries} after ${delay.toFixed(0)}ms (timeout)...`);
418
+ }
419
+ await new Promise((resolve) => setTimeout(resolve, delay));
420
+ lastError = timeoutError;
421
+ continue;
422
+ }
423
+ throw timeoutError;
424
+ }
425
+ const networkError = new GatewayError(
426
+ `Failed to connect to gateway: ${error instanceof Error ? error.message : String(error)}
427
+
428
+ Check your internet connection and gateway URL.`,
429
+ 0,
430
+ config.provider
431
+ );
432
+ if (attempt < maxRetries) {
433
+ const delay = calculateBackoff(attempt, retryDelay);
434
+ if (process.env.COMPUTESDK_DEBUG) {
435
+ console.log(`[Gateway] Retry ${attempt + 1}/${maxRetries} after ${delay.toFixed(0)}ms (network error)...`);
436
+ }
437
+ await new Promise((resolve) => setTimeout(resolve, delay));
438
+ lastError = networkError;
439
+ continue;
440
+ }
441
+ throw networkError;
48
442
  }
49
- throw new Error(`Failed to authorize API key (network error): ${error instanceof Error ? error.message : String(error)}`);
50
443
  }
444
+ throw lastError || new Error("Max retries exceeded");
51
445
  }
446
+ var gateway = createProvider({
447
+ name: "gateway",
448
+ methods: {
449
+ sandbox: {
450
+ create: async (config, options) => {
451
+ const gatewayUrl = config.gatewayUrl || DEFAULT_GATEWAY_URL;
452
+ const result = await gatewayFetch(`${gatewayUrl}/sandbox`, config, {
453
+ method: "POST",
454
+ body: JSON.stringify(options || {})
455
+ });
456
+ if (!result.success || !result.data) {
457
+ throw new Error(`Gateway returned invalid response: ${JSON.stringify(result)}`);
458
+ }
459
+ const { sandboxId, url, token, provider, metadata } = result.data;
460
+ if (process.env.COMPUTESDK_DEBUG) {
461
+ console.log(`[Gateway] Sandbox created:`, {
462
+ sandboxId,
463
+ url,
464
+ hasToken: !!token,
465
+ tokenPrefix: token ? token.substring(0, 10) + "..." : "none",
466
+ provider
467
+ });
468
+ }
469
+ if (!token && !hasWarnedAboutMissingToken) {
470
+ hasWarnedAboutMissingToken = true;
471
+ console.warn(
472
+ `[Gateway] No token received from gateway for sandbox ${sandboxId}. Falling back to API key for authentication. This may indicate the gateway is running an outdated version. Check gateway deployment at ${config.gatewayUrl || DEFAULT_GATEWAY_URL}`
473
+ );
474
+ }
475
+ const sandbox = new ClientSandbox({
476
+ sandboxUrl: url,
477
+ sandboxId,
478
+ provider,
479
+ token: token || config.apiKey,
480
+ // Use token from gateway, fallback to API key
481
+ metadata,
482
+ WebSocket: globalThis.WebSocket
483
+ });
484
+ await waitForComputeReady(sandbox);
485
+ return { sandbox, sandboxId };
486
+ },
487
+ getById: async (config, sandboxId) => {
488
+ const gatewayUrl = config.gatewayUrl || DEFAULT_GATEWAY_URL;
489
+ const result = await gatewayFetch(`${gatewayUrl}/sandbox/${sandboxId}`, config);
490
+ if (!result.success || !result.data) {
491
+ return null;
492
+ }
493
+ const { url, token, provider, metadata } = result.data;
494
+ if (!token && !hasWarnedAboutMissingToken) {
495
+ hasWarnedAboutMissingToken = true;
496
+ console.warn(
497
+ `[Gateway] No token received when reconnecting to sandbox ${sandboxId}. Falling back to API key for authentication. This may indicate the gateway is running an outdated version.`
498
+ );
499
+ }
500
+ const sandbox = new ClientSandbox({
501
+ sandboxUrl: url,
502
+ sandboxId,
503
+ provider,
504
+ token: token || config.apiKey,
505
+ // Use token from gateway, fallback to API key
506
+ metadata,
507
+ WebSocket: globalThis.WebSocket
508
+ });
509
+ await waitForComputeReady(sandbox);
510
+ return { sandbox, sandboxId };
511
+ },
512
+ list: async () => {
513
+ throw new Error(
514
+ "Gateway provider does not support listing sandboxes. Use getById() with a known sandbox ID instead."
515
+ );
516
+ },
517
+ destroy: async (config, sandboxId) => {
518
+ const gatewayUrl = config.gatewayUrl || DEFAULT_GATEWAY_URL;
519
+ await gatewayFetch(`${gatewayUrl}/sandbox/${sandboxId}`, config, {
520
+ method: "DELETE"
521
+ });
522
+ },
523
+ // All operations delegate directly to ClientSandbox
524
+ runCode: async (sandbox, code, runtime) => sandbox.runCode(code, runtime),
525
+ runCommand: async (sandbox, command, args) => sandbox.runCommand(command, args),
526
+ getUrl: async (sandbox, options) => sandbox.getUrl(options),
527
+ getInfo: async (sandbox) => {
528
+ const info = await sandbox.getInfo();
529
+ return {
530
+ id: info.id,
531
+ provider: info.provider,
532
+ runtime: info.runtime,
533
+ status: info.status,
534
+ createdAt: info.createdAt,
535
+ timeout: info.timeout,
536
+ metadata: info.metadata || {}
537
+ };
538
+ },
539
+ // Filesystem delegates directly to ClientSandbox
540
+ filesystem: {
541
+ readFile: async (sandbox, path) => sandbox.filesystem.readFile(path),
542
+ writeFile: async (sandbox, path, content) => sandbox.filesystem.writeFile(path, content),
543
+ mkdir: async (sandbox, path) => sandbox.filesystem.mkdir(path),
544
+ readdir: async (sandbox, path) => sandbox.filesystem.readdir(path),
545
+ exists: async (sandbox, path) => sandbox.filesystem.exists(path),
546
+ remove: async (sandbox, path) => sandbox.filesystem.remove(path)
547
+ },
548
+ // getInstance returns the ClientSandbox directly
549
+ getInstance: (sandbox) => sandbox
550
+ }
551
+ }
552
+ });
52
553
 
53
- // src/compute-daemon/dependencies.ts
54
- async function isCommandAvailable(sandbox, command) {
55
- const result = await sandbox.runCommand("sh", ["-c", `command -v ${command}`]);
56
- return result.exitCode === 0;
554
+ // src/auto-detect.ts
555
+ function isGatewayModeEnabled() {
556
+ return !!(typeof process !== "undefined" && process.env?.COMPUTESDK_API_KEY);
557
+ }
558
+ function hasProviderEnv(provider) {
559
+ if (typeof process === "undefined") return false;
560
+ const requiredVars = PROVIDER_ENV_VARS[provider];
561
+ if (!requiredVars) return false;
562
+ return requiredVars.every((varName) => !!process.env?.[varName]);
57
563
  }
58
- async function detectPackageManager(sandbox) {
59
- if (await isCommandAvailable(sandbox, "apk")) {
60
- return "apk";
564
+ function getProviderEnvStatus(provider) {
565
+ const requiredVars = PROVIDER_ENV_VARS[provider];
566
+ if (typeof process === "undefined" || !requiredVars) {
567
+ return { provider, present: [], missing: requiredVars ? [...requiredVars] : [], isComplete: false };
61
568
  }
62
- if (await isCommandAvailable(sandbox, "apt-get")) {
63
- return "apt";
569
+ const present = requiredVars.filter((varName) => !!process.env?.[varName]);
570
+ const missing = requiredVars.filter((varName) => !process.env?.[varName]);
571
+ return {
572
+ provider,
573
+ present: [...present],
574
+ missing: [...missing],
575
+ isComplete: missing.length === 0
576
+ };
577
+ }
578
+ function detectProvider() {
579
+ if (typeof process === "undefined") return null;
580
+ const explicit = process.env.COMPUTESDK_PROVIDER?.toLowerCase();
581
+ if (explicit && hasProviderEnv(explicit)) {
582
+ return explicit;
583
+ }
584
+ if (explicit && !hasProviderEnv(explicit)) {
585
+ console.warn(
586
+ `\u26A0\uFE0F COMPUTESDK_PROVIDER is set to "${explicit}" but required credentials are missing.
587
+ Required: ${PROVIDER_ENV_VARS[explicit]?.join(", ") || "unknown"}
588
+ Falling back to auto-detection...`
589
+ );
590
+ }
591
+ for (const provider of PROVIDER_PRIORITY) {
592
+ if (hasProviderEnv(provider)) {
593
+ return provider;
594
+ }
64
595
  }
65
596
  return null;
66
597
  }
67
- async function ensureDependencies(sandbox) {
68
- const hasCurl = await isCommandAvailable(sandbox, "curl");
69
- const hasBash = await isCommandAvailable(sandbox, "bash");
70
- if (hasCurl && hasBash) {
71
- return;
72
- }
73
- const packageManager = await detectPackageManager(sandbox);
74
- if (!packageManager) {
75
- throw new Error(
76
- `Missing required tools (curl: ${hasCurl}, bash: ${hasBash}), but no supported package manager found.
77
- Supported package managers: apk (Alpine), apt-get (Debian/Ubuntu).
78
- Please use a sandbox image that includes curl and bash, or install them manually first.`
79
- );
598
+ function getProviderHeaders(provider) {
599
+ if (typeof process === "undefined") return {};
600
+ const headers = {};
601
+ switch (provider) {
602
+ case "e2b":
603
+ if (process.env.E2B_API_KEY) {
604
+ headers["X-E2B-API-Key"] = process.env.E2B_API_KEY;
605
+ }
606
+ break;
607
+ case "railway":
608
+ if (process.env.RAILWAY_API_KEY) {
609
+ headers["X-Railway-API-Key"] = process.env.RAILWAY_API_KEY;
610
+ }
611
+ if (process.env.RAILWAY_PROJECT_ID) {
612
+ headers["X-Railway-Project-ID"] = process.env.RAILWAY_PROJECT_ID;
613
+ }
614
+ if (process.env.RAILWAY_ENVIRONMENT_ID) {
615
+ headers["X-Railway-Environment-ID"] = process.env.RAILWAY_ENVIRONMENT_ID;
616
+ }
617
+ break;
618
+ case "daytona":
619
+ if (process.env.DAYTONA_API_KEY) {
620
+ headers["X-Daytona-API-Key"] = process.env.DAYTONA_API_KEY;
621
+ }
622
+ break;
623
+ case "modal":
624
+ if (process.env.MODAL_TOKEN_ID) {
625
+ headers["X-Modal-Token-ID"] = process.env.MODAL_TOKEN_ID;
626
+ }
627
+ if (process.env.MODAL_TOKEN_SECRET) {
628
+ headers["X-Modal-Token-Secret"] = process.env.MODAL_TOKEN_SECRET;
629
+ }
630
+ break;
631
+ case "runloop":
632
+ if (process.env.RUNLOOP_API_KEY) {
633
+ headers["X-Runloop-API-Key"] = process.env.RUNLOOP_API_KEY;
634
+ }
635
+ break;
636
+ case "vercel":
637
+ if (process.env.VERCEL_TOKEN) {
638
+ headers["X-Vercel-Token"] = process.env.VERCEL_TOKEN;
639
+ }
640
+ if (process.env.VERCEL_TEAM_ID) {
641
+ headers["X-Vercel-Team-ID"] = process.env.VERCEL_TEAM_ID;
642
+ }
643
+ if (process.env.VERCEL_PROJECT_ID) {
644
+ headers["X-Vercel-Project-ID"] = process.env.VERCEL_PROJECT_ID;
645
+ }
646
+ break;
647
+ case "cloudflare":
648
+ if (process.env.CLOUDFLARE_API_TOKEN) {
649
+ headers["X-Cloudflare-API-Token"] = process.env.CLOUDFLARE_API_TOKEN;
650
+ }
651
+ if (process.env.CLOUDFLARE_ACCOUNT_ID) {
652
+ headers["X-Cloudflare-Account-ID"] = process.env.CLOUDFLARE_ACCOUNT_ID;
653
+ }
654
+ break;
655
+ case "codesandbox":
656
+ if (process.env.CSB_API_KEY) {
657
+ headers["X-CodeSandbox-API-Key"] = process.env.CSB_API_KEY;
658
+ }
659
+ break;
660
+ case "blaxel":
661
+ if (process.env.BL_API_KEY) {
662
+ headers["X-Blaxel-API-Key"] = process.env.BL_API_KEY;
663
+ }
664
+ if (process.env.BL_WORKSPACE) {
665
+ headers["X-Blaxel-Workspace"] = process.env.BL_WORKSPACE;
666
+ }
667
+ break;
80
668
  }
81
- let installResult;
82
- if (packageManager === "apk") {
83
- installResult = await sandbox.runCommand("sh", ["-c", "apk add --no-cache curl bash 2>&1"]);
84
- } else {
85
- installResult = await sandbox.runCommand("sh", ["-c", "apt-get update -qq && apt-get install -qq -y curl bash 2>&1"]);
669
+ return headers;
670
+ }
671
+ function autoConfigureCompute() {
672
+ if (!isGatewayModeEnabled()) {
673
+ return null;
86
674
  }
87
- if (installResult.exitCode !== 0) {
675
+ const provider = detectProvider();
676
+ if (!provider) {
677
+ const detectionResults = PROVIDER_PRIORITY.map((p) => getProviderEnvStatus(p));
678
+ const statusLines = detectionResults.map((result) => {
679
+ const status = result.isComplete ? "\u2705" : result.present.length > 0 ? "\u26A0\uFE0F " : "\u274C";
680
+ const ratio = `${result.present.length}/${result.present.length + result.missing.length}`;
681
+ let line = ` ${status} ${result.provider.padEnd(12)} ${ratio} credentials`;
682
+ if (result.present.length > 0 && result.missing.length > 0) {
683
+ line += ` (missing: ${result.missing.join(", ")})`;
684
+ }
685
+ return line;
686
+ });
88
687
  throw new Error(
89
- `Failed to install curl and bash using ${packageManager}.
90
- Install output: ${installResult.stderr || installResult.stdout}
91
- Please install curl and bash manually or use a different sandbox image.`
688
+ `COMPUTESDK_API_KEY is set but no provider detected.
689
+
690
+ Provider detection results:
691
+ ` + statusLines.join("\n") + `
692
+
693
+ To fix this, set one of the following:
694
+
695
+ E2B: export E2B_API_KEY=xxx
696
+ Railway: export RAILWAY_API_KEY=xxx RAILWAY_PROJECT_ID=xxx RAILWAY_ENVIRONMENT_ID=xxx
697
+ Daytona: export DAYTONA_API_KEY=xxx
698
+ Modal: export MODAL_TOKEN_ID=xxx MODAL_TOKEN_SECRET=xxx
699
+ Runloop: export RUNLOOP_API_KEY=xxx
700
+ Vercel: export VERCEL_TOKEN=xxx VERCEL_TEAM_ID=xxx VERCEL_PROJECT_ID=xxx
701
+ Cloudflare: export CLOUDFLARE_API_TOKEN=xxx CLOUDFLARE_ACCOUNT_ID=xxx
702
+ CodeSandbox: export CSB_API_KEY=xxx
703
+ Blaxel: export BL_API_KEY=xxx BL_WORKSPACE=xxx
704
+
705
+ Or set COMPUTESDK_PROVIDER to specify explicitly:
706
+ export COMPUTESDK_PROVIDER=e2b
707
+
708
+ Docs: https://computesdk.com/docs/quickstart`
92
709
  );
93
710
  }
94
- }
95
-
96
- // src/compute-daemon/installer.ts
97
- async function isComputeInstalled(sandbox) {
98
- const result = await sandbox.runCommand("sh", ["-c", 'test -f /usr/local/bin/compute && echo "exists" || echo "missing"']);
99
- return result.stdout?.trim() === "exists";
100
- }
101
- async function downloadInstallScript(sandbox) {
102
- const downloadResult = await sandbox.runCommand("sh", ["-c", "curl -fsSL https://computesdk.com/install.sh -o /tmp/compute-install.sh 2>&1"]);
103
- if (downloadResult.exitCode !== 0) {
104
- const errorOutput = downloadResult.stderr || downloadResult.stdout || "unknown error";
711
+ const gatewayUrl = process.env.COMPUTESDK_GATEWAY_URL || GATEWAY_URL;
712
+ const computesdkApiKey = process.env.COMPUTESDK_API_KEY;
713
+ const providerHeaders = getProviderHeaders(provider);
714
+ try {
715
+ new URL(gatewayUrl);
716
+ } catch (error) {
105
717
  throw new Error(
106
- `Failed to download install script from https://computesdk.com/install.sh: ${errorOutput}`
718
+ `Invalid gateway URL: "${gatewayUrl}"
719
+
720
+ The URL must be a valid HTTP/HTTPS URL.
721
+ Check your COMPUTESDK_GATEWAY_URL environment variable.`
107
722
  );
108
723
  }
109
- }
110
- async function runInstallScript(sandbox, accessToken) {
111
- const installCommand = accessToken ? `bash /tmp/compute-install.sh --non-interactive --access-token "${accessToken}" --location /usr/local/bin` : `bash /tmp/compute-install.sh --non-interactive --location /usr/local/bin`;
112
- const installResult = await sandbox.runCommand("bash", ["-c", installCommand]);
113
- if (installResult.exitCode !== 0) {
114
- const errorOutput = installResult.stderr || installResult.stdout || "unknown error";
115
- throw new Error(`Failed to install compute daemon: ${errorOutput}`);
116
- }
117
- }
118
- async function installComputeDaemon(sandbox, accessToken) {
119
- if (await isComputeInstalled(sandbox)) {
120
- return;
121
- }
122
- await ensureDependencies(sandbox);
123
- await downloadInstallScript(sandbox);
124
- await runInstallScript(sandbox, accessToken);
125
- if (!await isComputeInstalled(sandbox)) {
126
- throw new Error("Compute binary not found at /usr/local/bin/compute after installation");
127
- }
128
- }
129
-
130
- // src/sandbox/wrapper.ts
131
- import { ComputeClient } from "@computesdk/client";
132
-
133
- // src/compute-daemon/lifecycle.ts
134
- async function waitForComputeReady(client, maxRetries = 30, delayMs = 2e3) {
135
- let lastError = null;
136
- for (let i = 0; i < maxRetries; i++) {
137
- try {
138
- await client.health();
139
- return;
140
- } catch (error) {
141
- lastError = error instanceof Error ? error : new Error(String(error));
142
- if (i === maxRetries - 1) {
143
- throw new Error(
144
- `Compute daemon failed to start after ${maxRetries} attempts (${maxRetries * delayMs / 1e3}s).
145
- Last error: ${lastError.message}
146
- This could indicate:
147
- 1. The compute daemon failed to start in the sandbox
148
- 2. The sandbox_url is incorrect or unreachable
149
- 3. The sandbox is taking longer than expected to initialize`
150
- );
151
- }
152
- await new Promise((resolve) => setTimeout(resolve, delayMs));
153
- }
724
+ if (process.env.COMPUTESDK_DEBUG) {
725
+ console.log(`\u2728 ComputeSDK: Auto-detected ${provider} provider`);
726
+ console.log(`\u{1F310} Gateway: ${gatewayUrl}`);
727
+ console.log(`\u{1F511} Provider headers:`, Object.keys(providerHeaders).join(", "));
154
728
  }
155
- }
156
-
157
- // src/sandbox/wrapper.ts
158
- async function wrapWithComputeClient(originalSandbox, authResponse) {
159
- const client = new ComputeClient({
160
- sandboxUrl: authResponse.sandbox_url,
161
- sandboxId: originalSandbox.sandboxId,
162
- provider: originalSandbox.provider,
163
- token: authResponse.access_token,
164
- WebSocket: globalThis.WebSocket
729
+ return gateway({
730
+ gatewayUrl,
731
+ apiKey: computesdkApiKey,
732
+ provider,
733
+ providerHeaders
165
734
  });
166
- await waitForComputeReady(client);
167
- const wrappedSandbox = Object.assign(client, {
168
- __originalSandbox: originalSandbox,
169
- // Override getInstance to return the original provider's instance
170
- getInstance: () => originalSandbox.getInstance(),
171
- // Override getProvider to return the original provider
172
- getProvider: () => originalSandbox.getProvider()
173
- });
174
- return wrappedSandbox;
175
735
  }
176
736
 
177
737
  // src/compute.ts
178
738
  var ComputeManager = class {
179
739
  constructor() {
180
740
  this.config = null;
181
- this.computeAuth = {};
741
+ this.autoConfigured = false;
182
742
  this.sandbox = {
183
743
  /**
184
744
  * Create a sandbox from a provider (or default provider if configured)
185
- *
745
+ *
186
746
  * @example
187
747
  * ```typescript
188
748
  * import { e2b } from '@computesdk/e2b'
189
749
  * import { compute } from 'computesdk'
190
- *
750
+ *
191
751
  * // With explicit provider
192
752
  * const sandbox = await compute.sandbox.create({
193
753
  * provider: e2b({ apiKey: 'your-key' })
194
754
  * })
195
- *
196
- * // With default provider (both forms work)
755
+ *
756
+ * // With default provider
197
757
  * compute.setConfig({ defaultProvider: e2b({ apiKey: 'your-key' }) })
198
- * const sandbox1 = await compute.sandbox.create({})
199
- * const sandbox2 = await compute.sandbox.create()
758
+ * const sandbox = await compute.sandbox.create()
200
759
  * ```
201
760
  */
202
761
  create: async (params) => {
203
762
  const provider = params && "provider" in params && params.provider ? params.provider : this.getDefaultProvider();
204
763
  const options = params?.options;
205
- const sandbox = await provider.sandbox.create(options);
206
- if (this.computeAuth.apiKey || this.computeAuth.accessToken) {
207
- let authResponse = null;
208
- let accessToken = this.computeAuth.accessToken;
209
- if (this.computeAuth.apiKey && !accessToken) {
210
- authResponse = await authorizeApiKey(this.computeAuth.apiKey);
211
- accessToken = authResponse.access_token;
212
- }
213
- await installComputeDaemon(sandbox, accessToken);
214
- if (authResponse) {
215
- return await wrapWithComputeClient(sandbox, authResponse);
216
- } else if (accessToken) {
217
- const defaultAuthResponse = {
218
- access_token: accessToken,
219
- sandbox_url: "https://sandbox.computesdk.com",
220
- preview_url: "https://preview.computesdk.com"
221
- };
222
- return await wrapWithComputeClient(sandbox, defaultAuthResponse);
223
- }
224
- }
225
- return sandbox;
764
+ return await provider.sandbox.create(options);
226
765
  },
227
766
  /**
228
767
  * Get an existing sandbox by ID from a provider (or default provider if configured)
@@ -272,16 +811,9 @@ var ComputeManager = class {
272
811
  console.warn("Both defaultProvider and provider specified in setConfig. Using defaultProvider. The provider key is deprecated, please use defaultProvider instead.");
273
812
  }
274
813
  const actualProvider = config.defaultProvider || config.provider;
275
- const accessToken = config.accessToken || config.jwt;
276
814
  this.config = {
277
815
  provider: actualProvider,
278
- defaultProvider: actualProvider,
279
- apiKey: config.apiKey,
280
- accessToken
281
- };
282
- this.computeAuth = {
283
- apiKey: config.apiKey,
284
- accessToken
816
+ defaultProvider: actualProvider
285
817
  };
286
818
  }
287
819
  /**
@@ -296,39 +828,46 @@ var ComputeManager = class {
296
828
  clearConfig() {
297
829
  this.config = null;
298
830
  }
831
+ /**
832
+ * Lazy auto-configure from environment if not explicitly configured
833
+ */
834
+ ensureConfigured() {
835
+ if (this.config) return;
836
+ if (this.autoConfigured) return;
837
+ const provider = autoConfigureCompute();
838
+ this.autoConfigured = true;
839
+ if (provider) {
840
+ this.config = {
841
+ provider,
842
+ defaultProvider: provider
843
+ };
844
+ }
845
+ }
299
846
  /**
300
847
  * Get the default provider, throwing if not configured
301
848
  */
302
849
  getDefaultProvider() {
850
+ this.ensureConfigured();
303
851
  const provider = this.config?.defaultProvider || this.config?.provider;
304
852
  if (!provider) {
305
853
  throw new Error(
306
- "No default provider configured. Either call compute.setConfig({ defaultProvider }) or pass provider explicitly."
854
+ "No default provider configured.\n\nOptions:\n1. Zero-config mode: Set COMPUTESDK_API_KEY and provider credentials (e.g., E2B_API_KEY)\n2. Explicit mode: Call compute.setConfig({ defaultProvider }) or pass provider to create()\n\nDocs: https://computesdk.com/docs/quickstart"
307
855
  );
308
856
  }
309
857
  return provider;
310
858
  }
311
- // Future: compute.blob.*, compute.database.*, compute.git.* will be added here
312
- // blob = new BlobManager();
313
- // database = new DatabaseManager();
314
- // git = new GitManager();
315
859
  };
316
860
  var compute = new ComputeManager();
317
861
  function createCompute(config) {
318
862
  const manager = new ComputeManager();
863
+ if (!config) {
864
+ return manager;
865
+ }
319
866
  const actualProvider = config.defaultProvider || config.provider;
320
- const accessToken = config.accessToken || config.jwt;
321
867
  manager["config"] = {
322
868
  provider: actualProvider,
323
- defaultProvider: actualProvider,
324
- apiKey: config.apiKey,
325
- accessToken
326
- };
327
- manager["computeAuth"] = {
328
- apiKey: config.apiKey,
329
- accessToken
869
+ defaultProvider: actualProvider
330
870
  };
331
- const isEnhanced = !!(config.apiKey || config.accessToken || config.jwt);
332
871
  return {
333
872
  setConfig: (cfg) => createCompute(cfg),
334
873
  getConfig: () => manager.getConfig(),
@@ -336,24 +875,15 @@ function createCompute(config) {
336
875
  sandbox: {
337
876
  create: async (params) => {
338
877
  const sandbox = await manager.sandbox.create(params);
339
- if (isEnhanced) {
340
- return sandbox;
341
- }
342
878
  return sandbox;
343
879
  },
344
880
  getById: async (sandboxId) => {
345
881
  const sandbox = await manager.sandbox.getById(sandboxId);
346
882
  if (!sandbox) return null;
347
- if (isEnhanced) {
348
- return sandbox;
349
- }
350
883
  return sandbox;
351
884
  },
352
885
  list: async () => {
353
886
  const sandboxes = await manager.sandbox.list();
354
- if (isEnhanced) {
355
- return sandboxes;
356
- }
357
887
  return sandboxes;
358
888
  },
359
889
  destroy: async (sandboxId) => {
@@ -433,10 +963,9 @@ async function executeAction(body, provider) {
433
963
  sandboxId,
434
964
  provider: provider.name,
435
965
  result: {
436
- stdout: result.stdout,
437
- stderr: result.stderr,
966
+ output: result.output,
438
967
  exitCode: result.exitCode,
439
- executionTime: result.executionTime
968
+ language: result.language
440
969
  }
441
970
  };
442
971
  }
@@ -451,9 +980,7 @@ async function executeAction(body, provider) {
451
980
  stdout: result.stdout,
452
981
  stderr: result.stderr,
453
982
  exitCode: result.exitCode,
454
- executionTime: result.executionTime,
455
- ...result.isBackground && { isBackground: result.isBackground },
456
- ...result.pid && { pid: result.pid }
983
+ durationMs: result.durationMs
457
984
  }
458
985
  };
459
986
  }
@@ -565,253 +1092,22 @@ async function handleComputeRequest(paramsOrRequestOrBody, provider) {
565
1092
  }, { status: 500 });
566
1093
  }
567
1094
  }
568
-
569
- // src/factory.ts
570
- function createBackgroundCommand(command, args = [], options) {
571
- if (!options?.background) {
572
- return { command, args, isBackground: false };
573
- }
574
- const fullCommand = args.length > 0 ? `${command} ${args.join(" ")}` : command;
575
- return {
576
- command: "sh",
577
- args: ["-c", `nohup ${fullCommand} > /dev/null 2>&1 &`],
578
- isBackground: true
579
- };
580
- }
581
- var UnsupportedFileSystem = class {
582
- constructor(providerName) {
583
- this.providerName = providerName;
584
- }
585
- async readFile(_path) {
586
- throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
587
- }
588
- async writeFile(_path, _content) {
589
- throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
590
- }
591
- async mkdir(_path) {
592
- throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
593
- }
594
- async readdir(_path) {
595
- throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
596
- }
597
- async exists(_path) {
598
- throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
599
- }
600
- async remove(_path) {
601
- throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
602
- }
603
- };
604
- var SupportedFileSystem = class {
605
- constructor(sandbox, methods, allMethods) {
606
- this.sandbox = sandbox;
607
- this.methods = methods;
608
- this.allMethods = allMethods;
609
- }
610
- async readFile(path) {
611
- return this.methods.readFile(this.sandbox, path, this.allMethods.runCommand);
612
- }
613
- async writeFile(path, content) {
614
- return this.methods.writeFile(this.sandbox, path, content, this.allMethods.runCommand);
615
- }
616
- async mkdir(path) {
617
- return this.methods.mkdir(this.sandbox, path, this.allMethods.runCommand);
618
- }
619
- async readdir(path) {
620
- return this.methods.readdir(this.sandbox, path, this.allMethods.runCommand);
621
- }
622
- async exists(path) {
623
- return this.methods.exists(this.sandbox, path, this.allMethods.runCommand);
624
- }
625
- async remove(path) {
626
- return this.methods.remove(this.sandbox, path, this.allMethods.runCommand);
627
- }
628
- };
629
- var GeneratedSandbox = class {
630
- constructor(sandbox, sandboxId, providerName, methods, config, destroyMethod, providerInstance) {
631
- this.sandbox = sandbox;
632
- this.methods = methods;
633
- this.config = config;
634
- this.destroyMethod = destroyMethod;
635
- this.providerInstance = providerInstance;
636
- this.sandboxId = sandboxId;
637
- this.provider = providerName;
638
- if (methods.filesystem) {
639
- this.filesystem = new SupportedFileSystem(sandbox, methods.filesystem, methods);
640
- } else {
641
- this.filesystem = new UnsupportedFileSystem(providerName);
642
- }
643
- }
644
- getInstance() {
645
- if (this.methods.getInstance) {
646
- return this.methods.getInstance(this.sandbox);
647
- }
648
- return this.sandbox;
649
- }
650
- async runCode(code, runtime) {
651
- return await this.methods.runCode(this.sandbox, code, runtime, this.config);
652
- }
653
- async runCommand(command, args, options) {
654
- if (options?.background) {
655
- const fullCommand = args?.length ? `${command} ${args.join(" ")}` : command;
656
- const bgCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;
657
- const result = await this.methods.runCommand(this.sandbox, "sh", ["-c", bgCommand], void 0);
658
- return {
659
- ...result,
660
- isBackground: true,
661
- pid: -1
662
- };
663
- }
664
- return await this.methods.runCommand(this.sandbox, command, args, options);
665
- }
666
- async getInfo() {
667
- return await this.methods.getInfo(this.sandbox);
668
- }
669
- async getUrl(options) {
670
- return await this.methods.getUrl(this.sandbox, options);
671
- }
672
- getProvider() {
673
- return this.providerInstance;
674
- }
675
- async kill() {
676
- await this.destroy();
677
- }
678
- async destroy() {
679
- await this.destroyMethod(this.config, this.sandboxId);
680
- }
681
- };
682
- var GeneratedSandboxManager = class {
683
- constructor(config, providerName, methods, providerInstance) {
684
- this.config = config;
685
- this.providerName = providerName;
686
- this.methods = methods;
687
- this.providerInstance = providerInstance;
688
- this.activeSandboxes = /* @__PURE__ */ new Map();
689
- }
690
- async create(options) {
691
- const optionsWithDefaults = { runtime: "node", ...options };
692
- const result = await this.methods.create(this.config, optionsWithDefaults);
693
- const sandbox = new GeneratedSandbox(
694
- result.sandbox,
695
- result.sandboxId,
696
- this.providerName,
697
- this.methods,
698
- this.config,
699
- this.methods.destroy,
700
- this.providerInstance
701
- );
702
- this.activeSandboxes.set(result.sandboxId, sandbox);
703
- return sandbox;
704
- }
705
- async getById(sandboxId) {
706
- const existing = this.activeSandboxes.get(sandboxId);
707
- if (existing) {
708
- return existing;
709
- }
710
- const result = await this.methods.getById(this.config, sandboxId);
711
- if (!result) {
712
- return null;
713
- }
714
- const sandbox = new GeneratedSandbox(
715
- result.sandbox,
716
- result.sandboxId,
717
- this.providerName,
718
- this.methods,
719
- this.config,
720
- this.methods.destroy,
721
- this.providerInstance
722
- );
723
- this.activeSandboxes.set(result.sandboxId, sandbox);
724
- return sandbox;
725
- }
726
- async list() {
727
- const results = await this.methods.list(this.config);
728
- const sandboxes = [];
729
- for (const result of results) {
730
- let sandbox = this.activeSandboxes.get(result.sandboxId);
731
- if (!sandbox) {
732
- sandbox = new GeneratedSandbox(
733
- result.sandbox,
734
- result.sandboxId,
735
- this.providerName,
736
- this.methods,
737
- this.config,
738
- this.methods.destroy,
739
- this.providerInstance
740
- );
741
- this.activeSandboxes.set(result.sandboxId, sandbox);
742
- }
743
- sandboxes.push(sandbox);
744
- }
745
- return sandboxes;
746
- }
747
- async destroy(sandboxId) {
748
- await this.methods.destroy(this.config, sandboxId);
749
- this.activeSandboxes.delete(sandboxId);
750
- }
751
- };
752
- var GeneratedTemplateManager = class {
753
- constructor(config, methods) {
754
- this.config = config;
755
- this.methods = methods;
756
- }
757
- async create(options) {
758
- return await this.methods.create(this.config, options);
759
- }
760
- async list(options) {
761
- return await this.methods.list(this.config, options);
762
- }
763
- async delete(templateId) {
764
- return await this.methods.delete(this.config, templateId);
765
- }
766
- };
767
- var GeneratedSnapshotManager = class {
768
- constructor(config, methods) {
769
- this.config = config;
770
- this.methods = methods;
771
- }
772
- async create(sandboxId, options) {
773
- return await this.methods.create(this.config, sandboxId, options);
774
- }
775
- async list(options) {
776
- return await this.methods.list(this.config, options);
777
- }
778
- async delete(snapshotId) {
779
- return await this.methods.delete(this.config, snapshotId);
780
- }
781
- };
782
- var GeneratedProvider = class {
783
- // Phantom type for TypeScript inference
784
- constructor(config, providerConfig) {
785
- this.name = providerConfig.name;
786
- this.sandbox = new GeneratedSandboxManager(
787
- config,
788
- providerConfig.name,
789
- providerConfig.methods.sandbox,
790
- this
791
- );
792
- if (providerConfig.methods.template) {
793
- this.template = new GeneratedTemplateManager(config, providerConfig.methods.template);
794
- }
795
- if (providerConfig.methods.snapshot) {
796
- this.snapshot = new GeneratedSnapshotManager(config, providerConfig.methods.snapshot);
797
- }
798
- }
799
- getSupportedRuntimes() {
800
- return ["node", "python"];
801
- }
802
- };
803
- function createProvider(providerConfig) {
804
- return (config) => {
805
- return new GeneratedProvider(config, providerConfig);
806
- };
807
- }
808
1095
  export {
809
1096
  CommandExitError,
1097
+ GATEWAY_URL,
1098
+ PROVIDER_ENV_VARS,
1099
+ PROVIDER_PRIORITY,
1100
+ Sandbox,
1101
+ autoConfigureCompute,
1102
+ calculateBackoff,
810
1103
  compute,
811
- createBackgroundCommand,
812
1104
  createCompute,
813
1105
  createProvider,
1106
+ detectProvider,
1107
+ gateway,
1108
+ getProviderHeaders,
814
1109
  handleComputeRequest,
815
- isCommandExitError
1110
+ isCommandExitError,
1111
+ isGatewayModeEnabled
816
1112
  };
817
1113
  //# sourceMappingURL=index.mjs.map