@tensorlakeai/tensorlake 0.5.153 → 0.5.156

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 +260 -71
  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 +260 -71
  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 +344 -106
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +95 -38
  14. package/dist/index.d.ts +95 -38
  15. package/dist/index.js +339 -106
  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 +248 -61
  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 +248 -61
  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
@@ -151,10 +151,11 @@ var init_image = __esm({
151
151
  });
152
152
  }
153
153
  /**
154
- * Build this image as a sandbox template and register it.
154
+ * Build this image and register it as a CAS sandbox image (the default) or,
155
+ * with `cas: false`, a legacy sandbox image.
155
156
  *
156
157
  * Materializes the image in a build sandbox, snapshots the filesystem,
157
- * and registers the snapshot as a named sandbox template.
158
+ * and registers the snapshot under the image's name.
158
159
  */
159
160
  async build(options = {}) {
160
161
  const { createSandboxImage: createSandboxImage2 } = await Promise.resolve().then(() => (init_sandbox_image(), sandbox_image_exports));
@@ -314,7 +315,24 @@ var init_native_binding = __esm({
314
315
  }
315
316
  });
316
317
 
318
+ // src/enum.ts
319
+ function enumValue(values, value) {
320
+ return typeof value === "string" && Object.values(values).includes(value) ? value : values.UNKNOWN;
321
+ }
322
+ function withRaw(value, raw) {
323
+ return Object.defineProperty(value, "raw", { value: raw, enumerable: false, configurable: true });
324
+ }
325
+ var init_enum = __esm({
326
+ "src/enum.ts"() {
327
+ "use strict";
328
+ init_cjs_shims();
329
+ }
330
+ });
331
+
317
332
  // src/image-builds.ts
333
+ function isConfirmedCancellation(outcome) {
334
+ return outcome === "cancelled" /* CANCELLED */ || outcome === "already_cancelled" /* ALREADY_CANCELLED */ || outcome === "already_failed" /* ALREADY_FAILED */;
335
+ }
318
336
  function camelize(key) {
319
337
  return key.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
320
338
  }
@@ -332,48 +350,73 @@ function toImageBuildError(error) {
332
350
  if (key === "category") continue;
333
351
  details[camelize(key)] = value;
334
352
  }
353
+ details.code = enumValue(ImageBuildErrorCode, details.code || "internal" /* INTERNAL */);
354
+ if ("activeKind" in details) details.activeKind = details.activeKind ? enumValue(ImageBuildKind, details.activeKind) : null;
355
+ if ("activeStatus" in details) details.activeStatus = details.activeStatus ? enumValue(ImageBuildStatus, details.activeStatus) : null;
356
+ if ("outcome" in details) details.outcome = details.outcome ? enumValue(ImageBuildCancellationOutcome, details.outcome) : null;
357
+ if ("info" in details) details.info = buildInfoOrNull(details.info);
335
358
  const typed = details;
336
- switch (typed.code) {
337
- case "not_found":
338
- return new ImageBuildNotFoundError(typed);
339
- case "image_build_in_progress":
340
- return new ImageBuildInProgressError(typed);
341
- case "failed":
342
- return new ImageBuildFailedError(typed);
343
- case "cancelled":
344
- return new ImageBuildCancelledError(typed);
345
- case "timeout":
346
- return new ImageBuildTimeoutError(typed);
347
- case "interrupted":
348
- return new ImageBuildInterruptedError(typed);
349
- default:
350
- return new ImageBuildError(typed);
351
- }
359
+ const errors = {
360
+ not_found: ImageBuildNotFoundError,
361
+ image_build_in_progress: ImageBuildInProgressError,
362
+ failed: ImageBuildFailedError,
363
+ cancelled: ImageBuildCancelledError,
364
+ timeout: ImageBuildTimeoutError,
365
+ interrupted: ImageBuildInterruptedError
366
+ };
367
+ const ErrorClass = errors[typed.code] ?? ImageBuildError;
368
+ return withRaw(new ErrorClass(typed), payload);
352
369
  }
353
370
  function camelizeRecord(value) {
354
371
  const out = {};
355
372
  for (const [key, inner] of Object.entries(value)) out[camelize(key)] = inner;
356
373
  return out;
357
374
  }
358
- function parseBuildInfo(raw) {
375
+ function buildInfoOrNull(value) {
376
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
377
+ try {
378
+ return parseBuildInfo(value);
379
+ } catch (error) {
380
+ if (error instanceof ImageBuildError) return null;
381
+ throw error;
382
+ }
383
+ }
384
+ function decodeResponse(value) {
385
+ try {
386
+ const raw = typeof value === "string" ? JSON.parse(value) : value;
387
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) throw new TypeError("expected a response object");
388
+ return raw;
389
+ } catch (error) {
390
+ throw withRaw(new ImageBuildError({ code: "service" /* SERVICE */, message: `Invalid image-build response: ${String(error)}` }), { response: value });
391
+ }
392
+ }
393
+ function parseBuildInfo(value) {
394
+ const raw = decodeResponse(value);
395
+ if (raw.status == null) {
396
+ throw withRaw(new ImageBuildError({ code: "service" /* SERVICE */, message: "Invalid image-build response: missing status" }), { response: value });
397
+ }
398
+ const attempt = raw.attempt_no ?? 0;
399
+ const attemptNo = Number(attempt);
400
+ if (typeof attempt !== "number" && typeof attempt !== "string" || typeof attempt === "string" && attempt.trim() === "" || !Number.isSafeInteger(attemptNo)) {
401
+ throw withRaw(new ImageBuildError({ code: "service" /* SERVICE */, message: "Invalid image-build attempt_no" }), { response: value });
402
+ }
359
403
  const camel = camelizeRecord(raw);
360
404
  const result = raw.result && typeof raw.result === "object" ? camelizeRecord(raw.result) : null;
361
- return {
405
+ return withRaw({
362
406
  buildId: String(raw.build_id ?? ""),
363
407
  clientRequestId: camel.clientRequestId ?? null,
364
- kind: String(raw.kind ?? ""),
408
+ kind: raw.kind ? enumValue(ImageBuildKind, raw.kind) : null,
365
409
  name: raw.name ?? null,
366
- status: String(raw.status ?? ""),
367
- phase: raw.phase ?? null,
368
- attemptNo: Number(raw.attempt_no ?? 0),
410
+ status: enumValue(ImageBuildStatus, raw.status),
411
+ phase: raw.phase ? enumValue(ImageBuildPhase, raw.phase) : null,
412
+ attemptNo,
369
413
  builderSandboxId: camel.builderSandboxId ?? null,
370
414
  error: raw.error ?? null,
371
415
  result,
372
416
  operationDeadlineMs: camel.operationDeadlineMs ?? null,
373
417
  createdAtMs: camel.createdAtMs ?? null,
374
- updatedAtMs: camel.updatedAtMs ?? null,
375
- raw
376
- };
418
+ updatedAtMs: camel.updatedAtMs ?? null
419
+ }, raw);
377
420
  }
378
421
  async function __runWithInterrupt(signal, run) {
379
422
  const binding = __imageBuildInternals.loadNativeBinding();
@@ -397,16 +440,68 @@ async function __runWithInterrupt(signal, run) {
397
440
  binding.releaseImageBuildInterrupt(interruptId);
398
441
  }
399
442
  }
400
- var import_node_path2, import_node_os, import_node_fs, ImageBuildError, ImageBuildNotFoundError, ImageBuildInProgressError, ImageBuildFailedError, ImageBuildCancelledError, ImageBuildTimeoutError, ImageBuildInterruptedError;
443
+ var import_node_path2, import_node_os, import_node_fs, ImageBuildStatus, ImageBuildPhase, ImageBuildKind, ImageBuildCancellationOutcome, ImageBuildErrorCode, ImageBuildError, ImageBuildNotFoundError, ImageBuildInProgressError, ImageBuildFailedError, ImageBuildCancelledError, ImageBuildTimeoutError, ImageBuildInterruptedError;
401
444
  var init_image_builds = __esm({
402
445
  "src/image-builds.ts"() {
403
446
  "use strict";
404
447
  init_cjs_shims();
405
448
  import_node_path2 = __toESM(require("path"), 1);
449
+ init_enum();
406
450
  import_node_os = __toESM(require("os"), 1);
407
451
  import_node_fs = require("fs");
408
452
  init_image();
409
453
  init_sandbox_image();
454
+ ImageBuildStatus = /* @__PURE__ */ ((ImageBuildStatus2) => {
455
+ ImageBuildStatus2["PENDING"] = "pending";
456
+ ImageBuildStatus2["RUNNING"] = "running";
457
+ ImageBuildStatus2["SUCCEEDED"] = "succeeded";
458
+ ImageBuildStatus2["FAILED"] = "failed";
459
+ ImageBuildStatus2["CANCELLED"] = "cancelled";
460
+ ImageBuildStatus2["UNKNOWN"] = "unknown";
461
+ return ImageBuildStatus2;
462
+ })(ImageBuildStatus || {});
463
+ ImageBuildPhase = /* @__PURE__ */ ((ImageBuildPhase2) => {
464
+ ImageBuildPhase2["AWAITING_CONTEXT"] = "awaiting_context";
465
+ ImageBuildPhase2["STARTING_BUILDER"] = "starting_builder";
466
+ ImageBuildPhase2["EXECUTING"] = "executing";
467
+ ImageBuildPhase2["SNAPSHOTTING"] = "snapshotting";
468
+ ImageBuildPhase2["PUBLISHING"] = "publishing";
469
+ ImageBuildPhase2["FINISHED"] = "finished";
470
+ ImageBuildPhase2["UNKNOWN"] = "unknown";
471
+ return ImageBuildPhase2;
472
+ })(ImageBuildPhase || {});
473
+ ImageBuildKind = /* @__PURE__ */ ((ImageBuildKind2) => {
474
+ ImageBuildKind2["DOCKERFILE"] = "dockerfile";
475
+ ImageBuildKind2["IMPORT"] = "import";
476
+ ImageBuildKind2["DIRECT"] = "direct";
477
+ ImageBuildKind2["UNKNOWN"] = "unknown";
478
+ return ImageBuildKind2;
479
+ })(ImageBuildKind || {});
480
+ ImageBuildCancellationOutcome = /* @__PURE__ */ ((ImageBuildCancellationOutcome2) => {
481
+ ImageBuildCancellationOutcome2["CANCELLED"] = "cancelled";
482
+ ImageBuildCancellationOutcome2["ALREADY_CANCELLED"] = "already_cancelled";
483
+ ImageBuildCancellationOutcome2["ALREADY_COMPLETED"] = "already_completed";
484
+ ImageBuildCancellationOutcome2["ALREADY_FAILED"] = "already_failed";
485
+ ImageBuildCancellationOutcome2["NOT_ADMITTED"] = "not_admitted";
486
+ ImageBuildCancellationOutcome2["UNCONFIRMED"] = "unconfirmed";
487
+ ImageBuildCancellationOutcome2["UNKNOWN"] = "unknown";
488
+ return ImageBuildCancellationOutcome2;
489
+ })(ImageBuildCancellationOutcome || {});
490
+ ImageBuildErrorCode = /* @__PURE__ */ ((ImageBuildErrorCode2) => {
491
+ ImageBuildErrorCode2["USAGE"] = "usage";
492
+ ImageBuildErrorCode2["AUTH"] = "auth";
493
+ ImageBuildErrorCode2["NOT_FOUND"] = "not_found";
494
+ ImageBuildErrorCode2["IMAGE_BUILD_IN_PROGRESS"] = "image_build_in_progress";
495
+ ImageBuildErrorCode2["CLIENT_REQUEST_ID_MISMATCH"] = "client_request_id_mismatch";
496
+ ImageBuildErrorCode2["FAILED"] = "failed";
497
+ ImageBuildErrorCode2["CANCELLED"] = "cancelled";
498
+ ImageBuildErrorCode2["TIMEOUT"] = "timeout";
499
+ ImageBuildErrorCode2["INTERRUPTED"] = "interrupted";
500
+ ImageBuildErrorCode2["SERVICE"] = "service";
501
+ ImageBuildErrorCode2["INTERNAL"] = "internal";
502
+ ImageBuildErrorCode2["UNKNOWN"] = "unknown";
503
+ return ImageBuildErrorCode2;
504
+ })(ImageBuildErrorCode || {});
410
505
  ImageBuildError = class extends Error {
411
506
  code;
412
507
  buildId;
@@ -416,7 +511,11 @@ var init_image_builds = __esm({
416
511
  super(details.message);
417
512
  this.name = "ImageBuildError";
418
513
  this.code = details.code;
419
- this.details = details;
514
+ this.details = { ...details };
515
+ withRaw(this, {});
516
+ if ("confirmed" in details) {
517
+ this.details.confirmed = details.confirmed === true && isConfirmedCancellation(details.outcome);
518
+ }
420
519
  if (details.buildId) this.buildId = details.buildId;
421
520
  if (details.clientRequestId) this.clientRequestId = details.clientRequestId;
422
521
  }
@@ -448,7 +547,7 @@ var init_image_builds = __esm({
448
547
  super(details);
449
548
  this.name = "ImageBuildFailedError";
450
549
  this.error = details.error ?? "no error recorded";
451
- if (details.info) this.info = parseBuildInfo(details.info);
550
+ if (details.info) this.info = details.info;
452
551
  }
453
552
  };
454
553
  ImageBuildCancelledError = class extends ImageBuildError {
@@ -456,7 +555,7 @@ var init_image_builds = __esm({
456
555
  constructor(details) {
457
556
  super(details);
458
557
  this.name = "ImageBuildCancelledError";
459
- if (details.info) this.info = parseBuildInfo(details.info);
558
+ if (details.info) this.info = details.info;
460
559
  }
461
560
  };
462
561
  ImageBuildTimeoutError = class extends ImageBuildError {
@@ -472,8 +571,8 @@ var init_image_builds = __esm({
472
571
  constructor(details) {
473
572
  super(details);
474
573
  this.name = "ImageBuildInterruptedError";
475
- this.outcome = details.outcome ?? "unconfirmed";
476
- this.confirmed = details.confirmed === true;
574
+ this.outcome = details.outcome ?? "unconfirmed" /* UNCONFIRMED */;
575
+ this.confirmed = this.details.confirmed === true;
477
576
  if (details.result) this.result = details.result;
478
577
  }
479
578
  };
@@ -533,16 +632,58 @@ function defaultRegisteredName(dockerfilePath) {
533
632
  const parsed = import_node_path3.default.parse(dockerfilePath);
534
633
  if (parsed.name.toLowerCase() === "dockerfile") {
535
634
  const parentName = import_node_path3.default.basename(import_node_path3.default.dirname(dockerfilePath)).trim();
536
- return parentName || "sandbox-image";
635
+ return parentName || DEFAULT_SANDBOX_IMAGE_NAME;
537
636
  }
538
- return parsed.name || "sandbox-image";
637
+ return parsed.name || DEFAULT_SANDBOX_IMAGE_NAME;
638
+ }
639
+ function registeredImageName(explicit, generated, cas, fallback = DEFAULT_SANDBOX_IMAGE_NAME) {
640
+ if (explicit || generated === void 0) {
641
+ const name = explicit ?? "";
642
+ return cas ? canonicalCasImageName(name) : name;
643
+ }
644
+ return cas ? casImageNameFrom(generated, fallback) : generated;
645
+ }
646
+ function canonicalCasImageName(name) {
647
+ return name.replace(/[A-Z]/g, (c) => c.toLowerCase());
648
+ }
649
+ function casImageNameFrom(raw, fallback) {
650
+ const lowered = canonicalCasImageName(raw);
651
+ if (isAddressableCasImageName(lowered)) {
652
+ return lowered;
653
+ }
654
+ let name = "";
655
+ for (const original of lowered) {
656
+ const ch = /^[a-z0-9._-]$/.test(original) ? original : "-";
657
+ const previous = name[name.length - 1];
658
+ if (CAS_NAME_SEPARATORS.includes(ch) && previous !== void 0 && CAS_NAME_SEPARATORS.includes(previous)) {
659
+ continue;
660
+ }
661
+ name += ch;
662
+ }
663
+ name = name.replace(/^[._-]+|[._-]+$/g, "").slice(0, MAX_CAS_IMAGE_NAME_LENGTH).replace(/[._-]+$/, "");
664
+ return isAddressableCasImageName(name) ? name : fallback;
665
+ }
666
+ function isAddressableCasImageName(name) {
667
+ 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)) {
668
+ return false;
669
+ }
670
+ const colon = name.indexOf(":");
671
+ const repository = colon === -1 ? name : name.slice(0, colon);
672
+ if (!repository.split("/").every((component) => /^[a-z0-9]+(?:[._-][a-z0-9]+)*$/.test(component))) {
673
+ return false;
674
+ }
675
+ if (colon === -1) {
676
+ return true;
677
+ }
678
+ const tag = name.slice(colon + 1);
679
+ return tag.length > 0 && tag.length <= 128 && /^[a-z0-9._-]+$/.test(tag) && !tag.startsWith(".") && !tag.startsWith("-");
539
680
  }
540
681
  function defaultRegisteredNameFromImage(imageReference) {
541
682
  const withoutDigest = imageReference.split("@", 1)[0] ?? imageReference;
542
683
  const lastSegment = withoutDigest.split("/").pop() ?? withoutDigest;
543
684
  const colonIndex = lastSegment.lastIndexOf(":");
544
685
  const name = colonIndex > 0 && colonIndex < lastSegment.length - 1 ? lastSegment.slice(0, colonIndex) : lastSegment;
545
- return name || "imported-image";
686
+ return name || DEFAULT_IMPORTED_IMAGE_NAME;
546
687
  }
547
688
  function noopEmit(_event) {
548
689
  }
@@ -645,7 +786,11 @@ async function createSandboxImage(source, options = {}, deps = {}) {
645
786
  if (!text.endsWith("\n")) text += "\n";
646
787
  dockerfileText = text;
647
788
  nativeContextDir = resolvedContext;
648
- effectiveName = options.registeredName ?? source.name;
789
+ effectiveName = registeredImageName(
790
+ options.registeredName ?? source.name,
791
+ void 0,
792
+ options.cas ?? true
793
+ );
649
794
  } else if (typeof source === "string") {
650
795
  const resolvedPath = import_node_path3.default.resolve(source);
651
796
  if (!(0, import_node_fs2.existsSync)(resolvedPath)) {
@@ -654,7 +799,11 @@ async function createSandboxImage(source, options = {}, deps = {}) {
654
799
  dockerfilePath = resolvedPath;
655
800
  dockerfileText = void 0;
656
801
  nativeContextDir = void 0;
657
- effectiveName = options.registeredName ?? defaultRegisteredName(resolvedPath);
802
+ effectiveName = registeredImageName(
803
+ options.registeredName,
804
+ defaultRegisteredName(resolvedPath),
805
+ options.cas ?? true
806
+ );
658
807
  } else {
659
808
  throw new TypeError(
660
809
  `source must be an Image or a Dockerfile path, got ${typeof source}`
@@ -678,12 +827,16 @@ async function createSandboxImage(source, options = {}, deps = {}) {
678
827
  deps._allowPat ? "Missing TENSORLAKE_API_KEY or TENSORLAKE_PAT credentials." : "Missing TENSORLAKE_API_KEY credentials."
679
828
  );
680
829
  }
681
- if (options.signal !== void 0 && !options.cas) {
830
+ const cas = options.cas ?? true;
831
+ if (options.signal !== void 0 && !cas) {
682
832
  throw new Error(
683
- "signal is only supported for CAS image builds (cas: true); a legacy build has no Image Service build operation to cancel"
833
+ "signal is not supported for legacy image builds (cas: false): a legacy image build has no build operation to cancel"
684
834
  );
685
835
  }
686
- emit({ type: "status", message: `Building image '${effectiveName}'...` });
836
+ emit({
837
+ type: "status",
838
+ message: `Building ${cas ? "CAS" : "legacy"} image '${effectiveName}'...`
839
+ });
687
840
  const binding = loadNativeBinding();
688
841
  let emitError;
689
842
  const nativeOptions = {
@@ -705,7 +858,7 @@ async function createSandboxImage(source, options = {}, deps = {}) {
705
858
  dockerConfigJson: options.dockerConfigJson,
706
859
  dockerfileText,
707
860
  contextDir: nativeContextDir,
708
- cas: options.cas ?? false,
861
+ cas,
709
862
  buildArgs: options.buildArgs
710
863
  };
711
864
  const forward = (event) => {
@@ -715,7 +868,7 @@ async function createSandboxImage(source, options = {}, deps = {}) {
715
868
  emitError ??= error;
716
869
  }
717
870
  };
718
- const resultJson = options.cas ? await __runWithInterrupt(
871
+ const resultJson = cas ? await __runWithInterrupt(
719
872
  options.signal,
720
873
  (interruptId) => binding.buildSandboxImage(nativeOptions, forward, interruptId)
721
874
  ) : await binding.buildSandboxImage(nativeOptions, forward);
@@ -746,7 +899,12 @@ async function importSandboxImage(imageReference, options = {}, deps = {}) {
746
899
  }
747
900
  const reference = imageReference.trim();
748
901
  const context = buildContextFromEnv();
749
- const effectiveName = options.registeredName ?? defaultRegisteredNameFromImage(reference);
902
+ const effectiveName = registeredImageName(
903
+ options.registeredName,
904
+ defaultRegisteredNameFromImage(reference),
905
+ options.cas ?? true,
906
+ DEFAULT_IMPORTED_IMAGE_NAME
907
+ );
750
908
  if (effectiveName === DEFAULT_IMAGE_NAME2) {
751
909
  console.warn(
752
910
  `Importing sandbox image with the default name "${DEFAULT_IMAGE_NAME2}". Pass \`registeredName\` to avoid collisions with other default-named images in this project.`
@@ -764,14 +922,15 @@ async function importSandboxImage(imageReference, options = {}, deps = {}) {
764
922
  deps._allowPat ? "Missing TENSORLAKE_API_KEY or TENSORLAKE_PAT credentials." : "Missing TENSORLAKE_API_KEY credentials."
765
923
  );
766
924
  }
767
- if (options.signal !== void 0 && !options.cas) {
925
+ const cas = options.cas ?? true;
926
+ if (options.signal !== void 0 && !cas) {
768
927
  throw new Error(
769
- "signal is only supported for CAS image imports (cas: true); a legacy import has no Image Service build operation to cancel"
928
+ "signal is not supported for legacy image imports (cas: false): a legacy image import has no build operation to cancel"
770
929
  );
771
930
  }
772
931
  emit({
773
932
  type: "status",
774
- message: `Importing image '${reference}' as '${effectiveName}'...`
933
+ message: `Importing '${reference}' as ${cas ? "CAS" : "legacy"} image '${effectiveName}'...`
775
934
  });
776
935
  const binding = loadNativeBinding();
777
936
  let emitError;
@@ -792,7 +951,7 @@ async function importSandboxImage(imageReference, options = {}, deps = {}) {
792
951
  userAgent: void 0,
793
952
  dockerCompat: options.dockerCompat ?? false,
794
953
  dockerConfigJson: options.dockerConfigJson,
795
- cas: options.cas ?? false
954
+ cas
796
955
  };
797
956
  const forward = (event) => {
798
957
  try {
@@ -801,7 +960,7 @@ async function importSandboxImage(imageReference, options = {}, deps = {}) {
801
960
  emitError ??= error;
802
961
  }
803
962
  };
804
- const resultJson = options.cas ? await __runWithInterrupt(
963
+ const resultJson = cas ? await __runWithInterrupt(
805
964
  options.signal,
806
965
  (interruptId) => binding.importSandboxImage(nativeOptions, forward, interruptId)
807
966
  ) : await binding.importSandboxImage(nativeOptions, forward);
@@ -858,15 +1017,29 @@ async function deleteSandboxImage(imageName) {
858
1017
  if (typeof imageName !== "string" || imageName.length === 0) {
859
1018
  throw new TypeError("imageName must be a non-empty string");
860
1019
  }
861
- await loadNativeBinding().deleteSandboxImage(catalogOptionsFromEnv(), imageName);
1020
+ warnIncompleteLegacyCleanup(
1021
+ await loadNativeBinding().deleteSandboxImage(catalogOptionsFromEnv(), imageName)
1022
+ );
862
1023
  }
863
1024
  async function deleteSandboxImageWithCredentials(credentials, imageName) {
864
1025
  if (typeof imageName !== "string" || imageName.length === 0) {
865
1026
  throw new TypeError("imageName must be a non-empty string");
866
1027
  }
867
- await loadNativeBinding().deleteSandboxImage(
868
- catalogOptionsFromCredentials(credentials),
869
- imageName
1028
+ warnIncompleteLegacyCleanup(
1029
+ await loadNativeBinding().deleteSandboxImage(
1030
+ catalogOptionsFromCredentials(credentials),
1031
+ imageName
1032
+ )
1033
+ );
1034
+ }
1035
+ function warnIncompleteLegacyCleanup(failure) {
1036
+ if (failure == null) {
1037
+ return;
1038
+ }
1039
+ const legacyImageId = failure.legacyImageId ?? void 0;
1040
+ const label = legacyImageId ? ` (${legacyImageId})` : "";
1041
+ console.warn(
1042
+ `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}").`
870
1043
  );
871
1044
  }
872
1045
  async function findSandboxImageByName(imageName) {
@@ -910,13 +1083,14 @@ async function runCreateSandboxImageCli(argv = process.argv.slice(2)) {
910
1083
  disk_mb: { type: "string" },
911
1084
  builder_disk_mb: { type: "string" },
912
1085
  docker_compat: { type: "boolean", default: false },
913
- public: { type: "boolean", default: false }
1086
+ public: { type: "boolean", default: false },
1087
+ "no-cas": { type: "boolean", default: false }
914
1088
  }
915
1089
  });
916
1090
  const dockerfilePath = parsed.positionals[0];
917
1091
  if (!dockerfilePath) {
918
1092
  throw new Error(
919
- "Usage: tensorlake-create-sandbox-image <dockerfile_path> [--name NAME] [--cpus N] [--memory MiB] [--disk_mb MiB] [--builder_disk_mb MiB] [--docker_compat] [--public]"
1093
+ "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]"
920
1094
  );
921
1095
  }
922
1096
  const cpus = parsed.values.cpus != null ? Number(parsed.values.cpus) : void 0;
@@ -948,7 +1122,8 @@ async function runCreateSandboxImageCli(argv = process.argv.slice(2)) {
948
1122
  diskMb,
949
1123
  builderDiskMb,
950
1124
  dockerCompat: parsed.values.docker_compat,
951
- isPublic: parsed.values.public
1125
+ isPublic: parsed.values.public,
1126
+ cas: !parsed.values["no-cas"]
952
1127
  },
953
1128
  { emit: ndjsonStdoutEmit, _allowPat: true }
954
1129
  );
@@ -964,13 +1139,14 @@ async function runImportSandboxImageCli(argv = process.argv.slice(2)) {
964
1139
  disk_mb: { type: "string" },
965
1140
  builder_disk_mb: { type: "string" },
966
1141
  docker_compat: { type: "boolean", default: false },
967
- public: { type: "boolean", default: false }
1142
+ public: { type: "boolean", default: false },
1143
+ "no-cas": { type: "boolean", default: false }
968
1144
  }
969
1145
  });
970
1146
  const imageReference = parsed.positionals[0];
971
1147
  if (!imageReference) {
972
1148
  throw new Error(
973
- "Usage: tensorlake-import-sandbox-image <image_reference> [--name NAME] [--cpus N] [--memory MiB] [--disk_mb MiB] [--builder_disk_mb MiB] [--docker_compat] [--public]"
1149
+ "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]"
974
1150
  );
975
1151
  }
976
1152
  const cpus = parsed.values.cpus != null ? Number(parsed.values.cpus) : void 0;
@@ -1002,12 +1178,13 @@ async function runImportSandboxImageCli(argv = process.argv.slice(2)) {
1002
1178
  diskMb,
1003
1179
  builderDiskMb,
1004
1180
  dockerCompat: parsed.values.docker_compat,
1005
- isPublic: parsed.values.public
1181
+ isPublic: parsed.values.public,
1182
+ cas: !parsed.values["no-cas"]
1006
1183
  },
1007
1184
  { emit: ndjsonStdoutEmit, _allowPat: true }
1008
1185
  );
1009
1186
  }
1010
- var import_node_path3, import_node_os2, import_node_fs2, import_node_util, cachedNativeBinding, cachedNativeBindingError, DEFAULT_IMAGE_NAME2, __imageBuildInternals;
1187
+ 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;
1011
1188
  var init_sandbox_image = __esm({
1012
1189
  "src/sandbox-image.ts"() {
1013
1190
  init_cjs_shims();
@@ -1019,6 +1196,11 @@ var init_sandbox_image = __esm({
1019
1196
  init_native_binding();
1020
1197
  init_image_builds();
1021
1198
  DEFAULT_IMAGE_NAME2 = "default";
1199
+ DEFAULT_SANDBOX_IMAGE_NAME = "sandbox-image";
1200
+ DEFAULT_IMPORTED_IMAGE_NAME = "imported-image";
1201
+ CAS_NAME_SEPARATORS = "._-";
1202
+ RESERVED_IMAGE_NAME_PREFIXES = ["sandbox_template_", "image_", "cas-v1:"];
1203
+ MAX_CAS_IMAGE_NAME_LENGTH = 255;
1022
1204
  __imageBuildInternals = {
1023
1205
  loadNativeBinding: () => loadNativeBinding(),
1024
1206
  buildContextFromEnv: () => buildContextFromEnv(),
@@ -1027,7 +1209,12 @@ var init_sandbox_image = __esm({
1027
1209
  eventToEmitDict: (event) => eventToEmitDict(event),
1028
1210
  imageRequiresContext: (image) => imageRequiresContext(image),
1029
1211
  defaultRegisteredName: (dockerfilePath) => defaultRegisteredName(dockerfilePath),
1030
- defaultRegisteredNameFromImage: (reference) => defaultRegisteredNameFromImage(reference)
1212
+ defaultRegisteredNameFromImage: (reference) => defaultRegisteredNameFromImage(reference),
1213
+ registeredImageName: (explicit, generated, cas, fallback) => registeredImageName(explicit, generated, cas, fallback),
1214
+ casImageNameFrom: (raw, fallback) => casImageNameFrom(raw, fallback),
1215
+ canonicalCasImageName: (name) => canonicalCasImageName(name),
1216
+ isAddressableCasImageName: (name) => isAddressableCasImageName(name),
1217
+ defaultImportedImageName: DEFAULT_IMPORTED_IMAGE_NAME
1031
1218
  };
1032
1219
  }
1033
1220
  });