@blaxel/core 0.3.32 → 0.3.34-preview.340
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/posthog.js +2 -3
- package/dist/cjs/common/settings.js +2 -2
- package/dist/cjs/sandbox/client/sdk.gen.js +5 -1
- package/dist/cjs/sandbox/filesystem/filesystem.js +34 -1
- package/dist/cjs/sandbox/sandbox.dockerconfig.test.js +23 -0
- package/dist/cjs/sandbox/sandbox.js +5 -1
- package/dist/cjs/types/common/posthog.d.ts +1 -1
- package/dist/cjs/types/sandbox/client/sdk.gen.d.ts +5 -1
- package/dist/cjs/types/sandbox/client/types.gen.d.ts +49 -2
- package/dist/cjs/types/sandbox/filesystem/filesystem.d.ts +9 -0
- package/dist/cjs/types/sandbox/filesystem/types.d.ts +10 -0
- package/dist/cjs/types/sandbox/sandbox.dockerconfig.test.d.ts +1 -0
- package/dist/cjs/types/sandbox/types.d.ts +6 -0
- package/dist/cjs-browser/.tsbuildinfo +1 -1
- package/dist/cjs-browser/common/posthog.js +2 -3
- package/dist/cjs-browser/common/settings.js +2 -2
- package/dist/cjs-browser/sandbox/client/sdk.gen.js +5 -1
- package/dist/cjs-browser/sandbox/filesystem/filesystem.js +34 -1
- package/dist/cjs-browser/sandbox/sandbox.dockerconfig.test.js +23 -0
- package/dist/cjs-browser/sandbox/sandbox.js +5 -1
- package/dist/cjs-browser/types/common/posthog.d.ts +1 -1
- package/dist/cjs-browser/types/sandbox/client/sdk.gen.d.ts +5 -1
- package/dist/cjs-browser/types/sandbox/client/types.gen.d.ts +49 -2
- package/dist/cjs-browser/types/sandbox/filesystem/filesystem.d.ts +9 -0
- package/dist/cjs-browser/types/sandbox/filesystem/types.d.ts +10 -0
- package/dist/cjs-browser/types/sandbox/sandbox.dockerconfig.test.d.ts +1 -0
- package/dist/cjs-browser/types/sandbox/types.d.ts +6 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/common/posthog.js +2 -3
- package/dist/esm/common/settings.js +2 -2
- package/dist/esm/sandbox/client/sdk.gen.js +5 -1
- package/dist/esm/sandbox/filesystem/filesystem.js +35 -2
- package/dist/esm/sandbox/sandbox.dockerconfig.test.js +21 -0
- package/dist/esm/sandbox/sandbox.js +5 -1
- package/dist/esm-browser/.tsbuildinfo +1 -1
- package/dist/esm-browser/common/posthog.js +2 -3
- package/dist/esm-browser/common/settings.js +2 -2
- package/dist/esm-browser/sandbox/client/sdk.gen.js +5 -1
- package/dist/esm-browser/sandbox/filesystem/filesystem.js +35 -2
- package/dist/esm-browser/sandbox/sandbox.dockerconfig.test.js +21 -0
- package/dist/esm-browser/sandbox/sandbox.js +5 -1
- package/package.json +2 -2
|
@@ -2,14 +2,13 @@ import { fs, os, path } from "../common/node.js";
|
|
|
2
2
|
import { settings } from "./settings.js";
|
|
3
3
|
// PostHog API key injected at build time via build:replace-imports
|
|
4
4
|
const BUILD_POSTHOG_KEY = "";
|
|
5
|
-
|
|
6
|
-
const POSTHOG_HOST = "https://us.i.posthog.com";
|
|
5
|
+
const POSTHOG_HOST = "https://events.blaxel.ai";
|
|
7
6
|
/**
|
|
8
7
|
* How long a capture may stay outstanding.
|
|
9
8
|
*
|
|
10
9
|
* Node keeps the event loop alive while a fetch is pending, so this is what a
|
|
11
10
|
* short-lived script waits for before it can exit. A capture against
|
|
12
|
-
*
|
|
11
|
+
* events.blaxel.ai takes ~250-350ms end to end (DNS + TLS handshake + POST), so
|
|
13
12
|
* a second covers the happy path with headroom. The ceiling matters because a
|
|
14
13
|
* version is only recorded after a successful delivery: when the endpoint is
|
|
15
14
|
* unreachable every later run tries again, and networks that silently drop
|
|
@@ -24,8 +24,8 @@ function missingCredentialsMessage() {
|
|
|
24
24
|
return "No Blaxel credentials found. Set the BL_API_KEY and BL_WORKSPACE environment variables, or run `bl login`.";
|
|
25
25
|
}
|
|
26
26
|
// Build info - these placeholders are replaced at build time by build:replace-imports
|
|
27
|
-
const BUILD_VERSION = "0.3.
|
|
28
|
-
const BUILD_COMMIT = "
|
|
27
|
+
const BUILD_VERSION = "0.3.34-preview.340";
|
|
28
|
+
const BUILD_COMMIT = "e1289af07e1a5c5efeb0af7b397d2c2fd138d89f";
|
|
29
29
|
const BUILD_SENTRY_DSN = "https://fd5e60e1c9820e1eef5ccebb84a07127@o4508714045276160.ingest.us.sentry.io/4510465864564736";
|
|
30
30
|
const BLAXEL_API_VERSION = "2026-09-22";
|
|
31
31
|
// Bun < 1.3.11 never sends connection-level WINDOW_UPDATE: the pooled h2
|
|
@@ -440,7 +440,11 @@ export const deleteFilesystemTreeByPath = (options) => {
|
|
|
440
440
|
};
|
|
441
441
|
/**
|
|
442
442
|
* Get directory tree
|
|
443
|
-
*
|
|
443
|
+
* List a directory. Without query parameters, `files` and `subdirectories` hold its direct children.
|
|
444
|
+
*
|
|
445
|
+
* With `recursive=true`, they hold every file and directory below the path (flat, with full paths). With `content=true`, each regular file (or symlink to one) also carries its `content` as UTF-8 text, like a JSON file read; other entries have no `content`. `patterns`, `excludeDirs` and `excludeHidden` select entries the same way as find, but nothing is excluded by default.
|
|
446
|
+
*
|
|
447
|
+
* The response is all or nothing: when more than `maxFiles` files match, or `content=true` and they hold more than `maxBytes` bytes, the request fails with 422 before any content is read.
|
|
444
448
|
*/
|
|
445
449
|
export const getFilesystemTreeByPath = (options) => {
|
|
446
450
|
return (options.client ?? _heyApiClient).get({
|
|
@@ -4,7 +4,7 @@ import { withUploadSlot } from "../../common/h2fetch.js";
|
|
|
4
4
|
import { isTransientResetError, retryOnTransientReset } from "../../common/transient-retry.js";
|
|
5
5
|
import { shellQuote } from "../../common/shell.js";
|
|
6
6
|
import { SandboxAction } from "../action.js";
|
|
7
|
-
import { deleteFilesystemByPath, deleteFilesystemMultipartByUploadIdAbort, getFilesystemByPath, getFilesystemContentSearchByPath, getFilesystemFindByPath, getFilesystemSearchByPath, getWatchFilesystemByPath, postFilesystemMultipartByUploadIdComplete, postFilesystemMultipartInitiateByPath, putFilesystemByPath, putFilesystemMultipartByUploadIdPart } from "../client/index.js";
|
|
7
|
+
import { deleteFilesystemByPath, deleteFilesystemMultipartByUploadIdAbort, getFilesystemByPath, getFilesystemContentSearchByPath, getFilesystemFindByPath, getFilesystemSearchByPath, getFilesystemTreeByPath, getWatchFilesystemByPath, postFilesystemMultipartByUploadIdComplete, postFilesystemMultipartInitiateByPath, putFilesystemByPath, putFilesystemMultipartByUploadIdPart } from "../client/index.js";
|
|
8
8
|
// Multipart upload constants
|
|
9
9
|
const MULTIPART_THRESHOLD = 5 * 1024 * 1024; // 5MB
|
|
10
10
|
const CHUNK_SIZE = 5 * 1024 * 1024; // 5MB per part
|
|
@@ -203,12 +203,45 @@ export class SandboxFileSystem extends SandboxAction {
|
|
|
203
203
|
baseUrl: this.url,
|
|
204
204
|
}));
|
|
205
205
|
this.handleResponseError(response, data, error);
|
|
206
|
-
if (data && 'content' in data) {
|
|
206
|
+
if (data && 'content' in data && typeof data.content === "string") {
|
|
207
207
|
return data.content;
|
|
208
208
|
}
|
|
209
209
|
throw new Error("Unsupported file type");
|
|
210
210
|
});
|
|
211
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Reads the whole tree under `path` in one request and returns the API's `Directory`: every
|
|
214
|
+
* file below `path` in `files`, each regular file (or symlink to one) with its `content` as
|
|
215
|
+
* UTF-8 text. The sandbox API applies `patterns`, `excludeDirs` and `excludeHidden`, and rejects,
|
|
216
|
+
* returning nothing partial, when more than `maxFiles` files match or they hold more than
|
|
217
|
+
* `maxBytes` bytes.
|
|
218
|
+
*/
|
|
219
|
+
async readTree(path, options = {}) {
|
|
220
|
+
const { patterns, excludeDirs, excludeHidden, maxFiles, maxBytes } = options;
|
|
221
|
+
// Idempotent GET: self-heal a transient connection reset.
|
|
222
|
+
return retryOnTransientReset(async () => {
|
|
223
|
+
const { response, data, error } = await getFilesystemTreeByPath(this.withClient({
|
|
224
|
+
path: { path: this.formatPath(path) },
|
|
225
|
+
query: {
|
|
226
|
+
recursive: true,
|
|
227
|
+
content: true,
|
|
228
|
+
patterns: patterns?.join(","),
|
|
229
|
+
excludeDirs: excludeDirs?.join(","),
|
|
230
|
+
excludeHidden,
|
|
231
|
+
maxFiles,
|
|
232
|
+
maxBytes,
|
|
233
|
+
},
|
|
234
|
+
baseUrl: this.url,
|
|
235
|
+
}));
|
|
236
|
+
this.handleResponseError(response, data, error);
|
|
237
|
+
// An older sandbox API ignores the query and lists only direct children,
|
|
238
|
+
// without `recursive`. Fail instead of returning that as the whole tree.
|
|
239
|
+
if (data?.recursive !== true) {
|
|
240
|
+
throw new Error("readTree needs a newer sandbox API: this sandbox does not support recursive tree reads; update its image");
|
|
241
|
+
}
|
|
242
|
+
return data;
|
|
243
|
+
});
|
|
244
|
+
}
|
|
212
245
|
async readBinary(path) {
|
|
213
246
|
path = this.formatPath(path);
|
|
214
247
|
// Idempotent GET: self-heal a transient connection reset.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { SandboxInstance } from "./sandbox.js";
|
|
3
|
+
// toSandboxModel is private: reach it the same way the create path does, without a network call.
|
|
4
|
+
const { toSandboxModel } = SandboxInstance;
|
|
5
|
+
const toRuntime = (config) => toSandboxModel(config).model.spec?.runtime;
|
|
6
|
+
describe("SandboxInstance.create dockerConfig", () => {
|
|
7
|
+
const auths = { auths: { "ghcr.io": { auth: "dXNlcjp0b2tlbg==" } } };
|
|
8
|
+
it("sends an object as a JSON string in spec.runtime.dockerConfig", () => {
|
|
9
|
+
const runtime = toRuntime({ image: "ghcr.io/org/private:v1", dockerConfig: auths, region: "us-pdx-1" });
|
|
10
|
+
expect(runtime.image).toBe("ghcr.io/org/private:v1");
|
|
11
|
+
expect(JSON.parse(runtime.dockerConfig)).toEqual(auths);
|
|
12
|
+
});
|
|
13
|
+
it("passes a string through unchanged", () => {
|
|
14
|
+
const raw = JSON.stringify(auths);
|
|
15
|
+
expect(toRuntime({ dockerConfig: raw, region: "us-pdx-1" }).dockerConfig).toBe(raw);
|
|
16
|
+
});
|
|
17
|
+
it("omits it from the request when not set", () => {
|
|
18
|
+
const body = JSON.parse(JSON.stringify(toRuntime({ image: "ghcr.io/org/private:v1", region: "us-pdx-1" })));
|
|
19
|
+
expect(body).not.toHaveProperty("dockerConfig");
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -342,7 +342,8 @@ export class SandboxInstance {
|
|
|
342
342
|
'labels' in sandbox ||
|
|
343
343
|
'extraArgs' in sandbox ||
|
|
344
344
|
'terminationGracePeriodSeconds' in sandbox ||
|
|
345
|
-
'standbyGracePeriodSeconds' in sandbox
|
|
345
|
+
'standbyGracePeriodSeconds' in sandbox ||
|
|
346
|
+
'dockerConfig' in sandbox) {
|
|
346
347
|
if (!sandbox)
|
|
347
348
|
sandbox = {};
|
|
348
349
|
requested = { image: sandbox.image, memory: sandbox.memory, region: sandbox.region, envs: normalizeEnvs(sandbox.envs) };
|
|
@@ -365,6 +366,8 @@ export class SandboxInstance {
|
|
|
365
366
|
const snapshotEnabled = sandbox.snapshotEnabled;
|
|
366
367
|
const extraArgs = sandbox.extraArgs;
|
|
367
368
|
const { terminationGracePeriodSeconds, standbyGracePeriodSeconds } = sandbox;
|
|
369
|
+
// Not in the generated SandboxRuntime: the API reads it from the raw body, like the CLI sends it.
|
|
370
|
+
const dockerConfig = typeof sandbox.dockerConfig === "object" ? JSON.stringify(sandbox.dockerConfig) : sandbox.dockerConfig;
|
|
368
371
|
sandbox = {
|
|
369
372
|
metadata: { name: sandbox.name, labels: sandbox.labels, externalId: sandbox.externalId },
|
|
370
373
|
spec: {
|
|
@@ -379,6 +382,7 @@ export class SandboxInstance {
|
|
|
379
382
|
extraArgs,
|
|
380
383
|
terminationGracePeriodSeconds,
|
|
381
384
|
standbyGracePeriodSeconds,
|
|
385
|
+
dockerConfig,
|
|
382
386
|
},
|
|
383
387
|
volumes: volumes,
|
|
384
388
|
lifecycle: lifecycle,
|