@koda-sl/baker-cli 0.121.0-dev.6fedecad2 → 0.121.0-dev.775026ddd
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 +43 -83
- package/dist/{chunk-MWFJ5NOP.js → chunk-GQIOFHVI.js} +275 -132
- package/dist/chunk-GQIOFHVI.js.map +1 -0
- package/dist/cli.js +2669 -4244
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.d.ts +30 -1
- package/dist/engine/index.js +1 -2
- package/package.json +1 -1
- package/dist/chunk-5WRI5ZAA.js +0 -31
- package/dist/chunk-5WRI5ZAA.js.map +0 -1
- package/dist/chunk-AVJ3B6LC.js +0 -97
- package/dist/chunk-AVJ3B6LC.js.map +0 -1
- package/dist/chunk-ISFSUDEQ.js +0 -264
- package/dist/chunk-ISFSUDEQ.js.map +0 -1
- package/dist/chunk-K47Q73CK.js +0 -156
- package/dist/chunk-K47Q73CK.js.map +0 -1
- package/dist/chunk-MWFJ5NOP.js.map +0 -1
- package/dist/chunk-YTEAWSEM.js +0 -39
- package/dist/chunk-YTEAWSEM.js.map +0 -1
- package/dist/client-PGOTU24X.js +0 -15
- package/dist/client-PGOTU24X.js.map +0 -1
- package/dist/env-TD4VXCQ7.js +0 -10
- package/dist/env-TD4VXCQ7.js.map +0 -1
- package/dist/output-2LGBISBQ.js +0 -18
- package/dist/output-2LGBISBQ.js.map +0 -1
- package/dist/shared-CQC3YRBA.js +0 -23
- package/dist/shared-CQC3YRBA.js.map +0 -1
|
@@ -1,7 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
+
));
|
|
5
26
|
|
|
6
27
|
// ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/810146e81bae4e3a061fe487864f2fde80c4b03b886877dc0f1fffbc6480b67e/node_modules/safe-stable-stringify/index.js
|
|
7
28
|
var require_safe_stable_stringify = __commonJS({
|
|
@@ -138,9 +159,9 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
138
159
|
}
|
|
139
160
|
if (value) {
|
|
140
161
|
return (value2) => {
|
|
141
|
-
let
|
|
142
|
-
if (typeof value2 !== "function")
|
|
143
|
-
throw new Error(
|
|
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);
|
|
144
165
|
};
|
|
145
166
|
}
|
|
146
167
|
}
|
|
@@ -652,6 +673,9 @@ var HttpClient = class {
|
|
|
652
673
|
async postJson(path16, body, signal) {
|
|
653
674
|
return await this.requestJson("POST", path16, body, signal);
|
|
654
675
|
}
|
|
676
|
+
async putJson(path16, body, signal) {
|
|
677
|
+
return await this.requestJson("PUT", path16, body, signal);
|
|
678
|
+
}
|
|
655
679
|
async getJson(path16, signal) {
|
|
656
680
|
return await this.requestJson("GET", path16, void 0, signal);
|
|
657
681
|
}
|
|
@@ -679,8 +703,8 @@ var HttpClient = class {
|
|
|
679
703
|
try {
|
|
680
704
|
const res = await this.fetchFn(url, {
|
|
681
705
|
method,
|
|
682
|
-
headers: method === "
|
|
683
|
-
body: 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),
|
|
684
708
|
signal: controller.signal
|
|
685
709
|
});
|
|
686
710
|
if (res.ok) return { kind: "value", value: await res.json() };
|
|
@@ -717,33 +741,33 @@ async function parseErrorBody(res) {
|
|
|
717
741
|
const errObj = body.error ?? {};
|
|
718
742
|
return classifyHttpError(res.status, errObj, errObj.message ?? `HTTP ${res.status}`);
|
|
719
743
|
}
|
|
720
|
-
function classifyHttpError(status, errObj,
|
|
744
|
+
function classifyHttpError(status, errObj, message2) {
|
|
721
745
|
if (errObj.code === CONTENT_POLICY_CODE) {
|
|
722
|
-
return { kind: "content_policy", status, provider: errObj.provider, message };
|
|
746
|
+
return { kind: "content_policy", status, provider: errObj.provider, message: message2 };
|
|
723
747
|
}
|
|
724
748
|
if (status === 401 || status === 403) {
|
|
725
|
-
return { kind: "unauthorized", status, message };
|
|
749
|
+
return { kind: "unauthorized", status, message: message2 };
|
|
726
750
|
}
|
|
727
751
|
if (status === 400 || status === 422) {
|
|
728
|
-
return { kind: "validation", status, message, details: errObj.details };
|
|
752
|
+
return { kind: "validation", status, message: message2, details: errObj.details };
|
|
729
753
|
}
|
|
730
754
|
if (status === 502 || status === 504) {
|
|
731
755
|
if (errObj.code === "provider_timeout" || status === 504) {
|
|
732
|
-
return { kind: "timeout", provider: errObj.provider, message };
|
|
756
|
+
return { kind: "timeout", provider: errObj.provider, message: message2 };
|
|
733
757
|
}
|
|
734
758
|
return {
|
|
735
759
|
kind: "provider",
|
|
736
760
|
status,
|
|
737
761
|
provider: errObj.provider,
|
|
738
762
|
code: errObj.code ?? "provider_error",
|
|
739
|
-
message,
|
|
763
|
+
message: message2,
|
|
740
764
|
retryable: errObj.retryable ?? true
|
|
741
765
|
};
|
|
742
766
|
}
|
|
743
767
|
if (status >= 500 || status === 429) {
|
|
744
|
-
return { kind: "server", status, message };
|
|
768
|
+
return { kind: "server", status, message: message2 };
|
|
745
769
|
}
|
|
746
|
-
return { kind: "validation", status, message, details: errObj.details };
|
|
770
|
+
return { kind: "validation", status, message: message2, details: errObj.details };
|
|
747
771
|
}
|
|
748
772
|
function backoffMs(attempt) {
|
|
749
773
|
return 1e3 * 2 ** attempt;
|
|
@@ -814,6 +838,27 @@ var BackendClient = class {
|
|
|
814
838
|
signal
|
|
815
839
|
);
|
|
816
840
|
}
|
|
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
|
+
}
|
|
817
862
|
getArtifact(kind, name, version, signal) {
|
|
818
863
|
const path16 = version ? `/api/canvas/artifacts/${encodeURIComponent(kind)}/${encodeURIComponent(name)}/${encodeURIComponent(version)}` : `/api/canvas/artifacts/${encodeURIComponent(kind)}/${encodeURIComponent(name)}`;
|
|
819
864
|
return this.http.getJson(path16, signal);
|
|
@@ -837,14 +882,17 @@ function requireCredentialsFromEnv(env = process.env) {
|
|
|
837
882
|
}
|
|
838
883
|
return c;
|
|
839
884
|
}
|
|
885
|
+
function remoteCacheEnabledFromEnv(env = process.env) {
|
|
886
|
+
return env.BAKER_CANVAS_REMOTE_CACHE !== "off";
|
|
887
|
+
}
|
|
840
888
|
|
|
841
889
|
// src/engine/engine/errors.ts
|
|
842
890
|
function isBlocking(issue) {
|
|
843
891
|
return issue.severity !== "warning";
|
|
844
892
|
}
|
|
845
893
|
var CanvasError = class extends Error {
|
|
846
|
-
constructor(
|
|
847
|
-
super(
|
|
894
|
+
constructor(message2) {
|
|
895
|
+
super(message2);
|
|
848
896
|
this.name = "CanvasError";
|
|
849
897
|
}
|
|
850
898
|
};
|
|
@@ -1562,6 +1610,160 @@ function encodeRandom() {
|
|
|
1562
1610
|
return out;
|
|
1563
1611
|
}
|
|
1564
1612
|
|
|
1613
|
+
// src/engine/storage/remote-cache-store.ts
|
|
1614
|
+
var CANVAS_ASSETS_URL_SEGMENT = "/canvas-assets/";
|
|
1615
|
+
function isPersistedAssetRef(ref) {
|
|
1616
|
+
const { url, sha256 } = ref;
|
|
1617
|
+
if (typeof url !== "string" || typeof sha256 !== "string") return false;
|
|
1618
|
+
return url.includes(`${CANVAS_ASSETS_URL_SEGMENT}${sha256.slice(0, 2)}/${sha256}`) || url.includes(`${CANVAS_ASSETS_URL_SEGMENT}${sha256}`);
|
|
1619
|
+
}
|
|
1620
|
+
function isAssetRefLike(value) {
|
|
1621
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && typeof value.sha256 === "string" && typeof value.mime === "string";
|
|
1622
|
+
}
|
|
1623
|
+
function collectAssetRefLikes(value, out = []) {
|
|
1624
|
+
if (Array.isArray(value)) {
|
|
1625
|
+
for (const item of value) collectAssetRefLikes(item, out);
|
|
1626
|
+
return out;
|
|
1627
|
+
}
|
|
1628
|
+
if (typeof value !== "object" || value === null) return out;
|
|
1629
|
+
if (isAssetRefLike(value)) {
|
|
1630
|
+
out.push(value);
|
|
1631
|
+
}
|
|
1632
|
+
for (const item of Object.values(value)) collectAssetRefLikes(item, out);
|
|
1633
|
+
return out;
|
|
1634
|
+
}
|
|
1635
|
+
function entryFullyPersisted(entry) {
|
|
1636
|
+
return collectAssetRefLikes(entry.outputs).every((ref) => isPersistedAssetRef(ref));
|
|
1637
|
+
}
|
|
1638
|
+
function stripLocalFields(entry) {
|
|
1639
|
+
const clone = JSON.parse(JSON.stringify(entry));
|
|
1640
|
+
for (const ref of collectAssetRefLikes(clone.outputs)) {
|
|
1641
|
+
delete ref.path;
|
|
1642
|
+
delete ref.bytes;
|
|
1643
|
+
}
|
|
1644
|
+
return clone;
|
|
1645
|
+
}
|
|
1646
|
+
var RemoteCacheStore = class {
|
|
1647
|
+
client;
|
|
1648
|
+
log;
|
|
1649
|
+
constructor(client, log) {
|
|
1650
|
+
this.client = client;
|
|
1651
|
+
this.log = log ?? (() => void 0);
|
|
1652
|
+
}
|
|
1653
|
+
async get(cacheKey) {
|
|
1654
|
+
return await this.client.getCacheEntry(cacheKey);
|
|
1655
|
+
}
|
|
1656
|
+
async put(entry) {
|
|
1657
|
+
if (!entryFullyPersisted(entry)) {
|
|
1658
|
+
this.log(`[cache ] ${entry.cacheKey.slice(0, 12)}\u2026 has local-only assets, kept local`);
|
|
1659
|
+
return;
|
|
1660
|
+
}
|
|
1661
|
+
const stripped = stripLocalFields(entry);
|
|
1662
|
+
if (stripped.refs.length > MAX_REMOTE_REFS) {
|
|
1663
|
+
stripped.refs = stripped.refs.slice(0, MAX_REMOTE_REFS);
|
|
1664
|
+
}
|
|
1665
|
+
await this.client.putCacheEntry(stripped);
|
|
1666
|
+
}
|
|
1667
|
+
};
|
|
1668
|
+
var MAX_REMOTE_REFS = 512;
|
|
1669
|
+
var LayeredCacheStore = class {
|
|
1670
|
+
rootDir;
|
|
1671
|
+
local;
|
|
1672
|
+
remote;
|
|
1673
|
+
assets;
|
|
1674
|
+
log;
|
|
1675
|
+
constructor(opts) {
|
|
1676
|
+
this.local = opts.local;
|
|
1677
|
+
this.remote = opts.remote;
|
|
1678
|
+
this.assets = opts.assets;
|
|
1679
|
+
this.rootDir = opts.local.rootDir;
|
|
1680
|
+
this.log = opts.log ?? (() => void 0);
|
|
1681
|
+
}
|
|
1682
|
+
async get(cacheKey) {
|
|
1683
|
+
const localHit = await this.local.get(cacheKey);
|
|
1684
|
+
if (localHit) return localHit;
|
|
1685
|
+
let remoteEntry;
|
|
1686
|
+
try {
|
|
1687
|
+
remoteEntry = await this.remote.get(cacheKey);
|
|
1688
|
+
} catch (e) {
|
|
1689
|
+
this.log(`[cache ] remote lookup failed (${message(e)}) \u2014 treating as miss`);
|
|
1690
|
+
return null;
|
|
1691
|
+
}
|
|
1692
|
+
if (!remoteEntry) return null;
|
|
1693
|
+
let rehydrated;
|
|
1694
|
+
try {
|
|
1695
|
+
rehydrated = await this.rehydrate(remoteEntry);
|
|
1696
|
+
} catch (e) {
|
|
1697
|
+
this.log(`[cache ] ${cacheKey.slice(0, 12)}\u2026 rehydration failed (${message(e)}) \u2014 treating as miss`);
|
|
1698
|
+
return null;
|
|
1699
|
+
}
|
|
1700
|
+
await this.local.put(rehydrated);
|
|
1701
|
+
return rehydrated;
|
|
1702
|
+
}
|
|
1703
|
+
async put(entry) {
|
|
1704
|
+
await this.local.put(entry);
|
|
1705
|
+
try {
|
|
1706
|
+
await this.remote.put(entry);
|
|
1707
|
+
} catch (e) {
|
|
1708
|
+
this.log(`[cache ] remote write failed (${message(e)}) \u2014 entry kept local`);
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
/**
|
|
1712
|
+
* Download every referenced asset into the local content-addressed store
|
|
1713
|
+
* (sha-verified) and stamp fresh local paths. Any ref that cannot be
|
|
1714
|
+
* rehydrated fails the WHOLE entry — a partially-hydrated cache hit would
|
|
1715
|
+
* crash materialization later with a far less actionable error.
|
|
1716
|
+
*/
|
|
1717
|
+
async rehydrate(entry) {
|
|
1718
|
+
const clone = JSON.parse(JSON.stringify(entry));
|
|
1719
|
+
for (const ref of collectAssetRefLikes(clone.outputs)) {
|
|
1720
|
+
if (!isPersistedAssetRef(ref)) {
|
|
1721
|
+
throw new Error(`ref ${ref.sha256.slice(0, 12)}\u2026 has no persisted url`);
|
|
1722
|
+
}
|
|
1723
|
+
const ingested = await this.assets.ingestRemote({
|
|
1724
|
+
kind: typeof ref.kind === "string" ? ref.kind : "json",
|
|
1725
|
+
url: ref.url,
|
|
1726
|
+
sha256: ref.sha256,
|
|
1727
|
+
mime: ref.mime,
|
|
1728
|
+
metadata: ref.metadata ?? void 0
|
|
1729
|
+
});
|
|
1730
|
+
ref.path = ingested.path;
|
|
1731
|
+
}
|
|
1732
|
+
return clone;
|
|
1733
|
+
}
|
|
1734
|
+
};
|
|
1735
|
+
function message(e) {
|
|
1736
|
+
return e instanceof Error ? e.message : String(e);
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
// src/engine/nodes/remote/upload.ts
|
|
1740
|
+
async function presignAndPut(args) {
|
|
1741
|
+
const { putUrl, publicUrl } = await args.ctx.client.presignAssetUpload(args.sha256, args.mime, args.ctx.signal);
|
|
1742
|
+
const putRes = await fetch(putUrl, {
|
|
1743
|
+
method: "PUT",
|
|
1744
|
+
body: new Uint8Array(args.bytes),
|
|
1745
|
+
headers: { "Content-Type": args.mime },
|
|
1746
|
+
signal: args.ctx.signal
|
|
1747
|
+
});
|
|
1748
|
+
if (!putRes.ok) {
|
|
1749
|
+
throw new Error(`upload: presigned PUT failed ${putRes.status} ${putRes.statusText}`);
|
|
1750
|
+
}
|
|
1751
|
+
return publicUrl;
|
|
1752
|
+
}
|
|
1753
|
+
async function ensureUploaded(ref, ctx) {
|
|
1754
|
+
if (ref.url) return ref;
|
|
1755
|
+
const bytes = await ctx.assets.readBytes(ref.sha256, ref.mime);
|
|
1756
|
+
const url = await presignAndPut({ bytes, sha256: ref.sha256, mime: ref.mime, ctx });
|
|
1757
|
+
return { ...ref, url };
|
|
1758
|
+
}
|
|
1759
|
+
async function persistOutputAssetUrls(outputs, ctx) {
|
|
1760
|
+
for (const ref of collectAssetRefLikes(outputs)) {
|
|
1761
|
+
if (isPersistedAssetRef(ref)) continue;
|
|
1762
|
+
const bytes = await ctx.assets.readBytes(ref.sha256, ref.mime);
|
|
1763
|
+
ref.url = await presignAndPut({ bytes, sha256: ref.sha256, mime: ref.mime, ctx });
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1565
1767
|
// src/engine/schema/canvas.ts
|
|
1566
1768
|
import { z } from "zod";
|
|
1567
1769
|
var REF_PREFIX = "$ref:";
|
|
@@ -1623,11 +1825,7 @@ var VideoMeta = z.object({
|
|
|
1623
1825
|
// Advisory: the scene's visual length vs the estimated spoken length, so
|
|
1624
1826
|
// a reviewer can see a native line that may run past its cut. Not gated.
|
|
1625
1827
|
scene_s: z.number().optional(),
|
|
1626
|
-
est_speech_s: z.number().optional()
|
|
1627
|
-
// Word count of the line est_speech_s was measured for. Together they carry
|
|
1628
|
-
// the speaker's OBSERVED pace (from the deconstruct's word timings), so the
|
|
1629
|
-
// overrun check budgets re-authored lines at the real rate, not a wps guess.
|
|
1630
|
-
speech_words: z.number().optional()
|
|
1828
|
+
est_speech_s: z.number().optional()
|
|
1631
1829
|
}),
|
|
1632
1830
|
z.object({ scene: z.number(), lipsync_node: z.string() })
|
|
1633
1831
|
])
|
|
@@ -2157,9 +2355,7 @@ var STAGE_CODES = {
|
|
|
2157
2355
|
SPEECH_OVERRUN: "VIDEO_SPEECH_OVERRUN",
|
|
2158
2356
|
ASPECT_MISMATCH: "VIDEO_ASPECT_MISMATCH",
|
|
2159
2357
|
REFERENCE_MISSING: "VIDEO_REFERENCE_MISSING",
|
|
2160
|
-
SPAN_EXCEEDS_MODEL: "VIDEO_SPAN_EXCEEDS_MODEL"
|
|
2161
|
-
UI_IN_PROMPT: "VIDEO_UI_IN_PROMPT",
|
|
2162
|
-
BRANDMARK_IN_PROMPT: "VIDEO_BRANDMARK_IN_PROMPT"
|
|
2358
|
+
SPAN_EXCEEDS_MODEL: "VIDEO_SPAN_EXCEEDS_MODEL"
|
|
2163
2359
|
};
|
|
2164
2360
|
var SPAN_MODEL_SLACK_S = 0.25;
|
|
2165
2361
|
var VIDEO_TIME_SLACK_S = 0.75;
|
|
@@ -2538,8 +2734,6 @@ function checkVideoInvariants(ctx) {
|
|
|
2538
2734
|
}
|
|
2539
2735
|
checkSpeechOverrun(ctx, meta.talking_scenes);
|
|
2540
2736
|
checkAspectConsistency(ctx);
|
|
2541
|
-
checkUiInPrompt(ctx);
|
|
2542
|
-
checkBrandmarkInPrompt(ctx);
|
|
2543
2737
|
checkReferenceCompleteness(ctx, meta);
|
|
2544
2738
|
checkClipSpanFitsModel(ctx, meta);
|
|
2545
2739
|
}
|
|
@@ -2569,30 +2763,18 @@ function keywordTokens(text) {
|
|
|
2569
2763
|
if (!text) return [];
|
|
2570
2764
|
return text.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length >= 3 && !KEYWORD_STOPWORDS.has(t));
|
|
2571
2765
|
}
|
|
2572
|
-
function elementMentionKeywords(el) {
|
|
2573
|
-
const typeWords = ELEMENT_TYPE_KEYWORDS[el.type.toLowerCase()] ?? [];
|
|
2574
|
-
return [.../* @__PURE__ */ new Set([...typeWords, ...keywordTokens(el.label), ...keywordTokens(el.description)])];
|
|
2575
|
-
}
|
|
2576
2766
|
function keywordsForElement(el) {
|
|
2577
|
-
|
|
2767
|
+
const type = el.type.toLowerCase();
|
|
2768
|
+
const typeWords = ELEMENT_TYPE_KEYWORDS[type] ?? [];
|
|
2769
|
+
return [.../* @__PURE__ */ new Set([...typeWords, ...keywordTokens(el.label), ...keywordTokens(el.description)])];
|
|
2578
2770
|
}
|
|
2579
2771
|
function containsWord(text, word) {
|
|
2580
2772
|
const esc = word.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2581
2773
|
return new RegExp(`\\b${esc}\\b`, "i").test(text);
|
|
2582
2774
|
}
|
|
2583
|
-
var FRAME_DESCRIPTION_START = "FRAME DESCRIPTION (this frame's editable prompt):";
|
|
2584
|
-
var FRAME_DESCRIPTION_END = "Render exactly what the FRAME DESCRIPTION";
|
|
2585
|
-
function frameDescriptionOf(prompt) {
|
|
2586
|
-
const i = prompt.indexOf(FRAME_DESCRIPTION_START);
|
|
2587
|
-
if (i < 0) return prompt;
|
|
2588
|
-
const rest = prompt.slice(i + FRAME_DESCRIPTION_START.length);
|
|
2589
|
-
const j = rest.indexOf(FRAME_DESCRIPTION_END);
|
|
2590
|
-
return j < 0 ? rest : rest.slice(0, j);
|
|
2591
|
-
}
|
|
2592
2775
|
function checkFrameReferences(ctx, node, index, keyworded) {
|
|
2593
|
-
const
|
|
2594
|
-
if (typeof
|
|
2595
|
-
const prompt = frameDescriptionOf(rawPrompt);
|
|
2776
|
+
const prompt = node.params?.prompt;
|
|
2777
|
+
if (typeof prompt !== "string" || prompt.length === 0) return;
|
|
2596
2778
|
const inputsBlob = JSON.stringify(node.inputs ?? {});
|
|
2597
2779
|
for (const { el, keywords } of keyworded) {
|
|
2598
2780
|
if (inputsBlob.includes(el.ref)) continue;
|
|
@@ -2642,24 +2824,13 @@ function checkClipSpanFitsModel(ctx, meta) {
|
|
|
2642
2824
|
});
|
|
2643
2825
|
}
|
|
2644
2826
|
}
|
|
2645
|
-
|
|
2646
|
-
var OBSERVED_WPS_MAX = 6;
|
|
2647
|
-
function secondsPerWord(stamped) {
|
|
2648
|
-
const est = stamped?.est_speech_s;
|
|
2649
|
-
const words = stamped?.speech_words;
|
|
2650
|
-
if (est && words && est > 0 && words > 0) {
|
|
2651
|
-
const wps = words / est;
|
|
2652
|
-
if (wps >= OBSERVED_WPS_MIN && wps <= OBSERVED_WPS_MAX) return est / words;
|
|
2653
|
-
}
|
|
2654
|
-
return 1 / SPEECH_WORDS_PER_SECOND;
|
|
2655
|
-
}
|
|
2656
|
-
function speechOverrunOf(node, secPerWord) {
|
|
2827
|
+
function speechOverrunOf(node) {
|
|
2657
2828
|
const params = node.params;
|
|
2658
2829
|
if (params?.generate_audio !== true) return null;
|
|
2659
2830
|
const line = nativeDialogueOf(params.prompt);
|
|
2660
2831
|
const duration = typeof params.duration === "number" ? params.duration : void 0;
|
|
2661
2832
|
if (!line || !duration) return null;
|
|
2662
|
-
const estSpeechS = line.split(/\s+/).filter(Boolean).length
|
|
2833
|
+
const estSpeechS = line.split(/\s+/).filter(Boolean).length / SPEECH_WORDS_PER_SECOND;
|
|
2663
2834
|
return estSpeechS > duration * SPEECH_OVERRUN_RATIO ? { estSpeechS, duration } : null;
|
|
2664
2835
|
}
|
|
2665
2836
|
function checkSpeechOverrun(ctx, talkingScenes) {
|
|
@@ -2668,7 +2839,7 @@ function checkSpeechOverrun(ctx, talkingScenes) {
|
|
|
2668
2839
|
const nativeClipRe = new RegExp(`^s${entry.scene}(_r\\d+)?_clip$`);
|
|
2669
2840
|
for (const n of ctx.canvas.nodes) {
|
|
2670
2841
|
if (!nativeClipRe.test(n.id) || n.type !== "video_generate") continue;
|
|
2671
|
-
const overrun = speechOverrunOf(n
|
|
2842
|
+
const overrun = speechOverrunOf(n);
|
|
2672
2843
|
if (!overrun) continue;
|
|
2673
2844
|
ctx.issues.push({
|
|
2674
2845
|
path: `nodes[${ctx.idToIndex.get(n.id) ?? -1}].params.prompt`,
|
|
@@ -2678,38 +2849,6 @@ function checkSpeechOverrun(ctx, talkingScenes) {
|
|
|
2678
2849
|
}
|
|
2679
2850
|
}
|
|
2680
2851
|
}
|
|
2681
|
-
var UI_IN_PROMPT_RE = /\bscreen[- ]?(?:recording|capture|grab|share)\b|\bapp (?:interface|screen)\b|\bphone screen overlay\b/i;
|
|
2682
|
-
function checkUiInPrompt(ctx) {
|
|
2683
|
-
for (const n of ctx.canvas.nodes) {
|
|
2684
|
-
if (n.type !== "video_generate") continue;
|
|
2685
|
-
const prompt = n.params?.prompt;
|
|
2686
|
-
if (typeof prompt !== "string" || !UI_IN_PROMPT_RE.test(prompt)) continue;
|
|
2687
|
-
ctx.issues.push({
|
|
2688
|
-
path: `nodes[${ctx.idToIndex.get(n.id) ?? -1}].params.prompt`,
|
|
2689
|
-
code: STAGE_CODES.UI_IN_PROMPT,
|
|
2690
|
-
severity: "warning",
|
|
2691
|
-
message: `"${n.id}" asks the video model to render a screen/UI surface \u2014 generative video garbles UI text and chrome. Composite the real screen on the overlay layer (screenshot / brand HTML) and keep this prompt to the background plate`,
|
|
2692
|
-
node_id: n.id,
|
|
2693
|
-
node_type: "video_generate"
|
|
2694
|
-
});
|
|
2695
|
-
}
|
|
2696
|
-
}
|
|
2697
|
-
var BRANDMARK_IN_PROMPT_RE = /\b(?:logo|wordmark) (?:overlay|animation|sting|card|reveal)\b|\b(?:google|facebook|instagram|tiktok|youtube|amazon|apple|microsoft|whatsapp|netflix|spotify|excel|trustpilot) (?:logo|wordmark|branding)\b/i;
|
|
2698
|
-
function checkBrandmarkInPrompt(ctx) {
|
|
2699
|
-
for (const n of ctx.canvas.nodes) {
|
|
2700
|
-
if (n.type !== "video_generate" && n.type !== "image_generate") continue;
|
|
2701
|
-
const prompt = n.params?.prompt;
|
|
2702
|
-
if (typeof prompt !== "string" || !BRANDMARK_IN_PROMPT_RE.test(prompt)) continue;
|
|
2703
|
-
ctx.issues.push({
|
|
2704
|
-
path: `nodes[${ctx.idToIndex.get(n.id) ?? -1}].params.prompt`,
|
|
2705
|
-
code: STAGE_CODES.BRANDMARK_IN_PROMPT,
|
|
2706
|
-
severity: "warning",
|
|
2707
|
-
message: `"${n.id}" asks the model to render a brand logo/wordmark \u2014 generation garbles marks and third-party logos carry IP exposure. Source the real mark (baker images logo <domain>) and composite it on the overlay layer`,
|
|
2708
|
-
node_id: n.id,
|
|
2709
|
-
node_type: n.type
|
|
2710
|
-
});
|
|
2711
|
-
}
|
|
2712
|
-
}
|
|
2713
2852
|
function checkAspectConsistency(ctx) {
|
|
2714
2853
|
const clips = ctx.canvas.nodes.filter((n) => n.type === "video_generate");
|
|
2715
2854
|
if (clips.length < 2) return;
|
|
@@ -2841,6 +2980,7 @@ var Engine = class {
|
|
|
2841
2980
|
cache;
|
|
2842
2981
|
outputsDir;
|
|
2843
2982
|
log;
|
|
2983
|
+
persistAssets;
|
|
2844
2984
|
constructor(opts) {
|
|
2845
2985
|
this.registry = opts.registry;
|
|
2846
2986
|
this.client = opts.client;
|
|
@@ -2848,6 +2988,7 @@ var Engine = class {
|
|
|
2848
2988
|
this.cache = opts.cache;
|
|
2849
2989
|
this.outputsDir = opts.outputsDir;
|
|
2850
2990
|
this.log = opts.log ?? (() => void 0);
|
|
2991
|
+
this.persistAssets = opts.persistAssets ?? false;
|
|
2851
2992
|
}
|
|
2852
2993
|
validate(canvas) {
|
|
2853
2994
|
return validateCanvas(canvas, this.registry);
|
|
@@ -2894,7 +3035,7 @@ var Engine = class {
|
|
|
2894
3035
|
`[done ] ${stats.cached_nodes}/${stats.total_nodes} cached, ${stats.total_credits} credits, ${stats.duration_ms}ms`
|
|
2895
3036
|
);
|
|
2896
3037
|
this.log(`outputs in: ${writer.runDir}`);
|
|
2897
|
-
return { run_id: runId, output, outputs_by_node: outputs, stats, outputs_dir: writer.runDir };
|
|
3038
|
+
return { run_id: runId, output, outputs_by_node: outputs, stats, outputs_dir: writer.runDir, node_runs: nodeRuns };
|
|
2898
3039
|
}
|
|
2899
3040
|
async runLayers(canvas, outputs, runId, writer, opts, counters, nodeRuns) {
|
|
2900
3041
|
const layers = topologicalLayers(this.pruneToOutput(canvas, buildGraph(canvas)));
|
|
@@ -2991,6 +3132,14 @@ var Engine = class {
|
|
|
2991
3132
|
const credits = def.cost ? def.cost({ params: parsedParams }).credits : 0;
|
|
2992
3133
|
const outputsObj = result;
|
|
2993
3134
|
outputs[node.id] = outputsObj;
|
|
3135
|
+
if (this.persistAssets) {
|
|
3136
|
+
try {
|
|
3137
|
+
await persistOutputAssetUrls(outputsObj, ctx);
|
|
3138
|
+
} catch (e) {
|
|
3139
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
3140
|
+
this.log(`[warn ] ${node.id}: asset persistence failed (${msg}) \u2014 outputs stay local-only`);
|
|
3141
|
+
}
|
|
3142
|
+
}
|
|
2994
3143
|
if (policy === "read_write") {
|
|
2995
3144
|
await this.cache.put({
|
|
2996
3145
|
cacheKey: prepared.cacheKey,
|
|
@@ -3309,27 +3458,6 @@ var FontRef = BaseAssetRef.extend({
|
|
|
3309
3458
|
});
|
|
3310
3459
|
var AssetRef = z4.discriminatedUnion("kind", [ImageRef, VideoRef, AudioRef, JsonRef, TextRef, FontRef]);
|
|
3311
3460
|
|
|
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
|
-
|
|
3333
3461
|
// src/engine/nodes/remote/delegate.ts
|
|
3334
3462
|
function delegated(spec) {
|
|
3335
3463
|
return {
|
|
@@ -3724,10 +3852,10 @@ function inferKindFromMime(mime) {
|
|
|
3724
3852
|
if (mime.startsWith("font/")) return "font";
|
|
3725
3853
|
return null;
|
|
3726
3854
|
}
|
|
3727
|
-
function localExecError(ctx,
|
|
3855
|
+
function localExecError(ctx, message2) {
|
|
3728
3856
|
return new NodeExecutionError(ctx.nodeId, ctx.nodeType, {
|
|
3729
3857
|
kind: "local",
|
|
3730
|
-
cause: new Error(`ingest: ${
|
|
3858
|
+
cause: new Error(`ingest: ${message2}`)
|
|
3731
3859
|
});
|
|
3732
3860
|
}
|
|
3733
3861
|
async function execLocalFile(params, ctx) {
|
|
@@ -4394,7 +4522,7 @@ async function refToUrl(ref) {
|
|
|
4394
4522
|
return `data:${ref.mime};base64,${bytes.toString("base64")}`;
|
|
4395
4523
|
}
|
|
4396
4524
|
var ASSET_KINDS = /* @__PURE__ */ new Set(["image", "video", "audio", "json", "text", "font"]);
|
|
4397
|
-
function
|
|
4525
|
+
function isAssetRefLike2(value) {
|
|
4398
4526
|
if (!value || typeof value !== "object") return false;
|
|
4399
4527
|
const v = value;
|
|
4400
4528
|
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");
|
|
@@ -4766,8 +4894,8 @@ var NEVER_BLOCK = [
|
|
|
4766
4894
|
/text[_-]?occluded/i
|
|
4767
4895
|
];
|
|
4768
4896
|
var UNAVAILABLE = /unknown command|command not found|not found|Did you mean|Unknown argument|ENOENT/i;
|
|
4769
|
-
function isAdvisory(code,
|
|
4770
|
-
const hay = `${code} ${
|
|
4897
|
+
function isAdvisory(code, message2) {
|
|
4898
|
+
const hay = `${code} ${message2}`;
|
|
4771
4899
|
return NEVER_BLOCK.some((re) => re.test(hay));
|
|
4772
4900
|
}
|
|
4773
4901
|
function parseCheckJson(raw) {
|
|
@@ -4795,10 +4923,10 @@ function classifyLint(json) {
|
|
|
4795
4923
|
for (const f of findings) {
|
|
4796
4924
|
const rec = f;
|
|
4797
4925
|
const code = String(rec?.code ?? "");
|
|
4798
|
-
const
|
|
4926
|
+
const message2 = String(rec?.message ?? "");
|
|
4799
4927
|
const severity = String(rec?.severity ?? "info");
|
|
4800
|
-
const blocking = severity === "error" && !isAdvisory(code,
|
|
4801
|
-
out.push({ source: "lint", code, message, severity: blocking ? "blocking" : "warning" });
|
|
4928
|
+
const blocking = severity === "error" && !isAdvisory(code, message2);
|
|
4929
|
+
out.push({ source: "lint", code, message: message2, severity: blocking ? "blocking" : "warning" });
|
|
4802
4930
|
}
|
|
4803
4931
|
return out;
|
|
4804
4932
|
}
|
|
@@ -4810,9 +4938,9 @@ function classifyInspect(json) {
|
|
|
4810
4938
|
for (const iss of issues) {
|
|
4811
4939
|
const rec = iss;
|
|
4812
4940
|
const code = String(rec?.code ?? rec?.type ?? "overflow");
|
|
4813
|
-
const
|
|
4941
|
+
const message2 = String(rec?.message ?? rec?.detail ?? JSON.stringify(iss));
|
|
4814
4942
|
const severity = rec?.severity ? String(rec.severity) : obj?.ok === false ? "error" : "warning";
|
|
4815
|
-
out.push({ source: "inspect", code, message, severity: severity === "error" ? "blocking" : "warning" });
|
|
4943
|
+
out.push({ source: "inspect", code, message: message2, severity: severity === "error" ? "blocking" : "warning" });
|
|
4816
4944
|
}
|
|
4817
4945
|
return out;
|
|
4818
4946
|
}
|
|
@@ -5257,7 +5385,7 @@ async function buildSubstitutionValues(compositionParams, meta, duration) {
|
|
|
5257
5385
|
}
|
|
5258
5386
|
function coerceImageParam(value) {
|
|
5259
5387
|
if (typeof value === "string") return Promise.resolve(value);
|
|
5260
|
-
if (
|
|
5388
|
+
if (isAssetRefLike2(value)) return refToUrl(value);
|
|
5261
5389
|
throw new Error("hyperframe_render: image param must be a URL string or AssetRef");
|
|
5262
5390
|
}
|
|
5263
5391
|
async function substituteCompositionFiles(tmp, values) {
|
|
@@ -5487,7 +5615,7 @@ async function buildSubstitutionValues2(compositionParams, meta) {
|
|
|
5487
5615
|
}
|
|
5488
5616
|
function coerceImageParam2(value) {
|
|
5489
5617
|
if (typeof value === "string") return Promise.resolve(value);
|
|
5490
|
-
if (
|
|
5618
|
+
if (isAssetRefLike2(value)) return refToUrl(value);
|
|
5491
5619
|
throw new Error("hyperframe_snapshot: image param must be a URL string or AssetRef");
|
|
5492
5620
|
}
|
|
5493
5621
|
async function substituteCompositionFiles2(tmp, values) {
|
|
@@ -6513,17 +6641,29 @@ function createEngineFromEnv(opts = {}) {
|
|
|
6513
6641
|
const cacheDir = opts.cacheDir ?? path15.join(cwd, "canvas", ".cache");
|
|
6514
6642
|
const outputsDir = opts.outputsDir ?? path15.join(cwd, "canvas");
|
|
6515
6643
|
const creds = requireCredentialsFromEnv();
|
|
6644
|
+
const client = new BackendClient({ baseUrl: creds.url, apiKey: creds.apiKey });
|
|
6645
|
+
const assets = new LocalAssetStore(path15.join(cacheDir, "assets"));
|
|
6646
|
+
const localCache = new LocalCacheStore(path15.join(cacheDir, "index"));
|
|
6647
|
+
const remoteCacheEnabled = opts.remoteCache ?? remoteCacheEnabledFromEnv();
|
|
6648
|
+
const cache = remoteCacheEnabled ? new LayeredCacheStore({
|
|
6649
|
+
local: localCache,
|
|
6650
|
+
remote: new RemoteCacheStore(client, opts.log),
|
|
6651
|
+
assets,
|
|
6652
|
+
log: opts.log
|
|
6653
|
+
}) : localCache;
|
|
6516
6654
|
return new Engine({
|
|
6517
6655
|
registry: defaultRegistry(),
|
|
6518
|
-
client
|
|
6519
|
-
assets
|
|
6520
|
-
cache
|
|
6656
|
+
client,
|
|
6657
|
+
assets,
|
|
6658
|
+
cache,
|
|
6521
6659
|
outputsDir,
|
|
6522
|
-
log: opts.log
|
|
6660
|
+
log: opts.log,
|
|
6661
|
+
persistAssets: remoteCacheEnabled
|
|
6523
6662
|
});
|
|
6524
6663
|
}
|
|
6525
6664
|
|
|
6526
6665
|
export {
|
|
6666
|
+
requireCredentialsFromEnv,
|
|
6527
6667
|
LayerExecutionError,
|
|
6528
6668
|
describeFailureReason,
|
|
6529
6669
|
SEEDANCE_DURATIONS,
|
|
@@ -6531,7 +6671,10 @@ export {
|
|
|
6531
6671
|
IMAGE_GENERATE_MODELS,
|
|
6532
6672
|
MODEL_REGISTRY,
|
|
6533
6673
|
resolveConcurrency,
|
|
6534
|
-
|
|
6674
|
+
ulid,
|
|
6675
|
+
isPersistedAssetRef,
|
|
6676
|
+
collectAssetRefLikes,
|
|
6677
|
+
sha256Hex,
|
|
6535
6678
|
BackendClient2 as BackendClient,
|
|
6536
6679
|
Engine2 as Engine,
|
|
6537
6680
|
LocalAssetStore2 as LocalAssetStore,
|
|
@@ -6542,4 +6685,4 @@ export {
|
|
|
6542
6685
|
defaultRegistry,
|
|
6543
6686
|
createEngineFromEnv
|
|
6544
6687
|
};
|
|
6545
|
-
//# sourceMappingURL=chunk-
|
|
6688
|
+
//# sourceMappingURL=chunk-GQIOFHVI.js.map
|