@blaxel/core 0.2.83 → 0.2.84-preview.155
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/common/settings.js +10 -5
- package/dist/cjs/sandbox/action.js +11 -2
- package/dist/cjs/sandbox/codegen/codegen.js +4 -6
- package/dist/cjs/sandbox/drive/drive.js +6 -9
- package/dist/cjs/sandbox/filesystem/filesystem.js +28 -43
- package/dist/cjs/sandbox/interpreter.js +2 -2
- package/dist/cjs/sandbox/process/process.js +12 -18
- package/dist/cjs/sandbox/sandbox.js +30 -19
- package/dist/cjs/sandbox/system.js +2 -3
- package/dist/cjs/types/sandbox/action.d.ts +3 -0
- package/dist/cjs/types/sandbox/interpreter.d.ts +2 -1
- package/dist/cjs/types/sandbox/sandbox.d.ts +2 -1
- package/dist/cjs-browser/.tsbuildinfo +1 -1
- package/dist/cjs-browser/common/settings.js +10 -5
- package/dist/cjs-browser/sandbox/action.js +11 -2
- package/dist/cjs-browser/sandbox/codegen/codegen.js +4 -6
- package/dist/cjs-browser/sandbox/drive/drive.js +6 -9
- package/dist/cjs-browser/sandbox/filesystem/filesystem.js +28 -43
- package/dist/cjs-browser/sandbox/interpreter.js +2 -2
- package/dist/cjs-browser/sandbox/process/process.js +12 -18
- package/dist/cjs-browser/sandbox/sandbox.js +30 -19
- package/dist/cjs-browser/sandbox/system.js +2 -3
- package/dist/cjs-browser/types/sandbox/action.d.ts +3 -0
- package/dist/cjs-browser/types/sandbox/interpreter.d.ts +2 -1
- package/dist/cjs-browser/types/sandbox/sandbox.d.ts +2 -1
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/common/settings.js +10 -5
- package/dist/esm/sandbox/action.js +11 -2
- package/dist/esm/sandbox/codegen/codegen.js +4 -6
- package/dist/esm/sandbox/drive/drive.js +6 -9
- package/dist/esm/sandbox/filesystem/filesystem.js +28 -43
- package/dist/esm/sandbox/interpreter.js +2 -2
- package/dist/esm/sandbox/process/process.js +12 -18
- package/dist/esm/sandbox/sandbox.js +30 -19
- package/dist/esm/sandbox/system.js +2 -3
- package/dist/esm-browser/.tsbuildinfo +1 -1
- package/dist/esm-browser/common/settings.js +10 -5
- package/dist/esm-browser/sandbox/action.js +11 -2
- package/dist/esm-browser/sandbox/codegen/codegen.js +4 -6
- package/dist/esm-browser/sandbox/drive/drive.js +6 -9
- package/dist/esm-browser/sandbox/filesystem/filesystem.js +28 -43
- package/dist/esm-browser/sandbox/interpreter.js +2 -2
- package/dist/esm-browser/sandbox/process/process.js +12 -18
- package/dist/esm-browser/sandbox/sandbox.js +30 -19
- package/dist/esm-browser/sandbox/system.js +2 -3
- package/package.json +1 -1
|
@@ -5,8 +5,8 @@ import { authentication } from "../authentication/index.js";
|
|
|
5
5
|
import { env } from "../common/env.js";
|
|
6
6
|
import { fs, os, path } from "../common/node.js";
|
|
7
7
|
// Build info - these placeholders are replaced at build time by build:replace-imports
|
|
8
|
-
const BUILD_VERSION = "0.2.
|
|
9
|
-
const BUILD_COMMIT = "
|
|
8
|
+
const BUILD_VERSION = "0.2.84-preview.155";
|
|
9
|
+
const BUILD_COMMIT = "b37c7bd0ef1257de732b54a2f784c6c91a8d450d";
|
|
10
10
|
const BUILD_SENTRY_DSN = "https://fd5e60e1c9820e1eef5ccebb84a07127@o4508714045276160.ingest.us.sentry.io/4510465864564736";
|
|
11
11
|
const BLAXEL_API_VERSION = "2026-04-16";
|
|
12
12
|
// Cache for config.yaml tracking value
|
|
@@ -66,6 +66,10 @@ function getOsArch() {
|
|
|
66
66
|
}
|
|
67
67
|
return "browser/unknown";
|
|
68
68
|
}
|
|
69
|
+
function isDenoRuntime() {
|
|
70
|
+
const runtime = globalThis;
|
|
71
|
+
return typeof runtime.Deno !== "undefined";
|
|
72
|
+
}
|
|
69
73
|
class Settings {
|
|
70
74
|
_credentials;
|
|
71
75
|
config;
|
|
@@ -217,9 +221,10 @@ class Settings {
|
|
|
217
221
|
return this.config.disableH2;
|
|
218
222
|
}
|
|
219
223
|
const value = env.BL_DISABLE_H2;
|
|
220
|
-
if (
|
|
221
|
-
return
|
|
222
|
-
|
|
224
|
+
if (value) {
|
|
225
|
+
return ["1", "true", "yes", "on"].includes(value.toLowerCase());
|
|
226
|
+
}
|
|
227
|
+
return isDenoRuntime();
|
|
223
228
|
}
|
|
224
229
|
async authenticate() {
|
|
225
230
|
await this.credentials.authenticate();
|
|
@@ -61,7 +61,7 @@ export class SandboxAction {
|
|
|
61
61
|
});
|
|
62
62
|
}
|
|
63
63
|
const h2Domain = this.sandbox.h2Domain;
|
|
64
|
-
if (h2Domain) {
|
|
64
|
+
if (h2Domain && !settings.disableH2) {
|
|
65
65
|
if (!this._h2Client || this._h2ClientDomain !== h2Domain) {
|
|
66
66
|
this._h2Client = createClient({
|
|
67
67
|
fetch: createPoolBackedH2Fetch(h2Pool, h2Domain),
|
|
@@ -82,13 +82,22 @@ export class SandboxAction {
|
|
|
82
82
|
this._h2ClientDomain = null;
|
|
83
83
|
return defaultClient;
|
|
84
84
|
}
|
|
85
|
+
withClient(options) {
|
|
86
|
+
const requestOptions = { ...options };
|
|
87
|
+
Object.defineProperty(requestOptions, 'client', {
|
|
88
|
+
value: this.client,
|
|
89
|
+
enumerable: false,
|
|
90
|
+
configurable: true,
|
|
91
|
+
});
|
|
92
|
+
return requestOptions;
|
|
93
|
+
}
|
|
85
94
|
/**
|
|
86
95
|
* Routes through the H2 session when available, falling back to
|
|
87
96
|
* globalThis.fetch. Uses a direct H2 path that avoids Request allocation.
|
|
88
97
|
*/
|
|
89
98
|
h2Fetch(input, init) {
|
|
90
99
|
const h2Domain = this.sandbox.h2Domain;
|
|
91
|
-
if (h2Domain) {
|
|
100
|
+
if (h2Domain && !settings.disableH2) {
|
|
92
101
|
return h2RequestDirectFromPool(h2Pool, h2Domain, input.toString(), init);
|
|
93
102
|
}
|
|
94
103
|
return globalThis.fetch(input, init);
|
|
@@ -5,22 +5,20 @@ export class SandboxCodegen extends SandboxAction {
|
|
|
5
5
|
super(sandbox);
|
|
6
6
|
}
|
|
7
7
|
async fastapply(path, codeEdit, model) {
|
|
8
|
-
const result = await putCodegenFastapplyByPath({
|
|
8
|
+
const result = await putCodegenFastapplyByPath(this.withClient({
|
|
9
9
|
path: { path },
|
|
10
10
|
body: { codeEdit, model },
|
|
11
11
|
baseUrl: this.url,
|
|
12
|
-
|
|
13
|
-
});
|
|
12
|
+
}));
|
|
14
13
|
this.handleResponseError(result.response, result.data, result.error);
|
|
15
14
|
return result.data;
|
|
16
15
|
}
|
|
17
16
|
async reranking(path, query, scoreThreshold, tokenLimit, filePattern) {
|
|
18
|
-
const result = await getCodegenRerankingByPath({
|
|
17
|
+
const result = await getCodegenRerankingByPath(this.withClient({
|
|
19
18
|
path: { path },
|
|
20
19
|
query: { query, scoreThreshold, tokenLimit, filePattern },
|
|
21
20
|
baseUrl: this.url,
|
|
22
|
-
|
|
23
|
-
});
|
|
21
|
+
}));
|
|
24
22
|
this.handleResponseError(result.response, result.data, result.error);
|
|
25
23
|
return result.data;
|
|
26
24
|
}
|
|
@@ -8,11 +8,10 @@ export class SandboxDrive extends SandboxAction {
|
|
|
8
8
|
* Mount a drive to the sandbox at a specific mount path
|
|
9
9
|
*/
|
|
10
10
|
async mount(request) {
|
|
11
|
-
const { response, data, error } = await postDrivesMount({
|
|
11
|
+
const { response, data, error } = await postDrivesMount(this.withClient({
|
|
12
12
|
baseUrl: this.url,
|
|
13
|
-
client: this.client,
|
|
14
13
|
body: request,
|
|
15
|
-
});
|
|
14
|
+
}));
|
|
16
15
|
this.handleResponseError(response, data, error);
|
|
17
16
|
return data;
|
|
18
17
|
}
|
|
@@ -23,11 +22,10 @@ export class SandboxDrive extends SandboxAction {
|
|
|
23
22
|
// Strip leading slash for the path parameter since the URL template
|
|
24
23
|
// already includes the slash: /drives/mount/{mountPath}
|
|
25
24
|
const paramPath = mountPath.startsWith("/") ? mountPath.substring(1) : mountPath;
|
|
26
|
-
const { response, data, error } = await deleteDrivesMountByMountPath({
|
|
25
|
+
const { response, data, error } = await deleteDrivesMountByMountPath(this.withClient({
|
|
27
26
|
baseUrl: this.url,
|
|
28
|
-
client: this.client,
|
|
29
27
|
path: { mountPath: paramPath },
|
|
30
|
-
});
|
|
28
|
+
}));
|
|
31
29
|
this.handleResponseError(response, data, error);
|
|
32
30
|
return data;
|
|
33
31
|
}
|
|
@@ -35,10 +33,9 @@ export class SandboxDrive extends SandboxAction {
|
|
|
35
33
|
* List all mounted drives in the sandbox
|
|
36
34
|
*/
|
|
37
35
|
async list() {
|
|
38
|
-
const { response, data, error } = await getDrivesMount({
|
|
36
|
+
const { response, data, error } = await getDrivesMount(this.withClient({
|
|
39
37
|
baseUrl: this.url,
|
|
40
|
-
|
|
41
|
-
});
|
|
38
|
+
}));
|
|
42
39
|
this.handleResponseError(response, data, error);
|
|
43
40
|
const result = data;
|
|
44
41
|
return result.mounts ?? [];
|
|
@@ -15,12 +15,11 @@ export class SandboxFileSystem extends SandboxAction {
|
|
|
15
15
|
}
|
|
16
16
|
async mkdir(path, permissions = "0755") {
|
|
17
17
|
path = this.formatPath(path);
|
|
18
|
-
const { response, data, error } = await putFilesystemByPath({
|
|
18
|
+
const { response, data, error } = await putFilesystemByPath(this.withClient({
|
|
19
19
|
path: { path },
|
|
20
20
|
body: { isDirectory: true, permissions },
|
|
21
21
|
baseUrl: this.url,
|
|
22
|
-
|
|
23
|
-
});
|
|
22
|
+
}));
|
|
24
23
|
this.handleResponseError(response, data, error);
|
|
25
24
|
return data;
|
|
26
25
|
}
|
|
@@ -34,12 +33,11 @@ export class SandboxFileSystem extends SandboxAction {
|
|
|
34
33
|
return await this.uploadWithMultipart(path, blob, "0644");
|
|
35
34
|
}
|
|
36
35
|
// Use regular upload for small files
|
|
37
|
-
const { response, data, error } = await putFilesystemByPath({
|
|
36
|
+
const { response, data, error } = await putFilesystemByPath(this.withClient({
|
|
38
37
|
path: { path },
|
|
39
38
|
body: { content },
|
|
40
39
|
baseUrl: this.url,
|
|
41
|
-
|
|
42
|
-
});
|
|
40
|
+
}));
|
|
43
41
|
this.handleResponseError(response, data, error);
|
|
44
42
|
return data;
|
|
45
43
|
}
|
|
@@ -120,7 +118,6 @@ export class SandboxFileSystem extends SandboxAction {
|
|
|
120
118
|
}, {}),
|
|
121
119
|
},
|
|
122
120
|
baseUrl: this.url,
|
|
123
|
-
client: this.client,
|
|
124
121
|
};
|
|
125
122
|
const path = this.formatPath(destinationPath ?? "");
|
|
126
123
|
const { response, data, error } = await this.client.put({
|
|
@@ -135,11 +132,10 @@ export class SandboxFileSystem extends SandboxAction {
|
|
|
135
132
|
}
|
|
136
133
|
async read(path) {
|
|
137
134
|
path = this.formatPath(path);
|
|
138
|
-
const { response, data, error } = await getFilesystemByPath({
|
|
135
|
+
const { response, data, error } = await getFilesystemByPath(this.withClient({
|
|
139
136
|
path: { path },
|
|
140
137
|
baseUrl: this.url,
|
|
141
|
-
|
|
142
|
-
});
|
|
138
|
+
}));
|
|
143
139
|
this.handleResponseError(response, data, error);
|
|
144
140
|
if (data && 'content' in data) {
|
|
145
141
|
return data.content;
|
|
@@ -148,14 +144,13 @@ export class SandboxFileSystem extends SandboxAction {
|
|
|
148
144
|
}
|
|
149
145
|
async readBinary(path) {
|
|
150
146
|
path = this.formatPath(path);
|
|
151
|
-
const { response, data, error } = await getFilesystemByPath({
|
|
147
|
+
const { response, data, error } = await getFilesystemByPath(this.withClient({
|
|
152
148
|
path: { path },
|
|
153
149
|
baseUrl: this.url,
|
|
154
|
-
client: this.client,
|
|
155
150
|
headers: {
|
|
156
151
|
'Accept': 'application/octet-stream',
|
|
157
152
|
},
|
|
158
|
-
});
|
|
153
|
+
}));
|
|
159
154
|
this.handleResponseError(response, data, error);
|
|
160
155
|
if (typeof data === 'string') {
|
|
161
156
|
return new Blob([data]);
|
|
@@ -173,22 +168,20 @@ export class SandboxFileSystem extends SandboxAction {
|
|
|
173
168
|
}
|
|
174
169
|
async rm(path, recursive = false) {
|
|
175
170
|
path = this.formatPath(path);
|
|
176
|
-
const { response, data, error } = await deleteFilesystemByPath({
|
|
171
|
+
const { response, data, error } = await deleteFilesystemByPath(this.withClient({
|
|
177
172
|
path: { path },
|
|
178
173
|
query: { recursive },
|
|
179
174
|
baseUrl: this.url,
|
|
180
|
-
|
|
181
|
-
});
|
|
175
|
+
}));
|
|
182
176
|
this.handleResponseError(response, data, error);
|
|
183
177
|
return data;
|
|
184
178
|
}
|
|
185
179
|
async ls(path) {
|
|
186
180
|
path = this.formatPath(path);
|
|
187
|
-
const { response, data, error } = await getFilesystemByPath({
|
|
181
|
+
const { response, data, error } = await getFilesystemByPath(this.withClient({
|
|
188
182
|
path: { path },
|
|
189
183
|
baseUrl: this.url,
|
|
190
|
-
|
|
191
|
-
});
|
|
184
|
+
}));
|
|
192
185
|
this.handleResponseError(response, data, error);
|
|
193
186
|
if (!data || !('files' in data || 'subdirectories' in data)) {
|
|
194
187
|
throw new Error(JSON.stringify({ error: "Directory not found" }));
|
|
@@ -210,12 +203,11 @@ export class SandboxFileSystem extends SandboxAction {
|
|
|
210
203
|
if (options?.excludeHidden !== undefined) {
|
|
211
204
|
queryParams.excludeHidden = options.excludeHidden;
|
|
212
205
|
}
|
|
213
|
-
const result = await getFilesystemSearchByPath({
|
|
206
|
+
const result = await getFilesystemSearchByPath(this.withClient({
|
|
214
207
|
path: { path: formattedPath },
|
|
215
208
|
query: queryParams,
|
|
216
209
|
baseUrl: this.url,
|
|
217
|
-
|
|
218
|
-
});
|
|
210
|
+
}));
|
|
219
211
|
this.handleResponseError(result.response, result.data, result.error);
|
|
220
212
|
return result.data;
|
|
221
213
|
}
|
|
@@ -237,12 +229,11 @@ export class SandboxFileSystem extends SandboxAction {
|
|
|
237
229
|
if (options?.excludeHidden !== undefined) {
|
|
238
230
|
queryParams.excludeHidden = options.excludeHidden;
|
|
239
231
|
}
|
|
240
|
-
const result = await getFilesystemFindByPath({
|
|
232
|
+
const result = await getFilesystemFindByPath(this.withClient({
|
|
241
233
|
path: { path: formattedPath },
|
|
242
234
|
query: queryParams,
|
|
243
235
|
baseUrl: this.url,
|
|
244
|
-
|
|
245
|
-
});
|
|
236
|
+
}));
|
|
246
237
|
this.handleResponseError(result.response, result.data, result.error);
|
|
247
238
|
return result.data;
|
|
248
239
|
}
|
|
@@ -266,12 +257,11 @@ export class SandboxFileSystem extends SandboxAction {
|
|
|
266
257
|
if (options?.excludeDirs && options.excludeDirs.length > 0) {
|
|
267
258
|
queryParams.excludeDirs = options.excludeDirs.join(',');
|
|
268
259
|
}
|
|
269
|
-
const result = await getFilesystemContentSearchByPath({
|
|
260
|
+
const result = await getFilesystemContentSearchByPath(this.withClient({
|
|
270
261
|
path: { path: formattedPath },
|
|
271
262
|
query: queryParams,
|
|
272
263
|
baseUrl: this.url,
|
|
273
|
-
|
|
274
|
-
});
|
|
264
|
+
}));
|
|
275
265
|
this.handleResponseError(result.response, result.data, result.error);
|
|
276
266
|
return result.data;
|
|
277
267
|
}
|
|
@@ -298,14 +288,13 @@ export class SandboxFileSystem extends SandboxAction {
|
|
|
298
288
|
if (options?.ignore) {
|
|
299
289
|
query.ignore = options.ignore.join(",");
|
|
300
290
|
}
|
|
301
|
-
const { response, data, error } = await getWatchFilesystemByPath({
|
|
302
|
-
client: this.client,
|
|
291
|
+
const { response, data, error } = await getWatchFilesystemByPath(this.withClient({
|
|
303
292
|
path: { path },
|
|
304
293
|
query,
|
|
305
294
|
baseUrl: this.url,
|
|
306
295
|
parseAs: 'stream',
|
|
307
296
|
signal: controller.signal,
|
|
308
|
-
});
|
|
297
|
+
}));
|
|
309
298
|
if (error)
|
|
310
299
|
throw new Error(error instanceof Error ? error.message : JSON.stringify(error));
|
|
311
300
|
const stream = data ?? response.body;
|
|
@@ -380,43 +369,39 @@ export class SandboxFileSystem extends SandboxAction {
|
|
|
380
369
|
// Multipart upload helper methods
|
|
381
370
|
async initiateMultipartUpload(path, permissions = "0644") {
|
|
382
371
|
path = this.formatPath(path);
|
|
383
|
-
const { data } = await postFilesystemMultipartInitiateByPath({
|
|
372
|
+
const { data } = await postFilesystemMultipartInitiateByPath(this.withClient({
|
|
384
373
|
path: { path },
|
|
385
374
|
body: { permissions },
|
|
386
375
|
baseUrl: this.url,
|
|
387
|
-
client: this.client,
|
|
388
376
|
throwOnError: true,
|
|
389
|
-
});
|
|
377
|
+
}));
|
|
390
378
|
return data;
|
|
391
379
|
}
|
|
392
380
|
async uploadPart(uploadId, partNumber, fileBlob) {
|
|
393
|
-
const { data } = await putFilesystemMultipartByUploadIdPart({
|
|
381
|
+
const { data } = await putFilesystemMultipartByUploadIdPart(this.withClient({
|
|
394
382
|
path: { uploadId },
|
|
395
383
|
query: { partNumber },
|
|
396
384
|
body: { file: fileBlob },
|
|
397
385
|
baseUrl: this.url,
|
|
398
|
-
client: this.client,
|
|
399
386
|
throwOnError: true,
|
|
400
|
-
});
|
|
387
|
+
}));
|
|
401
388
|
return data;
|
|
402
389
|
}
|
|
403
390
|
async completeMultipartUpload(uploadId, parts) {
|
|
404
|
-
const { data } = await postFilesystemMultipartByUploadIdComplete({
|
|
391
|
+
const { data } = await postFilesystemMultipartByUploadIdComplete(this.withClient({
|
|
405
392
|
path: { uploadId },
|
|
406
393
|
body: { parts },
|
|
407
394
|
baseUrl: this.url,
|
|
408
|
-
client: this.client,
|
|
409
395
|
throwOnError: true,
|
|
410
|
-
});
|
|
396
|
+
}));
|
|
411
397
|
return data;
|
|
412
398
|
}
|
|
413
399
|
async abortMultipartUpload(uploadId) {
|
|
414
|
-
const { data } = await deleteFilesystemMultipartByUploadIdAbort({
|
|
400
|
+
const { data } = await deleteFilesystemMultipartByUploadIdAbort(this.withClient({
|
|
415
401
|
path: { uploadId },
|
|
416
402
|
baseUrl: this.url,
|
|
417
|
-
client: this.client,
|
|
418
403
|
throwOnError: true,
|
|
419
|
-
});
|
|
404
|
+
}));
|
|
420
405
|
return data;
|
|
421
406
|
}
|
|
422
407
|
async uploadWithMultipart(path, blob, permissions = "0644") {
|
|
@@ -30,7 +30,7 @@ export class CodeInterpreter extends SandboxInstance {
|
|
|
30
30
|
};
|
|
31
31
|
return new CodeInterpreter(config);
|
|
32
32
|
}
|
|
33
|
-
static async create(sandbox, { safe = true } = {}) {
|
|
33
|
+
static async create(sandbox, { safe = true, createIfNotExist = false } = {}) {
|
|
34
34
|
// Build a SandboxCreateConfiguration with CodeInterpreter defaults
|
|
35
35
|
const defaults = {
|
|
36
36
|
image: CodeInterpreter.DEFAULT_IMAGE,
|
|
@@ -63,7 +63,7 @@ export class CodeInterpreter extends SandboxInstance {
|
|
|
63
63
|
else {
|
|
64
64
|
merged = defaults;
|
|
65
65
|
}
|
|
66
|
-
const baseInstance = await super.create(merged, { safe });
|
|
66
|
+
const baseInstance = await super.create(merged, { safe, createIfNotExist });
|
|
67
67
|
// Create config from the instance
|
|
68
68
|
const config = {
|
|
69
69
|
metadata: baseInstance.metadata,
|
|
@@ -108,11 +108,10 @@ export class SandboxProcess extends SandboxAction {
|
|
|
108
108
|
return await this.execWithStreaming(process, { onLog, onStdout, onStderr });
|
|
109
109
|
}
|
|
110
110
|
else {
|
|
111
|
-
const { response, data, error } = await postProcess({
|
|
111
|
+
const { response, data, error } = await postProcess(this.withClient({
|
|
112
112
|
body: process,
|
|
113
113
|
baseUrl: this.url,
|
|
114
|
-
|
|
115
|
-
});
|
|
114
|
+
}));
|
|
116
115
|
this.handleResponseError(response, data, error);
|
|
117
116
|
const result = data;
|
|
118
117
|
if (onLog || onStdout || onStderr) {
|
|
@@ -300,46 +299,41 @@ export class SandboxProcess extends SandboxAction {
|
|
|
300
299
|
return data;
|
|
301
300
|
}
|
|
302
301
|
async get(identifier) {
|
|
303
|
-
const { response, data, error } = await getProcessByIdentifier({
|
|
302
|
+
const { response, data, error } = await getProcessByIdentifier(this.withClient({
|
|
304
303
|
path: { identifier },
|
|
305
304
|
baseUrl: this.url,
|
|
306
|
-
|
|
307
|
-
});
|
|
305
|
+
}));
|
|
308
306
|
this.handleResponseError(response, data, error);
|
|
309
307
|
return data;
|
|
310
308
|
}
|
|
311
309
|
async list() {
|
|
312
|
-
const { response, data, error } = await getProcess({
|
|
310
|
+
const { response, data, error } = await getProcess(this.withClient({
|
|
313
311
|
baseUrl: this.url,
|
|
314
|
-
|
|
315
|
-
});
|
|
312
|
+
}));
|
|
316
313
|
this.handleResponseError(response, data, error);
|
|
317
314
|
return data;
|
|
318
315
|
}
|
|
319
316
|
async stop(identifier) {
|
|
320
|
-
const { response, data, error } = await deleteProcessByIdentifier({
|
|
317
|
+
const { response, data, error } = await deleteProcessByIdentifier(this.withClient({
|
|
321
318
|
path: { identifier },
|
|
322
319
|
baseUrl: this.url,
|
|
323
|
-
|
|
324
|
-
});
|
|
320
|
+
}));
|
|
325
321
|
this.handleResponseError(response, data, error);
|
|
326
322
|
return data;
|
|
327
323
|
}
|
|
328
324
|
async kill(identifier) {
|
|
329
|
-
const { response, data, error } = await deleteProcessByIdentifierKill({
|
|
325
|
+
const { response, data, error } = await deleteProcessByIdentifierKill(this.withClient({
|
|
330
326
|
path: { identifier },
|
|
331
327
|
baseUrl: this.url,
|
|
332
|
-
|
|
333
|
-
});
|
|
328
|
+
}));
|
|
334
329
|
this.handleResponseError(response, data, error);
|
|
335
330
|
return data;
|
|
336
331
|
}
|
|
337
332
|
async logs(identifier, type = "all") {
|
|
338
|
-
const { response, data, error } = await getProcessByIdentifierLogs({
|
|
333
|
+
const { response, data, error } = await getProcessByIdentifierLogs(this.withClient({
|
|
339
334
|
path: { identifier },
|
|
340
335
|
baseUrl: this.url,
|
|
341
|
-
|
|
342
|
-
});
|
|
336
|
+
}));
|
|
343
337
|
this.handleResponseError(response, data, error);
|
|
344
338
|
if (type === "all") {
|
|
345
339
|
return data?.logs || "";
|
|
@@ -11,6 +11,13 @@ import { SandboxProcess } from "./process/index.js";
|
|
|
11
11
|
import { SandboxSessions } from "./session.js";
|
|
12
12
|
import { SandboxSystem } from "./system.js";
|
|
13
13
|
import { normalizeEnvs, normalizePorts, normalizeVolumes } from "./types.js";
|
|
14
|
+
const NON_REUSABLE_SANDBOX_STATUSES = new Set([
|
|
15
|
+
"FAILED",
|
|
16
|
+
"TERMINATED",
|
|
17
|
+
"TERMINATING",
|
|
18
|
+
"DELETING",
|
|
19
|
+
"DEACTIVATING",
|
|
20
|
+
]);
|
|
14
21
|
export class SandboxInstance {
|
|
15
22
|
sandbox;
|
|
16
23
|
fs;
|
|
@@ -96,7 +103,7 @@ export class SandboxInstance {
|
|
|
96
103
|
logger.warn("⚠️ Warning: sandbox.wait() is deprecated. You don't need to wait for the sandbox to be deployed anymore.");
|
|
97
104
|
return this;
|
|
98
105
|
}
|
|
99
|
-
static async create(sandbox, { safe = false } = {}) {
|
|
106
|
+
static async create(sandbox, { safe = false, createIfNotExist = false } = {}) {
|
|
100
107
|
const defaultName = `sandbox-${uuidv4().replace(/-/g, '').substring(0, 8)}`;
|
|
101
108
|
const defaultImage = `blaxel/base-image:latest`;
|
|
102
109
|
const defaultMemory = 4096;
|
|
@@ -180,6 +187,7 @@ export class SandboxInstance {
|
|
|
180
187
|
const [{ data }, h2Session] = await Promise.all([
|
|
181
188
|
createSandbox({
|
|
182
189
|
body: sandbox,
|
|
190
|
+
query: createIfNotExist ? { createIfNotExist } : undefined,
|
|
183
191
|
throwOnError: true,
|
|
184
192
|
}),
|
|
185
193
|
edgeDomain && !settings.disableH2 ? import("../common/h2pool.js").then(({ h2Pool }) => h2Pool.get(edgeDomain)).catch(() => null) : Promise.resolve(null),
|
|
@@ -266,27 +274,30 @@ export class SandboxInstance {
|
|
|
266
274
|
return SandboxInstance.attachH2Session(instance);
|
|
267
275
|
}
|
|
268
276
|
static async createIfNotExists(sandbox) {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
if (
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
//
|
|
283
|
-
|
|
277
|
+
const ATTEMPTS = 3;
|
|
278
|
+
for (let i = 0; i < ATTEMPTS; ++i) {
|
|
279
|
+
try {
|
|
280
|
+
return await this.create(sandbox, { createIfNotExist: true });
|
|
281
|
+
}
|
|
282
|
+
catch (e) {
|
|
283
|
+
if (typeof e === "object" && e !== null && "code" in e && (e.code === 409 || e.code === 'SANDBOX_ALREADY_EXISTS')) {
|
|
284
|
+
const name = 'name' in sandbox ? sandbox.name : sandbox.metadata.name;
|
|
285
|
+
if (!name) {
|
|
286
|
+
throw new Error("Sandbox name is required");
|
|
287
|
+
}
|
|
288
|
+
// Get the existing sandbox to check its status
|
|
289
|
+
const sandboxInstance = await this.get(name);
|
|
290
|
+
// Recreate instead of returning sandbox records that cannot be reused.
|
|
291
|
+
if (!NON_REUSABLE_SANDBOX_STATUSES.has(sandboxInstance.status ?? "")) {
|
|
292
|
+
return sandboxInstance;
|
|
293
|
+
}
|
|
294
|
+
// Retry creation. We want the same error handling on the retry as creates can race.
|
|
295
|
+
continue;
|
|
284
296
|
}
|
|
285
|
-
|
|
286
|
-
return sandboxInstance;
|
|
297
|
+
throw e;
|
|
287
298
|
}
|
|
288
|
-
throw e;
|
|
289
299
|
}
|
|
300
|
+
throw new Error(`Unable to create sandbox after ${ATTEMPTS} attempts.`);
|
|
290
301
|
}
|
|
291
302
|
/* eslint-disable */
|
|
292
303
|
static async fromSession(session) {
|
|
@@ -5,11 +5,10 @@ export class SandboxSystem extends SandboxAction {
|
|
|
5
5
|
super(sandbox);
|
|
6
6
|
}
|
|
7
7
|
async upgrade(body) {
|
|
8
|
-
const { response, data, error } = await postUpgrade({
|
|
8
|
+
const { response, data, error } = await postUpgrade(this.withClient({
|
|
9
9
|
baseUrl: this.url,
|
|
10
|
-
client: this.client,
|
|
11
10
|
body,
|
|
12
|
-
});
|
|
11
|
+
}));
|
|
13
12
|
this.handleResponseError(response, data, error);
|
|
14
13
|
return data;
|
|
15
14
|
}
|