computesdk 1.0.2 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +504 -229
- package/dist/index.d.mts +416 -340
- package/dist/index.d.ts +416 -340
- package/dist/index.js +911 -450
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +907 -436
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -34
package/dist/index.js
CHANGED
|
@@ -20,515 +20,976 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
ConfigurationError: () => ConfigurationError,
|
|
28
|
-
DEFAULT_TIMEOUT: () => DEFAULT_TIMEOUT,
|
|
29
|
-
ENV_KEYS: () => ENV_KEYS,
|
|
30
|
-
ExecutionError: () => ExecutionError,
|
|
31
|
-
ProviderError: () => ProviderError,
|
|
32
|
-
ProviderUnavailableError: () => ProviderUnavailableError,
|
|
33
|
-
TimeoutError: () => TimeoutError,
|
|
34
|
-
autoSelectProvider: () => autoSelectProvider,
|
|
35
|
-
createComputeRegistry: () => createComputeRegistry,
|
|
36
|
-
default: () => index_default,
|
|
37
|
-
detectAvailableProviders: () => detectAvailableProviders,
|
|
38
|
-
executeSandbox: () => executeSandbox,
|
|
39
|
-
getDefaultRuntime: () => getDefaultRuntime,
|
|
40
|
-
isCloudflareWorkers: () => isCloudflareWorkers,
|
|
41
|
-
normalizeContainerConfig: () => normalizeContainerConfig,
|
|
42
|
-
normalizeSandboxConfig: () => normalizeSandboxConfig,
|
|
43
|
-
retry: () => retry,
|
|
44
|
-
validateProviderApiKey: () => validateProviderApiKey
|
|
23
|
+
SandboxManager: () => SandboxManager,
|
|
24
|
+
compute: () => compute,
|
|
25
|
+
createProvider: () => createProvider,
|
|
26
|
+
handleComputeRequest: () => handleComputeRequest
|
|
45
27
|
});
|
|
46
28
|
module.exports = __toCommonJS(index_exports);
|
|
47
29
|
|
|
48
|
-
// src/
|
|
49
|
-
var
|
|
30
|
+
// src/sandbox.ts
|
|
31
|
+
var SandboxManager = class {
|
|
50
32
|
/**
|
|
51
|
-
* Create a
|
|
52
|
-
*
|
|
53
|
-
* @param message Error message
|
|
54
|
-
* @param provider Provider identifier
|
|
55
|
-
* @param sandboxId Optional sandbox identifier
|
|
33
|
+
* Create a sandbox from a provider
|
|
56
34
|
*/
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
this.name = this.constructor.name;
|
|
60
|
-
this.provider = provider;
|
|
61
|
-
this.sandboxId = sandboxId;
|
|
62
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
35
|
+
async create(provider, options) {
|
|
36
|
+
return await provider.sandbox.create(options);
|
|
63
37
|
}
|
|
64
|
-
};
|
|
65
|
-
var ExecutionError = class extends ComputeError {
|
|
66
38
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* @param message Error message
|
|
70
|
-
* @param provider Provider identifier
|
|
71
|
-
* @param exitCode Exit code from the execution
|
|
72
|
-
* @param sandboxId Optional sandbox identifier
|
|
39
|
+
* Get an existing sandbox by ID from a provider
|
|
73
40
|
*/
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
/** Error code */
|
|
77
|
-
this.code = "EXECUTION_ERROR";
|
|
78
|
-
/** Execution errors are generally not retryable */
|
|
79
|
-
this.isRetryable = false;
|
|
80
|
-
this.exitCode = exitCode;
|
|
41
|
+
async getById(provider, sandboxId) {
|
|
42
|
+
return await provider.sandbox.getById(sandboxId);
|
|
81
43
|
}
|
|
82
|
-
};
|
|
83
|
-
var TimeoutError = class extends ComputeError {
|
|
84
44
|
/**
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* @param message Error message
|
|
88
|
-
* @param provider Provider identifier
|
|
89
|
-
* @param timeoutMs Timeout duration in milliseconds
|
|
90
|
-
* @param sandboxId Optional sandbox identifier
|
|
45
|
+
* List all active sandboxes from a provider
|
|
91
46
|
*/
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
/** Error code */
|
|
95
|
-
this.code = "TIMEOUT_ERROR";
|
|
96
|
-
/** Timeout errors may be retryable with a longer timeout */
|
|
97
|
-
this.isRetryable = true;
|
|
98
|
-
this.timeoutMs = timeoutMs;
|
|
47
|
+
async list(provider) {
|
|
48
|
+
return await provider.sandbox.list();
|
|
99
49
|
}
|
|
100
|
-
};
|
|
101
|
-
var ProviderError = class extends ComputeError {
|
|
102
50
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* @param message Error message
|
|
106
|
-
* @param provider Provider identifier
|
|
107
|
-
* @param originalError Optional original error from the provider
|
|
108
|
-
* @param sandboxId Optional sandbox identifier
|
|
51
|
+
* Destroy a sandbox via a provider
|
|
109
52
|
*/
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
/** Error code */
|
|
113
|
-
this.code = "PROVIDER_ERROR";
|
|
114
|
-
/** Provider errors may be retryable */
|
|
115
|
-
this.isRetryable = true;
|
|
116
|
-
this.originalError = originalError;
|
|
53
|
+
async destroy(provider, sandboxId) {
|
|
54
|
+
return await provider.sandbox.destroy(sandboxId);
|
|
117
55
|
}
|
|
118
56
|
};
|
|
119
|
-
|
|
57
|
+
|
|
58
|
+
// src/compute.ts
|
|
59
|
+
var ComputeManager = class {
|
|
60
|
+
constructor() {
|
|
61
|
+
this.sandboxManager = new SandboxManager();
|
|
62
|
+
this.config = null;
|
|
63
|
+
this.sandbox = {
|
|
64
|
+
/**
|
|
65
|
+
* Create a sandbox from a provider (or default provider if configured)
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* import { e2b } from '@computesdk/e2b'
|
|
70
|
+
* import { compute } from 'computesdk'
|
|
71
|
+
*
|
|
72
|
+
* // With explicit provider
|
|
73
|
+
* const sandbox = await compute.sandbox.create({
|
|
74
|
+
* provider: e2b({ apiKey: 'your-key' })
|
|
75
|
+
* })
|
|
76
|
+
*
|
|
77
|
+
* // With default provider (both forms work)
|
|
78
|
+
* compute.setConfig({ provider: e2b({ apiKey: 'your-key' }) })
|
|
79
|
+
* const sandbox1 = await compute.sandbox.create({})
|
|
80
|
+
* const sandbox2 = await compute.sandbox.create()
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
create: async (params) => {
|
|
84
|
+
const provider = params && "provider" in params && params.provider ? params.provider : this.getDefaultProvider();
|
|
85
|
+
const options = params?.options;
|
|
86
|
+
return await this.sandboxManager.create(provider, options);
|
|
87
|
+
},
|
|
88
|
+
/**
|
|
89
|
+
* Get an existing sandbox by ID from a provider (or default provider if configured)
|
|
90
|
+
*/
|
|
91
|
+
getById: async (providerOrSandboxId, sandboxId) => {
|
|
92
|
+
if (typeof providerOrSandboxId === "string") {
|
|
93
|
+
const provider = this.getDefaultProvider();
|
|
94
|
+
return await this.sandboxManager.getById(provider, providerOrSandboxId);
|
|
95
|
+
} else {
|
|
96
|
+
if (!sandboxId) {
|
|
97
|
+
throw new Error("sandboxId is required when provider is specified");
|
|
98
|
+
}
|
|
99
|
+
return await this.sandboxManager.getById(providerOrSandboxId, sandboxId);
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
/**
|
|
103
|
+
* List all active sandboxes from a provider (or default provider if configured)
|
|
104
|
+
*/
|
|
105
|
+
list: async (provider) => {
|
|
106
|
+
const actualProvider = provider || this.getDefaultProvider();
|
|
107
|
+
return await this.sandboxManager.list(actualProvider);
|
|
108
|
+
},
|
|
109
|
+
/**
|
|
110
|
+
* Destroy a sandbox via a provider (or default provider if configured)
|
|
111
|
+
*/
|
|
112
|
+
destroy: async (providerOrSandboxId, sandboxId) => {
|
|
113
|
+
if (typeof providerOrSandboxId === "string") {
|
|
114
|
+
const provider = this.getDefaultProvider();
|
|
115
|
+
return await this.sandboxManager.destroy(provider, providerOrSandboxId);
|
|
116
|
+
} else {
|
|
117
|
+
if (!sandboxId) {
|
|
118
|
+
throw new Error("sandboxId is required when provider is specified");
|
|
119
|
+
}
|
|
120
|
+
return await this.sandboxManager.destroy(providerOrSandboxId, sandboxId);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
120
125
|
/**
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* @param message Error message
|
|
124
|
-
* @param provider Provider identifier
|
|
125
|
-
* @param sandboxId Optional sandbox identifier
|
|
126
|
+
* Set default configuration
|
|
126
127
|
*/
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
/** Error code */
|
|
130
|
-
this.code = "CONFIGURATION_ERROR";
|
|
131
|
-
/** Configuration errors are not retryable without changes */
|
|
132
|
-
this.isRetryable = false;
|
|
128
|
+
setConfig(config) {
|
|
129
|
+
this.config = config;
|
|
133
130
|
}
|
|
134
|
-
};
|
|
135
|
-
var AuthenticationError = class extends ComputeError {
|
|
136
131
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
* @param message Error message
|
|
140
|
-
* @param provider Provider identifier
|
|
141
|
-
* @param sandboxId Optional sandbox identifier
|
|
132
|
+
* Get current configuration
|
|
142
133
|
*/
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
/** Error code */
|
|
146
|
-
this.code = "AUTHENTICATION_ERROR";
|
|
147
|
-
/** Authentication errors are not retryable without new credentials */
|
|
148
|
-
this.isRetryable = false;
|
|
134
|
+
getConfig() {
|
|
135
|
+
return this.config;
|
|
149
136
|
}
|
|
150
|
-
};
|
|
151
|
-
var ProviderUnavailableError = class extends ComputeError {
|
|
152
137
|
/**
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
* @param message Error message
|
|
156
|
-
* @param provider Provider identifier
|
|
157
|
-
* @param sandboxId Optional sandbox identifier
|
|
138
|
+
* Clear current configuration
|
|
158
139
|
*/
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
140
|
+
clearConfig() {
|
|
141
|
+
this.config = null;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Get the default provider, throwing if not configured
|
|
145
|
+
*/
|
|
146
|
+
getDefaultProvider() {
|
|
147
|
+
if (!this.config?.provider) {
|
|
148
|
+
throw new Error(
|
|
149
|
+
"No default provider configured. Either call compute.setConfig({ provider }) or pass provider explicitly."
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
return this.config.provider;
|
|
153
|
+
}
|
|
154
|
+
// Future: compute.blob.*, compute.database.*, compute.git.* will be added here
|
|
155
|
+
// blob = new BlobManager();
|
|
156
|
+
// database = new DatabaseManager();
|
|
157
|
+
// git = new GitManager();
|
|
158
|
+
/**
|
|
159
|
+
* Get the sandbox manager (useful for testing)
|
|
160
|
+
*/
|
|
161
|
+
getSandboxManager() {
|
|
162
|
+
return this.sandboxManager;
|
|
165
163
|
}
|
|
166
164
|
};
|
|
165
|
+
var compute = new ComputeManager();
|
|
167
166
|
|
|
168
|
-
// src/
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
167
|
+
// src/request-handler.ts
|
|
168
|
+
async function handleComputeRequest(params) {
|
|
169
|
+
const { request, provider } = params;
|
|
170
|
+
try {
|
|
171
|
+
const getSandbox = async (sandboxId) => {
|
|
172
|
+
if (sandboxId) {
|
|
173
|
+
const existingSandbox = await compute.sandbox.getById(provider, sandboxId);
|
|
174
|
+
if (!existingSandbox) {
|
|
175
|
+
throw new Error(`Sandbox with ID ${sandboxId} not found`);
|
|
176
|
+
}
|
|
177
|
+
return existingSandbox;
|
|
178
|
+
} else {
|
|
179
|
+
return await compute.sandbox.create({
|
|
180
|
+
provider,
|
|
181
|
+
options: request.options || { runtime: "python" }
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
switch (request.action) {
|
|
186
|
+
// Sandbox operations
|
|
187
|
+
case "compute.sandbox.create": {
|
|
188
|
+
const sandbox = await compute.sandbox.create({
|
|
189
|
+
provider,
|
|
190
|
+
options: request.options || { runtime: "python" }
|
|
191
|
+
});
|
|
192
|
+
return {
|
|
193
|
+
success: true,
|
|
194
|
+
sandboxId: sandbox.sandboxId,
|
|
195
|
+
provider: provider.name
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
case "compute.sandbox.destroy": {
|
|
199
|
+
if (!request.sandboxId) {
|
|
200
|
+
return {
|
|
201
|
+
success: false,
|
|
202
|
+
error: "Sandbox ID is required for destroy action",
|
|
203
|
+
sandboxId: "",
|
|
204
|
+
provider: provider.name
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
await compute.sandbox.destroy(provider, request.sandboxId);
|
|
208
|
+
return {
|
|
209
|
+
success: true,
|
|
210
|
+
sandboxId: request.sandboxId,
|
|
211
|
+
provider: provider.name
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
case "compute.sandbox.getInfo": {
|
|
215
|
+
if (!request.sandboxId) {
|
|
216
|
+
return {
|
|
217
|
+
success: false,
|
|
218
|
+
error: "Sandbox ID is required for getInfo action",
|
|
219
|
+
sandboxId: "",
|
|
220
|
+
provider: provider.name
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
const sandbox = await getSandbox(request.sandboxId);
|
|
224
|
+
const info = await sandbox.getInfo();
|
|
225
|
+
return {
|
|
226
|
+
success: true,
|
|
227
|
+
sandboxId: request.sandboxId,
|
|
228
|
+
provider: provider.name,
|
|
229
|
+
info: {
|
|
230
|
+
id: info.id,
|
|
231
|
+
provider: info.provider,
|
|
232
|
+
runtime: info.runtime,
|
|
233
|
+
status: info.status,
|
|
234
|
+
createdAt: info.createdAt.toISOString(),
|
|
235
|
+
timeout: info.timeout,
|
|
236
|
+
metadata: info.metadata
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
case "compute.sandbox.list": {
|
|
241
|
+
const sandboxes = await compute.sandbox.list(provider);
|
|
242
|
+
return {
|
|
243
|
+
success: true,
|
|
244
|
+
sandboxId: "",
|
|
245
|
+
provider: provider.name,
|
|
246
|
+
sandboxes: sandboxes.map((sandbox) => ({
|
|
247
|
+
sandboxId: sandbox.sandboxId,
|
|
248
|
+
provider: sandbox.provider
|
|
249
|
+
}))
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
// Code execution
|
|
253
|
+
case "compute.sandbox.runCode": {
|
|
254
|
+
if (!request.code) {
|
|
255
|
+
return {
|
|
256
|
+
success: false,
|
|
257
|
+
error: "Code is required for runCode action",
|
|
258
|
+
sandboxId: request.sandboxId || "",
|
|
259
|
+
provider: provider.name
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
const sandbox = await getSandbox(request.sandboxId);
|
|
263
|
+
const result = await sandbox.runCode(request.code, request.runtime);
|
|
264
|
+
return {
|
|
265
|
+
success: true,
|
|
266
|
+
sandboxId: sandbox.sandboxId,
|
|
267
|
+
provider: provider.name,
|
|
268
|
+
result: {
|
|
269
|
+
stdout: result.stdout,
|
|
270
|
+
stderr: result.stderr,
|
|
271
|
+
exitCode: result.exitCode,
|
|
272
|
+
executionTime: result.executionTime
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
case "compute.sandbox.runCommand": {
|
|
277
|
+
if (!request.command) {
|
|
278
|
+
return {
|
|
279
|
+
success: false,
|
|
280
|
+
error: "Command is required for runCommand action",
|
|
281
|
+
sandboxId: request.sandboxId || "",
|
|
282
|
+
provider: provider.name
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
const sandbox = await getSandbox(request.sandboxId);
|
|
286
|
+
const result = await sandbox.runCommand(request.command, request.args);
|
|
287
|
+
return {
|
|
288
|
+
success: true,
|
|
289
|
+
sandboxId: sandbox.sandboxId,
|
|
290
|
+
provider: provider.name,
|
|
291
|
+
result: {
|
|
292
|
+
stdout: result.stdout,
|
|
293
|
+
stderr: result.stderr,
|
|
294
|
+
exitCode: result.exitCode,
|
|
295
|
+
executionTime: result.executionTime
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
// Filesystem operations
|
|
300
|
+
case "compute.sandbox.filesystem.readFile": {
|
|
301
|
+
if (!request.sandboxId) {
|
|
302
|
+
return {
|
|
303
|
+
success: false,
|
|
304
|
+
error: "Sandbox ID is required for filesystem operations",
|
|
305
|
+
sandboxId: "",
|
|
306
|
+
provider: provider.name
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
if (!request.path) {
|
|
310
|
+
return {
|
|
311
|
+
success: false,
|
|
312
|
+
error: "File path is required for readFile action",
|
|
313
|
+
sandboxId: request.sandboxId,
|
|
314
|
+
provider: provider.name
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
const sandbox = await getSandbox(request.sandboxId);
|
|
318
|
+
const content = await sandbox.filesystem.readFile(request.path);
|
|
319
|
+
return {
|
|
320
|
+
success: true,
|
|
321
|
+
sandboxId: request.sandboxId,
|
|
322
|
+
provider: provider.name,
|
|
323
|
+
fileContent: content
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
case "compute.sandbox.filesystem.writeFile": {
|
|
327
|
+
if (!request.sandboxId) {
|
|
328
|
+
return {
|
|
329
|
+
success: false,
|
|
330
|
+
error: "Sandbox ID is required for filesystem operations",
|
|
331
|
+
sandboxId: "",
|
|
332
|
+
provider: provider.name
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
if (!request.path) {
|
|
336
|
+
return {
|
|
337
|
+
success: false,
|
|
338
|
+
error: "File path is required for writeFile action",
|
|
339
|
+
sandboxId: request.sandboxId,
|
|
340
|
+
provider: provider.name
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
if (request.content === void 0) {
|
|
344
|
+
return {
|
|
345
|
+
success: false,
|
|
346
|
+
error: "File content is required for writeFile action",
|
|
347
|
+
sandboxId: request.sandboxId,
|
|
348
|
+
provider: provider.name
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
const sandbox = await getSandbox(request.sandboxId);
|
|
352
|
+
await sandbox.filesystem.writeFile(request.path, request.content);
|
|
353
|
+
return {
|
|
354
|
+
success: true,
|
|
355
|
+
sandboxId: request.sandboxId,
|
|
356
|
+
provider: provider.name
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
case "compute.sandbox.filesystem.mkdir": {
|
|
360
|
+
if (!request.sandboxId) {
|
|
361
|
+
return {
|
|
362
|
+
success: false,
|
|
363
|
+
error: "Sandbox ID is required for filesystem operations",
|
|
364
|
+
sandboxId: "",
|
|
365
|
+
provider: provider.name
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
if (!request.path) {
|
|
369
|
+
return {
|
|
370
|
+
success: false,
|
|
371
|
+
error: "Directory path is required for mkdir action",
|
|
372
|
+
sandboxId: request.sandboxId,
|
|
373
|
+
provider: provider.name
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
const sandbox = await getSandbox(request.sandboxId);
|
|
377
|
+
await sandbox.filesystem.mkdir(request.path);
|
|
378
|
+
return {
|
|
379
|
+
success: true,
|
|
380
|
+
sandboxId: request.sandboxId,
|
|
381
|
+
provider: provider.name
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
case "compute.sandbox.filesystem.readdir": {
|
|
385
|
+
if (!request.sandboxId) {
|
|
386
|
+
return {
|
|
387
|
+
success: false,
|
|
388
|
+
error: "Sandbox ID is required for filesystem operations",
|
|
389
|
+
sandboxId: "",
|
|
390
|
+
provider: provider.name
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
if (!request.path) {
|
|
394
|
+
return {
|
|
395
|
+
success: false,
|
|
396
|
+
error: "Directory path is required for readdir action",
|
|
397
|
+
sandboxId: request.sandboxId,
|
|
398
|
+
provider: provider.name
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
const sandbox = await getSandbox(request.sandboxId);
|
|
402
|
+
const entries = await sandbox.filesystem.readdir(request.path);
|
|
403
|
+
return {
|
|
404
|
+
success: true,
|
|
405
|
+
sandboxId: request.sandboxId,
|
|
406
|
+
provider: provider.name,
|
|
407
|
+
files: entries.map((entry) => ({
|
|
408
|
+
name: entry.name,
|
|
409
|
+
path: entry.path,
|
|
410
|
+
isDirectory: entry.isDirectory,
|
|
411
|
+
size: entry.size,
|
|
412
|
+
lastModified: entry.lastModified.toISOString()
|
|
413
|
+
}))
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
case "compute.sandbox.filesystem.exists": {
|
|
417
|
+
if (!request.sandboxId) {
|
|
418
|
+
return {
|
|
419
|
+
success: false,
|
|
420
|
+
error: "Sandbox ID is required for filesystem operations",
|
|
421
|
+
sandboxId: "",
|
|
422
|
+
provider: provider.name
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
if (!request.path) {
|
|
426
|
+
return {
|
|
427
|
+
success: false,
|
|
428
|
+
error: "Path is required for exists action",
|
|
429
|
+
sandboxId: request.sandboxId,
|
|
430
|
+
provider: provider.name
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
const sandbox = await getSandbox(request.sandboxId);
|
|
434
|
+
const exists = await sandbox.filesystem.exists(request.path);
|
|
435
|
+
return {
|
|
436
|
+
success: true,
|
|
437
|
+
sandboxId: request.sandboxId,
|
|
438
|
+
provider: provider.name,
|
|
439
|
+
exists
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
case "compute.sandbox.filesystem.remove": {
|
|
443
|
+
if (!request.sandboxId) {
|
|
444
|
+
return {
|
|
445
|
+
success: false,
|
|
446
|
+
error: "Sandbox ID is required for filesystem operations",
|
|
447
|
+
sandboxId: "",
|
|
448
|
+
provider: provider.name
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
if (!request.path) {
|
|
452
|
+
return {
|
|
453
|
+
success: false,
|
|
454
|
+
error: "Path is required for remove action",
|
|
455
|
+
sandboxId: request.sandboxId,
|
|
456
|
+
provider: provider.name
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
const sandbox = await getSandbox(request.sandboxId);
|
|
460
|
+
await sandbox.filesystem.remove(request.path);
|
|
461
|
+
return {
|
|
462
|
+
success: true,
|
|
463
|
+
sandboxId: request.sandboxId,
|
|
464
|
+
provider: provider.name
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
// Terminal operations
|
|
468
|
+
case "compute.sandbox.terminal.create": {
|
|
469
|
+
if (!request.sandboxId) {
|
|
470
|
+
return {
|
|
471
|
+
success: false,
|
|
472
|
+
error: "Sandbox ID is required for terminal operations",
|
|
473
|
+
sandboxId: "",
|
|
474
|
+
provider: provider.name
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
const sandbox = await getSandbox(request.sandboxId);
|
|
478
|
+
const terminal = await sandbox.terminal.create(request.terminalOptions);
|
|
479
|
+
return {
|
|
480
|
+
success: true,
|
|
481
|
+
sandboxId: request.sandboxId,
|
|
482
|
+
provider: provider.name,
|
|
483
|
+
terminal: {
|
|
484
|
+
pid: terminal.pid,
|
|
485
|
+
command: terminal.command,
|
|
486
|
+
status: terminal.status,
|
|
487
|
+
cols: terminal.cols,
|
|
488
|
+
rows: terminal.rows
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
case "compute.sandbox.terminal.list": {
|
|
493
|
+
if (!request.sandboxId) {
|
|
494
|
+
return {
|
|
495
|
+
success: false,
|
|
496
|
+
error: "Sandbox ID is required for terminal operations",
|
|
497
|
+
sandboxId: "",
|
|
498
|
+
provider: provider.name
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
const sandbox = await getSandbox(request.sandboxId);
|
|
502
|
+
const terminals = await sandbox.terminal.list();
|
|
503
|
+
return {
|
|
504
|
+
success: true,
|
|
505
|
+
sandboxId: request.sandboxId,
|
|
506
|
+
provider: provider.name,
|
|
507
|
+
terminals: terminals.map((terminal) => ({
|
|
508
|
+
pid: terminal.pid,
|
|
509
|
+
command: terminal.command,
|
|
510
|
+
status: terminal.status,
|
|
511
|
+
cols: terminal.cols,
|
|
512
|
+
rows: terminal.rows
|
|
513
|
+
}))
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
case "compute.sandbox.terminal.getById": {
|
|
517
|
+
if (!request.sandboxId) {
|
|
518
|
+
return {
|
|
519
|
+
success: false,
|
|
520
|
+
error: "Sandbox ID is required for terminal operations",
|
|
521
|
+
sandboxId: "",
|
|
522
|
+
provider: provider.name
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
if (!request.terminalId) {
|
|
526
|
+
return {
|
|
527
|
+
success: false,
|
|
528
|
+
error: "Terminal ID is required for getById action",
|
|
529
|
+
sandboxId: request.sandboxId,
|
|
530
|
+
provider: provider.name
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
const sandbox = await getSandbox(request.sandboxId);
|
|
534
|
+
const terminal = await sandbox.terminal.getById(request.terminalId);
|
|
535
|
+
if (!terminal) {
|
|
536
|
+
return {
|
|
537
|
+
success: false,
|
|
538
|
+
error: `Terminal with ID ${request.terminalId} not found`,
|
|
539
|
+
sandboxId: request.sandboxId,
|
|
540
|
+
provider: provider.name
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
return {
|
|
544
|
+
success: true,
|
|
545
|
+
sandboxId: request.sandboxId,
|
|
546
|
+
provider: provider.name,
|
|
547
|
+
terminal: {
|
|
548
|
+
pid: terminal.pid,
|
|
549
|
+
command: terminal.command,
|
|
550
|
+
status: terminal.status,
|
|
551
|
+
cols: terminal.cols,
|
|
552
|
+
rows: terminal.rows
|
|
553
|
+
}
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
case "compute.sandbox.terminal.destroy": {
|
|
557
|
+
if (!request.sandboxId) {
|
|
558
|
+
return {
|
|
559
|
+
success: false,
|
|
560
|
+
error: "Sandbox ID is required for terminal operations",
|
|
561
|
+
sandboxId: "",
|
|
562
|
+
provider: provider.name
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
if (!request.terminalId) {
|
|
566
|
+
return {
|
|
567
|
+
success: false,
|
|
568
|
+
error: "Terminal ID is required for destroy action",
|
|
569
|
+
sandboxId: request.sandboxId,
|
|
570
|
+
provider: provider.name
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
const sandbox = await getSandbox(request.sandboxId);
|
|
574
|
+
await sandbox.terminal.destroy(request.terminalId);
|
|
575
|
+
return {
|
|
576
|
+
success: true,
|
|
577
|
+
sandboxId: request.sandboxId,
|
|
578
|
+
provider: provider.name
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
// Terminal I/O operations
|
|
582
|
+
case "compute.sandbox.terminal.write": {
|
|
583
|
+
if (!request.sandboxId) {
|
|
584
|
+
return {
|
|
585
|
+
success: false,
|
|
586
|
+
error: "Sandbox ID is required for terminal operations",
|
|
587
|
+
sandboxId: "",
|
|
588
|
+
provider: provider.name
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
if (!request.terminalId) {
|
|
592
|
+
return {
|
|
593
|
+
success: false,
|
|
594
|
+
error: "Terminal ID is required for write action",
|
|
595
|
+
sandboxId: request.sandboxId,
|
|
596
|
+
provider: provider.name
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
if (!request.data) {
|
|
600
|
+
return {
|
|
601
|
+
success: false,
|
|
602
|
+
error: "Data is required for write action",
|
|
603
|
+
sandboxId: request.sandboxId,
|
|
604
|
+
provider: provider.name
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
const sandbox = await getSandbox(request.sandboxId);
|
|
608
|
+
const terminal = await sandbox.terminal.getById(request.terminalId);
|
|
609
|
+
if (!terminal) {
|
|
610
|
+
return {
|
|
611
|
+
success: false,
|
|
612
|
+
error: `Terminal with ID ${request.terminalId} not found`,
|
|
613
|
+
sandboxId: request.sandboxId,
|
|
614
|
+
provider: provider.name
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
await terminal.write(request.data);
|
|
618
|
+
return {
|
|
619
|
+
success: true,
|
|
620
|
+
sandboxId: request.sandboxId,
|
|
621
|
+
provider: provider.name
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
case "compute.sandbox.terminal.resize": {
|
|
625
|
+
if (!request.sandboxId) {
|
|
626
|
+
return {
|
|
627
|
+
success: false,
|
|
628
|
+
error: "Sandbox ID is required for terminal operations",
|
|
629
|
+
sandboxId: "",
|
|
630
|
+
provider: provider.name
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
if (!request.terminalId) {
|
|
634
|
+
return {
|
|
635
|
+
success: false,
|
|
636
|
+
error: "Terminal ID is required for resize action",
|
|
637
|
+
sandboxId: request.sandboxId,
|
|
638
|
+
provider: provider.name
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
if (!request.cols || !request.rows) {
|
|
642
|
+
return {
|
|
643
|
+
success: false,
|
|
644
|
+
error: "Cols and rows are required for resize action",
|
|
645
|
+
sandboxId: request.sandboxId,
|
|
646
|
+
provider: provider.name
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
const sandbox = await getSandbox(request.sandboxId);
|
|
650
|
+
const terminal = await sandbox.terminal.getById(request.terminalId);
|
|
651
|
+
if (!terminal) {
|
|
652
|
+
return {
|
|
653
|
+
success: false,
|
|
654
|
+
error: `Terminal with ID ${request.terminalId} not found`,
|
|
655
|
+
sandboxId: request.sandboxId,
|
|
656
|
+
provider: provider.name
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
await terminal.resize(request.cols, request.rows);
|
|
660
|
+
return {
|
|
661
|
+
success: true,
|
|
662
|
+
sandboxId: request.sandboxId,
|
|
663
|
+
provider: provider.name
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
case "compute.sandbox.terminal.kill": {
|
|
667
|
+
if (!request.sandboxId) {
|
|
668
|
+
return {
|
|
669
|
+
success: false,
|
|
670
|
+
error: "Sandbox ID is required for terminal operations",
|
|
671
|
+
sandboxId: "",
|
|
672
|
+
provider: provider.name
|
|
673
|
+
};
|
|
674
|
+
}
|
|
675
|
+
if (!request.terminalId) {
|
|
676
|
+
return {
|
|
677
|
+
success: false,
|
|
678
|
+
error: "Terminal ID is required for kill action",
|
|
679
|
+
sandboxId: request.sandboxId,
|
|
680
|
+
provider: provider.name
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
const sandbox = await getSandbox(request.sandboxId);
|
|
684
|
+
const terminal = await sandbox.terminal.getById(request.terminalId);
|
|
685
|
+
if (!terminal) {
|
|
686
|
+
return {
|
|
687
|
+
success: false,
|
|
688
|
+
error: `Terminal with ID ${request.terminalId} not found`,
|
|
689
|
+
sandboxId: request.sandboxId,
|
|
690
|
+
provider: provider.name
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
await terminal.kill();
|
|
694
|
+
return {
|
|
695
|
+
success: true,
|
|
696
|
+
sandboxId: request.sandboxId,
|
|
697
|
+
provider: provider.name
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
default:
|
|
701
|
+
return {
|
|
702
|
+
success: false,
|
|
703
|
+
error: `Unknown action: ${request.action}`,
|
|
704
|
+
sandboxId: request.sandboxId || "",
|
|
705
|
+
provider: provider.name
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
} catch (error) {
|
|
709
|
+
return {
|
|
710
|
+
success: false,
|
|
711
|
+
error: error instanceof Error ? error.message : "Unknown error occurred",
|
|
712
|
+
sandboxId: request.sandboxId || "",
|
|
713
|
+
provider: provider.name
|
|
714
|
+
};
|
|
715
|
+
}
|
|
178
716
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
717
|
+
|
|
718
|
+
// src/factory.ts
|
|
719
|
+
var UnsupportedFileSystem = class {
|
|
720
|
+
constructor(providerName) {
|
|
721
|
+
this.providerName = providerName;
|
|
183
722
|
}
|
|
184
|
-
|
|
185
|
-
|
|
723
|
+
async readFile(_path) {
|
|
724
|
+
throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
|
|
186
725
|
}
|
|
187
|
-
|
|
188
|
-
|
|
726
|
+
async writeFile(_path, _content) {
|
|
727
|
+
throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
|
|
189
728
|
}
|
|
190
|
-
|
|
191
|
-
|
|
729
|
+
async mkdir(_path) {
|
|
730
|
+
throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
|
|
192
731
|
}
|
|
193
|
-
|
|
194
|
-
}
|
|
195
|
-
function autoSelectProvider() {
|
|
196
|
-
const available = detectAvailableProviders();
|
|
197
|
-
return available.length > 0 ? available[0] : void 0;
|
|
198
|
-
}
|
|
199
|
-
function normalizeContainerConfig(container) {
|
|
200
|
-
if (!container) {
|
|
201
|
-
return void 0;
|
|
732
|
+
async readdir(_path) {
|
|
733
|
+
throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
|
|
202
734
|
}
|
|
203
|
-
|
|
204
|
-
|
|
735
|
+
async exists(_path) {
|
|
736
|
+
throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
|
|
205
737
|
}
|
|
206
|
-
|
|
207
|
-
throw new
|
|
738
|
+
async remove(_path) {
|
|
739
|
+
throw new Error(`Filesystem operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
|
|
208
740
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
return runtime;
|
|
214
|
-
}
|
|
215
|
-
switch (provider) {
|
|
216
|
-
case "e2b":
|
|
217
|
-
return "python";
|
|
218
|
-
case "vercel":
|
|
219
|
-
return "node";
|
|
220
|
-
case "cloudflare":
|
|
221
|
-
case "fly":
|
|
222
|
-
throw new ConfigurationError(
|
|
223
|
-
`Container-based provider '${provider}' requires explicit runtime or container configuration`,
|
|
224
|
-
provider
|
|
225
|
-
);
|
|
226
|
-
default:
|
|
227
|
-
return "node";
|
|
741
|
+
};
|
|
742
|
+
var UnsupportedTerminal = class {
|
|
743
|
+
constructor(providerName) {
|
|
744
|
+
this.providerName = providerName;
|
|
228
745
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
let envKey;
|
|
232
|
-
switch (provider) {
|
|
233
|
-
case "e2b":
|
|
234
|
-
envKey = ENV_KEYS.E2B;
|
|
235
|
-
break;
|
|
236
|
-
case "vercel":
|
|
237
|
-
envKey = ENV_KEYS.VERCEL;
|
|
238
|
-
break;
|
|
239
|
-
case "cloudflare":
|
|
240
|
-
if (isCloudflareWorkers()) {
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
|
-
envKey = ENV_KEYS.CLOUDFLARE;
|
|
244
|
-
break;
|
|
245
|
-
case "fly":
|
|
246
|
-
envKey = ENV_KEYS.FLY;
|
|
247
|
-
break;
|
|
248
|
-
case "auto":
|
|
249
|
-
return;
|
|
250
|
-
// Will be handled by auto-selection
|
|
251
|
-
default:
|
|
252
|
-
throw new ConfigurationError(`Unknown provider: ${provider}`, "config");
|
|
253
|
-
}
|
|
254
|
-
if (!process.env[envKey]) {
|
|
255
|
-
const available = detectAvailableProviders();
|
|
256
|
-
const suggestions = available.length > 0 ? `Available providers: ${available.join(", ")}` : `No provider API keys found. Set ${Object.values(ENV_KEYS).join(" or ")} environment variables.`;
|
|
257
|
-
throw new ConfigurationError(
|
|
258
|
-
`Missing API key for provider '${provider}'. ${suggestions}`,
|
|
259
|
-
provider
|
|
260
|
-
);
|
|
746
|
+
async create(_options) {
|
|
747
|
+
throw new Error(`Terminal operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
|
|
261
748
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
const normalized = {
|
|
265
|
-
provider: config?.provider || "auto",
|
|
266
|
-
timeout: config?.timeout || DEFAULT_TIMEOUT
|
|
267
|
-
};
|
|
268
|
-
if (normalized.provider === "auto") {
|
|
269
|
-
const autoProvider = autoSelectProvider();
|
|
270
|
-
if (!autoProvider) {
|
|
271
|
-
throw new ConfigurationError(
|
|
272
|
-
`No provider API keys found. Set one of the following environment variables: ${Object.values(ENV_KEYS).join(", ")}`,
|
|
273
|
-
"config"
|
|
274
|
-
);
|
|
275
|
-
}
|
|
276
|
-
normalized.provider = autoProvider;
|
|
277
|
-
} else {
|
|
278
|
-
validateProviderApiKey(normalized.provider);
|
|
749
|
+
async getById(_terminalId) {
|
|
750
|
+
throw new Error(`Terminal operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
|
|
279
751
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
} else if (!config?.container) {
|
|
283
|
-
normalized.runtime = getDefaultRuntime(normalized.provider);
|
|
752
|
+
async list() {
|
|
753
|
+
throw new Error(`Terminal operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
|
|
284
754
|
}
|
|
285
|
-
|
|
286
|
-
|
|
755
|
+
async destroy(_terminalId) {
|
|
756
|
+
throw new Error(`Terminal operations are not supported by ${this.providerName}'s sandbox environment. ${this.providerName} sandboxes are designed for code execution only.`);
|
|
287
757
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
758
|
+
};
|
|
759
|
+
var SupportedFileSystem = class {
|
|
760
|
+
constructor(sandbox, methods) {
|
|
761
|
+
this.sandbox = sandbox;
|
|
762
|
+
this.methods = methods;
|
|
763
|
+
}
|
|
764
|
+
async readFile(path) {
|
|
765
|
+
return this.methods.readFile(this.sandbox, path);
|
|
766
|
+
}
|
|
767
|
+
async writeFile(path, content) {
|
|
768
|
+
return this.methods.writeFile(this.sandbox, path, content);
|
|
769
|
+
}
|
|
770
|
+
async mkdir(path) {
|
|
771
|
+
return this.methods.mkdir(this.sandbox, path);
|
|
772
|
+
}
|
|
773
|
+
async readdir(path) {
|
|
774
|
+
return this.methods.readdir(this.sandbox, path);
|
|
775
|
+
}
|
|
776
|
+
async exists(path) {
|
|
777
|
+
return this.methods.exists(this.sandbox, path);
|
|
778
|
+
}
|
|
779
|
+
async remove(path) {
|
|
780
|
+
return this.methods.remove(this.sandbox, path);
|
|
781
|
+
}
|
|
782
|
+
};
|
|
783
|
+
var GeneratedTerminalSession = class {
|
|
784
|
+
constructor(terminal, sandbox, methods, terminalId, command, cols = 80, rows = 24) {
|
|
785
|
+
this.terminal = terminal;
|
|
786
|
+
this.sandbox = sandbox;
|
|
787
|
+
this.methods = methods;
|
|
788
|
+
this.pid = parseInt(terminalId);
|
|
789
|
+
this.command = command;
|
|
790
|
+
this.status = "running";
|
|
791
|
+
this.cols = cols;
|
|
792
|
+
this.rows = rows;
|
|
793
|
+
}
|
|
794
|
+
async write(data) {
|
|
795
|
+
return this.methods.write(this.sandbox, this.terminal, data);
|
|
796
|
+
}
|
|
797
|
+
async resize(cols, rows) {
|
|
798
|
+
return this.methods.resize(this.sandbox, this.terminal, cols, rows);
|
|
799
|
+
}
|
|
800
|
+
async kill() {
|
|
801
|
+
return this.methods.kill(this.sandbox, this.terminal);
|
|
802
|
+
}
|
|
803
|
+
};
|
|
804
|
+
var SupportedTerminal = class {
|
|
805
|
+
constructor(sandbox, methods) {
|
|
806
|
+
this.sandbox = sandbox;
|
|
807
|
+
this.methods = methods;
|
|
808
|
+
}
|
|
809
|
+
async create(options) {
|
|
810
|
+
let terminalSession;
|
|
811
|
+
const createOptions = {
|
|
812
|
+
...options,
|
|
813
|
+
onData: (data) => {
|
|
814
|
+
if (terminalSession?.onData) {
|
|
815
|
+
terminalSession.onData(data);
|
|
816
|
+
}
|
|
817
|
+
},
|
|
818
|
+
onExit: (exitCode) => {
|
|
819
|
+
if (terminalSession?.onExit) {
|
|
820
|
+
terminalSession.onExit(exitCode);
|
|
821
|
+
}
|
|
304
822
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
823
|
+
};
|
|
824
|
+
const result = await this.methods.create(this.sandbox, createOptions);
|
|
825
|
+
terminalSession = new GeneratedTerminalSession(
|
|
826
|
+
result.terminal,
|
|
827
|
+
this.sandbox,
|
|
828
|
+
this.methods,
|
|
829
|
+
result.terminalId,
|
|
830
|
+
options?.command || "bash",
|
|
831
|
+
options?.cols || 80,
|
|
832
|
+
options?.rows || 24
|
|
833
|
+
);
|
|
834
|
+
terminalSession.onData = options?.onData;
|
|
835
|
+
terminalSession.onExit = options?.onExit;
|
|
836
|
+
return terminalSession;
|
|
308
837
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
838
|
+
async getById(terminalId) {
|
|
839
|
+
const result = await this.methods.getById(this.sandbox, terminalId);
|
|
840
|
+
if (!result) return null;
|
|
841
|
+
return new GeneratedTerminalSession(
|
|
842
|
+
result.terminal,
|
|
843
|
+
this.sandbox,
|
|
844
|
+
this.methods,
|
|
845
|
+
result.terminalId,
|
|
846
|
+
"bash",
|
|
847
|
+
// Default command for existing terminals
|
|
848
|
+
80,
|
|
849
|
+
// Default cols
|
|
850
|
+
24
|
|
851
|
+
// Default rows
|
|
852
|
+
);
|
|
853
|
+
}
|
|
854
|
+
async list() {
|
|
855
|
+
const results = await this.methods.list(this.sandbox);
|
|
856
|
+
return results.map((result) => new GeneratedTerminalSession(
|
|
857
|
+
result.terminal,
|
|
858
|
+
this.sandbox,
|
|
859
|
+
this.methods,
|
|
860
|
+
result.terminalId,
|
|
861
|
+
"bash",
|
|
862
|
+
// Default command
|
|
863
|
+
80,
|
|
864
|
+
// Default cols
|
|
865
|
+
24
|
|
866
|
+
// Default rows
|
|
867
|
+
));
|
|
868
|
+
}
|
|
869
|
+
async destroy(terminalId) {
|
|
870
|
+
return this.methods.destroy(this.sandbox, terminalId);
|
|
871
|
+
}
|
|
872
|
+
};
|
|
873
|
+
var GeneratedSandbox = class {
|
|
874
|
+
constructor(sandbox, sandboxId, providerName, methods, config, destroyMethod) {
|
|
875
|
+
this.sandbox = sandbox;
|
|
876
|
+
this.methods = methods;
|
|
877
|
+
this.config = config;
|
|
878
|
+
this.destroyMethod = destroyMethod;
|
|
879
|
+
this.sandboxId = sandboxId;
|
|
880
|
+
this.provider = providerName;
|
|
881
|
+
if (methods.filesystem) {
|
|
882
|
+
this.filesystem = new SupportedFileSystem(sandbox, methods.filesystem);
|
|
883
|
+
} else {
|
|
884
|
+
this.filesystem = new UnsupportedFileSystem(providerName);
|
|
330
885
|
}
|
|
331
|
-
if (
|
|
332
|
-
|
|
333
|
-
} else if (parts.length === 2) {
|
|
334
|
-
const runtimeOrImage = parts[1];
|
|
335
|
-
if (isRuntime(runtimeOrImage)) {
|
|
336
|
-
return providerFactory({ runtime: runtimeOrImage });
|
|
337
|
-
}
|
|
338
|
-
return providerFactory({ container: { image: runtimeOrImage } });
|
|
886
|
+
if (methods.terminal) {
|
|
887
|
+
this.terminal = new SupportedTerminal(sandbox, methods.terminal);
|
|
339
888
|
} else {
|
|
340
|
-
|
|
341
|
-
return providerFactory({ container: { image: containerImage } });
|
|
889
|
+
this.terminal = new UnsupportedTerminal(providerName);
|
|
342
890
|
}
|
|
343
891
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
function isRuntime(value) {
|
|
347
|
-
return ["node", "python"].includes(value);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
// src/providers/base.ts
|
|
351
|
-
var import_uuid = require("uuid");
|
|
352
|
-
var BaseProvider = class {
|
|
353
|
-
/**
|
|
354
|
-
* Create a new base provider
|
|
355
|
-
*
|
|
356
|
-
* @param provider Provider identifier
|
|
357
|
-
* @param timeout Execution timeout in milliseconds
|
|
358
|
-
*/
|
|
359
|
-
constructor(provider, timeout) {
|
|
360
|
-
/** Specification version */
|
|
361
|
-
this.specificationVersion = "v1";
|
|
362
|
-
this.provider = provider;
|
|
363
|
-
this.sandboxId = (0, import_uuid.v4)();
|
|
364
|
-
this.timeout = timeout;
|
|
892
|
+
async runCode(code, runtime) {
|
|
893
|
+
return await this.methods.runCode(this.sandbox, code, runtime, this.config);
|
|
365
894
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
* @returns Execution result
|
|
372
|
-
*/
|
|
373
|
-
async execute(code, runtime) {
|
|
374
|
-
const startTime = Date.now();
|
|
375
|
-
try {
|
|
376
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
377
|
-
setTimeout(() => {
|
|
378
|
-
reject(new TimeoutError(
|
|
379
|
-
`Execution timed out after ${this.timeout}ms`,
|
|
380
|
-
this.provider,
|
|
381
|
-
this.timeout,
|
|
382
|
-
this.sandboxId
|
|
383
|
-
));
|
|
384
|
-
}, this.timeout);
|
|
385
|
-
});
|
|
386
|
-
const result = await Promise.race([
|
|
387
|
-
this.doExecute(code, runtime),
|
|
388
|
-
timeoutPromise
|
|
389
|
-
]);
|
|
390
|
-
const executionTime = Date.now() - startTime;
|
|
391
|
-
return {
|
|
392
|
-
...result,
|
|
393
|
-
executionTime,
|
|
394
|
-
sandboxId: this.sandboxId,
|
|
395
|
-
provider: this.provider
|
|
396
|
-
};
|
|
397
|
-
} catch (error) {
|
|
398
|
-
if (error instanceof Error && error.name.includes("Error") && "code" in error) {
|
|
399
|
-
throw error;
|
|
400
|
-
}
|
|
401
|
-
throw new ProviderError(
|
|
402
|
-
`Execution failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
403
|
-
this.provider,
|
|
404
|
-
error instanceof Error ? error : void 0,
|
|
405
|
-
this.sandboxId
|
|
406
|
-
);
|
|
407
|
-
}
|
|
895
|
+
async runCommand(command, args) {
|
|
896
|
+
return await this.methods.runCommand(this.sandbox, command, args);
|
|
897
|
+
}
|
|
898
|
+
async getInfo() {
|
|
899
|
+
return await this.methods.getInfo(this.sandbox);
|
|
408
900
|
}
|
|
409
|
-
/**
|
|
410
|
-
* Kill the sandbox
|
|
411
|
-
*
|
|
412
|
-
* @returns Promise that resolves when the sandbox is killed
|
|
413
|
-
*/
|
|
414
901
|
async kill() {
|
|
415
|
-
|
|
416
|
-
await this.doKill();
|
|
417
|
-
} catch (error) {
|
|
418
|
-
throw new ProviderError(
|
|
419
|
-
`Failed to kill sandbox: ${error instanceof Error ? error.message : String(error)}`,
|
|
420
|
-
this.provider,
|
|
421
|
-
error instanceof Error ? error : void 0,
|
|
422
|
-
this.sandboxId
|
|
423
|
-
);
|
|
424
|
-
}
|
|
902
|
+
await this.destroy();
|
|
425
903
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
*
|
|
429
|
-
* @returns Sandbox information
|
|
430
|
-
*/
|
|
431
|
-
async getInfo() {
|
|
432
|
-
try {
|
|
433
|
-
return await this.doGetInfo();
|
|
434
|
-
} catch (error) {
|
|
435
|
-
throw new ProviderError(
|
|
436
|
-
`Failed to get sandbox info: ${error instanceof Error ? error.message : String(error)}`,
|
|
437
|
-
this.provider,
|
|
438
|
-
error instanceof Error ? error : void 0,
|
|
439
|
-
this.sandboxId
|
|
440
|
-
);
|
|
441
|
-
}
|
|
904
|
+
async destroy() {
|
|
905
|
+
await this.destroyMethod(this.config, this.sandboxId);
|
|
442
906
|
}
|
|
443
907
|
};
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
908
|
+
var GeneratedSandboxManager = class {
|
|
909
|
+
constructor(config, providerName, methods) {
|
|
910
|
+
this.config = config;
|
|
911
|
+
this.providerName = providerName;
|
|
912
|
+
this.methods = methods;
|
|
913
|
+
this.activeSandboxes = /* @__PURE__ */ new Map();
|
|
914
|
+
}
|
|
915
|
+
async create(options) {
|
|
916
|
+
const result = await this.methods.create(this.config, options);
|
|
917
|
+
const sandbox = new GeneratedSandbox(
|
|
918
|
+
result.sandbox,
|
|
919
|
+
result.sandboxId,
|
|
920
|
+
this.providerName,
|
|
921
|
+
this.methods,
|
|
922
|
+
this.config,
|
|
923
|
+
this.methods.destroy
|
|
924
|
+
);
|
|
925
|
+
this.activeSandboxes.set(result.sandboxId, sandbox);
|
|
926
|
+
return sandbox;
|
|
927
|
+
}
|
|
928
|
+
async getById(sandboxId) {
|
|
929
|
+
const existing = this.activeSandboxes.get(sandboxId);
|
|
930
|
+
if (existing) {
|
|
931
|
+
return existing;
|
|
932
|
+
}
|
|
933
|
+
const result = await this.methods.getById(this.config, sandboxId);
|
|
934
|
+
if (!result) {
|
|
935
|
+
return null;
|
|
936
|
+
}
|
|
937
|
+
const sandbox = new GeneratedSandbox(
|
|
938
|
+
result.sandbox,
|
|
939
|
+
result.sandboxId,
|
|
940
|
+
this.providerName,
|
|
941
|
+
this.methods,
|
|
942
|
+
this.config,
|
|
943
|
+
this.methods.destroy
|
|
944
|
+
);
|
|
945
|
+
this.activeSandboxes.set(result.sandboxId, sandbox);
|
|
946
|
+
return sandbox;
|
|
947
|
+
}
|
|
948
|
+
async list() {
|
|
949
|
+
const results = await this.methods.list(this.config);
|
|
950
|
+
const sandboxes = [];
|
|
951
|
+
for (const result of results) {
|
|
952
|
+
let sandbox = this.activeSandboxes.get(result.sandboxId);
|
|
953
|
+
if (!sandbox) {
|
|
954
|
+
sandbox = new GeneratedSandbox(
|
|
955
|
+
result.sandbox,
|
|
956
|
+
result.sandboxId,
|
|
957
|
+
this.providerName,
|
|
958
|
+
this.methods,
|
|
959
|
+
this.config,
|
|
960
|
+
this.methods.destroy
|
|
490
961
|
);
|
|
962
|
+
this.activeSandboxes.set(result.sandboxId, sandbox);
|
|
491
963
|
}
|
|
492
|
-
|
|
493
|
-
`Failed to load provider '${providerName}': ${error.message}`,
|
|
494
|
-
"sdk"
|
|
495
|
-
);
|
|
964
|
+
sandboxes.push(sandbox);
|
|
496
965
|
}
|
|
966
|
+
return sandboxes;
|
|
497
967
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
* @returns Array of available provider types
|
|
502
|
-
*/
|
|
503
|
-
static detectProviders() {
|
|
504
|
-
return detectAvailableProviders();
|
|
968
|
+
async destroy(sandboxId) {
|
|
969
|
+
await this.methods.destroy(this.config, sandboxId);
|
|
970
|
+
this.activeSandboxes.delete(sandboxId);
|
|
505
971
|
}
|
|
506
972
|
};
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
973
|
+
var GeneratedProvider = class {
|
|
974
|
+
constructor(config, providerConfig) {
|
|
975
|
+
this.name = providerConfig.name;
|
|
976
|
+
this.sandbox = new GeneratedSandboxManager(
|
|
977
|
+
config,
|
|
978
|
+
providerConfig.name,
|
|
979
|
+
providerConfig.methods.sandbox
|
|
980
|
+
);
|
|
981
|
+
}
|
|
982
|
+
};
|
|
983
|
+
function createProvider(providerConfig) {
|
|
984
|
+
return (config) => {
|
|
985
|
+
return new GeneratedProvider(config, providerConfig);
|
|
986
|
+
};
|
|
987
|
+
}
|
|
510
988
|
// Annotate the CommonJS export names for ESM import in node:
|
|
511
989
|
0 && (module.exports = {
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
ConfigurationError,
|
|
517
|
-
DEFAULT_TIMEOUT,
|
|
518
|
-
ENV_KEYS,
|
|
519
|
-
ExecutionError,
|
|
520
|
-
ProviderError,
|
|
521
|
-
ProviderUnavailableError,
|
|
522
|
-
TimeoutError,
|
|
523
|
-
autoSelectProvider,
|
|
524
|
-
createComputeRegistry,
|
|
525
|
-
detectAvailableProviders,
|
|
526
|
-
executeSandbox,
|
|
527
|
-
getDefaultRuntime,
|
|
528
|
-
isCloudflareWorkers,
|
|
529
|
-
normalizeContainerConfig,
|
|
530
|
-
normalizeSandboxConfig,
|
|
531
|
-
retry,
|
|
532
|
-
validateProviderApiKey
|
|
990
|
+
SandboxManager,
|
|
991
|
+
compute,
|
|
992
|
+
createProvider,
|
|
993
|
+
handleComputeRequest
|
|
533
994
|
});
|
|
534
995
|
//# sourceMappingURL=index.js.map
|