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/README.md +98 -17
- package/dist/index.d.mts +312 -353
- package/dist/index.d.ts +312 -353
- package/dist/index.js +748 -509
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +739 -506
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -1,228 +1,767 @@
|
|
|
1
1
|
// src/types/sandbox.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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"]
|
|
8
31
|
};
|
|
9
|
-
function isCommandExitError(error) {
|
|
10
|
-
return typeof error === "object" && error !== null && "name" in error && error.name === "CommandExitError" && "result" in error;
|
|
11
|
-
}
|
|
12
32
|
|
|
13
|
-
// src/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
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.`);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
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);
|
|
33
99
|
}
|
|
34
|
-
|
|
35
|
-
|
|
100
|
+
}
|
|
101
|
+
getInstance() {
|
|
102
|
+
if (this.methods.getInstance) {
|
|
103
|
+
return this.methods.getInstance(this.sandbox);
|
|
36
104
|
}
|
|
37
|
-
|
|
38
|
-
|
|
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;
|
|
39
121
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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);
|
|
48
130
|
}
|
|
49
|
-
|
|
131
|
+
return await this.methods.runCommand(this.sandbox, command, args, options);
|
|
50
132
|
}
|
|
51
|
-
|
|
52
|
-
|
|
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;
|
|
57
|
-
}
|
|
58
|
-
async function detectPackageManager(sandbox) {
|
|
59
|
-
if (await isCommandAvailable(sandbox, "apk")) {
|
|
60
|
-
return "apk";
|
|
133
|
+
async getInfo() {
|
|
134
|
+
return await this.methods.getInfo(this.sandbox);
|
|
61
135
|
}
|
|
62
|
-
|
|
63
|
-
return
|
|
136
|
+
async getUrl(options) {
|
|
137
|
+
return await this.methods.getUrl(this.sandbox, options);
|
|
64
138
|
}
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
);
|
|
139
|
+
getProvider() {
|
|
140
|
+
return this.providerInstance;
|
|
80
141
|
}
|
|
81
|
-
|
|
82
|
-
|
|
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"]);
|
|
142
|
+
async kill() {
|
|
143
|
+
await this.destroy();
|
|
86
144
|
}
|
|
87
|
-
|
|
88
|
-
|
|
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.`
|
|
92
|
-
);
|
|
145
|
+
async destroy() {
|
|
146
|
+
await this.destroyMethod(this.config, this.sandboxId);
|
|
93
147
|
}
|
|
148
|
+
};
|
|
149
|
+
function getEffectiveMode(config, defaultMode) {
|
|
150
|
+
if (config.mode) {
|
|
151
|
+
return config.mode;
|
|
152
|
+
}
|
|
153
|
+
return defaultMode;
|
|
94
154
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
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
|
|
107
174
|
);
|
|
108
175
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
176
|
+
async getById(sandboxId) {
|
|
177
|
+
const result = await this.methods.getById(this.config, sandboxId);
|
|
178
|
+
if (!result) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
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
|
+
);
|
|
116
190
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
+
));
|
|
121
202
|
}
|
|
122
|
-
|
|
123
|
-
|
|
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");
|
|
203
|
+
async destroy(sandboxId) {
|
|
204
|
+
await this.methods.destroy(this.config, sandboxId);
|
|
127
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);
|
|
249
|
+
}
|
|
250
|
+
if (providerConfig.methods.snapshot) {
|
|
251
|
+
this.snapshot = new GeneratedSnapshotManager(config, providerConfig.methods.snapshot);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
getSupportedRuntimes() {
|
|
255
|
+
return ["node", "python"];
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
function createProvider(providerConfig) {
|
|
259
|
+
return (config) => {
|
|
260
|
+
return new GeneratedProvider(config, providerConfig);
|
|
261
|
+
};
|
|
128
262
|
}
|
|
129
263
|
|
|
130
|
-
// src/sandbox/wrapper.ts
|
|
131
|
-
import { ComputeClient } from "@computesdk/client";
|
|
132
|
-
|
|
133
264
|
// src/compute-daemon/lifecycle.ts
|
|
134
|
-
async function waitForComputeReady(client,
|
|
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;
|
|
135
270
|
let lastError = null;
|
|
271
|
+
let currentDelay = initialDelayMs;
|
|
136
272
|
for (let i = 0; i < maxRetries; i++) {
|
|
137
273
|
try {
|
|
138
274
|
await client.health();
|
|
275
|
+
if (process.env.COMPUTESDK_DEBUG) {
|
|
276
|
+
console.log(`[Lifecycle] Sandbox ready after ${i + 1} attempt${i === 0 ? "" : "s"}`);
|
|
277
|
+
}
|
|
139
278
|
return;
|
|
140
279
|
} catch (error) {
|
|
141
280
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
142
281
|
if (i === maxRetries - 1) {
|
|
143
282
|
throw new Error(
|
|
144
|
-
`
|
|
283
|
+
`Sandbox failed to become ready after ${maxRetries} attempts.
|
|
145
284
|
Last error: ${lastError.message}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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`
|
|
150
297
|
);
|
|
151
298
|
}
|
|
152
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
153
|
-
|
|
299
|
+
await new Promise((resolve) => setTimeout(resolve, currentDelay));
|
|
300
|
+
currentDelay = Math.min(currentDelay * backoffFactor, maxDelayMs);
|
|
301
|
+
}
|
|
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;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
throw lastError || new Error("Max retries exceeded");
|
|
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
|
+
});
|
|
553
|
+
|
|
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]);
|
|
563
|
+
}
|
|
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 };
|
|
568
|
+
}
|
|
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
|
+
}
|
|
595
|
+
}
|
|
596
|
+
return null;
|
|
597
|
+
}
|
|
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;
|
|
154
668
|
}
|
|
669
|
+
return headers;
|
|
155
670
|
}
|
|
671
|
+
function autoConfigureCompute() {
|
|
672
|
+
if (!isGatewayModeEnabled()) {
|
|
673
|
+
return null;
|
|
674
|
+
}
|
|
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
|
+
});
|
|
687
|
+
throw new Error(
|
|
688
|
+
`COMPUTESDK_API_KEY is set but no provider detected.
|
|
156
689
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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`
|
|
709
|
+
);
|
|
710
|
+
}
|
|
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) {
|
|
717
|
+
throw new Error(
|
|
718
|
+
`Invalid gateway URL: "${gatewayUrl}"
|
|
719
|
+
|
|
720
|
+
The URL must be a valid HTTP/HTTPS URL.
|
|
721
|
+
Check your COMPUTESDK_GATEWAY_URL environment variable.`
|
|
722
|
+
);
|
|
723
|
+
}
|
|
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(", "));
|
|
728
|
+
}
|
|
729
|
+
return gateway({
|
|
730
|
+
gatewayUrl,
|
|
731
|
+
apiKey: computesdkApiKey,
|
|
732
|
+
provider,
|
|
733
|
+
providerHeaders
|
|
173
734
|
});
|
|
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.
|
|
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
|
|
755
|
+
*
|
|
756
|
+
* // With default provider
|
|
197
757
|
* compute.setConfig({ defaultProvider: e2b({ apiKey: 'your-key' }) })
|
|
198
|
-
* const
|
|
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
|
-
|
|
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.
|
|
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
|
|
869
|
+
defaultProvider: actualProvider
|
|
326
870
|
};
|
|
327
|
-
manager["computeAuth"] = {
|
|
328
|
-
apiKey: config.apiKey,
|
|
329
|
-
accessToken
|
|
330
|
-
};
|
|
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
|
-
|
|
437
|
-
stderr: result.stderr,
|
|
966
|
+
output: result.output,
|
|
438
967
|
exitCode: result.exitCode,
|
|
439
|
-
|
|
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
|
-
|
|
455
|
-
...result.isBackground && { isBackground: result.isBackground },
|
|
456
|
-
...result.pid && { pid: result.pid }
|
|
983
|
+
durationMs: result.durationMs
|
|
457
984
|
}
|
|
458
985
|
};
|
|
459
986
|
}
|
|
@@ -565,316 +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", `${fullCommand} &`],
|
|
578
|
-
isBackground: true
|
|
579
|
-
};
|
|
580
|
-
}
|
|
581
|
-
var defaultFilesystemMethods = {
|
|
582
|
-
readFile: async (sandbox, path, runCommand) => {
|
|
583
|
-
const result = await runCommand(sandbox, "cat", [path]);
|
|
584
|
-
if (result.exitCode !== 0) {
|
|
585
|
-
throw new Error(`Failed to read file ${path}: ${result.stderr}`);
|
|
586
|
-
}
|
|
587
|
-
return result.stdout.replace(/\n$/, "");
|
|
588
|
-
},
|
|
589
|
-
writeFile: async (sandbox, path, content, runCommand) => {
|
|
590
|
-
const result = await runCommand(sandbox, "sh", ["-c", `echo ${JSON.stringify(content)} > ${JSON.stringify(path)}`]);
|
|
591
|
-
if (result.exitCode !== 0) {
|
|
592
|
-
throw new Error(`Failed to write file ${path}: ${result.stderr}`);
|
|
593
|
-
}
|
|
594
|
-
},
|
|
595
|
-
mkdir: async (sandbox, path, runCommand) => {
|
|
596
|
-
const result = await runCommand(sandbox, "mkdir", ["-p", path]);
|
|
597
|
-
if (result.exitCode !== 0) {
|
|
598
|
-
throw new Error(`Failed to create directory ${path}: ${result.stderr}`);
|
|
599
|
-
}
|
|
600
|
-
},
|
|
601
|
-
readdir: async (sandbox, path, runCommand) => {
|
|
602
|
-
let result = await runCommand(sandbox, "ls", ["-la", path]);
|
|
603
|
-
let hasDetailedOutput = true;
|
|
604
|
-
if (result.exitCode !== 0) {
|
|
605
|
-
result = await runCommand(sandbox, "ls", ["-l", path]);
|
|
606
|
-
}
|
|
607
|
-
if (result.exitCode !== 0) {
|
|
608
|
-
result = await runCommand(sandbox, "ls", [path]);
|
|
609
|
-
hasDetailedOutput = false;
|
|
610
|
-
}
|
|
611
|
-
if (result.exitCode !== 0) {
|
|
612
|
-
throw new Error(`Failed to list directory ${path}: ${result.stderr}`);
|
|
613
|
-
}
|
|
614
|
-
const lines = (result.stdout || "").split("\n").filter((line) => line.trim() && !line.startsWith("total"));
|
|
615
|
-
return lines.map((line) => {
|
|
616
|
-
if (hasDetailedOutput && line.includes(" ")) {
|
|
617
|
-
const parts = line.trim().split(/\s+/);
|
|
618
|
-
const name = parts[parts.length - 1];
|
|
619
|
-
const isDirectory = line.startsWith("d");
|
|
620
|
-
return {
|
|
621
|
-
name,
|
|
622
|
-
path: `${path}/${name}`,
|
|
623
|
-
isDirectory,
|
|
624
|
-
size: parseInt(parts[4]) || 0,
|
|
625
|
-
lastModified: /* @__PURE__ */ new Date()
|
|
626
|
-
};
|
|
627
|
-
} else {
|
|
628
|
-
const name = line.trim();
|
|
629
|
-
return {
|
|
630
|
-
name,
|
|
631
|
-
path: `${path}/${name}`,
|
|
632
|
-
isDirectory: false,
|
|
633
|
-
// Can't determine from simple ls
|
|
634
|
-
size: 0,
|
|
635
|
-
lastModified: /* @__PURE__ */ new Date()
|
|
636
|
-
};
|
|
637
|
-
}
|
|
638
|
-
});
|
|
639
|
-
},
|
|
640
|
-
exists: async (sandbox, path, runCommand) => {
|
|
641
|
-
const result = await runCommand(sandbox, "test", ["-e", path]);
|
|
642
|
-
return result.exitCode === 0;
|
|
643
|
-
},
|
|
644
|
-
remove: async (sandbox, path, runCommand) => {
|
|
645
|
-
const result = await runCommand(sandbox, "rm", ["-rf", path]);
|
|
646
|
-
if (result.exitCode !== 0) {
|
|
647
|
-
throw new Error(`Failed to remove ${path}: ${result.stderr}`);
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
};
|
|
651
|
-
var UnsupportedFileSystem = class {
|
|
652
|
-
constructor(providerName) {
|
|
653
|
-
this.providerName = providerName;
|
|
654
|
-
}
|
|
655
|
-
async readFile(_path) {
|
|
656
|
-
throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
|
|
657
|
-
}
|
|
658
|
-
async writeFile(_path, _content) {
|
|
659
|
-
throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
|
|
660
|
-
}
|
|
661
|
-
async mkdir(_path) {
|
|
662
|
-
throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
|
|
663
|
-
}
|
|
664
|
-
async readdir(_path) {
|
|
665
|
-
throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
|
|
666
|
-
}
|
|
667
|
-
async exists(_path) {
|
|
668
|
-
throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
|
|
669
|
-
}
|
|
670
|
-
async remove(_path) {
|
|
671
|
-
throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
|
|
672
|
-
}
|
|
673
|
-
};
|
|
674
|
-
var SupportedFileSystem = class {
|
|
675
|
-
constructor(sandbox, methods, allMethods) {
|
|
676
|
-
this.sandbox = sandbox;
|
|
677
|
-
this.methods = methods;
|
|
678
|
-
this.allMethods = allMethods;
|
|
679
|
-
}
|
|
680
|
-
async readFile(path) {
|
|
681
|
-
return this.methods.readFile(this.sandbox, path, this.allMethods.runCommand);
|
|
682
|
-
}
|
|
683
|
-
async writeFile(path, content) {
|
|
684
|
-
return this.methods.writeFile(this.sandbox, path, content, this.allMethods.runCommand);
|
|
685
|
-
}
|
|
686
|
-
async mkdir(path) {
|
|
687
|
-
return this.methods.mkdir(this.sandbox, path, this.allMethods.runCommand);
|
|
688
|
-
}
|
|
689
|
-
async readdir(path) {
|
|
690
|
-
return this.methods.readdir(this.sandbox, path, this.allMethods.runCommand);
|
|
691
|
-
}
|
|
692
|
-
async exists(path) {
|
|
693
|
-
return this.methods.exists(this.sandbox, path, this.allMethods.runCommand);
|
|
694
|
-
}
|
|
695
|
-
async remove(path) {
|
|
696
|
-
return this.methods.remove(this.sandbox, path, this.allMethods.runCommand);
|
|
697
|
-
}
|
|
698
|
-
};
|
|
699
|
-
var GeneratedSandbox = class {
|
|
700
|
-
constructor(sandbox, sandboxId, providerName, methods, config, destroyMethod, providerInstance) {
|
|
701
|
-
this.sandbox = sandbox;
|
|
702
|
-
this.methods = methods;
|
|
703
|
-
this.config = config;
|
|
704
|
-
this.destroyMethod = destroyMethod;
|
|
705
|
-
this.providerInstance = providerInstance;
|
|
706
|
-
this.sandboxId = sandboxId;
|
|
707
|
-
this.provider = providerName;
|
|
708
|
-
if (methods.filesystem) {
|
|
709
|
-
this.filesystem = new SupportedFileSystem(sandbox, methods.filesystem, methods);
|
|
710
|
-
} else {
|
|
711
|
-
this.filesystem = new UnsupportedFileSystem(providerName);
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
getInstance() {
|
|
715
|
-
if (this.methods.getInstance) {
|
|
716
|
-
return this.methods.getInstance(this.sandbox);
|
|
717
|
-
}
|
|
718
|
-
return this.sandbox;
|
|
719
|
-
}
|
|
720
|
-
async runCode(code, runtime) {
|
|
721
|
-
return await this.methods.runCode(this.sandbox, code, runtime, this.config);
|
|
722
|
-
}
|
|
723
|
-
async runCommand(command, args, options) {
|
|
724
|
-
return await this.methods.runCommand(this.sandbox, command, args, options);
|
|
725
|
-
}
|
|
726
|
-
async getInfo() {
|
|
727
|
-
return await this.methods.getInfo(this.sandbox);
|
|
728
|
-
}
|
|
729
|
-
async getUrl(options) {
|
|
730
|
-
return await this.methods.getUrl(this.sandbox, options);
|
|
731
|
-
}
|
|
732
|
-
getProvider() {
|
|
733
|
-
return this.providerInstance;
|
|
734
|
-
}
|
|
735
|
-
async kill() {
|
|
736
|
-
await this.destroy();
|
|
737
|
-
}
|
|
738
|
-
async destroy() {
|
|
739
|
-
await this.destroyMethod(this.config, this.sandboxId);
|
|
740
|
-
}
|
|
741
|
-
};
|
|
742
|
-
var GeneratedSandboxManager = class {
|
|
743
|
-
constructor(config, providerName, methods, providerInstance) {
|
|
744
|
-
this.config = config;
|
|
745
|
-
this.providerName = providerName;
|
|
746
|
-
this.methods = methods;
|
|
747
|
-
this.providerInstance = providerInstance;
|
|
748
|
-
this.activeSandboxes = /* @__PURE__ */ new Map();
|
|
749
|
-
}
|
|
750
|
-
async create(options) {
|
|
751
|
-
const optionsWithDefaults = { runtime: "node", ...options };
|
|
752
|
-
const result = await this.methods.create(this.config, optionsWithDefaults);
|
|
753
|
-
const sandbox = new GeneratedSandbox(
|
|
754
|
-
result.sandbox,
|
|
755
|
-
result.sandboxId,
|
|
756
|
-
this.providerName,
|
|
757
|
-
this.methods,
|
|
758
|
-
this.config,
|
|
759
|
-
this.methods.destroy,
|
|
760
|
-
this.providerInstance
|
|
761
|
-
);
|
|
762
|
-
this.activeSandboxes.set(result.sandboxId, sandbox);
|
|
763
|
-
return sandbox;
|
|
764
|
-
}
|
|
765
|
-
async getById(sandboxId) {
|
|
766
|
-
const existing = this.activeSandboxes.get(sandboxId);
|
|
767
|
-
if (existing) {
|
|
768
|
-
return existing;
|
|
769
|
-
}
|
|
770
|
-
const result = await this.methods.getById(this.config, sandboxId);
|
|
771
|
-
if (!result) {
|
|
772
|
-
return null;
|
|
773
|
-
}
|
|
774
|
-
const sandbox = new GeneratedSandbox(
|
|
775
|
-
result.sandbox,
|
|
776
|
-
result.sandboxId,
|
|
777
|
-
this.providerName,
|
|
778
|
-
this.methods,
|
|
779
|
-
this.config,
|
|
780
|
-
this.methods.destroy,
|
|
781
|
-
this.providerInstance
|
|
782
|
-
);
|
|
783
|
-
this.activeSandboxes.set(result.sandboxId, sandbox);
|
|
784
|
-
return sandbox;
|
|
785
|
-
}
|
|
786
|
-
async list() {
|
|
787
|
-
const results = await this.methods.list(this.config);
|
|
788
|
-
const sandboxes = [];
|
|
789
|
-
for (const result of results) {
|
|
790
|
-
let sandbox = this.activeSandboxes.get(result.sandboxId);
|
|
791
|
-
if (!sandbox) {
|
|
792
|
-
sandbox = new GeneratedSandbox(
|
|
793
|
-
result.sandbox,
|
|
794
|
-
result.sandboxId,
|
|
795
|
-
this.providerName,
|
|
796
|
-
this.methods,
|
|
797
|
-
this.config,
|
|
798
|
-
this.methods.destroy,
|
|
799
|
-
this.providerInstance
|
|
800
|
-
);
|
|
801
|
-
this.activeSandboxes.set(result.sandboxId, sandbox);
|
|
802
|
-
}
|
|
803
|
-
sandboxes.push(sandbox);
|
|
804
|
-
}
|
|
805
|
-
return sandboxes;
|
|
806
|
-
}
|
|
807
|
-
async destroy(sandboxId) {
|
|
808
|
-
await this.methods.destroy(this.config, sandboxId);
|
|
809
|
-
this.activeSandboxes.delete(sandboxId);
|
|
810
|
-
}
|
|
811
|
-
};
|
|
812
|
-
var GeneratedTemplateManager = class {
|
|
813
|
-
constructor(config, methods) {
|
|
814
|
-
this.config = config;
|
|
815
|
-
this.methods = methods;
|
|
816
|
-
}
|
|
817
|
-
async create(options) {
|
|
818
|
-
return await this.methods.create(this.config, options);
|
|
819
|
-
}
|
|
820
|
-
async list(options) {
|
|
821
|
-
return await this.methods.list(this.config, options);
|
|
822
|
-
}
|
|
823
|
-
async delete(templateId) {
|
|
824
|
-
return await this.methods.delete(this.config, templateId);
|
|
825
|
-
}
|
|
826
|
-
};
|
|
827
|
-
var GeneratedSnapshotManager = class {
|
|
828
|
-
constructor(config, methods) {
|
|
829
|
-
this.config = config;
|
|
830
|
-
this.methods = methods;
|
|
831
|
-
}
|
|
832
|
-
async create(sandboxId, options) {
|
|
833
|
-
return await this.methods.create(this.config, sandboxId, options);
|
|
834
|
-
}
|
|
835
|
-
async list(options) {
|
|
836
|
-
return await this.methods.list(this.config, options);
|
|
837
|
-
}
|
|
838
|
-
async delete(snapshotId) {
|
|
839
|
-
return await this.methods.delete(this.config, snapshotId);
|
|
840
|
-
}
|
|
841
|
-
};
|
|
842
|
-
var GeneratedProvider = class {
|
|
843
|
-
// Phantom type for TypeScript inference
|
|
844
|
-
constructor(config, providerConfig) {
|
|
845
|
-
this.name = providerConfig.name;
|
|
846
|
-
this.sandbox = new GeneratedSandboxManager(
|
|
847
|
-
config,
|
|
848
|
-
providerConfig.name,
|
|
849
|
-
providerConfig.methods.sandbox,
|
|
850
|
-
this
|
|
851
|
-
);
|
|
852
|
-
if (providerConfig.methods.template) {
|
|
853
|
-
this.template = new GeneratedTemplateManager(config, providerConfig.methods.template);
|
|
854
|
-
}
|
|
855
|
-
if (providerConfig.methods.snapshot) {
|
|
856
|
-
this.snapshot = new GeneratedSnapshotManager(config, providerConfig.methods.snapshot);
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
getSupportedRuntimes() {
|
|
860
|
-
return ["node", "python"];
|
|
861
|
-
}
|
|
862
|
-
};
|
|
863
|
-
function createProvider(providerConfig) {
|
|
864
|
-
if (!providerConfig.methods.sandbox.filesystem) {
|
|
865
|
-
providerConfig.methods.sandbox.filesystem = defaultFilesystemMethods;
|
|
866
|
-
}
|
|
867
|
-
return (config) => {
|
|
868
|
-
return new GeneratedProvider(config, providerConfig);
|
|
869
|
-
};
|
|
870
|
-
}
|
|
871
1095
|
export {
|
|
872
1096
|
CommandExitError,
|
|
1097
|
+
GATEWAY_URL,
|
|
1098
|
+
PROVIDER_ENV_VARS,
|
|
1099
|
+
PROVIDER_PRIORITY,
|
|
1100
|
+
Sandbox,
|
|
1101
|
+
autoConfigureCompute,
|
|
1102
|
+
calculateBackoff,
|
|
873
1103
|
compute,
|
|
874
|
-
createBackgroundCommand,
|
|
875
1104
|
createCompute,
|
|
876
1105
|
createProvider,
|
|
1106
|
+
detectProvider,
|
|
1107
|
+
gateway,
|
|
1108
|
+
getProviderHeaders,
|
|
877
1109
|
handleComputeRequest,
|
|
878
|
-
isCommandExitError
|
|
1110
|
+
isCommandExitError,
|
|
1111
|
+
isGatewayModeEnabled
|
|
879
1112
|
};
|
|
880
1113
|
//# sourceMappingURL=index.mjs.map
|