@koda-sl/baker-cli 0.120.0-dev.3b02f951b → 0.120.0
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.
- package/README.md +0 -33
- package/dist/{chunk-AWSEBYP4.js → chunk-IWPAXJC3.js} +57 -243
- package/dist/chunk-IWPAXJC3.js.map +1 -0
- package/dist/cli.js +92 -412
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.d.ts +0 -30
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-AWSEBYP4.js.map +0 -1
package/README.md
CHANGED
|
@@ -2661,17 +2661,6 @@ baker canvas run my-canvas.json
|
|
|
2661
2661
|
# single node — that old serial workaround is obsolete.
|
|
2662
2662
|
baker canvas run my-canvas.json --parallel 8
|
|
2663
2663
|
|
|
2664
|
-
# 2c. Runs persist across sandboxes/sessions by default: node results sync to a
|
|
2665
|
-
# company-scoped remote cache (small JSON pointers; bytes stay in R2), so a FRESH
|
|
2666
|
-
# sandbox re-runs an already-computed canvas at zero credits — assets rehydrate
|
|
2667
|
-
# from R2, sha-verified. Every run also posts a durable history record (per-node
|
|
2668
|
-
# outputs, credits, cached/fresh) that powers the dashboard's Creatives
|
|
2669
|
-
# generations timeline. Opt out with --remote-cache off (env
|
|
2670
|
-
# BAKER_CANVAS_REMOTE_CACHE=off) and --no-record. With --remote-cache off,
|
|
2671
|
-
# assets are not uploaded, so a recorded run keeps its stats but has no
|
|
2672
|
-
# browsable outputs — pass --no-record too if you want nothing persisted.
|
|
2673
|
-
baker canvas run my-canvas.json --remote-cache off --no-record
|
|
2674
|
-
|
|
2675
2664
|
# 3. Inspect a finished run (per-node timing, file list, optional video thumbs)
|
|
2676
2665
|
baker canvas inspect <run_id>
|
|
2677
2666
|
|
|
@@ -3983,7 +3972,6 @@ baker canvas run ./reference-ad.video.canvas.json
|
|
|
3983
3972
|
| Flag | Default | Effect |
|
|
3984
3973
|
|---|---|---|
|
|
3985
3974
|
| `--out <path>` | `<video-dir>/<name>.video.canvas.json` | Where to write the canvas (composition is copied alongside). |
|
|
3986
|
-
| `--slug <slug>` | — | Creative slug (lowercase kebab): writes the canvas to `src/creatives/<slug>/<slug>.canvas.json` — the repo convention that attaches every run to the creative's dashboard generation history. `--out` wins over `--slug`. |
|
|
3987
3975
|
| `--frames <mode>` | `generate` | `generate` emits ONE recast keyframe per scene (the original frame is dropped so the dropped `el_*` assets drive identity); `reuse` wires the real extracted first+last frames straight into the clips (faithful, cheaper, no recast). |
|
|
3988
3976
|
| `--ambient` | off | Give silent **b-roll** scenes native diegetic ambient (Seedance `generate_audio`), mixed deep under the music bed. Talking scenes already carry voice; check levels don't muddy the mix before keeping it. |
|
|
3989
3977
|
| `--max-scenes <n>` | all source scenes | **Cost lever that reduces fidelity** — caps the deconstruct, MERGING away every scene beyond the cap (fewer cuts, lost beats). Prints a warning when set; omit it to reproduce every scene. |
|
|
@@ -4025,7 +4013,6 @@ baker canvas run ./static-ad.canvas.json
|
|
|
4025
4013
|
|---|---|---|
|
|
4026
4014
|
| `--context <text>` | — | Known provenance (advertiser, category, market) to ground the describe. |
|
|
4027
4015
|
| `--out <path>` | `<image-dir>/static-ad.canvas.json` (cwd when `<image>` is a URL) | Where to write the canvas (`prompt.json` is written alongside). |
|
|
4028
|
-
| `--slug <slug>` | — | Creative slug (lowercase kebab): writes the canvas to `src/creatives/<slug>/<slug>.canvas.json` — the repo convention that attaches every run to the creative's dashboard generation history. `--out` wins over `--slug`. |
|
|
4029
4016
|
| `--describe-model <id>` | registry default (`~google/gemini-pro-latest`) | Override the `image_describe` model. |
|
|
4030
4017
|
| `--select-model <id>` | registry default (`~google/gemini-flash-latest`) | Override the element-selection `text_generate` model. |
|
|
4031
4018
|
| `--layout-model <id>` | registry default (`~google/gemini-flash-latest`) | Override the global-layout `text_generate` model. |
|
|
@@ -4497,26 +4484,6 @@ import {
|
|
|
4497
4484
|
} from "@koda-sl/baker-cli/engine";
|
|
4498
4485
|
```
|
|
4499
4486
|
|
|
4500
|
-
## Creatives
|
|
4501
|
-
|
|
4502
|
-
Publish an approved canvas render as a first-class Baker creative. The image uploads to the Baker image library (tagged `creative`), a creative record is created/updated, and the command prints the creative reference JSON the dashboard renders in chat.
|
|
4503
|
-
|
|
4504
|
-
```bash
|
|
4505
|
-
baker creatives publish ./canvas/<run_id>/<final>.png --title "Spring Offer 4x5" \
|
|
4506
|
-
--slug spring-offer-4x5 --run-id r_01JXYZ... \
|
|
4507
|
-
--source-reference-url "https://www.facebook.com/ads/library/?id=..."
|
|
4508
|
-
```
|
|
4509
|
-
|
|
4510
|
-
| Flag | Effect |
|
|
4511
|
-
|---|---|
|
|
4512
|
-
| `--title <text>` | Required. Human title for the creative. |
|
|
4513
|
-
| `--slug <slug>` | Creative slug (`src/creatives/<slug>/`) — attaches the image to that creative's row, marks it `published`. |
|
|
4514
|
-
| `--run-id <r_…>` | Pins the approved generation from the creative's run history as the published one. |
|
|
4515
|
-
| `--source-reference-url <url>` | Original reference ad URL, recorded on the creative. |
|
|
4516
|
-
| `--context <text>` | Optional describe context for the uploaded image asset. |
|
|
4517
|
-
|
|
4518
|
-
Without `--slug` the command behaves as before (one creative record per published image). With `--slug` it upserts the repo-convention row — the same one the dashboard's Creatives tab and the `src/creatives/{slug}/` folder describe — so publish, repo sync, and run history all land on a single record regardless of order.
|
|
4519
|
-
|
|
4520
4487
|
## Help & Discovery
|
|
4521
4488
|
|
|
4522
4489
|
Every command supports `--help` for usage info:
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
__toESM
|
|
4
4
|
} from "./chunk-5WRI5ZAA.js";
|
|
5
5
|
|
|
6
|
-
//
|
|
6
|
+
// ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js
|
|
7
7
|
var require_safe_stable_stringify = __commonJS({
|
|
8
|
-
"
|
|
8
|
+
"../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js"(exports, module) {
|
|
9
9
|
"use strict";
|
|
10
10
|
var { hasOwnProperty } = Object.prototype;
|
|
11
11
|
var stringify = configure2();
|
|
@@ -138,9 +138,9 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
138
138
|
}
|
|
139
139
|
if (value) {
|
|
140
140
|
return (value2) => {
|
|
141
|
-
let
|
|
142
|
-
if (typeof value2 !== "function")
|
|
143
|
-
throw new Error(
|
|
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);
|
|
144
144
|
};
|
|
145
145
|
}
|
|
146
146
|
}
|
|
@@ -652,9 +652,6 @@ var HttpClient = class {
|
|
|
652
652
|
async postJson(path16, body, signal) {
|
|
653
653
|
return await this.requestJson("POST", path16, body, signal);
|
|
654
654
|
}
|
|
655
|
-
async putJson(path16, body, signal) {
|
|
656
|
-
return await this.requestJson("PUT", path16, body, signal);
|
|
657
|
-
}
|
|
658
655
|
async getJson(path16, signal) {
|
|
659
656
|
return await this.requestJson("GET", path16, void 0, signal);
|
|
660
657
|
}
|
|
@@ -682,8 +679,8 @@ var HttpClient = class {
|
|
|
682
679
|
try {
|
|
683
680
|
const res = await this.fetchFn(url, {
|
|
684
681
|
method,
|
|
685
|
-
headers: method === "
|
|
686
|
-
body: method === "
|
|
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,
|
|
687
684
|
signal: controller.signal
|
|
688
685
|
});
|
|
689
686
|
if (res.ok) return { kind: "value", value: await res.json() };
|
|
@@ -720,33 +717,33 @@ async function parseErrorBody(res) {
|
|
|
720
717
|
const errObj = body.error ?? {};
|
|
721
718
|
return classifyHttpError(res.status, errObj, errObj.message ?? `HTTP ${res.status}`);
|
|
722
719
|
}
|
|
723
|
-
function classifyHttpError(status, errObj,
|
|
720
|
+
function classifyHttpError(status, errObj, message) {
|
|
724
721
|
if (errObj.code === CONTENT_POLICY_CODE) {
|
|
725
|
-
return { kind: "content_policy", status, provider: errObj.provider, message
|
|
722
|
+
return { kind: "content_policy", status, provider: errObj.provider, message };
|
|
726
723
|
}
|
|
727
724
|
if (status === 401 || status === 403) {
|
|
728
|
-
return { kind: "unauthorized", status, message
|
|
725
|
+
return { kind: "unauthorized", status, message };
|
|
729
726
|
}
|
|
730
727
|
if (status === 400 || status === 422) {
|
|
731
|
-
return { kind: "validation", status, message
|
|
728
|
+
return { kind: "validation", status, message, details: errObj.details };
|
|
732
729
|
}
|
|
733
730
|
if (status === 502 || status === 504) {
|
|
734
731
|
if (errObj.code === "provider_timeout" || status === 504) {
|
|
735
|
-
return { kind: "timeout", provider: errObj.provider, message
|
|
732
|
+
return { kind: "timeout", provider: errObj.provider, message };
|
|
736
733
|
}
|
|
737
734
|
return {
|
|
738
735
|
kind: "provider",
|
|
739
736
|
status,
|
|
740
737
|
provider: errObj.provider,
|
|
741
738
|
code: errObj.code ?? "provider_error",
|
|
742
|
-
message
|
|
739
|
+
message,
|
|
743
740
|
retryable: errObj.retryable ?? true
|
|
744
741
|
};
|
|
745
742
|
}
|
|
746
743
|
if (status >= 500 || status === 429) {
|
|
747
|
-
return { kind: "server", status, message
|
|
744
|
+
return { kind: "server", status, message };
|
|
748
745
|
}
|
|
749
|
-
return { kind: "validation", status, message
|
|
746
|
+
return { kind: "validation", status, message, details: errObj.details };
|
|
750
747
|
}
|
|
751
748
|
function backoffMs(attempt) {
|
|
752
749
|
return 1e3 * 2 ** attempt;
|
|
@@ -817,27 +814,6 @@ var BackendClient = class {
|
|
|
817
814
|
signal
|
|
818
815
|
);
|
|
819
816
|
}
|
|
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
|
-
}
|
|
841
817
|
getArtifact(kind, name, version, signal) {
|
|
842
818
|
const path16 = version ? `/api/canvas/artifacts/${encodeURIComponent(kind)}/${encodeURIComponent(name)}/${encodeURIComponent(version)}` : `/api/canvas/artifacts/${encodeURIComponent(kind)}/${encodeURIComponent(name)}`;
|
|
843
819
|
return this.http.getJson(path16, signal);
|
|
@@ -861,17 +837,14 @@ function requireCredentialsFromEnv(env = process.env) {
|
|
|
861
837
|
}
|
|
862
838
|
return c;
|
|
863
839
|
}
|
|
864
|
-
function remoteCacheEnabledFromEnv(env = process.env) {
|
|
865
|
-
return env.BAKER_CANVAS_REMOTE_CACHE !== "off";
|
|
866
|
-
}
|
|
867
840
|
|
|
868
841
|
// src/engine/engine/errors.ts
|
|
869
842
|
function isBlocking(issue) {
|
|
870
843
|
return issue.severity !== "warning";
|
|
871
844
|
}
|
|
872
845
|
var CanvasError = class extends Error {
|
|
873
|
-
constructor(
|
|
874
|
-
super(
|
|
846
|
+
constructor(message) {
|
|
847
|
+
super(message);
|
|
875
848
|
this.name = "CanvasError";
|
|
876
849
|
}
|
|
877
850
|
};
|
|
@@ -928,7 +901,7 @@ function describeCause(c) {
|
|
|
928
901
|
}
|
|
929
902
|
}
|
|
930
903
|
|
|
931
|
-
//
|
|
904
|
+
// ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/esm/wrapper.js
|
|
932
905
|
var import__ = __toESM(require_safe_stable_stringify(), 1);
|
|
933
906
|
var configure = import__.default.configure;
|
|
934
907
|
var wrapper_default = import__.default;
|
|
@@ -1589,160 +1562,6 @@ function encodeRandom() {
|
|
|
1589
1562
|
return out;
|
|
1590
1563
|
}
|
|
1591
1564
|
|
|
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
|
-
|
|
1746
1565
|
// src/engine/schema/canvas.ts
|
|
1747
1566
|
import { z } from "zod";
|
|
1748
1567
|
var REF_PREFIX = "$ref:";
|
|
@@ -3022,7 +2841,6 @@ var Engine = class {
|
|
|
3022
2841
|
cache;
|
|
3023
2842
|
outputsDir;
|
|
3024
2843
|
log;
|
|
3025
|
-
persistAssets;
|
|
3026
2844
|
constructor(opts) {
|
|
3027
2845
|
this.registry = opts.registry;
|
|
3028
2846
|
this.client = opts.client;
|
|
@@ -3030,7 +2848,6 @@ var Engine = class {
|
|
|
3030
2848
|
this.cache = opts.cache;
|
|
3031
2849
|
this.outputsDir = opts.outputsDir;
|
|
3032
2850
|
this.log = opts.log ?? (() => void 0);
|
|
3033
|
-
this.persistAssets = opts.persistAssets ?? false;
|
|
3034
2851
|
}
|
|
3035
2852
|
validate(canvas) {
|
|
3036
2853
|
return validateCanvas(canvas, this.registry);
|
|
@@ -3077,7 +2894,7 @@ var Engine = class {
|
|
|
3077
2894
|
`[done ] ${stats.cached_nodes}/${stats.total_nodes} cached, ${stats.total_credits} credits, ${stats.duration_ms}ms`
|
|
3078
2895
|
);
|
|
3079
2896
|
this.log(`outputs in: ${writer.runDir}`);
|
|
3080
|
-
return { run_id: runId, output, outputs_by_node: outputs, stats, outputs_dir: writer.runDir
|
|
2897
|
+
return { run_id: runId, output, outputs_by_node: outputs, stats, outputs_dir: writer.runDir };
|
|
3081
2898
|
}
|
|
3082
2899
|
async runLayers(canvas, outputs, runId, writer, opts, counters, nodeRuns) {
|
|
3083
2900
|
const layers = topologicalLayers(this.pruneToOutput(canvas, buildGraph(canvas)));
|
|
@@ -3174,14 +2991,6 @@ var Engine = class {
|
|
|
3174
2991
|
const credits = def.cost ? def.cost({ params: parsedParams }).credits : 0;
|
|
3175
2992
|
const outputsObj = result;
|
|
3176
2993
|
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
|
-
}
|
|
3185
2994
|
if (policy === "read_write") {
|
|
3186
2995
|
await this.cache.put({
|
|
3187
2996
|
cacheKey: prepared.cacheKey,
|
|
@@ -3500,6 +3309,27 @@ var FontRef = BaseAssetRef.extend({
|
|
|
3500
3309
|
});
|
|
3501
3310
|
var AssetRef = z4.discriminatedUnion("kind", [ImageRef, VideoRef, AudioRef, JsonRef, TextRef, FontRef]);
|
|
3502
3311
|
|
|
3312
|
+
// src/engine/nodes/remote/upload.ts
|
|
3313
|
+
async function presignAndPut(args) {
|
|
3314
|
+
const { putUrl, publicUrl } = await args.ctx.client.presignAssetUpload(args.sha256, args.mime, args.ctx.signal);
|
|
3315
|
+
const putRes = await fetch(putUrl, {
|
|
3316
|
+
method: "PUT",
|
|
3317
|
+
body: new Uint8Array(args.bytes),
|
|
3318
|
+
headers: { "Content-Type": args.mime },
|
|
3319
|
+
signal: args.ctx.signal
|
|
3320
|
+
});
|
|
3321
|
+
if (!putRes.ok) {
|
|
3322
|
+
throw new Error(`upload: presigned PUT failed ${putRes.status} ${putRes.statusText}`);
|
|
3323
|
+
}
|
|
3324
|
+
return publicUrl;
|
|
3325
|
+
}
|
|
3326
|
+
async function ensureUploaded(ref, ctx) {
|
|
3327
|
+
if (ref.url) return ref;
|
|
3328
|
+
const bytes = await ctx.assets.readBytes(ref.sha256, ref.mime);
|
|
3329
|
+
const url = await presignAndPut({ bytes, sha256: ref.sha256, mime: ref.mime, ctx });
|
|
3330
|
+
return { ...ref, url };
|
|
3331
|
+
}
|
|
3332
|
+
|
|
3503
3333
|
// src/engine/nodes/remote/delegate.ts
|
|
3504
3334
|
function delegated(spec) {
|
|
3505
3335
|
return {
|
|
@@ -3894,10 +3724,10 @@ function inferKindFromMime(mime) {
|
|
|
3894
3724
|
if (mime.startsWith("font/")) return "font";
|
|
3895
3725
|
return null;
|
|
3896
3726
|
}
|
|
3897
|
-
function localExecError(ctx,
|
|
3727
|
+
function localExecError(ctx, message) {
|
|
3898
3728
|
return new NodeExecutionError(ctx.nodeId, ctx.nodeType, {
|
|
3899
3729
|
kind: "local",
|
|
3900
|
-
cause: new Error(`ingest: ${
|
|
3730
|
+
cause: new Error(`ingest: ${message}`)
|
|
3901
3731
|
});
|
|
3902
3732
|
}
|
|
3903
3733
|
async function execLocalFile(params, ctx) {
|
|
@@ -4564,7 +4394,7 @@ async function refToUrl(ref) {
|
|
|
4564
4394
|
return `data:${ref.mime};base64,${bytes.toString("base64")}`;
|
|
4565
4395
|
}
|
|
4566
4396
|
var ASSET_KINDS = /* @__PURE__ */ new Set(["image", "video", "audio", "json", "text", "font"]);
|
|
4567
|
-
function
|
|
4397
|
+
function isAssetRefLike(value) {
|
|
4568
4398
|
if (!value || typeof value !== "object") return false;
|
|
4569
4399
|
const v = value;
|
|
4570
4400
|
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");
|
|
@@ -4936,8 +4766,8 @@ var NEVER_BLOCK = [
|
|
|
4936
4766
|
/text[_-]?occluded/i
|
|
4937
4767
|
];
|
|
4938
4768
|
var UNAVAILABLE = /unknown command|command not found|not found|Did you mean|Unknown argument|ENOENT/i;
|
|
4939
|
-
function isAdvisory(code,
|
|
4940
|
-
const hay = `${code} ${
|
|
4769
|
+
function isAdvisory(code, message) {
|
|
4770
|
+
const hay = `${code} ${message}`;
|
|
4941
4771
|
return NEVER_BLOCK.some((re) => re.test(hay));
|
|
4942
4772
|
}
|
|
4943
4773
|
function parseCheckJson(raw) {
|
|
@@ -4965,10 +4795,10 @@ function classifyLint(json) {
|
|
|
4965
4795
|
for (const f of findings) {
|
|
4966
4796
|
const rec = f;
|
|
4967
4797
|
const code = String(rec?.code ?? "");
|
|
4968
|
-
const
|
|
4798
|
+
const message = String(rec?.message ?? "");
|
|
4969
4799
|
const severity = String(rec?.severity ?? "info");
|
|
4970
|
-
const blocking = severity === "error" && !isAdvisory(code,
|
|
4971
|
-
out.push({ source: "lint", code, message
|
|
4800
|
+
const blocking = severity === "error" && !isAdvisory(code, message);
|
|
4801
|
+
out.push({ source: "lint", code, message, severity: blocking ? "blocking" : "warning" });
|
|
4972
4802
|
}
|
|
4973
4803
|
return out;
|
|
4974
4804
|
}
|
|
@@ -4980,9 +4810,9 @@ function classifyInspect(json) {
|
|
|
4980
4810
|
for (const iss of issues) {
|
|
4981
4811
|
const rec = iss;
|
|
4982
4812
|
const code = String(rec?.code ?? rec?.type ?? "overflow");
|
|
4983
|
-
const
|
|
4813
|
+
const message = String(rec?.message ?? rec?.detail ?? JSON.stringify(iss));
|
|
4984
4814
|
const severity = rec?.severity ? String(rec.severity) : obj?.ok === false ? "error" : "warning";
|
|
4985
|
-
out.push({ source: "inspect", code, message
|
|
4815
|
+
out.push({ source: "inspect", code, message, severity: severity === "error" ? "blocking" : "warning" });
|
|
4986
4816
|
}
|
|
4987
4817
|
return out;
|
|
4988
4818
|
}
|
|
@@ -5427,7 +5257,7 @@ async function buildSubstitutionValues(compositionParams, meta, duration) {
|
|
|
5427
5257
|
}
|
|
5428
5258
|
function coerceImageParam(value) {
|
|
5429
5259
|
if (typeof value === "string") return Promise.resolve(value);
|
|
5430
|
-
if (
|
|
5260
|
+
if (isAssetRefLike(value)) return refToUrl(value);
|
|
5431
5261
|
throw new Error("hyperframe_render: image param must be a URL string or AssetRef");
|
|
5432
5262
|
}
|
|
5433
5263
|
async function substituteCompositionFiles(tmp, values) {
|
|
@@ -5657,7 +5487,7 @@ async function buildSubstitutionValues2(compositionParams, meta) {
|
|
|
5657
5487
|
}
|
|
5658
5488
|
function coerceImageParam2(value) {
|
|
5659
5489
|
if (typeof value === "string") return Promise.resolve(value);
|
|
5660
|
-
if (
|
|
5490
|
+
if (isAssetRefLike(value)) return refToUrl(value);
|
|
5661
5491
|
throw new Error("hyperframe_snapshot: image param must be a URL string or AssetRef");
|
|
5662
5492
|
}
|
|
5663
5493
|
async function substituteCompositionFiles2(tmp, values) {
|
|
@@ -6683,29 +6513,17 @@ function createEngineFromEnv(opts = {}) {
|
|
|
6683
6513
|
const cacheDir = opts.cacheDir ?? path15.join(cwd, "canvas", ".cache");
|
|
6684
6514
|
const outputsDir = opts.outputsDir ?? path15.join(cwd, "canvas");
|
|
6685
6515
|
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;
|
|
6696
6516
|
return new Engine({
|
|
6697
6517
|
registry: defaultRegistry(),
|
|
6698
|
-
client,
|
|
6699
|
-
assets,
|
|
6700
|
-
cache,
|
|
6518
|
+
client: new BackendClient({ baseUrl: creds.url, apiKey: creds.apiKey }),
|
|
6519
|
+
assets: new LocalAssetStore(path15.join(cacheDir, "assets")),
|
|
6520
|
+
cache: new LocalCacheStore(path15.join(cacheDir, "index")),
|
|
6701
6521
|
outputsDir,
|
|
6702
|
-
log: opts.log
|
|
6703
|
-
persistAssets: remoteCacheEnabled
|
|
6522
|
+
log: opts.log
|
|
6704
6523
|
});
|
|
6705
6524
|
}
|
|
6706
6525
|
|
|
6707
6526
|
export {
|
|
6708
|
-
requireCredentialsFromEnv,
|
|
6709
6527
|
LayerExecutionError,
|
|
6710
6528
|
describeFailureReason,
|
|
6711
6529
|
SEEDANCE_DURATIONS,
|
|
@@ -6713,10 +6531,6 @@ export {
|
|
|
6713
6531
|
IMAGE_GENERATE_MODELS,
|
|
6714
6532
|
MODEL_REGISTRY,
|
|
6715
6533
|
resolveConcurrency,
|
|
6716
|
-
ulid,
|
|
6717
|
-
isPersistedAssetRef,
|
|
6718
|
-
collectAssetRefLikes,
|
|
6719
|
-
sha256Hex,
|
|
6720
6534
|
elementMentionKeywords,
|
|
6721
6535
|
BackendClient2 as BackendClient,
|
|
6722
6536
|
Engine2 as Engine,
|
|
@@ -6728,4 +6542,4 @@ export {
|
|
|
6728
6542
|
defaultRegistry,
|
|
6729
6543
|
createEngineFromEnv
|
|
6730
6544
|
};
|
|
6731
|
-
//# sourceMappingURL=chunk-
|
|
6545
|
+
//# sourceMappingURL=chunk-IWPAXJC3.js.map
|