@tensorlakeai/tensorlake 0.5.154 → 0.5.157

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 (35) hide show
  1. package/dist/applications/index.cjs +131 -40
  2. package/dist/applications/index.cjs.map +1 -1
  3. package/dist/applications/index.d.cts +3 -3
  4. package/dist/applications/index.d.ts +3 -3
  5. package/dist/applications/index.js +131 -40
  6. package/dist/applications/index.js.map +1 -1
  7. package/dist/function-agent/main.cjs +1 -1
  8. package/dist/function-agent/main.js +1 -1
  9. package/dist/function-executor/main.cjs +2 -2
  10. package/dist/function-executor/main.js +2 -2
  11. package/dist/index.cjs +175 -62
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +31 -23
  14. package/dist/index.d.ts +31 -23
  15. package/dist/index.js +175 -62
  16. package/dist/index.js.map +1 -1
  17. package/dist/{remote-B3vn4tt1.d.cts → remote-CEs4GFGP.d.cts} +1 -1
  18. package/dist/{remote-DqBUuciu.d.ts → remote-DYBXCTNC.d.ts} +1 -1
  19. package/dist/{sandbox-image-BMiFlzAs.d.cts → sandbox-image-C2GTVnx3.d.cts} +99 -52
  20. package/dist/{sandbox-image-BMiFlzAs.d.ts → sandbox-image-C2GTVnx3.d.ts} +99 -52
  21. package/dist/sandbox-image.cjs +119 -30
  22. package/dist/sandbox-image.cjs.map +1 -1
  23. package/dist/sandbox-image.d.cts +1 -1
  24. package/dist/sandbox-image.d.ts +1 -1
  25. package/dist/sandbox-image.js +119 -30
  26. package/dist/sandbox-image.js.map +1 -1
  27. package/package.json +7 -7
  28. package/runtime/function-executor/manifest.json +5 -5
  29. package/runtime/function-executor/package/dist/function-executor/main.js +2 -2
  30. package/runtime/function-executor/package/npm-shrinkwrap.json +2 -2
  31. package/runtime/function-executor/package/package.json +1 -1
  32. package/runtime/typescript-function-runner/manifest.json +5 -5
  33. package/runtime/typescript-function-runner/package/dist/function-agent/main.js +1 -1
  34. package/runtime/typescript-function-runner/package/npm-shrinkwrap.json +26 -26
  35. package/runtime/typescript-function-runner/package/package.json +7 -7
@@ -402,7 +402,7 @@ var NativeWorkerClient = class {
402
402
  }
403
403
  };
404
404
  var runtimeKey = /* @__PURE__ */ Symbol.for(
405
- `tensorlake.native.worker.${false ? "source" : "0.5.154"}.v1`
405
+ `tensorlake.native.worker.${false ? "source" : "0.5.157"}.v1`
406
406
  );
407
407
  var runtimes = globalThis;
408
408
  function configureNativeWorker(workerPath) {
@@ -390,7 +390,7 @@ var NativeWorkerClient = class {
390
390
  }
391
391
  };
392
392
  var runtimeKey = /* @__PURE__ */ Symbol.for(
393
- `tensorlake.native.worker.${false ? "source" : "0.5.154"}.v1`
393
+ `tensorlake.native.worker.${false ? "source" : "0.5.157"}.v1`
394
394
  );
395
395
  var runtimes = globalThis;
396
396
  function configureNativeWorker(workerPath) {
@@ -51,7 +51,7 @@ var cancelNativeCall = /* @__PURE__ */ Symbol.for("tensorlake.native.cancel.v1")
51
51
  var closeNativeHandle = /* @__PURE__ */ Symbol.for("tensorlake.native.close.v1");
52
52
 
53
53
  // src/defaults.ts
54
- var SDK_VERSION = "0.5.154";
54
+ var SDK_VERSION = "0.5.157";
55
55
  var API_URL = process.env.TENSORLAKE_API_URL ?? "https://api.tensorlake.ai";
56
56
  var API_KEY = process.env.TENSORLAKE_API_KEY ?? void 0;
57
57
  var NAMESPACE = process.env.INDEXIFY_NAMESPACE ?? "default";
@@ -247,7 +247,7 @@ var NativeWorkerClient = class {
247
247
  }
248
248
  };
249
249
  var runtimeKey = /* @__PURE__ */ Symbol.for(
250
- `tensorlake.native.worker.${false ? "source" : "0.5.154"}.v1`
250
+ `tensorlake.native.worker.${false ? "source" : "0.5.157"}.v1`
251
251
  );
252
252
  var runtimes = globalThis;
253
253
  function configureNativeWorker(workerPath) {
@@ -10,7 +10,7 @@ var cancelNativeCall = /* @__PURE__ */ Symbol.for("tensorlake.native.cancel.v1")
10
10
  var closeNativeHandle = /* @__PURE__ */ Symbol.for("tensorlake.native.close.v1");
11
11
 
12
12
  // src/defaults.ts
13
- var SDK_VERSION = "0.5.154";
13
+ var SDK_VERSION = "0.5.157";
14
14
  var API_URL = process.env.TENSORLAKE_API_URL ?? "https://api.tensorlake.ai";
15
15
  var API_KEY = process.env.TENSORLAKE_API_KEY ?? void 0;
16
16
  var NAMESPACE = process.env.INDEXIFY_NAMESPACE ?? "default";
@@ -206,7 +206,7 @@ var NativeWorkerClient = class {
206
206
  }
207
207
  };
208
208
  var runtimeKey = /* @__PURE__ */ Symbol.for(
209
- `tensorlake.native.worker.${false ? "source" : "0.5.154"}.v1`
209
+ `tensorlake.native.worker.${false ? "source" : "0.5.157"}.v1`
210
210
  );
211
211
  var runtimes = globalThis;
212
212
  function configureNativeWorker(workerPath) {
package/dist/index.cjs CHANGED
@@ -49,7 +49,7 @@ var init_defaults = __esm({
49
49
  "src/defaults.ts"() {
50
50
  "use strict";
51
51
  init_cjs_shims();
52
- SDK_VERSION = "0.5.154";
52
+ SDK_VERSION = "0.5.157";
53
53
  API_URL = process.env.TENSORLAKE_API_URL ?? "https://api.tensorlake.ai";
54
54
  API_KEY = process.env.TENSORLAKE_API_KEY ?? void 0;
55
55
  NAMESPACE = process.env.INDEXIFY_NAMESPACE ?? "default";
@@ -512,7 +512,7 @@ var init_native_worker_client = __esm({
512
512
  }
513
513
  };
514
514
  runtimeKey = /* @__PURE__ */ Symbol.for(
515
- `tensorlake.native.worker.${false ? "source" : "0.5.154"}.v1`
515
+ `tensorlake.native.worker.${false ? "source" : "0.5.157"}.v1`
516
516
  );
517
517
  runtimes = globalThis;
518
518
  }
@@ -4088,9 +4088,7 @@ var init_sandbox = __esm({
4088
4088
  */
4089
4089
  async listSnapshots() {
4090
4090
  const client = this.requireLifecycleClient("listSnapshots");
4091
- const all = await client.listSnapshots();
4092
- const filtered = all.filter((s) => s.sandboxId === this.lifecycleIdentifier);
4093
- return Object.assign(filtered, { traceId: all.traceId });
4091
+ return client.listSandboxSnapshots(this.lifecycleIdentifier);
4094
4092
  }
4095
4093
  /** Close the proxy connection. The sandbox keeps running. */
4096
4094
  close() {
@@ -4638,6 +4636,18 @@ function validateResizeWait(options) {
4638
4636
  throw new SandboxError("pollInterval must be finite and positive");
4639
4637
  }
4640
4638
  }
4639
+ function parseSnapshotList({ traceId, json }) {
4640
+ const parsed = JSON.parse(json);
4641
+ if (parsed !== null && (typeof parsed !== "object" || Array.isArray(parsed))) {
4642
+ throw new SandboxError("Invalid snapshot list response: expected an object");
4643
+ }
4644
+ const records = parsed?.snapshots ?? [];
4645
+ if (!Array.isArray(records)) {
4646
+ throw new SandboxError("Invalid snapshot list response: snapshots must be an array");
4647
+ }
4648
+ const snapshots = records.map((s) => parseSnapshot(s));
4649
+ return Object.assign(snapshots, { traceId });
4650
+ }
4641
4651
  var DEFAULT_WAIT_POLL_INTERVAL_SEC, GPU_MODELS, SandboxClient, RESERVED_SANDBOX_MANAGEMENT_PORT;
4642
4652
  var init_client = __esm({
4643
4653
  "src/client.ts"() {
@@ -5307,19 +5317,18 @@ var init_client = __esm({
5307
5317
  }
5308
5318
  /** List all snapshots in the namespace. */
5309
5319
  async listSnapshots() {
5310
- const { traceId, json } = await callNative(
5311
- () => this.native.listSnapshots()
5320
+ return parseSnapshotList(
5321
+ await callNative(() => this.native.listSnapshots())
5322
+ );
5323
+ }
5324
+ /**
5325
+ * List snapshots taken from one sandbox (its ID or name), from the
5326
+ * sandbox's own listing rather than the whole namespace's.
5327
+ */
5328
+ async listSandboxSnapshots(sandboxId) {
5329
+ return parseSnapshotList(
5330
+ await callNative(() => this.native.listSandboxSnapshots(sandboxId))
5312
5331
  );
5313
- const parsed = JSON.parse(json);
5314
- if (parsed !== null && (typeof parsed !== "object" || Array.isArray(parsed))) {
5315
- throw new SandboxError("Invalid snapshot list response: expected an object");
5316
- }
5317
- const records = parsed?.snapshots ?? [];
5318
- if (!Array.isArray(records)) {
5319
- throw new SandboxError("Invalid snapshot list response: snapshots must be an array");
5320
- }
5321
- const snapshots = records.map((s) => parseSnapshot(s));
5322
- return Object.assign(snapshots, { traceId });
5323
5332
  }
5324
5333
  /** Delete a snapshot by ID. */
5325
5334
  async deleteSnapshot(snapshotId) {
@@ -5719,10 +5728,11 @@ var init_image = __esm({
5719
5728
  });
5720
5729
  }
5721
5730
  /**
5722
- * Build this image as a sandbox template and register it.
5731
+ * Build this image and register it as a CAS sandbox image (the default) or,
5732
+ * with `cas: false`, a legacy sandbox image.
5723
5733
  *
5724
5734
  * Materializes the image in a build sandbox, snapshots the filesystem,
5725
- * and registers the snapshot as a named sandbox template.
5735
+ * and registers the snapshot under the image's name.
5726
5736
  */
5727
5737
  async build(options = {}) {
5728
5738
  const { createSandboxImage: createSandboxImage2 } = await Promise.resolve().then(() => (init_sandbox_image(), sandbox_image_exports));
@@ -6002,14 +6012,14 @@ function rejectLegacyReference(buildId) {
6002
6012
  if (buildId.startsWith("sandbox_template_")) {
6003
6013
  throw new ImageBuildError({
6004
6014
  code: "usage" /* USAGE */,
6005
- message: `'${buildId}' is a legacy sandbox template id; legacy images have no build operation to get, wait for or cancel`,
6015
+ message: `'${buildId}' is a legacy image id; legacy images have no build operation to get, wait for or cancel`,
6006
6016
  buildId
6007
6017
  });
6008
6018
  }
6009
6019
  if (buildId.startsWith("image_")) {
6010
6020
  throw new ImageBuildError({
6011
6021
  code: "usage" /* USAGE */,
6012
- message: `'${buildId}' is an image id, not a build id; look the image up with findSandboxImageByName or use the build id admission returned`,
6022
+ message: `'${buildId}' is a CAS image id, not a build id; look the CAS image up with findSandboxImageByName or use the build id admission returned`,
6013
6023
  buildId
6014
6024
  });
6015
6025
  }
@@ -6088,19 +6098,27 @@ async function startImageBuild(source, options = {}, deps = {}) {
6088
6098
  let text = dockerfileContent(source);
6089
6099
  if (!text.endsWith("\n")) text += "\n";
6090
6100
  dockerfileText = text;
6091
- name = options.registeredName ?? source.name;
6101
+ name = __imageBuildInternals.registeredImageName(
6102
+ options.registeredName ?? source.name,
6103
+ void 0,
6104
+ true
6105
+ );
6092
6106
  } else if (typeof source === "string") {
6093
6107
  const resolved = import_node_path2.default.resolve(source);
6094
6108
  if (!(0, import_node_fs.existsSync)(resolved)) throw new Error(`Dockerfile not found: ${source}`);
6095
6109
  dockerfilePath = resolved;
6096
- name = options.registeredName ?? __imageBuildInternals.defaultRegisteredName(resolved);
6110
+ name = __imageBuildInternals.registeredImageName(
6111
+ options.registeredName,
6112
+ __imageBuildInternals.defaultRegisteredName(resolved),
6113
+ true
6114
+ );
6097
6115
  } else {
6098
6116
  throw new TypeError(`source must be an Image or a Dockerfile path, got ${typeof source}`);
6099
6117
  }
6100
6118
  try {
6101
6119
  const credentials = credentialsFromEnv();
6102
6120
  const binding = __imageBuildInternals.loadNativeBinding();
6103
- emitter.emit({ type: "status", message: `Building image '${name}'...` });
6121
+ emitter.emit({ type: "status", message: `Building CAS image '${name}'...` });
6104
6122
  const json = await __runWithInterrupt(
6105
6123
  options.signal,
6106
6124
  (interruptId) => binding.startImageBuild(
@@ -6136,11 +6154,16 @@ async function startImageImport(imageReference, options = {}, deps = {}) {
6136
6154
  throw new Error("image reference to import must not be empty");
6137
6155
  }
6138
6156
  const reference = imageReference.trim();
6139
- const name = options.registeredName ?? __imageBuildInternals.defaultRegisteredNameFromImage(reference);
6157
+ const name = __imageBuildInternals.registeredImageName(
6158
+ options.registeredName,
6159
+ __imageBuildInternals.defaultRegisteredNameFromImage(reference),
6160
+ true,
6161
+ __imageBuildInternals.defaultImportedImageName
6162
+ );
6140
6163
  const emitter = makeEmitter({ emit: deps.emit ?? options.emit, verbose: options.verbose });
6141
6164
  const credentials = credentialsFromEnv();
6142
6165
  const binding = __imageBuildInternals.loadNativeBinding();
6143
- emitter.emit({ type: "status", message: `Importing image '${reference}' as '${name}'...` });
6166
+ emitter.emit({ type: "status", message: `Importing '${reference}' as CAS image '${name}'...` });
6144
6167
  const json = await __runWithInterrupt(
6145
6168
  options.signal,
6146
6169
  (interruptId) => binding.startImageImport(
@@ -6476,16 +6499,58 @@ function defaultRegisteredName(dockerfilePath) {
6476
6499
  const parsed = import_node_path3.default.parse(dockerfilePath);
6477
6500
  if (parsed.name.toLowerCase() === "dockerfile") {
6478
6501
  const parentName = import_node_path3.default.basename(import_node_path3.default.dirname(dockerfilePath)).trim();
6479
- return parentName || "sandbox-image";
6502
+ return parentName || DEFAULT_SANDBOX_IMAGE_NAME;
6503
+ }
6504
+ return parsed.name || DEFAULT_SANDBOX_IMAGE_NAME;
6505
+ }
6506
+ function registeredImageName(explicit, generated, cas, fallback = DEFAULT_SANDBOX_IMAGE_NAME) {
6507
+ if (explicit || generated === void 0) {
6508
+ const name = explicit ?? "";
6509
+ return cas ? canonicalCasImageName(name) : name;
6510
+ }
6511
+ return cas ? casImageNameFrom(generated, fallback) : generated;
6512
+ }
6513
+ function canonicalCasImageName(name) {
6514
+ return name.replace(/[A-Z]/g, (c) => c.toLowerCase());
6515
+ }
6516
+ function casImageNameFrom(raw, fallback) {
6517
+ const lowered = canonicalCasImageName(raw);
6518
+ if (isAddressableCasImageName(lowered)) {
6519
+ return lowered;
6520
+ }
6521
+ let name = "";
6522
+ for (const original of lowered) {
6523
+ const ch = /^[a-z0-9._-]$/.test(original) ? original : "-";
6524
+ const previous = name[name.length - 1];
6525
+ if (CAS_NAME_SEPARATORS.includes(ch) && previous !== void 0 && CAS_NAME_SEPARATORS.includes(previous)) {
6526
+ continue;
6527
+ }
6528
+ name += ch;
6480
6529
  }
6481
- return parsed.name || "sandbox-image";
6530
+ name = name.replace(/^[._-]+|[._-]+$/g, "").slice(0, MAX_CAS_IMAGE_NAME_LENGTH).replace(/[._-]+$/, "");
6531
+ return isAddressableCasImageName(name) ? name : fallback;
6532
+ }
6533
+ function isAddressableCasImageName(name) {
6534
+ if (name.length === 0 || name.length > MAX_CAS_IMAGE_NAME_LENGTH || RESERVED_IMAGE_NAME_PREFIXES.some((prefix) => name.startsWith(prefix)) || /^[0-9a-f]{64}$/.test(name)) {
6535
+ return false;
6536
+ }
6537
+ const colon = name.indexOf(":");
6538
+ const repository = colon === -1 ? name : name.slice(0, colon);
6539
+ if (!repository.split("/").every((component) => /^[a-z0-9]+(?:[._-][a-z0-9]+)*$/.test(component))) {
6540
+ return false;
6541
+ }
6542
+ if (colon === -1) {
6543
+ return true;
6544
+ }
6545
+ const tag = name.slice(colon + 1);
6546
+ return tag.length > 0 && tag.length <= 128 && /^[a-z0-9._-]+$/.test(tag) && !tag.startsWith(".") && !tag.startsWith("-");
6482
6547
  }
6483
6548
  function defaultRegisteredNameFromImage(imageReference) {
6484
6549
  const withoutDigest = imageReference.split("@", 1)[0] ?? imageReference;
6485
6550
  const lastSegment = withoutDigest.split("/").pop() ?? withoutDigest;
6486
6551
  const colonIndex = lastSegment.lastIndexOf(":");
6487
6552
  const name = colonIndex > 0 && colonIndex < lastSegment.length - 1 ? lastSegment.slice(0, colonIndex) : lastSegment;
6488
- return name || "imported-image";
6553
+ return name || DEFAULT_IMPORTED_IMAGE_NAME;
6489
6554
  }
6490
6555
  function noopEmit(_event) {
6491
6556
  }
@@ -6588,7 +6653,11 @@ async function createSandboxImage(source, options = {}, deps = {}) {
6588
6653
  if (!text.endsWith("\n")) text += "\n";
6589
6654
  dockerfileText = text;
6590
6655
  nativeContextDir = resolvedContext;
6591
- effectiveName = options.registeredName ?? source.name;
6656
+ effectiveName = registeredImageName(
6657
+ options.registeredName ?? source.name,
6658
+ void 0,
6659
+ options.cas ?? true
6660
+ );
6592
6661
  } else if (typeof source === "string") {
6593
6662
  const resolvedPath = import_node_path3.default.resolve(source);
6594
6663
  if (!(0, import_node_fs2.existsSync)(resolvedPath)) {
@@ -6597,7 +6666,11 @@ async function createSandboxImage(source, options = {}, deps = {}) {
6597
6666
  dockerfilePath = resolvedPath;
6598
6667
  dockerfileText = void 0;
6599
6668
  nativeContextDir = void 0;
6600
- effectiveName = options.registeredName ?? defaultRegisteredName(resolvedPath);
6669
+ effectiveName = registeredImageName(
6670
+ options.registeredName,
6671
+ defaultRegisteredName(resolvedPath),
6672
+ options.cas ?? true
6673
+ );
6601
6674
  } else {
6602
6675
  throw new TypeError(
6603
6676
  `source must be an Image or a Dockerfile path, got ${typeof source}`
@@ -6621,12 +6694,16 @@ async function createSandboxImage(source, options = {}, deps = {}) {
6621
6694
  deps._allowPat ? "Missing TENSORLAKE_API_KEY or TENSORLAKE_PAT credentials." : "Missing TENSORLAKE_API_KEY credentials."
6622
6695
  );
6623
6696
  }
6624
- if (options.signal !== void 0 && !options.cas) {
6697
+ const cas = options.cas ?? true;
6698
+ if (options.signal !== void 0 && !cas) {
6625
6699
  throw new Error(
6626
- "signal is only supported for CAS image builds (cas: true); a legacy build has no Image Service build operation to cancel"
6700
+ "signal is not supported for legacy image builds (cas: false): a legacy image build has no build operation to cancel"
6627
6701
  );
6628
6702
  }
6629
- emit({ type: "status", message: `Building image '${effectiveName}'...` });
6703
+ emit({
6704
+ type: "status",
6705
+ message: `Building ${cas ? "CAS" : "legacy"} image '${effectiveName}'...`
6706
+ });
6630
6707
  const binding = loadNativeBinding();
6631
6708
  let emitError;
6632
6709
  const nativeOptions = {
@@ -6648,7 +6725,7 @@ async function createSandboxImage(source, options = {}, deps = {}) {
6648
6725
  dockerConfigJson: options.dockerConfigJson,
6649
6726
  dockerfileText,
6650
6727
  contextDir: nativeContextDir,
6651
- cas: options.cas ?? false,
6728
+ cas,
6652
6729
  buildArgs: options.buildArgs
6653
6730
  };
6654
6731
  const forward = (event) => {
@@ -6658,7 +6735,7 @@ async function createSandboxImage(source, options = {}, deps = {}) {
6658
6735
  emitError ??= error;
6659
6736
  }
6660
6737
  };
6661
- const resultJson = options.cas ? await __runWithInterrupt(
6738
+ const resultJson = cas ? await __runWithInterrupt(
6662
6739
  options.signal,
6663
6740
  (interruptId) => binding.buildSandboxImage(nativeOptions, forward, interruptId)
6664
6741
  ) : await binding.buildSandboxImage(nativeOptions, forward);
@@ -6689,7 +6766,12 @@ async function importSandboxImage(imageReference, options = {}, deps = {}) {
6689
6766
  }
6690
6767
  const reference = imageReference.trim();
6691
6768
  const context = buildContextFromEnv();
6692
- const effectiveName = options.registeredName ?? defaultRegisteredNameFromImage(reference);
6769
+ const effectiveName = registeredImageName(
6770
+ options.registeredName,
6771
+ defaultRegisteredNameFromImage(reference),
6772
+ options.cas ?? true,
6773
+ DEFAULT_IMPORTED_IMAGE_NAME
6774
+ );
6693
6775
  if (effectiveName === DEFAULT_IMAGE_NAME2) {
6694
6776
  console.warn(
6695
6777
  `Importing sandbox image with the default name "${DEFAULT_IMAGE_NAME2}". Pass \`registeredName\` to avoid collisions with other default-named images in this project.`
@@ -6707,14 +6789,15 @@ async function importSandboxImage(imageReference, options = {}, deps = {}) {
6707
6789
  deps._allowPat ? "Missing TENSORLAKE_API_KEY or TENSORLAKE_PAT credentials." : "Missing TENSORLAKE_API_KEY credentials."
6708
6790
  );
6709
6791
  }
6710
- if (options.signal !== void 0 && !options.cas) {
6792
+ const cas = options.cas ?? true;
6793
+ if (options.signal !== void 0 && !cas) {
6711
6794
  throw new Error(
6712
- "signal is only supported for CAS image imports (cas: true); a legacy import has no Image Service build operation to cancel"
6795
+ "signal is not supported for legacy image imports (cas: false): a legacy image import has no build operation to cancel"
6713
6796
  );
6714
6797
  }
6715
6798
  emit({
6716
6799
  type: "status",
6717
- message: `Importing image '${reference}' as '${effectiveName}'...`
6800
+ message: `Importing '${reference}' as ${cas ? "CAS" : "legacy"} image '${effectiveName}'...`
6718
6801
  });
6719
6802
  const binding = loadNativeBinding();
6720
6803
  let emitError;
@@ -6735,7 +6818,7 @@ async function importSandboxImage(imageReference, options = {}, deps = {}) {
6735
6818
  userAgent: void 0,
6736
6819
  dockerCompat: options.dockerCompat ?? false,
6737
6820
  dockerConfigJson: options.dockerConfigJson,
6738
- cas: options.cas ?? false
6821
+ cas
6739
6822
  };
6740
6823
  const forward = (event) => {
6741
6824
  try {
@@ -6744,7 +6827,7 @@ async function importSandboxImage(imageReference, options = {}, deps = {}) {
6744
6827
  emitError ??= error;
6745
6828
  }
6746
6829
  };
6747
- const resultJson = options.cas ? await __runWithInterrupt(
6830
+ const resultJson = cas ? await __runWithInterrupt(
6748
6831
  options.signal,
6749
6832
  (interruptId) => binding.importSandboxImage(nativeOptions, forward, interruptId)
6750
6833
  ) : await binding.importSandboxImage(nativeOptions, forward);
@@ -6801,15 +6884,29 @@ async function deleteSandboxImage(imageName) {
6801
6884
  if (typeof imageName !== "string" || imageName.length === 0) {
6802
6885
  throw new TypeError("imageName must be a non-empty string");
6803
6886
  }
6804
- await loadNativeBinding().deleteSandboxImage(catalogOptionsFromEnv(), imageName);
6887
+ warnIncompleteLegacyCleanup(
6888
+ await loadNativeBinding().deleteSandboxImage(catalogOptionsFromEnv(), imageName)
6889
+ );
6805
6890
  }
6806
6891
  async function deleteSandboxImageWithCredentials(credentials, imageName) {
6807
6892
  if (typeof imageName !== "string" || imageName.length === 0) {
6808
6893
  throw new TypeError("imageName must be a non-empty string");
6809
6894
  }
6810
- await loadNativeBinding().deleteSandboxImage(
6811
- catalogOptionsFromCredentials(credentials),
6812
- imageName
6895
+ warnIncompleteLegacyCleanup(
6896
+ await loadNativeBinding().deleteSandboxImage(
6897
+ catalogOptionsFromCredentials(credentials),
6898
+ imageName
6899
+ )
6900
+ );
6901
+ }
6902
+ function warnIncompleteLegacyCleanup(failure) {
6903
+ if (failure == null) {
6904
+ return;
6905
+ }
6906
+ const legacyImageId = failure.legacyImageId ?? void 0;
6907
+ const label = legacyImageId ? ` (${legacyImageId})` : "";
6908
+ console.warn(
6909
+ `Deleted CAS image '${failure.legacyImageName}', but could not delete the legacy image of the same name${label}, which can no longer start sandboxes: ${failure.error}. Delete it with deleteSandboxImage("${legacyImageId ?? failure.legacyImageName}").`
6813
6910
  );
6814
6911
  }
6815
6912
  async function findSandboxImageByName(imageName) {
@@ -6853,13 +6950,14 @@ async function runCreateSandboxImageCli(argv = process.argv.slice(2)) {
6853
6950
  disk_mb: { type: "string" },
6854
6951
  builder_disk_mb: { type: "string" },
6855
6952
  docker_compat: { type: "boolean", default: false },
6856
- public: { type: "boolean", default: false }
6953
+ public: { type: "boolean", default: false },
6954
+ "no-cas": { type: "boolean", default: false }
6857
6955
  }
6858
6956
  });
6859
6957
  const dockerfilePath = parsed.positionals[0];
6860
6958
  if (!dockerfilePath) {
6861
6959
  throw new Error(
6862
- "Usage: tensorlake-create-sandbox-image <dockerfile_path> [--name NAME] [--cpus N] [--memory MiB] [--disk_mb MiB] [--builder_disk_mb MiB] [--docker_compat] [--public]"
6960
+ "Usage: tensorlake-create-sandbox-image <dockerfile_path> [--name NAME] [--cpus N] [--memory MiB] [--disk_mb MiB] [--builder_disk_mb MiB] [--docker_compat] [--public] [--no-cas]"
6863
6961
  );
6864
6962
  }
6865
6963
  const cpus = parsed.values.cpus != null ? Number(parsed.values.cpus) : void 0;
@@ -6891,7 +6989,8 @@ async function runCreateSandboxImageCli(argv = process.argv.slice(2)) {
6891
6989
  diskMb,
6892
6990
  builderDiskMb,
6893
6991
  dockerCompat: parsed.values.docker_compat,
6894
- isPublic: parsed.values.public
6992
+ isPublic: parsed.values.public,
6993
+ cas: !parsed.values["no-cas"]
6895
6994
  },
6896
6995
  { emit: ndjsonStdoutEmit, _allowPat: true }
6897
6996
  );
@@ -6907,13 +7006,14 @@ async function runImportSandboxImageCli(argv = process.argv.slice(2)) {
6907
7006
  disk_mb: { type: "string" },
6908
7007
  builder_disk_mb: { type: "string" },
6909
7008
  docker_compat: { type: "boolean", default: false },
6910
- public: { type: "boolean", default: false }
7009
+ public: { type: "boolean", default: false },
7010
+ "no-cas": { type: "boolean", default: false }
6911
7011
  }
6912
7012
  });
6913
7013
  const imageReference = parsed.positionals[0];
6914
7014
  if (!imageReference) {
6915
7015
  throw new Error(
6916
- "Usage: tensorlake-import-sandbox-image <image_reference> [--name NAME] [--cpus N] [--memory MiB] [--disk_mb MiB] [--builder_disk_mb MiB] [--docker_compat] [--public]"
7016
+ "Usage: tensorlake-import-sandbox-image <image_reference> [--name NAME] [--cpus N] [--memory MiB] [--disk_mb MiB] [--builder_disk_mb MiB] [--docker_compat] [--public] [--no-cas]"
6917
7017
  );
6918
7018
  }
6919
7019
  const cpus = parsed.values.cpus != null ? Number(parsed.values.cpus) : void 0;
@@ -6945,12 +7045,13 @@ async function runImportSandboxImageCli(argv = process.argv.slice(2)) {
6945
7045
  diskMb,
6946
7046
  builderDiskMb,
6947
7047
  dockerCompat: parsed.values.docker_compat,
6948
- isPublic: parsed.values.public
7048
+ isPublic: parsed.values.public,
7049
+ cas: !parsed.values["no-cas"]
6949
7050
  },
6950
7051
  { emit: ndjsonStdoutEmit, _allowPat: true }
6951
7052
  );
6952
7053
  }
6953
- var import_node_path3, import_node_os2, import_node_fs2, import_node_util, cachedNativeBinding, cachedNativeBindingError, DEFAULT_IMAGE_NAME2, __imageBuildInternals;
7054
+ var import_node_path3, import_node_os2, import_node_fs2, import_node_util, cachedNativeBinding, cachedNativeBindingError, DEFAULT_IMAGE_NAME2, DEFAULT_SANDBOX_IMAGE_NAME, DEFAULT_IMPORTED_IMAGE_NAME, CAS_NAME_SEPARATORS, RESERVED_IMAGE_NAME_PREFIXES, MAX_CAS_IMAGE_NAME_LENGTH, __imageBuildInternals;
6954
7055
  var init_sandbox_image = __esm({
6955
7056
  "src/sandbox-image.ts"() {
6956
7057
  "use strict";
@@ -6963,6 +7064,11 @@ var init_sandbox_image = __esm({
6963
7064
  init_native_binding();
6964
7065
  init_image_builds();
6965
7066
  DEFAULT_IMAGE_NAME2 = "default";
7067
+ DEFAULT_SANDBOX_IMAGE_NAME = "sandbox-image";
7068
+ DEFAULT_IMPORTED_IMAGE_NAME = "imported-image";
7069
+ CAS_NAME_SEPARATORS = "._-";
7070
+ RESERVED_IMAGE_NAME_PREFIXES = ["sandbox_template_", "image_", "cas-v1:"];
7071
+ MAX_CAS_IMAGE_NAME_LENGTH = 255;
6966
7072
  __imageBuildInternals = {
6967
7073
  loadNativeBinding: () => loadNativeBinding(),
6968
7074
  buildContextFromEnv: () => buildContextFromEnv(),
@@ -6971,7 +7077,12 @@ var init_sandbox_image = __esm({
6971
7077
  eventToEmitDict: (event) => eventToEmitDict(event),
6972
7078
  imageRequiresContext: (image) => imageRequiresContext(image),
6973
7079
  defaultRegisteredName: (dockerfilePath) => defaultRegisteredName(dockerfilePath),
6974
- defaultRegisteredNameFromImage: (reference) => defaultRegisteredNameFromImage(reference)
7080
+ defaultRegisteredNameFromImage: (reference) => defaultRegisteredNameFromImage(reference),
7081
+ registeredImageName: (explicit, generated, cas, fallback) => registeredImageName(explicit, generated, cas, fallback),
7082
+ casImageNameFrom: (raw, fallback) => casImageNameFrom(raw, fallback),
7083
+ canonicalCasImageName: (name) => canonicalCasImageName(name),
7084
+ isAddressableCasImageName: (name) => isAddressableCasImageName(name),
7085
+ defaultImportedImageName: DEFAULT_IMPORTED_IMAGE_NAME
6975
7086
  };
6976
7087
  }
6977
7088
  });
@@ -7229,10 +7340,12 @@ var CloudClient = class _CloudClient {
7229
7340
  );
7230
7341
  }
7231
7342
  /**
7232
- * Delete a registered sandbox image by name or id through the merged
7233
- * catalog, with this client's credentials: an `image_` id or a name the
7234
- * Image Service knows deletes a CAS image, a `sandbox_template_` id or a
7235
- * name registered only in the platform registry deletes a legacy image.
7343
+ * Delete a registered CAS or legacy sandbox image by name or id through the
7344
+ * merged catalog, with this client's credentials: an `image_` id or a name
7345
+ * the CAS image registry knows deletes a CAS image, a `sandbox_template_` id
7346
+ * or a name registered only in the legacy image registry deletes a legacy
7347
+ * image.
7348
+ * A name is deleted from both the CAS and the legacy image registries.
7236
7349
  * Rejects when neither catalog knows the reference. The same semantics
7237
7350
  * and accepted differences as the module-level `deleteSandboxImage`.
7238
7351
  */
@@ -7240,10 +7353,10 @@ var CloudClient = class _CloudClient {
7240
7353
  await deleteSandboxImageWithCredentials(this.catalogCredentials(), imageName);
7241
7354
  }
7242
7355
  /**
7243
- * Look up a registered sandbox image by name or id through the merged
7244
- * catalog, with this client's credentials. Returns the image in the
7245
- * sandbox-template shape, or `null` when neither the Image Service nor the
7246
- * platform registry knows the reference. An explicit organization/project
7356
+ * Look up a registered CAS or legacy sandbox image by name or id through
7357
+ * the merged catalog, with this client's credentials. Returns the image in
7358
+ * the sandbox-template shape, or `null` when neither the CAS nor the legacy
7359
+ * image registry knows the reference. An explicit organization/project
7247
7360
  * scope (the client's, or the call's override) addresses that project's
7248
7361
  * routes directly, as before; without one the key's own scope applies.
7249
7362
  */