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