@koda-sl/baker-cli 0.116.0-dev.3bcc79f9c → 0.116.0-dev.86609d2a7

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.
@@ -0,0 +1,156 @@
1
+ import {
2
+ getEnv
3
+ } from "./chunk-YTEAWSEM.js";
4
+
5
+ // src/client.ts
6
+ var MAX_RATE_LIMIT_RETRIES = 3;
7
+ var MAX_TOTAL_WAIT_MS = 2 * 60 * 1e3;
8
+ async function fetchWithRateLimitRetry(url, init) {
9
+ let totalWaited = 0;
10
+ for (let attempt = 0; attempt <= MAX_RATE_LIMIT_RETRIES; attempt++) {
11
+ const response = await fetch(url, init);
12
+ if (response.status !== 429 || attempt >= MAX_RATE_LIMIT_RETRIES) {
13
+ return response;
14
+ }
15
+ const retryAfterHeader = response.headers.get("Retry-After");
16
+ const waitMs = retryAfterHeader ? Number(retryAfterHeader) * 1e3 : 2e3 * 2 ** attempt;
17
+ if (totalWaited + waitMs > MAX_TOTAL_WAIT_MS) {
18
+ return response;
19
+ }
20
+ totalWaited += waitMs;
21
+ await new Promise((resolve) => setTimeout(resolve, waitMs));
22
+ }
23
+ return fetch(url, init);
24
+ }
25
+ var ApiError = class extends Error {
26
+ code;
27
+ constructor(code, message) {
28
+ super(message);
29
+ this.name = "ApiError";
30
+ this.code = code;
31
+ }
32
+ };
33
+ var CONVEX_ID_RE = /^[a-zA-Z0-9_]+$/;
34
+ function hasControlCharacters(value) {
35
+ for (let i = 0; i < value.length; i++) {
36
+ const code = value.charCodeAt(i);
37
+ if (code < 32 && code !== 9 && code !== 10 && code !== 13) {
38
+ return true;
39
+ }
40
+ }
41
+ return false;
42
+ }
43
+ function validateStringValue(value) {
44
+ if (hasControlCharacters(value)) {
45
+ throw new ApiError("VALIDATION_ERROR", "String value contains invalid control characters");
46
+ }
47
+ }
48
+ function validateConvexId(id) {
49
+ if (!CONVEX_ID_RE.test(id)) {
50
+ throw new ApiError("VALIDATION_ERROR", `Invalid ID format: "${id}". Expected alphanumeric string.`);
51
+ }
52
+ }
53
+ function sanitizeParams(params) {
54
+ const sanitized = {};
55
+ for (const [key, value] of Object.entries(params)) {
56
+ validateStringValue(value);
57
+ sanitized[key] = value;
58
+ }
59
+ return sanitized;
60
+ }
61
+ function mapHttpError(status) {
62
+ if (status === 401 || status === 403) {
63
+ return "UNAUTHORIZED";
64
+ }
65
+ if (status === 404) {
66
+ return "NOT_FOUND";
67
+ }
68
+ if (status === 422 || status === 400) {
69
+ return "VALIDATION_ERROR";
70
+ }
71
+ if (status === 429) {
72
+ return "RATE_LIMITED";
73
+ }
74
+ return "INTERNAL_ERROR";
75
+ }
76
+ async function handleResponse(response) {
77
+ const body = await response.text();
78
+ if (!response.ok) {
79
+ let message = `HTTP ${response.status}: ${response.statusText}`;
80
+ try {
81
+ const parsed = JSON.parse(body);
82
+ if (typeof parsed.error === "string") {
83
+ message = parsed.error;
84
+ } else if (parsed.error?.message) {
85
+ message = parsed.error.message;
86
+ } else if (parsed.message) {
87
+ message = parsed.message;
88
+ }
89
+ } catch {
90
+ }
91
+ throw new ApiError(mapHttpError(response.status), message);
92
+ }
93
+ try {
94
+ return JSON.parse(body);
95
+ } catch {
96
+ throw new ApiError("INTERNAL_ERROR", "Failed to parse API response as JSON");
97
+ }
98
+ }
99
+ async function apiGet(path, params) {
100
+ const env = getEnv();
101
+ const url = new URL(path, env.BAKER_API_URL);
102
+ if (params) {
103
+ const clean = sanitizeParams(params);
104
+ for (const [key, value] of Object.entries(clean)) {
105
+ url.searchParams.set(key, value);
106
+ }
107
+ }
108
+ let response;
109
+ try {
110
+ response = await fetchWithRateLimitRetry(url.toString(), {
111
+ method: "GET",
112
+ headers: {
113
+ Authorization: `Bearer ${env.BAKER_API_KEY}`,
114
+ Accept: "application/json"
115
+ },
116
+ signal: AbortSignal.timeout(6e4)
117
+ });
118
+ } catch (err) {
119
+ if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError")) {
120
+ throw new ApiError("TIMEOUT", "Request timed out after 60 seconds");
121
+ }
122
+ throw new ApiError("NETWORK_ERROR", `Request failed: ${err instanceof Error ? err.message : "Unknown error"}`);
123
+ }
124
+ return handleResponse(response);
125
+ }
126
+ async function apiPost(path, body, opts) {
127
+ const env = getEnv();
128
+ const timeoutMs = opts?.timeoutMs ?? 6e4;
129
+ let response;
130
+ try {
131
+ response = await fetchWithRateLimitRetry(new URL(path, env.BAKER_API_URL).toString(), {
132
+ method: "POST",
133
+ headers: {
134
+ Authorization: `Bearer ${env.BAKER_API_KEY}`,
135
+ "Content-Type": "application/json",
136
+ Accept: "application/json"
137
+ },
138
+ body: JSON.stringify(body),
139
+ signal: AbortSignal.timeout(timeoutMs)
140
+ });
141
+ } catch (err) {
142
+ if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError")) {
143
+ throw new ApiError("TIMEOUT", `Request timed out after ${Math.round(timeoutMs / 1e3)} seconds`);
144
+ }
145
+ throw new ApiError("NETWORK_ERROR", `Request failed: ${err instanceof Error ? err.message : "Unknown error"}`);
146
+ }
147
+ return handleResponse(response);
148
+ }
149
+
150
+ export {
151
+ ApiError,
152
+ validateConvexId,
153
+ apiGet,
154
+ apiPost
155
+ };
156
+ //# sourceMappingURL=chunk-K47Q73CK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["import { getEnv } from \"./env.ts\";\n\nconst MAX_RATE_LIMIT_RETRIES = 3;\nconst MAX_TOTAL_WAIT_MS = 2 * 60 * 1000;\n\nasync function fetchWithRateLimitRetry(url: string, init: RequestInit): Promise<Response> {\n let totalWaited = 0;\n\n for (let attempt = 0; attempt <= MAX_RATE_LIMIT_RETRIES; attempt++) {\n const response = await fetch(url, init);\n\n if (response.status !== 429 || attempt >= MAX_RATE_LIMIT_RETRIES) {\n return response;\n }\n\n const retryAfterHeader = response.headers.get(\"Retry-After\");\n const waitMs = retryAfterHeader ? Number(retryAfterHeader) * 1000 : 2000 * 2 ** attempt;\n\n if (totalWaited + waitMs > MAX_TOTAL_WAIT_MS) {\n return response;\n }\n\n totalWaited += waitMs;\n await new Promise((resolve) => setTimeout(resolve, waitMs));\n }\n\n return fetch(url, init);\n}\n\ntype ErrorCode =\n | \"UNAUTHORIZED\"\n | \"NOT_FOUND\"\n | \"VALIDATION_ERROR\"\n | \"RATE_LIMITED\"\n | \"INTERNAL_ERROR\"\n | \"NETWORK_ERROR\"\n | \"TIMEOUT\"\n | \"IMAGE_PROCESSING_ERROR\";\n\nexport class ApiError extends Error {\n code: ErrorCode;\n\n constructor(code: ErrorCode, message: string) {\n super(message);\n this.name = \"ApiError\";\n this.code = code;\n }\n}\n\nconst CONVEX_ID_RE = /^[a-zA-Z0-9_]+$/;\n\nfunction hasControlCharacters(value: string): boolean {\n for (let i = 0; i < value.length; i++) {\n const code = value.charCodeAt(i);\n // Allow tab (9), newline (10), carriage return (13)\n if (code < 32 && code !== 9 && code !== 10 && code !== 13) {\n return true;\n }\n }\n return false;\n}\n\nfunction validateStringValue(value: string): void {\n if (hasControlCharacters(value)) {\n throw new ApiError(\"VALIDATION_ERROR\", \"String value contains invalid control characters\");\n }\n}\n\nexport function validateConvexId(id: string): void {\n if (!CONVEX_ID_RE.test(id)) {\n throw new ApiError(\"VALIDATION_ERROR\", `Invalid ID format: \"${id}\". Expected alphanumeric string.`);\n }\n}\n\nfunction sanitizeParams(params: Record<string, string>): Record<string, string> {\n const sanitized: Record<string, string> = {};\n for (const [key, value] of Object.entries(params)) {\n validateStringValue(value);\n sanitized[key] = value;\n }\n return sanitized;\n}\n\nfunction mapHttpError(status: number): ErrorCode {\n if (status === 401 || status === 403) {\n return \"UNAUTHORIZED\";\n }\n if (status === 404) {\n return \"NOT_FOUND\";\n }\n if (status === 422 || status === 400) {\n return \"VALIDATION_ERROR\";\n }\n if (status === 429) {\n return \"RATE_LIMITED\";\n }\n return \"INTERNAL_ERROR\";\n}\n\nasync function handleResponse<T>(response: Response): Promise<T> {\n const body = await response.text();\n\n if (!response.ok) {\n let message = `HTTP ${response.status}: ${response.statusText}`;\n try {\n const parsed = JSON.parse(body) as { error?: string | { message?: string }; message?: string };\n if (typeof parsed.error === \"string\") {\n message = parsed.error;\n } else if (parsed.error?.message) {\n message = parsed.error.message;\n } else if (parsed.message) {\n message = parsed.message;\n }\n } catch {\n // Use default message\n }\n throw new ApiError(mapHttpError(response.status), message);\n }\n\n try {\n return JSON.parse(body) as T;\n } catch {\n throw new ApiError(\"INTERNAL_ERROR\", \"Failed to parse API response as JSON\");\n }\n}\n\nexport async function apiGet<T>(path: string, params?: Record<string, string>): Promise<T> {\n const env = getEnv();\n const url = new URL(path, env.BAKER_API_URL);\n if (params) {\n const clean = sanitizeParams(params);\n for (const [key, value] of Object.entries(clean)) {\n url.searchParams.set(key, value);\n }\n }\n\n let response: Response;\n try {\n response = await fetchWithRateLimitRetry(url.toString(), {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${env.BAKER_API_KEY}`,\n Accept: \"application/json\",\n },\n signal: AbortSignal.timeout(60_000),\n });\n } catch (err) {\n if (err instanceof Error && (err.name === \"TimeoutError\" || err.name === \"AbortError\")) {\n throw new ApiError(\"TIMEOUT\", \"Request timed out after 60 seconds\");\n }\n throw new ApiError(\"NETWORK_ERROR\", `Request failed: ${err instanceof Error ? err.message : \"Unknown error\"}`);\n }\n\n return handleResponse<T>(response);\n}\n\nexport async function apiPost<T>(path: string, body: unknown, opts?: { timeoutMs?: number }): Promise<T> {\n const env = getEnv();\n const timeoutMs = opts?.timeoutMs ?? 60_000;\n let response: Response;\n try {\n response = await fetchWithRateLimitRetry(new URL(path, env.BAKER_API_URL).toString(), {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${env.BAKER_API_KEY}`,\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(timeoutMs),\n });\n } catch (err) {\n if (err instanceof Error && (err.name === \"TimeoutError\" || err.name === \"AbortError\")) {\n throw new ApiError(\"TIMEOUT\", `Request timed out after ${Math.round(timeoutMs / 1000)} seconds`);\n }\n throw new ApiError(\"NETWORK_ERROR\", `Request failed: ${err instanceof Error ? err.message : \"Unknown error\"}`);\n }\n\n return handleResponse<T>(response);\n}\n"],"mappings":"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","names":[]}
@@ -1,28 +1,7 @@
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
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({
@@ -159,9 +138,9 @@ var require_safe_stable_stringify = __commonJS({
159
138
  }
160
139
  if (value) {
161
140
  return (value2) => {
162
- let message2 = `Object can not safely be stringified. Received type ${typeof value2}`;
163
- if (typeof value2 !== "function") message2 += ` (${value2.toString()})`;
164
- throw new Error(message2);
141
+ let message = `Object can not safely be stringified. Received type ${typeof value2}`;
142
+ if (typeof value2 !== "function") message += ` (${value2.toString()})`;
143
+ throw new Error(message);
165
144
  };
166
145
  }
167
146
  }
@@ -673,9 +652,6 @@ var HttpClient = class {
673
652
  async postJson(path16, body, signal) {
674
653
  return await this.requestJson("POST", path16, body, signal);
675
654
  }
676
- async putJson(path16, body, signal) {
677
- return await this.requestJson("PUT", path16, body, signal);
678
- }
679
655
  async getJson(path16, signal) {
680
656
  return await this.requestJson("GET", path16, void 0, signal);
681
657
  }
@@ -703,8 +679,8 @@ var HttpClient = class {
703
679
  try {
704
680
  const res = await this.fetchFn(url, {
705
681
  method,
706
- headers: method === "GET" ? { Authorization: `Bearer ${this.apiKey}` } : { "Content-Type": "application/json", Authorization: `Bearer ${this.apiKey}` },
707
- body: method === "GET" ? void 0 : JSON.stringify(body),
682
+ headers: method === "POST" ? { "Content-Type": "application/json", Authorization: `Bearer ${this.apiKey}` } : { Authorization: `Bearer ${this.apiKey}` },
683
+ body: method === "POST" ? JSON.stringify(body) : void 0,
708
684
  signal: controller.signal
709
685
  });
710
686
  if (res.ok) return { kind: "value", value: await res.json() };
@@ -741,33 +717,33 @@ async function parseErrorBody(res) {
741
717
  const errObj = body.error ?? {};
742
718
  return classifyHttpError(res.status, errObj, errObj.message ?? `HTTP ${res.status}`);
743
719
  }
744
- function classifyHttpError(status, errObj, message2) {
720
+ function classifyHttpError(status, errObj, message) {
745
721
  if (errObj.code === CONTENT_POLICY_CODE) {
746
- return { kind: "content_policy", status, provider: errObj.provider, message: message2 };
722
+ return { kind: "content_policy", status, provider: errObj.provider, message };
747
723
  }
748
724
  if (status === 401 || status === 403) {
749
- return { kind: "unauthorized", status, message: message2 };
725
+ return { kind: "unauthorized", status, message };
750
726
  }
751
727
  if (status === 400 || status === 422) {
752
- return { kind: "validation", status, message: message2, details: errObj.details };
728
+ return { kind: "validation", status, message, details: errObj.details };
753
729
  }
754
730
  if (status === 502 || status === 504) {
755
731
  if (errObj.code === "provider_timeout" || status === 504) {
756
- return { kind: "timeout", provider: errObj.provider, message: message2 };
732
+ return { kind: "timeout", provider: errObj.provider, message };
757
733
  }
758
734
  return {
759
735
  kind: "provider",
760
736
  status,
761
737
  provider: errObj.provider,
762
738
  code: errObj.code ?? "provider_error",
763
- message: message2,
739
+ message,
764
740
  retryable: errObj.retryable ?? true
765
741
  };
766
742
  }
767
743
  if (status >= 500 || status === 429) {
768
- return { kind: "server", status, message: message2 };
744
+ return { kind: "server", status, message };
769
745
  }
770
- return { kind: "validation", status, message: message2, details: errObj.details };
746
+ return { kind: "validation", status, message, details: errObj.details };
771
747
  }
772
748
  function backoffMs(attempt) {
773
749
  return 1e3 * 2 ** attempt;
@@ -838,27 +814,6 @@ var BackendClient = class {
838
814
  signal
839
815
  );
840
816
  }
841
- /** Remote cache lookup. A miss (404) — or an old backend without the route — returns null. */
842
- async getCacheEntry(cacheKey, signal) {
843
- try {
844
- const res = await this.http.getJson(`/api/canvas/cache/${encodeURIComponent(cacheKey)}`, signal);
845
- return res.entry;
846
- } catch (e) {
847
- if (e instanceof BackendHttpError && "status" in e.detail && e.detail.status === 404) return null;
848
- throw e;
849
- }
850
- }
851
- async putCacheEntry(entry, signal) {
852
- await this.http.putJson(
853
- `/api/canvas/cache/${encodeURIComponent(entry.cacheKey)}`,
854
- entry,
855
- signal
856
- );
857
- }
858
- /** Durable run-history record — POST /api/canvas/runs (idempotent server-side on runId). */
859
- async recordRun(payload, signal) {
860
- await this.http.postJson("/api/canvas/runs", payload, signal);
861
- }
862
817
  getArtifact(kind, name, version, signal) {
863
818
  const path16 = version ? `/api/canvas/artifacts/${encodeURIComponent(kind)}/${encodeURIComponent(name)}/${encodeURIComponent(version)}` : `/api/canvas/artifacts/${encodeURIComponent(kind)}/${encodeURIComponent(name)}`;
864
819
  return this.http.getJson(path16, signal);
@@ -882,17 +837,14 @@ function requireCredentialsFromEnv(env = process.env) {
882
837
  }
883
838
  return c;
884
839
  }
885
- function remoteCacheEnabledFromEnv(env = process.env) {
886
- return env.BAKER_CANVAS_REMOTE_CACHE !== "off";
887
- }
888
840
 
889
841
  // src/engine/engine/errors.ts
890
842
  function isBlocking(issue) {
891
843
  return issue.severity !== "warning";
892
844
  }
893
845
  var CanvasError = class extends Error {
894
- constructor(message2) {
895
- super(message2);
846
+ constructor(message) {
847
+ super(message);
896
848
  this.name = "CanvasError";
897
849
  }
898
850
  };
@@ -1610,158 +1562,6 @@ function encodeRandom() {
1610
1562
  return out;
1611
1563
  }
1612
1564
 
1613
- // src/engine/storage/remote-cache-store.ts
1614
- var CANVAS_ASSETS_URL_SEGMENT = "/canvas-assets/";
1615
- function isPersistedAssetRef(ref) {
1616
- return typeof ref.url === "string" && ref.url.includes(`${CANVAS_ASSETS_URL_SEGMENT}${ref.sha256}`);
1617
- }
1618
- function isAssetRefLike(value) {
1619
- return typeof value === "object" && value !== null && !Array.isArray(value) && typeof value.sha256 === "string" && typeof value.mime === "string";
1620
- }
1621
- function collectAssetRefLikes(value, out = []) {
1622
- if (Array.isArray(value)) {
1623
- for (const item of value) collectAssetRefLikes(item, out);
1624
- return out;
1625
- }
1626
- if (typeof value !== "object" || value === null) return out;
1627
- if (isAssetRefLike(value)) {
1628
- out.push(value);
1629
- }
1630
- for (const item of Object.values(value)) collectAssetRefLikes(item, out);
1631
- return out;
1632
- }
1633
- function entryFullyPersisted(entry) {
1634
- return collectAssetRefLikes(entry.outputs).every((ref) => isPersistedAssetRef(ref));
1635
- }
1636
- function stripLocalFields(entry) {
1637
- const clone = JSON.parse(JSON.stringify(entry));
1638
- for (const ref of collectAssetRefLikes(clone.outputs)) {
1639
- delete ref.path;
1640
- delete ref.bytes;
1641
- }
1642
- return clone;
1643
- }
1644
- var RemoteCacheStore = class {
1645
- client;
1646
- log;
1647
- constructor(client, log) {
1648
- this.client = client;
1649
- this.log = log ?? (() => void 0);
1650
- }
1651
- async get(cacheKey) {
1652
- return await this.client.getCacheEntry(cacheKey);
1653
- }
1654
- async put(entry) {
1655
- if (!entryFullyPersisted(entry)) {
1656
- this.log(`[cache ] ${entry.cacheKey.slice(0, 12)}\u2026 has local-only assets, kept local`);
1657
- return;
1658
- }
1659
- const stripped = stripLocalFields(entry);
1660
- if (stripped.refs.length > MAX_REMOTE_REFS) {
1661
- stripped.refs = stripped.refs.slice(0, MAX_REMOTE_REFS);
1662
- }
1663
- await this.client.putCacheEntry(stripped);
1664
- }
1665
- };
1666
- var MAX_REMOTE_REFS = 512;
1667
- var LayeredCacheStore = class {
1668
- rootDir;
1669
- local;
1670
- remote;
1671
- assets;
1672
- log;
1673
- constructor(opts) {
1674
- this.local = opts.local;
1675
- this.remote = opts.remote;
1676
- this.assets = opts.assets;
1677
- this.rootDir = opts.local.rootDir;
1678
- this.log = opts.log ?? (() => void 0);
1679
- }
1680
- async get(cacheKey) {
1681
- const localHit = await this.local.get(cacheKey);
1682
- if (localHit) return localHit;
1683
- let remoteEntry;
1684
- try {
1685
- remoteEntry = await this.remote.get(cacheKey);
1686
- } catch (e) {
1687
- this.log(`[cache ] remote lookup failed (${message(e)}) \u2014 treating as miss`);
1688
- return null;
1689
- }
1690
- if (!remoteEntry) return null;
1691
- let rehydrated;
1692
- try {
1693
- rehydrated = await this.rehydrate(remoteEntry);
1694
- } catch (e) {
1695
- this.log(`[cache ] ${cacheKey.slice(0, 12)}\u2026 rehydration failed (${message(e)}) \u2014 treating as miss`);
1696
- return null;
1697
- }
1698
- await this.local.put(rehydrated);
1699
- return rehydrated;
1700
- }
1701
- async put(entry) {
1702
- await this.local.put(entry);
1703
- try {
1704
- await this.remote.put(entry);
1705
- } catch (e) {
1706
- this.log(`[cache ] remote write failed (${message(e)}) \u2014 entry kept local`);
1707
- }
1708
- }
1709
- /**
1710
- * Download every referenced asset into the local content-addressed store
1711
- * (sha-verified) and stamp fresh local paths. Any ref that cannot be
1712
- * rehydrated fails the WHOLE entry — a partially-hydrated cache hit would
1713
- * crash materialization later with a far less actionable error.
1714
- */
1715
- async rehydrate(entry) {
1716
- const clone = JSON.parse(JSON.stringify(entry));
1717
- for (const ref of collectAssetRefLikes(clone.outputs)) {
1718
- if (!isPersistedAssetRef(ref)) {
1719
- throw new Error(`ref ${ref.sha256.slice(0, 12)}\u2026 has no persisted url`);
1720
- }
1721
- const ingested = await this.assets.ingestRemote({
1722
- kind: typeof ref.kind === "string" ? ref.kind : "json",
1723
- url: ref.url,
1724
- sha256: ref.sha256,
1725
- mime: ref.mime,
1726
- metadata: ref.metadata ?? void 0
1727
- });
1728
- ref.path = ingested.path;
1729
- }
1730
- return clone;
1731
- }
1732
- };
1733
- function message(e) {
1734
- return e instanceof Error ? e.message : String(e);
1735
- }
1736
-
1737
- // src/engine/nodes/remote/upload.ts
1738
- async function presignAndPut(args) {
1739
- const { putUrl, publicUrl } = await args.ctx.client.presignAssetUpload(args.sha256, args.mime, args.ctx.signal);
1740
- const putRes = await fetch(putUrl, {
1741
- method: "PUT",
1742
- body: new Uint8Array(args.bytes),
1743
- headers: { "Content-Type": args.mime },
1744
- signal: args.ctx.signal
1745
- });
1746
- if (!putRes.ok) {
1747
- throw new Error(`upload: presigned PUT failed ${putRes.status} ${putRes.statusText}`);
1748
- }
1749
- return publicUrl;
1750
- }
1751
- async function ensureUploaded(ref, ctx) {
1752
- if (ref.url) return ref;
1753
- const bytes = await ctx.assets.readBytes(ref.sha256, ref.mime);
1754
- const url = await presignAndPut({ bytes, sha256: ref.sha256, mime: ref.mime, ctx });
1755
- return { ...ref, url };
1756
- }
1757
- async function persistOutputAssetUrls(outputs, ctx) {
1758
- for (const ref of collectAssetRefLikes(outputs)) {
1759
- if (isPersistedAssetRef(ref)) continue;
1760
- const bytes = await ctx.assets.readBytes(ref.sha256, ref.mime);
1761
- ref.url = await presignAndPut({ bytes, sha256: ref.sha256, mime: ref.mime, ctx });
1762
- }
1763
- }
1764
-
1765
1565
  // src/engine/schema/canvas.ts
1766
1566
  import { z } from "zod";
1767
1567
  var REF_PREFIX = "$ref:";
@@ -2978,7 +2778,6 @@ var Engine = class {
2978
2778
  cache;
2979
2779
  outputsDir;
2980
2780
  log;
2981
- persistAssets;
2982
2781
  constructor(opts) {
2983
2782
  this.registry = opts.registry;
2984
2783
  this.client = opts.client;
@@ -2986,7 +2785,6 @@ var Engine = class {
2986
2785
  this.cache = opts.cache;
2987
2786
  this.outputsDir = opts.outputsDir;
2988
2787
  this.log = opts.log ?? (() => void 0);
2989
- this.persistAssets = opts.persistAssets ?? false;
2990
2788
  }
2991
2789
  validate(canvas) {
2992
2790
  return validateCanvas(canvas, this.registry);
@@ -3033,7 +2831,7 @@ var Engine = class {
3033
2831
  `[done ] ${stats.cached_nodes}/${stats.total_nodes} cached, ${stats.total_credits} credits, ${stats.duration_ms}ms`
3034
2832
  );
3035
2833
  this.log(`outputs in: ${writer.runDir}`);
3036
- return { run_id: runId, output, outputs_by_node: outputs, stats, outputs_dir: writer.runDir, node_runs: nodeRuns };
2834
+ return { run_id: runId, output, outputs_by_node: outputs, stats, outputs_dir: writer.runDir };
3037
2835
  }
3038
2836
  async runLayers(canvas, outputs, runId, writer, opts, counters, nodeRuns) {
3039
2837
  const layers = topologicalLayers(this.pruneToOutput(canvas, buildGraph(canvas)));
@@ -3130,14 +2928,6 @@ var Engine = class {
3130
2928
  const credits = def.cost ? def.cost({ params: parsedParams }).credits : 0;
3131
2929
  const outputsObj = result;
3132
2930
  outputs[node.id] = outputsObj;
3133
- if (this.persistAssets) {
3134
- try {
3135
- await persistOutputAssetUrls(outputsObj, ctx);
3136
- } catch (e) {
3137
- const msg = e instanceof Error ? e.message : String(e);
3138
- this.log(`[warn ] ${node.id}: asset persistence failed (${msg}) \u2014 outputs stay local-only`);
3139
- }
3140
- }
3141
2931
  if (policy === "read_write") {
3142
2932
  await this.cache.put({
3143
2933
  cacheKey: prepared.cacheKey,
@@ -3456,6 +3246,27 @@ var FontRef = BaseAssetRef.extend({
3456
3246
  });
3457
3247
  var AssetRef = z4.discriminatedUnion("kind", [ImageRef, VideoRef, AudioRef, JsonRef, TextRef, FontRef]);
3458
3248
 
3249
+ // src/engine/nodes/remote/upload.ts
3250
+ async function presignAndPut(args) {
3251
+ const { putUrl, publicUrl } = await args.ctx.client.presignAssetUpload(args.sha256, args.mime, args.ctx.signal);
3252
+ const putRes = await fetch(putUrl, {
3253
+ method: "PUT",
3254
+ body: new Uint8Array(args.bytes),
3255
+ headers: { "Content-Type": args.mime },
3256
+ signal: args.ctx.signal
3257
+ });
3258
+ if (!putRes.ok) {
3259
+ throw new Error(`upload: presigned PUT failed ${putRes.status} ${putRes.statusText}`);
3260
+ }
3261
+ return publicUrl;
3262
+ }
3263
+ async function ensureUploaded(ref, ctx) {
3264
+ if (ref.url) return ref;
3265
+ const bytes = await ctx.assets.readBytes(ref.sha256, ref.mime);
3266
+ const url = await presignAndPut({ bytes, sha256: ref.sha256, mime: ref.mime, ctx });
3267
+ return { ...ref, url };
3268
+ }
3269
+
3459
3270
  // src/engine/nodes/remote/delegate.ts
3460
3271
  function delegated(spec) {
3461
3272
  return {
@@ -3850,10 +3661,10 @@ function inferKindFromMime(mime) {
3850
3661
  if (mime.startsWith("font/")) return "font";
3851
3662
  return null;
3852
3663
  }
3853
- function localExecError(ctx, message2) {
3664
+ function localExecError(ctx, message) {
3854
3665
  return new NodeExecutionError(ctx.nodeId, ctx.nodeType, {
3855
3666
  kind: "local",
3856
- cause: new Error(`ingest: ${message2}`)
3667
+ cause: new Error(`ingest: ${message}`)
3857
3668
  });
3858
3669
  }
3859
3670
  async function execLocalFile(params, ctx) {
@@ -4520,7 +4331,7 @@ async function refToUrl(ref) {
4520
4331
  return `data:${ref.mime};base64,${bytes.toString("base64")}`;
4521
4332
  }
4522
4333
  var ASSET_KINDS = /* @__PURE__ */ new Set(["image", "video", "audio", "json", "text", "font"]);
4523
- function isAssetRefLike2(value) {
4334
+ function isAssetRefLike(value) {
4524
4335
  if (!value || typeof value !== "object") return false;
4525
4336
  const v = value;
4526
4337
  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");
@@ -4892,8 +4703,8 @@ var NEVER_BLOCK = [
4892
4703
  /text[_-]?occluded/i
4893
4704
  ];
4894
4705
  var UNAVAILABLE = /unknown command|command not found|not found|Did you mean|Unknown argument|ENOENT/i;
4895
- function isAdvisory(code, message2) {
4896
- const hay = `${code} ${message2}`;
4706
+ function isAdvisory(code, message) {
4707
+ const hay = `${code} ${message}`;
4897
4708
  return NEVER_BLOCK.some((re) => re.test(hay));
4898
4709
  }
4899
4710
  function parseCheckJson(raw) {
@@ -4921,10 +4732,10 @@ function classifyLint(json) {
4921
4732
  for (const f of findings) {
4922
4733
  const rec = f;
4923
4734
  const code = String(rec?.code ?? "");
4924
- const message2 = String(rec?.message ?? "");
4735
+ const message = String(rec?.message ?? "");
4925
4736
  const severity = String(rec?.severity ?? "info");
4926
- const blocking = severity === "error" && !isAdvisory(code, message2);
4927
- out.push({ source: "lint", code, message: message2, severity: blocking ? "blocking" : "warning" });
4737
+ const blocking = severity === "error" && !isAdvisory(code, message);
4738
+ out.push({ source: "lint", code, message, severity: blocking ? "blocking" : "warning" });
4928
4739
  }
4929
4740
  return out;
4930
4741
  }
@@ -4936,9 +4747,9 @@ function classifyInspect(json) {
4936
4747
  for (const iss of issues) {
4937
4748
  const rec = iss;
4938
4749
  const code = String(rec?.code ?? rec?.type ?? "overflow");
4939
- const message2 = String(rec?.message ?? rec?.detail ?? JSON.stringify(iss));
4750
+ const message = String(rec?.message ?? rec?.detail ?? JSON.stringify(iss));
4940
4751
  const severity = rec?.severity ? String(rec.severity) : obj?.ok === false ? "error" : "warning";
4941
- out.push({ source: "inspect", code, message: message2, severity: severity === "error" ? "blocking" : "warning" });
4752
+ out.push({ source: "inspect", code, message, severity: severity === "error" ? "blocking" : "warning" });
4942
4753
  }
4943
4754
  return out;
4944
4755
  }
@@ -5383,7 +5194,7 @@ async function buildSubstitutionValues(compositionParams, meta, duration) {
5383
5194
  }
5384
5195
  function coerceImageParam(value) {
5385
5196
  if (typeof value === "string") return Promise.resolve(value);
5386
- if (isAssetRefLike2(value)) return refToUrl(value);
5197
+ if (isAssetRefLike(value)) return refToUrl(value);
5387
5198
  throw new Error("hyperframe_render: image param must be a URL string or AssetRef");
5388
5199
  }
5389
5200
  async function substituteCompositionFiles(tmp, values) {
@@ -5613,7 +5424,7 @@ async function buildSubstitutionValues2(compositionParams, meta) {
5613
5424
  }
5614
5425
  function coerceImageParam2(value) {
5615
5426
  if (typeof value === "string") return Promise.resolve(value);
5616
- if (isAssetRefLike2(value)) return refToUrl(value);
5427
+ if (isAssetRefLike(value)) return refToUrl(value);
5617
5428
  throw new Error("hyperframe_snapshot: image param must be a URL string or AssetRef");
5618
5429
  }
5619
5430
  async function substituteCompositionFiles2(tmp, values) {
@@ -6639,29 +6450,17 @@ function createEngineFromEnv(opts = {}) {
6639
6450
  const cacheDir = opts.cacheDir ?? path15.join(cwd, "canvas", ".cache");
6640
6451
  const outputsDir = opts.outputsDir ?? path15.join(cwd, "canvas");
6641
6452
  const creds = requireCredentialsFromEnv();
6642
- const client = new BackendClient({ baseUrl: creds.url, apiKey: creds.apiKey });
6643
- const assets = new LocalAssetStore(path15.join(cacheDir, "assets"));
6644
- const localCache = new LocalCacheStore(path15.join(cacheDir, "index"));
6645
- const remoteCacheEnabled = opts.remoteCache ?? remoteCacheEnabledFromEnv();
6646
- const cache = remoteCacheEnabled ? new LayeredCacheStore({
6647
- local: localCache,
6648
- remote: new RemoteCacheStore(client, opts.log),
6649
- assets,
6650
- log: opts.log
6651
- }) : localCache;
6652
6453
  return new Engine({
6653
6454
  registry: defaultRegistry(),
6654
- client,
6655
- assets,
6656
- cache,
6455
+ client: new BackendClient({ baseUrl: creds.url, apiKey: creds.apiKey }),
6456
+ assets: new LocalAssetStore(path15.join(cacheDir, "assets")),
6457
+ cache: new LocalCacheStore(path15.join(cacheDir, "index")),
6657
6458
  outputsDir,
6658
- log: opts.log,
6659
- persistAssets: remoteCacheEnabled
6459
+ log: opts.log
6660
6460
  });
6661
6461
  }
6662
6462
 
6663
6463
  export {
6664
- requireCredentialsFromEnv,
6665
6464
  LayerExecutionError,
6666
6465
  describeFailureReason,
6667
6466
  SEEDANCE_DURATIONS,
@@ -6669,10 +6468,6 @@ export {
6669
6468
  IMAGE_GENERATE_MODELS,
6670
6469
  MODEL_REGISTRY,
6671
6470
  resolveConcurrency,
6672
- ulid,
6673
- isPersistedAssetRef,
6674
- collectAssetRefLikes,
6675
- sha256Hex,
6676
6471
  BackendClient2 as BackendClient,
6677
6472
  Engine2 as Engine,
6678
6473
  LocalAssetStore2 as LocalAssetStore,
@@ -6683,4 +6478,4 @@ export {
6683
6478
  defaultRegistry,
6684
6479
  createEngineFromEnv
6685
6480
  };
6686
- //# sourceMappingURL=chunk-OCMOQOIJ.js.map
6481
+ //# sourceMappingURL=chunk-KBWQRZL2.js.map