@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.
Files changed (43) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/common/posthog.js +2 -3
  3. package/dist/cjs/common/settings.js +2 -2
  4. package/dist/cjs/sandbox/client/sdk.gen.js +5 -1
  5. package/dist/cjs/sandbox/filesystem/filesystem.js +34 -1
  6. package/dist/cjs/sandbox/sandbox.dockerconfig.test.js +23 -0
  7. package/dist/cjs/sandbox/sandbox.js +5 -1
  8. package/dist/cjs/types/common/posthog.d.ts +1 -1
  9. package/dist/cjs/types/sandbox/client/sdk.gen.d.ts +5 -1
  10. package/dist/cjs/types/sandbox/client/types.gen.d.ts +49 -2
  11. package/dist/cjs/types/sandbox/filesystem/filesystem.d.ts +9 -0
  12. package/dist/cjs/types/sandbox/filesystem/types.d.ts +10 -0
  13. package/dist/cjs/types/sandbox/sandbox.dockerconfig.test.d.ts +1 -0
  14. package/dist/cjs/types/sandbox/types.d.ts +6 -0
  15. package/dist/cjs-browser/.tsbuildinfo +1 -1
  16. package/dist/cjs-browser/common/posthog.js +2 -3
  17. package/dist/cjs-browser/common/settings.js +2 -2
  18. package/dist/cjs-browser/sandbox/client/sdk.gen.js +5 -1
  19. package/dist/cjs-browser/sandbox/filesystem/filesystem.js +34 -1
  20. package/dist/cjs-browser/sandbox/sandbox.dockerconfig.test.js +23 -0
  21. package/dist/cjs-browser/sandbox/sandbox.js +5 -1
  22. package/dist/cjs-browser/types/common/posthog.d.ts +1 -1
  23. package/dist/cjs-browser/types/sandbox/client/sdk.gen.d.ts +5 -1
  24. package/dist/cjs-browser/types/sandbox/client/types.gen.d.ts +49 -2
  25. package/dist/cjs-browser/types/sandbox/filesystem/filesystem.d.ts +9 -0
  26. package/dist/cjs-browser/types/sandbox/filesystem/types.d.ts +10 -0
  27. package/dist/cjs-browser/types/sandbox/sandbox.dockerconfig.test.d.ts +1 -0
  28. package/dist/cjs-browser/types/sandbox/types.d.ts +6 -0
  29. package/dist/esm/.tsbuildinfo +1 -1
  30. package/dist/esm/common/posthog.js +2 -3
  31. package/dist/esm/common/settings.js +2 -2
  32. package/dist/esm/sandbox/client/sdk.gen.js +5 -1
  33. package/dist/esm/sandbox/filesystem/filesystem.js +35 -2
  34. package/dist/esm/sandbox/sandbox.dockerconfig.test.js +21 -0
  35. package/dist/esm/sandbox/sandbox.js +5 -1
  36. package/dist/esm-browser/.tsbuildinfo +1 -1
  37. package/dist/esm-browser/common/posthog.js +2 -3
  38. package/dist/esm-browser/common/settings.js +2 -2
  39. package/dist/esm-browser/sandbox/client/sdk.gen.js +5 -1
  40. package/dist/esm-browser/sandbox/filesystem/filesystem.js +35 -2
  41. package/dist/esm-browser/sandbox/sandbox.dockerconfig.test.js +21 -0
  42. package/dist/esm-browser/sandbox/sandbox.js +5 -1
  43. 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
- // PostHog API endpoint
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
- * us.i.posthog.com takes ~250-350ms end to end (DNS + TLS handshake + POST), so
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.32";
28
- const BUILD_COMMIT = "85c4e5d52f8c501ac8db9409390611090a3e4df2";
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
- * Get a recursive directory tree structure starting from the specified path
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,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blaxel/core",
3
- "version": "0.3.32",
3
+ "version": "0.3.34-preview.340",
4
4
  "description": "Blaxel Core SDK for TypeScript",
5
5
  "license": "MIT",
6
6
  "author": "Blaxel, INC (https://blaxel.ai)",
@@ -76,7 +76,7 @@
76
76
  "uuid": "^11.1.0",
77
77
  "ws": "^8.18.2",
78
78
  "yaml": "^2.7.1",
79
- "zod": "^3.25.0 || ^4.0.0"
79
+ "zod": "^3.25.0 || ^4.6.6"
80
80
  },
81
81
  "devDependencies": {
82
82
  "@eslint/js": "^9.26.0",