@koda-sl/baker-cli 0.118.0 → 0.120.0-dev.3b02f951b

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.
@@ -1,32 +1,11 @@
1
- var __create = Object.create;
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __commonJS = (cb, mod) => function __require() {
8
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
- // If the importer is in node compatibility mode or this is not an ESM
20
- // file that has been converted to a CommonJS file using a Babel-
21
- // compatible transform (i.e. "__esModule" has not been set), then set
22
- // "default" to the CommonJS "module.exports" for node compatibility.
23
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
- mod
25
- ));
1
+ import {
2
+ __commonJS,
3
+ __toESM
4
+ } from "./chunk-5WRI5ZAA.js";
26
5
 
27
- // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js
6
+ // ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/810146e81bae4e3a061fe487864f2fde80c4b03b886877dc0f1fffbc6480b67e/node_modules/safe-stable-stringify/index.js
28
7
  var require_safe_stable_stringify = __commonJS({
29
- "../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js"(exports, module) {
8
+ "../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/810146e81bae4e3a061fe487864f2fde80c4b03b886877dc0f1fffbc6480b67e/node_modules/safe-stable-stringify/index.js"(exports, module) {
30
9
  "use strict";
31
10
  var { hasOwnProperty } = Object.prototype;
32
11
  var stringify = configure2();
@@ -159,9 +138,9 @@ var require_safe_stable_stringify = __commonJS({
159
138
  }
160
139
  if (value) {
161
140
  return (value2) => {
162
- let message = `Object can not safely be stringified. Received type ${typeof value2}`;
163
- if (typeof value2 !== "function") message += ` (${value2.toString()})`;
164
- throw new Error(message);
141
+ let message2 = `Object can not safely be stringified. Received type ${typeof value2}`;
142
+ if (typeof value2 !== "function") message2 += ` (${value2.toString()})`;
143
+ throw new Error(message2);
165
144
  };
166
145
  }
167
146
  }
@@ -673,6 +652,9 @@ var HttpClient = class {
673
652
  async postJson(path16, body, signal) {
674
653
  return await this.requestJson("POST", path16, body, signal);
675
654
  }
655
+ async putJson(path16, body, signal) {
656
+ return await this.requestJson("PUT", path16, body, signal);
657
+ }
676
658
  async getJson(path16, signal) {
677
659
  return await this.requestJson("GET", path16, void 0, signal);
678
660
  }
@@ -700,8 +682,8 @@ var HttpClient = class {
700
682
  try {
701
683
  const res = await this.fetchFn(url, {
702
684
  method,
703
- headers: method === "POST" ? { "Content-Type": "application/json", Authorization: `Bearer ${this.apiKey}` } : { Authorization: `Bearer ${this.apiKey}` },
704
- body: method === "POST" ? JSON.stringify(body) : void 0,
685
+ headers: method === "GET" ? { Authorization: `Bearer ${this.apiKey}` } : { "Content-Type": "application/json", Authorization: `Bearer ${this.apiKey}` },
686
+ body: method === "GET" ? void 0 : JSON.stringify(body),
705
687
  signal: controller.signal
706
688
  });
707
689
  if (res.ok) return { kind: "value", value: await res.json() };
@@ -738,33 +720,33 @@ async function parseErrorBody(res) {
738
720
  const errObj = body.error ?? {};
739
721
  return classifyHttpError(res.status, errObj, errObj.message ?? `HTTP ${res.status}`);
740
722
  }
741
- function classifyHttpError(status, errObj, message) {
723
+ function classifyHttpError(status, errObj, message2) {
742
724
  if (errObj.code === CONTENT_POLICY_CODE) {
743
- return { kind: "content_policy", status, provider: errObj.provider, message };
725
+ return { kind: "content_policy", status, provider: errObj.provider, message: message2 };
744
726
  }
745
727
  if (status === 401 || status === 403) {
746
- return { kind: "unauthorized", status, message };
728
+ return { kind: "unauthorized", status, message: message2 };
747
729
  }
748
730
  if (status === 400 || status === 422) {
749
- return { kind: "validation", status, message, details: errObj.details };
731
+ return { kind: "validation", status, message: message2, details: errObj.details };
750
732
  }
751
733
  if (status === 502 || status === 504) {
752
734
  if (errObj.code === "provider_timeout" || status === 504) {
753
- return { kind: "timeout", provider: errObj.provider, message };
735
+ return { kind: "timeout", provider: errObj.provider, message: message2 };
754
736
  }
755
737
  return {
756
738
  kind: "provider",
757
739
  status,
758
740
  provider: errObj.provider,
759
741
  code: errObj.code ?? "provider_error",
760
- message,
742
+ message: message2,
761
743
  retryable: errObj.retryable ?? true
762
744
  };
763
745
  }
764
746
  if (status >= 500 || status === 429) {
765
- return { kind: "server", status, message };
747
+ return { kind: "server", status, message: message2 };
766
748
  }
767
- return { kind: "validation", status, message, details: errObj.details };
749
+ return { kind: "validation", status, message: message2, details: errObj.details };
768
750
  }
769
751
  function backoffMs(attempt) {
770
752
  return 1e3 * 2 ** attempt;
@@ -835,6 +817,27 @@ var BackendClient = class {
835
817
  signal
836
818
  );
837
819
  }
820
+ /** Remote cache lookup. A miss (404) — or an old backend without the route — returns null. */
821
+ async getCacheEntry(cacheKey, signal) {
822
+ try {
823
+ const res = await this.http.getJson(`/api/canvas/cache/${encodeURIComponent(cacheKey)}`, signal);
824
+ return res.entry;
825
+ } catch (e) {
826
+ if (e instanceof BackendHttpError && "status" in e.detail && e.detail.status === 404) return null;
827
+ throw e;
828
+ }
829
+ }
830
+ async putCacheEntry(entry, signal) {
831
+ await this.http.putJson(
832
+ `/api/canvas/cache/${encodeURIComponent(entry.cacheKey)}`,
833
+ entry,
834
+ signal
835
+ );
836
+ }
837
+ /** Durable run-history record — POST /api/canvas/runs (idempotent server-side on runId). */
838
+ async recordRun(payload, signal) {
839
+ await this.http.postJson("/api/canvas/runs", payload, signal);
840
+ }
838
841
  getArtifact(kind, name, version, signal) {
839
842
  const path16 = version ? `/api/canvas/artifacts/${encodeURIComponent(kind)}/${encodeURIComponent(name)}/${encodeURIComponent(version)}` : `/api/canvas/artifacts/${encodeURIComponent(kind)}/${encodeURIComponent(name)}`;
840
843
  return this.http.getJson(path16, signal);
@@ -858,14 +861,17 @@ function requireCredentialsFromEnv(env = process.env) {
858
861
  }
859
862
  return c;
860
863
  }
864
+ function remoteCacheEnabledFromEnv(env = process.env) {
865
+ return env.BAKER_CANVAS_REMOTE_CACHE !== "off";
866
+ }
861
867
 
862
868
  // src/engine/engine/errors.ts
863
869
  function isBlocking(issue) {
864
870
  return issue.severity !== "warning";
865
871
  }
866
872
  var CanvasError = class extends Error {
867
- constructor(message) {
868
- super(message);
873
+ constructor(message2) {
874
+ super(message2);
869
875
  this.name = "CanvasError";
870
876
  }
871
877
  };
@@ -922,7 +928,7 @@ function describeCause(c) {
922
928
  }
923
929
  }
924
930
 
925
- // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/esm/wrapper.js
931
+ // ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/810146e81bae4e3a061fe487864f2fde80c4b03b886877dc0f1fffbc6480b67e/node_modules/safe-stable-stringify/esm/wrapper.js
926
932
  var import__ = __toESM(require_safe_stable_stringify(), 1);
927
933
  var configure = import__.default.configure;
928
934
  var wrapper_default = import__.default;
@@ -1583,6 +1589,160 @@ function encodeRandom() {
1583
1589
  return out;
1584
1590
  }
1585
1591
 
1592
+ // src/engine/storage/remote-cache-store.ts
1593
+ var CANVAS_ASSETS_URL_SEGMENT = "/canvas-assets/";
1594
+ function isPersistedAssetRef(ref) {
1595
+ const { url, sha256 } = ref;
1596
+ if (typeof url !== "string" || typeof sha256 !== "string") return false;
1597
+ return url.includes(`${CANVAS_ASSETS_URL_SEGMENT}${sha256.slice(0, 2)}/${sha256}`) || url.includes(`${CANVAS_ASSETS_URL_SEGMENT}${sha256}`);
1598
+ }
1599
+ function isAssetRefLike(value) {
1600
+ return typeof value === "object" && value !== null && !Array.isArray(value) && typeof value.sha256 === "string" && typeof value.mime === "string";
1601
+ }
1602
+ function collectAssetRefLikes(value, out = []) {
1603
+ if (Array.isArray(value)) {
1604
+ for (const item of value) collectAssetRefLikes(item, out);
1605
+ return out;
1606
+ }
1607
+ if (typeof value !== "object" || value === null) return out;
1608
+ if (isAssetRefLike(value)) {
1609
+ out.push(value);
1610
+ }
1611
+ for (const item of Object.values(value)) collectAssetRefLikes(item, out);
1612
+ return out;
1613
+ }
1614
+ function entryFullyPersisted(entry) {
1615
+ return collectAssetRefLikes(entry.outputs).every((ref) => isPersistedAssetRef(ref));
1616
+ }
1617
+ function stripLocalFields(entry) {
1618
+ const clone = JSON.parse(JSON.stringify(entry));
1619
+ for (const ref of collectAssetRefLikes(clone.outputs)) {
1620
+ delete ref.path;
1621
+ delete ref.bytes;
1622
+ }
1623
+ return clone;
1624
+ }
1625
+ var RemoteCacheStore = class {
1626
+ client;
1627
+ log;
1628
+ constructor(client, log) {
1629
+ this.client = client;
1630
+ this.log = log ?? (() => void 0);
1631
+ }
1632
+ async get(cacheKey) {
1633
+ return await this.client.getCacheEntry(cacheKey);
1634
+ }
1635
+ async put(entry) {
1636
+ if (!entryFullyPersisted(entry)) {
1637
+ this.log(`[cache ] ${entry.cacheKey.slice(0, 12)}\u2026 has local-only assets, kept local`);
1638
+ return;
1639
+ }
1640
+ const stripped = stripLocalFields(entry);
1641
+ if (stripped.refs.length > MAX_REMOTE_REFS) {
1642
+ stripped.refs = stripped.refs.slice(0, MAX_REMOTE_REFS);
1643
+ }
1644
+ await this.client.putCacheEntry(stripped);
1645
+ }
1646
+ };
1647
+ var MAX_REMOTE_REFS = 512;
1648
+ var LayeredCacheStore = class {
1649
+ rootDir;
1650
+ local;
1651
+ remote;
1652
+ assets;
1653
+ log;
1654
+ constructor(opts) {
1655
+ this.local = opts.local;
1656
+ this.remote = opts.remote;
1657
+ this.assets = opts.assets;
1658
+ this.rootDir = opts.local.rootDir;
1659
+ this.log = opts.log ?? (() => void 0);
1660
+ }
1661
+ async get(cacheKey) {
1662
+ const localHit = await this.local.get(cacheKey);
1663
+ if (localHit) return localHit;
1664
+ let remoteEntry;
1665
+ try {
1666
+ remoteEntry = await this.remote.get(cacheKey);
1667
+ } catch (e) {
1668
+ this.log(`[cache ] remote lookup failed (${message(e)}) \u2014 treating as miss`);
1669
+ return null;
1670
+ }
1671
+ if (!remoteEntry) return null;
1672
+ let rehydrated;
1673
+ try {
1674
+ rehydrated = await this.rehydrate(remoteEntry);
1675
+ } catch (e) {
1676
+ this.log(`[cache ] ${cacheKey.slice(0, 12)}\u2026 rehydration failed (${message(e)}) \u2014 treating as miss`);
1677
+ return null;
1678
+ }
1679
+ await this.local.put(rehydrated);
1680
+ return rehydrated;
1681
+ }
1682
+ async put(entry) {
1683
+ await this.local.put(entry);
1684
+ try {
1685
+ await this.remote.put(entry);
1686
+ } catch (e) {
1687
+ this.log(`[cache ] remote write failed (${message(e)}) \u2014 entry kept local`);
1688
+ }
1689
+ }
1690
+ /**
1691
+ * Download every referenced asset into the local content-addressed store
1692
+ * (sha-verified) and stamp fresh local paths. Any ref that cannot be
1693
+ * rehydrated fails the WHOLE entry — a partially-hydrated cache hit would
1694
+ * crash materialization later with a far less actionable error.
1695
+ */
1696
+ async rehydrate(entry) {
1697
+ const clone = JSON.parse(JSON.stringify(entry));
1698
+ for (const ref of collectAssetRefLikes(clone.outputs)) {
1699
+ if (!isPersistedAssetRef(ref)) {
1700
+ throw new Error(`ref ${ref.sha256.slice(0, 12)}\u2026 has no persisted url`);
1701
+ }
1702
+ const ingested = await this.assets.ingestRemote({
1703
+ kind: typeof ref.kind === "string" ? ref.kind : "json",
1704
+ url: ref.url,
1705
+ sha256: ref.sha256,
1706
+ mime: ref.mime,
1707
+ metadata: ref.metadata ?? void 0
1708
+ });
1709
+ ref.path = ingested.path;
1710
+ }
1711
+ return clone;
1712
+ }
1713
+ };
1714
+ function message(e) {
1715
+ return e instanceof Error ? e.message : String(e);
1716
+ }
1717
+
1718
+ // src/engine/nodes/remote/upload.ts
1719
+ async function presignAndPut(args) {
1720
+ const { putUrl, publicUrl } = await args.ctx.client.presignAssetUpload(args.sha256, args.mime, args.ctx.signal);
1721
+ const putRes = await fetch(putUrl, {
1722
+ method: "PUT",
1723
+ body: new Uint8Array(args.bytes),
1724
+ headers: { "Content-Type": args.mime },
1725
+ signal: args.ctx.signal
1726
+ });
1727
+ if (!putRes.ok) {
1728
+ throw new Error(`upload: presigned PUT failed ${putRes.status} ${putRes.statusText}`);
1729
+ }
1730
+ return publicUrl;
1731
+ }
1732
+ async function ensureUploaded(ref, ctx) {
1733
+ if (ref.url) return ref;
1734
+ const bytes = await ctx.assets.readBytes(ref.sha256, ref.mime);
1735
+ const url = await presignAndPut({ bytes, sha256: ref.sha256, mime: ref.mime, ctx });
1736
+ return { ...ref, url };
1737
+ }
1738
+ async function persistOutputAssetUrls(outputs, ctx) {
1739
+ for (const ref of collectAssetRefLikes(outputs)) {
1740
+ if (isPersistedAssetRef(ref)) continue;
1741
+ const bytes = await ctx.assets.readBytes(ref.sha256, ref.mime);
1742
+ ref.url = await presignAndPut({ bytes, sha256: ref.sha256, mime: ref.mime, ctx });
1743
+ }
1744
+ }
1745
+
1586
1746
  // src/engine/schema/canvas.ts
1587
1747
  import { z } from "zod";
1588
1748
  var REF_PREFIX = "$ref:";
@@ -2862,6 +3022,7 @@ var Engine = class {
2862
3022
  cache;
2863
3023
  outputsDir;
2864
3024
  log;
3025
+ persistAssets;
2865
3026
  constructor(opts) {
2866
3027
  this.registry = opts.registry;
2867
3028
  this.client = opts.client;
@@ -2869,6 +3030,7 @@ var Engine = class {
2869
3030
  this.cache = opts.cache;
2870
3031
  this.outputsDir = opts.outputsDir;
2871
3032
  this.log = opts.log ?? (() => void 0);
3033
+ this.persistAssets = opts.persistAssets ?? false;
2872
3034
  }
2873
3035
  validate(canvas) {
2874
3036
  return validateCanvas(canvas, this.registry);
@@ -2915,7 +3077,7 @@ var Engine = class {
2915
3077
  `[done ] ${stats.cached_nodes}/${stats.total_nodes} cached, ${stats.total_credits} credits, ${stats.duration_ms}ms`
2916
3078
  );
2917
3079
  this.log(`outputs in: ${writer.runDir}`);
2918
- return { run_id: runId, output, outputs_by_node: outputs, stats, outputs_dir: writer.runDir };
3080
+ return { run_id: runId, output, outputs_by_node: outputs, stats, outputs_dir: writer.runDir, node_runs: nodeRuns };
2919
3081
  }
2920
3082
  async runLayers(canvas, outputs, runId, writer, opts, counters, nodeRuns) {
2921
3083
  const layers = topologicalLayers(this.pruneToOutput(canvas, buildGraph(canvas)));
@@ -3012,6 +3174,14 @@ var Engine = class {
3012
3174
  const credits = def.cost ? def.cost({ params: parsedParams }).credits : 0;
3013
3175
  const outputsObj = result;
3014
3176
  outputs[node.id] = outputsObj;
3177
+ if (this.persistAssets) {
3178
+ try {
3179
+ await persistOutputAssetUrls(outputsObj, ctx);
3180
+ } catch (e) {
3181
+ const msg = e instanceof Error ? e.message : String(e);
3182
+ this.log(`[warn ] ${node.id}: asset persistence failed (${msg}) \u2014 outputs stay local-only`);
3183
+ }
3184
+ }
3015
3185
  if (policy === "read_write") {
3016
3186
  await this.cache.put({
3017
3187
  cacheKey: prepared.cacheKey,
@@ -3330,27 +3500,6 @@ var FontRef = BaseAssetRef.extend({
3330
3500
  });
3331
3501
  var AssetRef = z4.discriminatedUnion("kind", [ImageRef, VideoRef, AudioRef, JsonRef, TextRef, FontRef]);
3332
3502
 
3333
- // src/engine/nodes/remote/upload.ts
3334
- async function presignAndPut(args) {
3335
- const { putUrl, publicUrl } = await args.ctx.client.presignAssetUpload(args.sha256, args.mime, args.ctx.signal);
3336
- const putRes = await fetch(putUrl, {
3337
- method: "PUT",
3338
- body: new Uint8Array(args.bytes),
3339
- headers: { "Content-Type": args.mime },
3340
- signal: args.ctx.signal
3341
- });
3342
- if (!putRes.ok) {
3343
- throw new Error(`upload: presigned PUT failed ${putRes.status} ${putRes.statusText}`);
3344
- }
3345
- return publicUrl;
3346
- }
3347
- async function ensureUploaded(ref, ctx) {
3348
- if (ref.url) return ref;
3349
- const bytes = await ctx.assets.readBytes(ref.sha256, ref.mime);
3350
- const url = await presignAndPut({ bytes, sha256: ref.sha256, mime: ref.mime, ctx });
3351
- return { ...ref, url };
3352
- }
3353
-
3354
3503
  // src/engine/nodes/remote/delegate.ts
3355
3504
  function delegated(spec) {
3356
3505
  return {
@@ -3745,10 +3894,10 @@ function inferKindFromMime(mime) {
3745
3894
  if (mime.startsWith("font/")) return "font";
3746
3895
  return null;
3747
3896
  }
3748
- function localExecError(ctx, message) {
3897
+ function localExecError(ctx, message2) {
3749
3898
  return new NodeExecutionError(ctx.nodeId, ctx.nodeType, {
3750
3899
  kind: "local",
3751
- cause: new Error(`ingest: ${message}`)
3900
+ cause: new Error(`ingest: ${message2}`)
3752
3901
  });
3753
3902
  }
3754
3903
  async function execLocalFile(params, ctx) {
@@ -4415,7 +4564,7 @@ async function refToUrl(ref) {
4415
4564
  return `data:${ref.mime};base64,${bytes.toString("base64")}`;
4416
4565
  }
4417
4566
  var ASSET_KINDS = /* @__PURE__ */ new Set(["image", "video", "audio", "json", "text", "font"]);
4418
- function isAssetRefLike(value) {
4567
+ function isAssetRefLike2(value) {
4419
4568
  if (!value || typeof value !== "object") return false;
4420
4569
  const v = value;
4421
4570
  return typeof v.kind === "string" && ASSET_KINDS.has(v.kind) && typeof v.mime === "string" && typeof v.sha256 === "string" && (typeof v.url === "string" || typeof v.path === "string");
@@ -4787,8 +4936,8 @@ var NEVER_BLOCK = [
4787
4936
  /text[_-]?occluded/i
4788
4937
  ];
4789
4938
  var UNAVAILABLE = /unknown command|command not found|not found|Did you mean|Unknown argument|ENOENT/i;
4790
- function isAdvisory(code, message) {
4791
- const hay = `${code} ${message}`;
4939
+ function isAdvisory(code, message2) {
4940
+ const hay = `${code} ${message2}`;
4792
4941
  return NEVER_BLOCK.some((re) => re.test(hay));
4793
4942
  }
4794
4943
  function parseCheckJson(raw) {
@@ -4816,10 +4965,10 @@ function classifyLint(json) {
4816
4965
  for (const f of findings) {
4817
4966
  const rec = f;
4818
4967
  const code = String(rec?.code ?? "");
4819
- const message = String(rec?.message ?? "");
4968
+ const message2 = String(rec?.message ?? "");
4820
4969
  const severity = String(rec?.severity ?? "info");
4821
- const blocking = severity === "error" && !isAdvisory(code, message);
4822
- out.push({ source: "lint", code, message, severity: blocking ? "blocking" : "warning" });
4970
+ const blocking = severity === "error" && !isAdvisory(code, message2);
4971
+ out.push({ source: "lint", code, message: message2, severity: blocking ? "blocking" : "warning" });
4823
4972
  }
4824
4973
  return out;
4825
4974
  }
@@ -4831,9 +4980,9 @@ function classifyInspect(json) {
4831
4980
  for (const iss of issues) {
4832
4981
  const rec = iss;
4833
4982
  const code = String(rec?.code ?? rec?.type ?? "overflow");
4834
- const message = String(rec?.message ?? rec?.detail ?? JSON.stringify(iss));
4983
+ const message2 = String(rec?.message ?? rec?.detail ?? JSON.stringify(iss));
4835
4984
  const severity = rec?.severity ? String(rec.severity) : obj?.ok === false ? "error" : "warning";
4836
- out.push({ source: "inspect", code, message, severity: severity === "error" ? "blocking" : "warning" });
4985
+ out.push({ source: "inspect", code, message: message2, severity: severity === "error" ? "blocking" : "warning" });
4837
4986
  }
4838
4987
  return out;
4839
4988
  }
@@ -5278,7 +5427,7 @@ async function buildSubstitutionValues(compositionParams, meta, duration) {
5278
5427
  }
5279
5428
  function coerceImageParam(value) {
5280
5429
  if (typeof value === "string") return Promise.resolve(value);
5281
- if (isAssetRefLike(value)) return refToUrl(value);
5430
+ if (isAssetRefLike2(value)) return refToUrl(value);
5282
5431
  throw new Error("hyperframe_render: image param must be a URL string or AssetRef");
5283
5432
  }
5284
5433
  async function substituteCompositionFiles(tmp, values) {
@@ -5508,7 +5657,7 @@ async function buildSubstitutionValues2(compositionParams, meta) {
5508
5657
  }
5509
5658
  function coerceImageParam2(value) {
5510
5659
  if (typeof value === "string") return Promise.resolve(value);
5511
- if (isAssetRefLike(value)) return refToUrl(value);
5660
+ if (isAssetRefLike2(value)) return refToUrl(value);
5512
5661
  throw new Error("hyperframe_snapshot: image param must be a URL string or AssetRef");
5513
5662
  }
5514
5663
  async function substituteCompositionFiles2(tmp, values) {
@@ -6534,17 +6683,29 @@ function createEngineFromEnv(opts = {}) {
6534
6683
  const cacheDir = opts.cacheDir ?? path15.join(cwd, "canvas", ".cache");
6535
6684
  const outputsDir = opts.outputsDir ?? path15.join(cwd, "canvas");
6536
6685
  const creds = requireCredentialsFromEnv();
6686
+ const client = new BackendClient({ baseUrl: creds.url, apiKey: creds.apiKey });
6687
+ const assets = new LocalAssetStore(path15.join(cacheDir, "assets"));
6688
+ const localCache = new LocalCacheStore(path15.join(cacheDir, "index"));
6689
+ const remoteCacheEnabled = opts.remoteCache ?? remoteCacheEnabledFromEnv();
6690
+ const cache = remoteCacheEnabled ? new LayeredCacheStore({
6691
+ local: localCache,
6692
+ remote: new RemoteCacheStore(client, opts.log),
6693
+ assets,
6694
+ log: opts.log
6695
+ }) : localCache;
6537
6696
  return new Engine({
6538
6697
  registry: defaultRegistry(),
6539
- client: new BackendClient({ baseUrl: creds.url, apiKey: creds.apiKey }),
6540
- assets: new LocalAssetStore(path15.join(cacheDir, "assets")),
6541
- cache: new LocalCacheStore(path15.join(cacheDir, "index")),
6698
+ client,
6699
+ assets,
6700
+ cache,
6542
6701
  outputsDir,
6543
- log: opts.log
6702
+ log: opts.log,
6703
+ persistAssets: remoteCacheEnabled
6544
6704
  });
6545
6705
  }
6546
6706
 
6547
6707
  export {
6708
+ requireCredentialsFromEnv,
6548
6709
  LayerExecutionError,
6549
6710
  describeFailureReason,
6550
6711
  SEEDANCE_DURATIONS,
@@ -6552,6 +6713,10 @@ export {
6552
6713
  IMAGE_GENERATE_MODELS,
6553
6714
  MODEL_REGISTRY,
6554
6715
  resolveConcurrency,
6716
+ ulid,
6717
+ isPersistedAssetRef,
6718
+ collectAssetRefLikes,
6719
+ sha256Hex,
6555
6720
  elementMentionKeywords,
6556
6721
  BackendClient2 as BackendClient,
6557
6722
  Engine2 as Engine,
@@ -6563,4 +6728,4 @@ export {
6563
6728
  defaultRegistry,
6564
6729
  createEngineFromEnv
6565
6730
  };
6566
- //# sourceMappingURL=chunk-MF34WJ7M.js.map
6731
+ //# sourceMappingURL=chunk-AWSEBYP4.js.map