computesdk 1.8.7 → 1.9.0

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