@koda-sl/baker-cli 0.400.0 → 0.402.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 +41 -2
- package/dist/{chunk-UW62VPTH.js → chunk-X7PLV5QH.js} +211 -116
- package/dist/chunk-X7PLV5QH.js.map +1 -0
- package/dist/cli.js +871 -388
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.d.ts +8 -0
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-UW62VPTH.js.map +0 -1
|
@@ -617,7 +617,7 @@ ${originalIndentation}`;
|
|
|
617
617
|
});
|
|
618
618
|
|
|
619
619
|
// src/engine/index.ts
|
|
620
|
-
import
|
|
620
|
+
import path22 from "path";
|
|
621
621
|
|
|
622
622
|
// src/engine/client/http.ts
|
|
623
623
|
var CONTENT_POLICY_CODE = "content_policy_blocked";
|
|
@@ -667,17 +667,17 @@ var HttpClient = class {
|
|
|
667
667
|
this.fetchFn = opts.fetchFn ?? fetch;
|
|
668
668
|
this.sleepFn = opts.sleepFn ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
669
669
|
}
|
|
670
|
-
async postJson(
|
|
671
|
-
return await this.requestJson("POST",
|
|
670
|
+
async postJson(path23, body, signal) {
|
|
671
|
+
return await this.requestJson("POST", path23, body, signal);
|
|
672
672
|
}
|
|
673
|
-
async putJson(
|
|
674
|
-
return await this.requestJson("PUT",
|
|
673
|
+
async putJson(path23, body, signal) {
|
|
674
|
+
return await this.requestJson("PUT", path23, body, signal);
|
|
675
675
|
}
|
|
676
|
-
async getJson(
|
|
677
|
-
return await this.requestJson("GET",
|
|
676
|
+
async getJson(path23, signal) {
|
|
677
|
+
return await this.requestJson("GET", path23, void 0, signal);
|
|
678
678
|
}
|
|
679
|
-
async requestJson(method,
|
|
680
|
-
const url = `${this.baseUrl}${
|
|
679
|
+
async requestJson(method, path23, body, signal) {
|
|
680
|
+
const url = `${this.baseUrl}${path23.startsWith("/") ? path23 : `/${path23}`}`;
|
|
681
681
|
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
682
682
|
const outcome = await this.attempt(method, url, body, attempt, signal);
|
|
683
683
|
if (outcome.kind === "value") return outcome.value;
|
|
@@ -869,12 +869,12 @@ var BackendClient = class {
|
|
|
869
869
|
}
|
|
870
870
|
async pollJob(jobId, signal) {
|
|
871
871
|
const deadline = Date.now() + JOB_POLL_MAX_MS;
|
|
872
|
-
const
|
|
872
|
+
const path23 = `/api/canvas/jobs/${encodeURIComponent(jobId)}`;
|
|
873
873
|
for (let attempt = 0; ; attempt++) {
|
|
874
874
|
if (signal?.aborted) {
|
|
875
875
|
throw new BackendHttpError({ kind: "network", cause: signal.reason ?? new Error("aborted") });
|
|
876
876
|
}
|
|
877
|
-
const job = await this.http.getJson(
|
|
877
|
+
const job = await this.http.getJson(path23, signal);
|
|
878
878
|
if (job.status === "completed") return job.result;
|
|
879
879
|
if (job.status === "failed") throw failedJobError(job.error);
|
|
880
880
|
if (Date.now() > deadline) {
|
|
@@ -953,8 +953,8 @@ var BackendClient = class {
|
|
|
953
953
|
await this.http.postJson("/api/creatives/definition", payload, signal);
|
|
954
954
|
}
|
|
955
955
|
getArtifact(kind, name, version, signal) {
|
|
956
|
-
const
|
|
957
|
-
return this.http.getJson(
|
|
956
|
+
const path23 = version ? `/api/canvas/artifacts/${encodeURIComponent(kind)}/${encodeURIComponent(name)}/${encodeURIComponent(version)}` : `/api/canvas/artifacts/${encodeURIComponent(kind)}/${encodeURIComponent(name)}`;
|
|
957
|
+
return this.http.getJson(path23, signal);
|
|
958
958
|
}
|
|
959
959
|
};
|
|
960
960
|
|
|
@@ -3279,17 +3279,17 @@ async function mapWithConcurrency(items, limit, fn) {
|
|
|
3279
3279
|
function isContainerObject(value) {
|
|
3280
3280
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
3281
3281
|
}
|
|
3282
|
-
function forEachString(value, visit,
|
|
3282
|
+
function forEachString(value, visit, path23 = "") {
|
|
3283
3283
|
if (typeof value === "string") {
|
|
3284
|
-
visit(value,
|
|
3284
|
+
visit(value, path23);
|
|
3285
3285
|
return;
|
|
3286
3286
|
}
|
|
3287
3287
|
if (Array.isArray(value)) {
|
|
3288
|
-
for (let i = 0; i < value.length; i++) forEachString(value[i], visit,
|
|
3288
|
+
for (let i = 0; i < value.length; i++) forEachString(value[i], visit, path23 ? `${path23}[${i}]` : `[${i}]`);
|
|
3289
3289
|
return;
|
|
3290
3290
|
}
|
|
3291
3291
|
if (isContainerObject(value)) {
|
|
3292
|
-
for (const [k, v] of Object.entries(value)) forEachString(v, visit,
|
|
3292
|
+
for (const [k, v] of Object.entries(value)) forEachString(v, visit, path23 ? `${path23}.${k}` : k);
|
|
3293
3293
|
}
|
|
3294
3294
|
}
|
|
3295
3295
|
function forEachObject(value, visit) {
|
|
@@ -4282,6 +4282,7 @@ function nodesBeforeCheckpoint(graph, types, stopKinds) {
|
|
|
4282
4282
|
}
|
|
4283
4283
|
|
|
4284
4284
|
// src/engine/engine/validator.ts
|
|
4285
|
+
import path5 from "path";
|
|
4285
4286
|
import { z as z5 } from "zod";
|
|
4286
4287
|
|
|
4287
4288
|
// src/engine/lib/url.ts
|
|
@@ -5731,6 +5732,7 @@ async function validateCanvasDeep(input, registry) {
|
|
|
5731
5732
|
const issues = [];
|
|
5732
5733
|
const ctx = { canvas, registry, issues, idToIndex: buildIdToIndex(canvas) };
|
|
5733
5734
|
const inputKindOf = (value) => staticInputKind(ctx, value);
|
|
5735
|
+
const inputSourceOf = (value) => staticInputSource(ctx, value);
|
|
5734
5736
|
for (let i = 0; i < canvas.nodes.length; i++) {
|
|
5735
5737
|
const n = canvas.nodes[i];
|
|
5736
5738
|
if (!n) continue;
|
|
@@ -5738,7 +5740,13 @@ async function validateCanvasDeep(input, registry) {
|
|
|
5738
5740
|
if (!def?.validateExtra) continue;
|
|
5739
5741
|
let extra;
|
|
5740
5742
|
try {
|
|
5741
|
-
extra = await def.validateExtra({
|
|
5743
|
+
extra = await def.validateExtra({
|
|
5744
|
+
rawParams: n.params,
|
|
5745
|
+
rawInputs: n.inputs,
|
|
5746
|
+
nodeId: n.id,
|
|
5747
|
+
inputKindOf,
|
|
5748
|
+
inputSourceOf
|
|
5749
|
+
});
|
|
5742
5750
|
} catch (e) {
|
|
5743
5751
|
issues.push({
|
|
5744
5752
|
path: `nodes[${i}].params`,
|
|
@@ -5933,6 +5941,18 @@ function staticInputKind(ctx, value) {
|
|
|
5933
5941
|
const plain = outputSchema instanceof z5.ZodString || outputSchema instanceof z5.ZodNumber;
|
|
5934
5942
|
return plain || outputSchema instanceof z5.ZodBoolean ? "value" : "unknown";
|
|
5935
5943
|
}
|
|
5944
|
+
function staticInputSource(ctx, value) {
|
|
5945
|
+
if (typeof value !== "string" || !value.startsWith(REF_PREFIX)) return void 0;
|
|
5946
|
+
const target = refTarget(ctx, value);
|
|
5947
|
+
if (!target || target.node.type !== "ingest" || target.expr.output !== "asset" || target.expr.index !== void 0)
|
|
5948
|
+
return void 0;
|
|
5949
|
+
const parsed = target.def.params.safeParse(target.node.params ?? {});
|
|
5950
|
+
if (!parsed.success) return void 0;
|
|
5951
|
+
const params = parsed.data;
|
|
5952
|
+
if (params.source === "path" && typeof params.path === "string") return { path: path5.resolve(params.path) };
|
|
5953
|
+
if (params.source === "url" && typeof params.url === "string") return { url: params.url };
|
|
5954
|
+
return void 0;
|
|
5955
|
+
}
|
|
5936
5956
|
function checkOneRef(ctx, n, i, refStr, jsonPath, field) {
|
|
5937
5957
|
if (!refStr.startsWith(REF_PREFIX)) return;
|
|
5938
5958
|
const expr = parseRefExpr(refStr);
|
|
@@ -6061,9 +6081,9 @@ function checkOutputRef(ctx) {
|
|
|
6061
6081
|
function pushZodIssues(issues, err, pathPrefix, code, nodeId, nodeType) {
|
|
6062
6082
|
for (const issue of err.issues) {
|
|
6063
6083
|
const tail2 = pathToString(issue.path);
|
|
6064
|
-
const
|
|
6084
|
+
const path23 = pathPrefix ? tail2 ? `${pathPrefix}.${tail2}` : pathPrefix : tail2;
|
|
6065
6085
|
issues.push({
|
|
6066
|
-
path:
|
|
6086
|
+
path: path23,
|
|
6067
6087
|
code,
|
|
6068
6088
|
message: issue.message,
|
|
6069
6089
|
received: issue.code === "invalid_type" ? issue.received : void 0,
|
|
@@ -6072,12 +6092,12 @@ function pushZodIssues(issues, err, pathPrefix, code, nodeId, nodeType) {
|
|
|
6072
6092
|
});
|
|
6073
6093
|
}
|
|
6074
6094
|
}
|
|
6075
|
-
function pathToString(
|
|
6076
|
-
return
|
|
6095
|
+
function pathToString(path23) {
|
|
6096
|
+
return path23.map((p) => typeof p === "number" ? `[${p}]` : `.${String(p)}`).join("").replace(/^\./, "");
|
|
6077
6097
|
}
|
|
6078
6098
|
function walkRefs(value, cb) {
|
|
6079
|
-
forEachString(value, (s,
|
|
6080
|
-
if (s.startsWith(REF_PREFIX)) cb(s,
|
|
6099
|
+
forEachString(value, (s, path23) => {
|
|
6100
|
+
if (s.startsWith(REF_PREFIX)) cb(s, path23);
|
|
6081
6101
|
});
|
|
6082
6102
|
}
|
|
6083
6103
|
function listShapeKeys(schema) {
|
|
@@ -6623,7 +6643,7 @@ var NodeRegistry = class {
|
|
|
6623
6643
|
import { execFile as execFileCb } from "child_process";
|
|
6624
6644
|
import { mkdtemp, readFile as readFile5, rm, stat as stat2 } from "fs/promises";
|
|
6625
6645
|
import { tmpdir } from "os";
|
|
6626
|
-
import
|
|
6646
|
+
import path8 from "path";
|
|
6627
6647
|
import { promisify } from "util";
|
|
6628
6648
|
import { z as z6 } from "zod";
|
|
6629
6649
|
|
|
@@ -6944,11 +6964,11 @@ async function fetchExternalBytes(url, options) {
|
|
|
6944
6964
|
// src/lib/ytDlp.ts
|
|
6945
6965
|
import { spawn } from "child_process";
|
|
6946
6966
|
import { readdir, readFile as readFile4 } from "fs/promises";
|
|
6947
|
-
import
|
|
6967
|
+
import path7 from "path";
|
|
6948
6968
|
|
|
6949
6969
|
// src/lib/vimeoCookie.ts
|
|
6950
6970
|
import { writeFile as writeFile3 } from "fs/promises";
|
|
6951
|
-
import
|
|
6971
|
+
import path6 from "path";
|
|
6952
6972
|
var COOKIE_NAME = "vimeo";
|
|
6953
6973
|
async function writeVimeoCookieFile(cookie, workDir) {
|
|
6954
6974
|
const value = cookie?.trim();
|
|
@@ -6959,7 +6979,7 @@ async function writeVimeoCookieFile(cookie, workDir) {
|
|
|
6959
6979
|
[".vimeo.com", "TRUE", "/", "TRUE", String(expires), COOKIE_NAME, value].join(" "),
|
|
6960
6980
|
""
|
|
6961
6981
|
].join("\n");
|
|
6962
|
-
const filePath =
|
|
6982
|
+
const filePath = path6.join(workDir, "vimeo-cookies.txt");
|
|
6963
6983
|
await writeFile3(filePath, jar, { mode: 384 });
|
|
6964
6984
|
return filePath;
|
|
6965
6985
|
}
|
|
@@ -6970,6 +6990,12 @@ function isVimeoAuthFailure(detail) {
|
|
|
6970
6990
|
return VIMEO_AUTH_SIGNATURES.some((signature) => haystack.includes(signature));
|
|
6971
6991
|
}
|
|
6972
6992
|
|
|
6993
|
+
// src/lib/ytDlpFormat.ts
|
|
6994
|
+
function videoFormatArgs(maxResolution) {
|
|
6995
|
+
const sort = maxResolution ? ["-S", `res:${maxResolution}`] : [];
|
|
6996
|
+
return ["--format", "bv*+ba/b", ...sort, "--merge-output-format", "mp4"];
|
|
6997
|
+
}
|
|
6998
|
+
|
|
6973
6999
|
// src/lib/ytDlpPlayerClient.ts
|
|
6974
7000
|
var YOUTUBE_FALLBACK_CLIENT_ARGS = ["--extractor-args", "youtube:player_client=android"];
|
|
6975
7001
|
var MEDIA_FETCH_REFUSED = "unable to download video data";
|
|
@@ -7023,8 +7049,8 @@ function tail(text, maxLines) {
|
|
|
7023
7049
|
return text.split("\n").slice(-maxLines).join("\n");
|
|
7024
7050
|
}
|
|
7025
7051
|
async function runYtDlp(args) {
|
|
7026
|
-
const outTemplate =
|
|
7027
|
-
const infoPath =
|
|
7052
|
+
const outTemplate = path7.join(args.workDir, "out.%(ext)s");
|
|
7053
|
+
const infoPath = path7.join(args.workDir, "out.info.json");
|
|
7028
7054
|
const argv = [
|
|
7029
7055
|
args.url,
|
|
7030
7056
|
"--no-playlist",
|
|
@@ -7038,7 +7064,7 @@ async function runYtDlp(args) {
|
|
|
7038
7064
|
if (args.audioOnly) {
|
|
7039
7065
|
argv.push("-x", "--audio-format", "m4a");
|
|
7040
7066
|
} else {
|
|
7041
|
-
argv.push(
|
|
7067
|
+
argv.push(...videoFormatArgs(args.maxHeight));
|
|
7042
7068
|
}
|
|
7043
7069
|
const cookieFile = await writeVimeoCookieFile(args.vimeoCookie, args.workDir);
|
|
7044
7070
|
if (cookieFile) argv.push("--cookies", cookieFile);
|
|
@@ -7065,7 +7091,7 @@ async function runYtDlp(args) {
|
|
|
7065
7091
|
info = JSON.parse(await readFile4(infoPath, "utf-8"));
|
|
7066
7092
|
} catch {
|
|
7067
7093
|
}
|
|
7068
|
-
return { filePath:
|
|
7094
|
+
return { filePath: path7.join(args.workDir, downloaded), info, tier, reducedQuality };
|
|
7069
7095
|
}
|
|
7070
7096
|
async function probeYtDlp(args) {
|
|
7071
7097
|
const argv = [
|
|
@@ -7537,8 +7563,8 @@ function resolveLocalPath(input) {
|
|
|
7537
7563
|
`ingest: ~ path expansion is not supported (got "${input}"). Use an absolute path or a cwd-relative path.`
|
|
7538
7564
|
);
|
|
7539
7565
|
}
|
|
7540
|
-
if (
|
|
7541
|
-
return
|
|
7566
|
+
if (path8.isAbsolute(input)) return input;
|
|
7567
|
+
return path8.resolve(process.cwd(), input);
|
|
7542
7568
|
}
|
|
7543
7569
|
var EXT_TO_MIME = {
|
|
7544
7570
|
png: "image/png",
|
|
@@ -7586,7 +7612,7 @@ function sniffSvg(buf) {
|
|
|
7586
7612
|
return head.startsWith("<?xml") ? head.includes("<svg") : head.startsWith("<svg");
|
|
7587
7613
|
}
|
|
7588
7614
|
function inferMimeFromPath(absPath, sniffBytes) {
|
|
7589
|
-
const ext =
|
|
7615
|
+
const ext = path8.extname(absPath).slice(1).toLowerCase();
|
|
7590
7616
|
const fromExt = EXT_TO_MIME[ext];
|
|
7591
7617
|
if (fromExt) return fromExt;
|
|
7592
7618
|
const fromBytes = sniffImageMime(sniffBytes);
|
|
@@ -7823,7 +7849,7 @@ function localFileMetadata(args) {
|
|
|
7823
7849
|
strategy: "local_file",
|
|
7824
7850
|
ingested_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7825
7851
|
file_size: args.fileSize,
|
|
7826
|
-
original_filename:
|
|
7852
|
+
original_filename: path8.basename(args.absPath),
|
|
7827
7853
|
...args.rasterizedFrom ? { rasterized_from: args.rasterizedFrom } : {},
|
|
7828
7854
|
...args.durationMs !== void 0 ? { duration_ms: args.durationMs } : {}
|
|
7829
7855
|
};
|
|
@@ -7845,7 +7871,7 @@ async function execYtDlp(params, ctx) {
|
|
|
7845
7871
|
if (params.expect !== "video" && params.expect !== "audio") {
|
|
7846
7872
|
throw new Error(`ingest: yt_dlp only handles video/audio, got expect=${params.expect}`);
|
|
7847
7873
|
}
|
|
7848
|
-
const workDir = await mkdtemp(
|
|
7874
|
+
const workDir = await mkdtemp(path8.join(tmpdir(), "ingest-yt-"));
|
|
7849
7875
|
try {
|
|
7850
7876
|
const { filePath, info, reducedQuality } = await runYtDlpForNode({
|
|
7851
7877
|
url: params.url,
|
|
@@ -7951,7 +7977,7 @@ import { z as z7 } from "zod";
|
|
|
7951
7977
|
import { execFile as execFileCb2, spawn as spawn2 } from "child_process";
|
|
7952
7978
|
import { copyFile as copyFile2, mkdtemp as mkdtemp2, readFile as readFile6, rm as rm2, stat as stat3 } from "fs/promises";
|
|
7953
7979
|
import { tmpdir as tmpdir2 } from "os";
|
|
7954
|
-
import
|
|
7980
|
+
import path9 from "path";
|
|
7955
7981
|
import { promisify as promisify2 } from "util";
|
|
7956
7982
|
var execFile2 = promisify2(execFileCb2);
|
|
7957
7983
|
var DEFAULT_TIMEOUT_MS2 = 10 * 60 * 1e3;
|
|
@@ -7978,7 +8004,7 @@ function mimeForExt(ext) {
|
|
|
7978
8004
|
}
|
|
7979
8005
|
function extForAssetRef(ref) {
|
|
7980
8006
|
if (ref.path) {
|
|
7981
|
-
const e =
|
|
8007
|
+
const e = path9.extname(ref.path);
|
|
7982
8008
|
if (e) return e;
|
|
7983
8009
|
}
|
|
7984
8010
|
const reverse = {
|
|
@@ -8000,14 +8026,14 @@ function planArrayInputSlot(tmpDir, slot, values, lookup, stagedInputs) {
|
|
|
8000
8026
|
const ref = values[i];
|
|
8001
8027
|
if (!ref) continue;
|
|
8002
8028
|
if (!ref.path) throw new Error(`cli-runner: inputs.${slot}[${i}] has no local path`);
|
|
8003
|
-
const dest =
|
|
8029
|
+
const dest = path9.join(tmpDir, `in_${slot}_${i}${extForAssetRef(ref)}`);
|
|
8004
8030
|
stagedInputs.push({ srcPath: ref.path, destPath: dest });
|
|
8005
8031
|
lookup.set(`in.${slot}.${i}`, dest);
|
|
8006
8032
|
}
|
|
8007
8033
|
}
|
|
8008
8034
|
function planSingleInputSlot(tmpDir, slot, ref, lookup, stagedInputs) {
|
|
8009
8035
|
if (!ref.path) throw new Error(`cli-runner: inputs.${slot} has no local path`);
|
|
8010
|
-
const dest =
|
|
8036
|
+
const dest = path9.join(tmpDir, `in_${slot}${extForAssetRef(ref)}`);
|
|
8011
8037
|
stagedInputs.push({ srcPath: ref.path, destPath: dest });
|
|
8012
8038
|
lookup.set(`in.${slot}`, dest);
|
|
8013
8039
|
}
|
|
@@ -8015,7 +8041,7 @@ function planOutputs(tmpDir, outputs, lookup) {
|
|
|
8015
8041
|
const outputPaths = [];
|
|
8016
8042
|
for (const [name, spec] of Object.entries(outputs)) {
|
|
8017
8043
|
const ext = spec.ext.startsWith(".") ? spec.ext : `.${spec.ext}`;
|
|
8018
|
-
const absPath =
|
|
8044
|
+
const absPath = path9.join(tmpDir, `out_${name}${ext}`);
|
|
8019
8045
|
outputPaths.push({ name, absPath, spec });
|
|
8020
8046
|
lookup.set(`out.${name}`, absPath);
|
|
8021
8047
|
}
|
|
@@ -8056,8 +8082,8 @@ function rejectRawPaths(substituted, original, stagingDir) {
|
|
|
8056
8082
|
throw new Error(`cli-runner: home-relative path "${original}" not allowed in args.`);
|
|
8057
8083
|
}
|
|
8058
8084
|
if (substituted.startsWith("/")) {
|
|
8059
|
-
const resolved =
|
|
8060
|
-
if (!resolved.startsWith(`${stagingDir}${
|
|
8085
|
+
const resolved = path9.resolve(substituted);
|
|
8086
|
+
if (!resolved.startsWith(`${stagingDir}${path9.sep}`) && resolved !== stagingDir) {
|
|
8061
8087
|
throw new Error(
|
|
8062
8088
|
`cli-runner: raw filesystem path "${original}" not allowed \u2014 declare an input slot and use {{in.<slot>}} instead.`
|
|
8063
8089
|
);
|
|
@@ -8107,7 +8133,7 @@ function tailLines(text, maxLines) {
|
|
|
8107
8133
|
}
|
|
8108
8134
|
async function runCli(opts) {
|
|
8109
8135
|
const { bin, args, inputs, outputs, ctx, timeoutMs = DEFAULT_TIMEOUT_MS2 } = opts;
|
|
8110
|
-
const tmpDir = await mkdtemp2(
|
|
8136
|
+
const tmpDir = await mkdtemp2(path9.join(tmpdir2(), `cli-${bin.replace(/[^a-z0-9]/gi, "")}-`));
|
|
8111
8137
|
try {
|
|
8112
8138
|
const { lookup, stagedInputs, outputPaths } = planPlaceholders(tmpDir, inputs, outputs);
|
|
8113
8139
|
await stageInputs(stagedInputs);
|
|
@@ -8488,17 +8514,17 @@ var ffmpegNode = defineNode({
|
|
|
8488
8514
|
import { mkdtemp as mkdtemp3, rm as rm3, writeFile as writeFile4 } from "fs/promises";
|
|
8489
8515
|
import { createRequire } from "module";
|
|
8490
8516
|
import { tmpdir as tmpdir3 } from "os";
|
|
8491
|
-
import
|
|
8517
|
+
import path11 from "path";
|
|
8492
8518
|
import { z as z11 } from "zod";
|
|
8493
8519
|
|
|
8494
8520
|
// src/engine/nodes/local/lib/assets.ts
|
|
8495
8521
|
import { copyFile as copyFile3, readFile as readFile7 } from "fs/promises";
|
|
8496
|
-
import
|
|
8522
|
+
import path10 from "path";
|
|
8497
8523
|
async function stageAsset(ref, destDir, filename) {
|
|
8498
8524
|
if (!ref.path) {
|
|
8499
8525
|
throw new Error(`stageAsset: ref (${ref.kind}/${ref.mime}) has no local path`);
|
|
8500
8526
|
}
|
|
8501
|
-
const dest =
|
|
8527
|
+
const dest = path10.join(destDir, filename);
|
|
8502
8528
|
await copyFile3(ref.path, dest);
|
|
8503
8529
|
return dest;
|
|
8504
8530
|
}
|
|
@@ -8575,11 +8601,11 @@ var fontSpecimenNode = defineNode({
|
|
|
8575
8601
|
outputKinds: { image: "image" },
|
|
8576
8602
|
cost: () => ({ credits: 0, seconds_estimate: 5 }),
|
|
8577
8603
|
async execute({ inputs, params, ctx }) {
|
|
8578
|
-
const tmp = await mkdtemp3(
|
|
8604
|
+
const tmp = await mkdtemp3(path11.join(tmpdir3(), "font-specimen-"));
|
|
8579
8605
|
try {
|
|
8580
8606
|
const fontFilename = `font.${extForMime(inputs.font.mime)}`;
|
|
8581
8607
|
await stageAsset(inputs.font, tmp, fontFilename);
|
|
8582
|
-
const entryPath =
|
|
8608
|
+
const entryPath = path11.join(tmp, "index.html");
|
|
8583
8609
|
await writeFile4(entryPath, buildSpecimenHtml(params, fontFilename), "utf-8");
|
|
8584
8610
|
ctx.log(`rendering specimen (${params.font_size}px, ${params.text.split("\n").length} lines)`);
|
|
8585
8611
|
const pwSpecifier = ["play", "wright"].join("");
|
|
@@ -8663,15 +8689,15 @@ var fontSpecimenNode = defineNode({
|
|
|
8663
8689
|
|
|
8664
8690
|
// src/engine/nodes/local/hyperframe.ts
|
|
8665
8691
|
import { execFile as execFile4 } from "child_process";
|
|
8666
|
-
import { mkdtemp as mkdtemp5, readFile as readFile12, rm as rm5, stat as
|
|
8692
|
+
import { mkdtemp as mkdtemp5, readFile as readFile12, rm as rm5, stat as stat6, writeFile as writeFile7 } from "fs/promises";
|
|
8667
8693
|
import { cpus, tmpdir as tmpdir5 } from "os";
|
|
8668
|
-
import
|
|
8694
|
+
import path18 from "path";
|
|
8669
8695
|
import { promisify as promisify4 } from "util";
|
|
8670
8696
|
import { z as z13 } from "zod";
|
|
8671
8697
|
|
|
8672
8698
|
// src/engine/engine/composition-hash.ts
|
|
8673
8699
|
import { readdir as readdir2, readFile as readFile8, stat as stat4 } from "fs/promises";
|
|
8674
|
-
import
|
|
8700
|
+
import path12 from "path";
|
|
8675
8701
|
var SKIP_DIRS = /* @__PURE__ */ new Set([".cache", ".git", "node_modules", "dist", "build", ".next", ".turbo"]);
|
|
8676
8702
|
function isSkippedName(name) {
|
|
8677
8703
|
if (name.startsWith(".")) return true;
|
|
@@ -8688,7 +8714,7 @@ async function collectFiles(root, current) {
|
|
|
8688
8714
|
const names = await readdir2(current);
|
|
8689
8715
|
for (const name of names) {
|
|
8690
8716
|
if (isSkippedName(name)) continue;
|
|
8691
|
-
const abs =
|
|
8717
|
+
const abs = path12.join(current, name);
|
|
8692
8718
|
const s = await stat4(abs);
|
|
8693
8719
|
if (s.isDirectory()) {
|
|
8694
8720
|
out.push(...await collectFiles(root, abs));
|
|
@@ -8696,7 +8722,7 @@ async function collectFiles(root, current) {
|
|
|
8696
8722
|
}
|
|
8697
8723
|
if (!s.isFile()) continue;
|
|
8698
8724
|
const bytes = await readFile8(abs);
|
|
8699
|
-
const relPath =
|
|
8725
|
+
const relPath = path12.relative(root, abs).split(path12.sep).join("/");
|
|
8700
8726
|
out.push({ relPath, contentSha: sha256Hex(bytes) });
|
|
8701
8727
|
}
|
|
8702
8728
|
return out;
|
|
@@ -8704,7 +8730,7 @@ async function collectFiles(root, current) {
|
|
|
8704
8730
|
|
|
8705
8731
|
// src/engine/engine/composition-meta.ts
|
|
8706
8732
|
import { readFile as readFile9 } from "fs/promises";
|
|
8707
|
-
import
|
|
8733
|
+
import path13 from "path";
|
|
8708
8734
|
import { z as z12 } from "zod";
|
|
8709
8735
|
var InputKind = z12.enum(["video", "image", "audio", "json", "font"]);
|
|
8710
8736
|
var InputSpec = z12.object({
|
|
@@ -8781,7 +8807,7 @@ var CompositionMetaSchema = z12.object({
|
|
|
8781
8807
|
params: z12.record(z12.string(), ParamSpec).default({})
|
|
8782
8808
|
}).strict();
|
|
8783
8809
|
async function loadCompositionMeta(compositionDir) {
|
|
8784
|
-
const metaPath =
|
|
8810
|
+
const metaPath = path13.join(compositionDir, "meta.json");
|
|
8785
8811
|
let raw;
|
|
8786
8812
|
try {
|
|
8787
8813
|
raw = await readFile9(metaPath, "utf-8");
|
|
@@ -8864,13 +8890,13 @@ function defaultFilenameForInput(key, kind) {
|
|
|
8864
8890
|
// src/engine/nodes/local/lib/composition-stage.ts
|
|
8865
8891
|
import { copyFile as copyFile4, cp } from "fs/promises";
|
|
8866
8892
|
import { createRequire as createRequire2 } from "module";
|
|
8867
|
-
import
|
|
8893
|
+
import path14 from "path";
|
|
8868
8894
|
var require_2 = createRequire2(import.meta.url);
|
|
8869
8895
|
async function copyComposition(srcDir, destDir) {
|
|
8870
8896
|
await cp(srcDir, destDir, {
|
|
8871
8897
|
recursive: true,
|
|
8872
8898
|
filter: (src) => {
|
|
8873
|
-
const name =
|
|
8899
|
+
const name = path14.basename(src);
|
|
8874
8900
|
if (name === ".cache" || name === "node_modules" || name === ".git") return false;
|
|
8875
8901
|
return true;
|
|
8876
8902
|
}
|
|
@@ -8879,21 +8905,21 @@ async function copyComposition(srcDir, destDir) {
|
|
|
8879
8905
|
async function vendorGsap(dir, ctx) {
|
|
8880
8906
|
try {
|
|
8881
8907
|
const gsapMin = require_2.resolve("gsap/dist/gsap.min.js");
|
|
8882
|
-
await copyFile4(gsapMin,
|
|
8908
|
+
await copyFile4(gsapMin, path14.join(dir, "gsap.min.js"));
|
|
8883
8909
|
} catch (e) {
|
|
8884
8910
|
ctx.log(`warning: could not vendor gsap.min.js (${e.message}); compositions must self-supply`);
|
|
8885
8911
|
}
|
|
8886
8912
|
}
|
|
8887
8913
|
|
|
8888
8914
|
// src/engine/nodes/local/lib/composition-static-check.ts
|
|
8889
|
-
import { mkdtemp as mkdtemp4, readFile as readFile11, rm as rm4, writeFile as writeFile6 } from "fs/promises";
|
|
8915
|
+
import { mkdtemp as mkdtemp4, readFile as readFile11, rm as rm4, stat as stat5, writeFile as writeFile6 } from "fs/promises";
|
|
8890
8916
|
import { tmpdir as tmpdir4 } from "os";
|
|
8891
|
-
import
|
|
8917
|
+
import path17 from "path";
|
|
8892
8918
|
|
|
8893
8919
|
// src/engine/nodes/local/lib/hyperframe-check.ts
|
|
8894
8920
|
import { execFile as execFile3 } from "child_process";
|
|
8895
8921
|
import { readFile as readFile10 } from "fs/promises";
|
|
8896
|
-
import
|
|
8922
|
+
import path15 from "path";
|
|
8897
8923
|
import { promisify as promisify3 } from "util";
|
|
8898
8924
|
|
|
8899
8925
|
// src/engine/nodes/local/lib/caption-style.ts
|
|
@@ -9076,6 +9102,13 @@ async function lintPreparedComposition(dir, timeoutMs) {
|
|
|
9076
9102
|
const lintRaw = await runOne(buildLintArgsNoInstall(dir), timeoutMs);
|
|
9077
9103
|
return lintRaw === null ? [] : lintBlockers(lintRaw);
|
|
9078
9104
|
}
|
|
9105
|
+
function layoutBlockers(checkRaw) {
|
|
9106
|
+
return classifyGateOutput(checkRaw).blocking.filter((f) => f.source === "layout").map((f) => ({ code: f.code, message: explainGateFinding(f) }));
|
|
9107
|
+
}
|
|
9108
|
+
async function checkPreparedLayout(dir, timeoutMs) {
|
|
9109
|
+
const checkRaw = await runOne(["--no-install", ...buildCheckArgs(dir, 1)], timeoutMs);
|
|
9110
|
+
return checkRaw === null ? [] : layoutBlockers(checkRaw);
|
|
9111
|
+
}
|
|
9079
9112
|
function buildInspectArgs(dir, samples) {
|
|
9080
9113
|
return ["hyperframes", "inspect", dir, "--json", "--samples", String(samples)];
|
|
9081
9114
|
}
|
|
@@ -9116,7 +9149,7 @@ async function runSnapshotSmoke(args, timeoutMs) {
|
|
|
9116
9149
|
}
|
|
9117
9150
|
async function runNestedCompositionSmoke(opts) {
|
|
9118
9151
|
const { dir, nodeId, ctx, timeoutMs, samples } = opts;
|
|
9119
|
-
const indexHtml = await readFile10(
|
|
9152
|
+
const indexHtml = await readFile10(path15.join(dir, "index.html"), "utf-8").catch(() => "");
|
|
9120
9153
|
if (!indexHtml || !usesNestedCompositions(indexHtml)) return;
|
|
9121
9154
|
const snap = await runSnapshotSmoke(
|
|
9122
9155
|
buildSnapshotArgs(dir, Math.min(samples, 3), hasFrameVisionKey()),
|
|
@@ -9132,7 +9165,7 @@ async function runNestedCompositionSmoke(opts) {
|
|
|
9132
9165
|
${snap.message}`
|
|
9133
9166
|
);
|
|
9134
9167
|
}
|
|
9135
|
-
const described = await readFile10(
|
|
9168
|
+
const described = await readFile10(path15.join(dir, "snapshots", "descriptions.md"), "utf-8").catch(() => "");
|
|
9136
9169
|
for (const line of condenseFrameDescriptions(described)) {
|
|
9137
9170
|
ctx.log(`${nodeId}: frame check \u2014 ${line}`);
|
|
9138
9171
|
}
|
|
@@ -9168,7 +9201,7 @@ async function runHyperframesCheck(opts) {
|
|
|
9168
9201
|
${detail}`
|
|
9169
9202
|
);
|
|
9170
9203
|
}
|
|
9171
|
-
const composition = await readFile10(
|
|
9204
|
+
const composition = await readFile10(path15.join(dir, "index.html"), "utf-8").catch(() => "");
|
|
9172
9205
|
const captionComplaint = fragmentedCaptions(captionTextsFrom(composition));
|
|
9173
9206
|
if (captionComplaint) {
|
|
9174
9207
|
ctx.log(`${nodeId}: caption style \u2014 ${captionComplaint}`);
|
|
@@ -9179,9 +9212,9 @@ ${detail}`
|
|
|
9179
9212
|
|
|
9180
9213
|
// src/engine/nodes/local/lib/hyperframe-meta.ts
|
|
9181
9214
|
import { writeFile as writeFile5 } from "fs/promises";
|
|
9182
|
-
import
|
|
9215
|
+
import path16 from "path";
|
|
9183
9216
|
async function ensureHyperframesMetaJson(tmp, nodeId, meta, duration) {
|
|
9184
|
-
const metaPath =
|
|
9217
|
+
const metaPath = path16.join(tmp, "meta.json");
|
|
9185
9218
|
await writeFile5(
|
|
9186
9219
|
metaPath,
|
|
9187
9220
|
JSON.stringify(
|
|
@@ -9244,11 +9277,11 @@ function extractReferencedTokens(source) {
|
|
|
9244
9277
|
|
|
9245
9278
|
// src/engine/nodes/local/lib/composition-static-check.ts
|
|
9246
9279
|
async function staticCompositionIssues(args) {
|
|
9247
|
-
const html = await readFile11(
|
|
9280
|
+
const html = await readFile11(path17.join(args.dir, "index.html"), "utf-8").catch(() => null);
|
|
9248
9281
|
const issues = inputIssues(args.meta, args.rawInputs, args.inputKindOf);
|
|
9249
9282
|
if (html === null) return issues;
|
|
9250
9283
|
issues.push(...undefinedVariableIssues(html, args.meta, args.compositionParams));
|
|
9251
|
-
issues.push(...await
|
|
9284
|
+
issues.push(...await gateIssues(args));
|
|
9252
9285
|
return issues;
|
|
9253
9286
|
}
|
|
9254
9287
|
function substitutionValues(meta, compositionParams) {
|
|
@@ -9312,34 +9345,92 @@ function kindMismatch(expected, got) {
|
|
|
9312
9345
|
if (got === "value") return "got a plain value, not an asset";
|
|
9313
9346
|
return `got "${got}"`;
|
|
9314
9347
|
}
|
|
9315
|
-
async function
|
|
9348
|
+
async function gateIssues(args) {
|
|
9316
9349
|
if (!await isHyperframesAvailable()) return [];
|
|
9317
|
-
const tmp = await mkdtemp4(
|
|
9350
|
+
const tmp = await mkdtemp4(path17.join(tmpdir4(), "hf-validate-"));
|
|
9318
9351
|
try {
|
|
9319
|
-
await
|
|
9320
|
-
await
|
|
9321
|
-
await
|
|
9322
|
-
|
|
9323
|
-
|
|
9324
|
-
|
|
9325
|
-
|
|
9326
|
-
|
|
9327
|
-
|
|
9328
|
-
|
|
9329
|
-
|
|
9330
|
-
|
|
9352
|
+
const { faithful } = await prepareForGate(tmp, args);
|
|
9353
|
+
const lint = await lintPreparedComposition(tmp, args.lintTimeoutMs);
|
|
9354
|
+
const layout = args.checkLayout && faithful ? await checkPreparedLayout(tmp, LAYOUT_CHECK_TIMEOUT_MS) : [];
|
|
9355
|
+
return [
|
|
9356
|
+
...lint.map((b) => ({
|
|
9357
|
+
path: "params.composition",
|
|
9358
|
+
message: `pre-render gate would fail: [${b.code}] ${b.message}`
|
|
9359
|
+
})),
|
|
9360
|
+
...layout.map((b) => ({
|
|
9361
|
+
path: "params.composition",
|
|
9362
|
+
message: `pre-render gate would fail: [layout/${b.code}] ${b.message} Nothing was rendered or billed.`
|
|
9363
|
+
}))
|
|
9364
|
+
];
|
|
9331
9365
|
} finally {
|
|
9332
9366
|
await rm4(tmp, { recursive: true, force: true }).catch(() => void 0);
|
|
9333
9367
|
}
|
|
9334
9368
|
}
|
|
9335
|
-
|
|
9336
|
-
|
|
9337
|
-
|
|
9338
|
-
|
|
9339
|
-
|
|
9340
|
-
|
|
9369
|
+
var LAYOUT_CHECK_TIMEOUT_MS = 6e4;
|
|
9370
|
+
var MAX_INPUT_BYTES = 20 * 1024 * 1024;
|
|
9371
|
+
var STAND_IN_PICTURE = Buffer.from(
|
|
9372
|
+
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=",
|
|
9373
|
+
"base64"
|
|
9374
|
+
);
|
|
9375
|
+
async function readSource(source) {
|
|
9376
|
+
try {
|
|
9377
|
+
if ("path" in source) {
|
|
9378
|
+
const info = await stat5(source.path);
|
|
9379
|
+
return info.isFile() && info.size <= MAX_INPUT_BYTES ? await readFile11(source.path) : null;
|
|
9380
|
+
}
|
|
9381
|
+
return (await fetchExternalBytes(source.url, { maxBytes: MAX_INPUT_BYTES, timeoutMs: 15e3 })).buffer;
|
|
9382
|
+
} catch {
|
|
9383
|
+
return null;
|
|
9341
9384
|
}
|
|
9342
9385
|
}
|
|
9386
|
+
function standIn(kind) {
|
|
9387
|
+
if (kind === "image") return STAND_IN_PICTURE;
|
|
9388
|
+
return kind === "json" ? "{}" : "";
|
|
9389
|
+
}
|
|
9390
|
+
async function prepareForGate(target, args) {
|
|
9391
|
+
await copyComposition(args.dir, target);
|
|
9392
|
+
await vendorGsap(target, { log: () => void 0 });
|
|
9393
|
+
const staged = await stageGateInputs(target, args);
|
|
9394
|
+
const filled = fillParamSlots(args.meta, args.compositionParams, staged.slotTexts);
|
|
9395
|
+
const entry = path17.join(target, "index.html");
|
|
9396
|
+
const html = await readFile11(entry, "utf-8");
|
|
9397
|
+
await writeFile6(entry, substituteVariables(html, substitutionValues(args.meta, filled.params)).output);
|
|
9398
|
+
await ensureHyperframesMetaJson(target, args.meta.id, args.meta, args.meta.default_duration);
|
|
9399
|
+
return { faithful: staged.faithful && filled.faithful };
|
|
9400
|
+
}
|
|
9401
|
+
async function stageGateInputs(target, args) {
|
|
9402
|
+
const inputs = args.rawInputs && typeof args.rawInputs === "object" ? args.rawInputs : {};
|
|
9403
|
+
const wired = Object.entries(args.meta.inputs).filter(([key]) => Object.hasOwn(inputs, key));
|
|
9404
|
+
const staged = await Promise.all(
|
|
9405
|
+
wired.map(async ([key, spec]) => {
|
|
9406
|
+
const filename = path17.join(target, spec.staged_as ?? defaultFilenameForInput(key, spec.kind));
|
|
9407
|
+
const source = args.inputSourceOf?.(inputs[key]);
|
|
9408
|
+
const bytes = source ? await readSource(source) : null;
|
|
9409
|
+
await writeFile6(filename, bytes ?? standIn(spec.kind));
|
|
9410
|
+
const faithful = bytes !== null || !source && spec.kind === "image";
|
|
9411
|
+
return { key, faithful, text: bytes && spec.kind === "json" ? bytes.toString("utf8") : null };
|
|
9412
|
+
})
|
|
9413
|
+
);
|
|
9414
|
+
const slotTexts = {};
|
|
9415
|
+
for (const { key, text } of staged) if (text !== null) slotTexts[key] = text;
|
|
9416
|
+
return { faithful: staged.every((s) => s.faithful), slotTexts };
|
|
9417
|
+
}
|
|
9418
|
+
function fillParamSlots(meta, compositionParams, slotTexts) {
|
|
9419
|
+
let faithful = true;
|
|
9420
|
+
const params = {};
|
|
9421
|
+
for (const [name, value] of Object.entries(compositionParams)) {
|
|
9422
|
+
const slots = typeof value === "string" ? extractReferencedTokens(value) : [];
|
|
9423
|
+
if (typeof value !== "string" || slots.length === 0) {
|
|
9424
|
+
params[name] = value;
|
|
9425
|
+
} else if (slots.every((slot) => Object.hasOwn(slotTexts, slot))) {
|
|
9426
|
+
params[name] = renderTemplate(value, slotTexts);
|
|
9427
|
+
} else {
|
|
9428
|
+
faithful = false;
|
|
9429
|
+
params[name] = placeholderFor(meta.params[name]?.kind);
|
|
9430
|
+
}
|
|
9431
|
+
}
|
|
9432
|
+
return { faithful, params };
|
|
9433
|
+
}
|
|
9343
9434
|
|
|
9344
9435
|
// src/engine/nodes/local/lib/hyperframe-errors.ts
|
|
9345
9436
|
var KNOWN_ERROR_PATTERNS = [
|
|
@@ -9430,7 +9521,7 @@ var hyperframeRenderNode = defineNode({
|
|
|
9430
9521
|
const compositionDir = await resolveCompositionDir(params.composition);
|
|
9431
9522
|
const meta = await loadCompositionMeta(compositionDir);
|
|
9432
9523
|
const compositionParams = validateAndParseDynamicParams(meta, params);
|
|
9433
|
-
const tmp = await mkdtemp5(
|
|
9524
|
+
const tmp = await mkdtemp5(path18.join(tmpdir5(), "hf-render-"));
|
|
9434
9525
|
try {
|
|
9435
9526
|
await copyComposition(compositionDir, tmp);
|
|
9436
9527
|
await vendorGsap(tmp, ctx);
|
|
@@ -9440,7 +9531,7 @@ var hyperframeRenderNode = defineNode({
|
|
|
9440
9531
|
await substituteCompositionFiles(tmp, substitutionValues2);
|
|
9441
9532
|
await ensureHyperframesMetaJson(tmp, ctx.nodeId, meta, duration);
|
|
9442
9533
|
await runHyperframesCheck({ dir: tmp, nodeId: "hyperframe_render", ctx, timeoutMs: params.timeout_ms });
|
|
9443
|
-
const outputPath =
|
|
9534
|
+
const outputPath = path18.join(tmp, `output.${params.format}`);
|
|
9444
9535
|
await runRender({ tmp, outputPath, params, meta, ctx });
|
|
9445
9536
|
const bytes = await readFile12(outputPath);
|
|
9446
9537
|
ctx.log(`rendered ${bytes.length} bytes`);
|
|
@@ -9464,12 +9555,12 @@ var hyperframeRenderNode = defineNode({
|
|
|
9464
9555
|
}
|
|
9465
9556
|
});
|
|
9466
9557
|
async function resolveCompositionDir(composition) {
|
|
9467
|
-
const compositionPath =
|
|
9468
|
-
const s = await
|
|
9558
|
+
const compositionPath = path18.isAbsolute(composition) ? composition : path18.resolve(process.cwd(), composition);
|
|
9559
|
+
const s = await stat6(compositionPath);
|
|
9469
9560
|
if (s.isDirectory()) return compositionPath;
|
|
9470
|
-
return
|
|
9561
|
+
return path18.dirname(compositionPath);
|
|
9471
9562
|
}
|
|
9472
|
-
async function validateCompositionNode(args, ownedKeys) {
|
|
9563
|
+
async function validateCompositionNode(args, ownedKeys, options = {}) {
|
|
9473
9564
|
const issues = await validateCompositionParams(args.rawParams, ownedKeys);
|
|
9474
9565
|
const params = args.rawParams ?? {};
|
|
9475
9566
|
if (typeof params.composition !== "string") return issues;
|
|
@@ -9485,7 +9576,9 @@ async function validateCompositionNode(args, ownedKeys) {
|
|
|
9485
9576
|
compositionParams,
|
|
9486
9577
|
rawInputs: args.rawInputs,
|
|
9487
9578
|
inputKindOf: args.inputKindOf,
|
|
9488
|
-
|
|
9579
|
+
inputSourceOf: args.inputSourceOf,
|
|
9580
|
+
lintTimeoutMs: 2e4,
|
|
9581
|
+
checkLayout: options.checkLayout
|
|
9489
9582
|
})
|
|
9490
9583
|
);
|
|
9491
9584
|
return issues;
|
|
@@ -9560,7 +9653,7 @@ async function stageInputs2(tmp, inputs, meta, ctx) {
|
|
|
9560
9653
|
await stageAsset(ref, tmp, filename);
|
|
9561
9654
|
ctx.log(`staged ${spec.kind} \u2192 ${filename}`);
|
|
9562
9655
|
if (spec.kind === "video" && primaryDuration === null) {
|
|
9563
|
-
primaryDuration = await probeDurationSeconds(
|
|
9656
|
+
primaryDuration = await probeDurationSeconds(path18.join(tmp, filename));
|
|
9564
9657
|
}
|
|
9565
9658
|
}
|
|
9566
9659
|
return primaryDuration;
|
|
@@ -9606,7 +9699,7 @@ function coerceImageParam(value) {
|
|
|
9606
9699
|
throw new Error("hyperframe_render: image param must be a URL string or AssetRef");
|
|
9607
9700
|
}
|
|
9608
9701
|
async function substituteCompositionFiles(tmp, values) {
|
|
9609
|
-
const entryPath =
|
|
9702
|
+
const entryPath = path18.join(tmp, "index.html");
|
|
9610
9703
|
const original = await readFile12(entryPath, "utf-8");
|
|
9611
9704
|
const { output, missing } = substituteVariables(original, values);
|
|
9612
9705
|
if (missing.length > 0) {
|
|
@@ -9623,7 +9716,7 @@ function workerCount() {
|
|
|
9623
9716
|
async function runRender(opts) {
|
|
9624
9717
|
const { tmp, outputPath, params, meta, ctx } = opts;
|
|
9625
9718
|
const args = buildRenderArgs(tmp, outputPath, meta, params.format);
|
|
9626
|
-
ctx.log(`rendering ${meta.width}x${meta.height}@${meta.fps}fps ${params.format} from ${
|
|
9719
|
+
ctx.log(`rendering ${meta.width}x${meta.height}@${meta.fps}fps ${params.format} from ${path18.basename(tmp)}`);
|
|
9627
9720
|
try {
|
|
9628
9721
|
await execFileAsync2("npx", args, { timeout: params.timeout_ms, maxBuffer: 64 * 1024 * 1024 });
|
|
9629
9722
|
} catch (e) {
|
|
@@ -9670,7 +9763,7 @@ import { execFile as execFile5 } from "child_process";
|
|
|
9670
9763
|
import { mkdtemp as mkdtemp6, readFile as readFile13, rm as rm6, writeFile as writeFile8 } from "fs/promises";
|
|
9671
9764
|
import { createRequire as createRequire3 } from "module";
|
|
9672
9765
|
import { tmpdir as tmpdir6 } from "os";
|
|
9673
|
-
import
|
|
9766
|
+
import path19 from "path";
|
|
9674
9767
|
import { promisify as promisify5 } from "util";
|
|
9675
9768
|
import { z as z14 } from "zod";
|
|
9676
9769
|
var _execFileAsync = promisify5(execFile5);
|
|
@@ -9705,7 +9798,9 @@ var hyperframeSnapshotNode = defineNode({
|
|
|
9705
9798
|
cost: () => ({ credits: 0, seconds_estimate: 3 }),
|
|
9706
9799
|
// The snapshot's own keys (`wait_for`) are not composition params: checked against the
|
|
9707
9800
|
// render node's key set, a canvas that waited on a selector failed validate every time.
|
|
9708
|
-
|
|
9801
|
+
// A still has one frame and its copy is known before the run, so validate lays it out
|
|
9802
|
+
// and refuses colliding lines before a single picture is paid for.
|
|
9803
|
+
validateExtra: (args) => validateCompositionNode(args, NODE_OWNED_PARAM_KEYS2, { checkLayout: true }),
|
|
9709
9804
|
cacheKeyExtras: async ({ params }) => {
|
|
9710
9805
|
const out = {};
|
|
9711
9806
|
const composition = params.composition;
|
|
@@ -9719,7 +9814,7 @@ var hyperframeSnapshotNode = defineNode({
|
|
|
9719
9814
|
const compositionDir = await resolveCompositionDir(params.composition);
|
|
9720
9815
|
const meta = await loadCompositionMeta(compositionDir);
|
|
9721
9816
|
const compositionParams = validateAndParseDynamicParams2(meta, params);
|
|
9722
|
-
const tmp = await mkdtemp6(
|
|
9817
|
+
const tmp = await mkdtemp6(path19.join(tmpdir6(), "hf-snap-"));
|
|
9723
9818
|
try {
|
|
9724
9819
|
await copyComposition(compositionDir, tmp);
|
|
9725
9820
|
await vendorGsap(tmp, ctx);
|
|
@@ -9734,7 +9829,7 @@ var hyperframeSnapshotNode = defineNode({
|
|
|
9734
9829
|
timeoutMs: params.timeout_ms,
|
|
9735
9830
|
samples: 1
|
|
9736
9831
|
});
|
|
9737
|
-
const entryPath =
|
|
9832
|
+
const entryPath = path19.join(tmp, "index.html");
|
|
9738
9833
|
const entryUrl = `file://${entryPath}`;
|
|
9739
9834
|
ctx.log(`snapshotting ${meta.width}x${meta.height}@${DEVICE_SCALE_FACTOR2}x wait=${params.wait_for.kind}`);
|
|
9740
9835
|
const pwSpecifier = ["play", "wright"].join("");
|
|
@@ -9819,7 +9914,7 @@ function coerceImageParam2(value) {
|
|
|
9819
9914
|
throw new Error("hyperframe_snapshot: image param must be a URL string or AssetRef");
|
|
9820
9915
|
}
|
|
9821
9916
|
async function substituteCompositionFiles2(tmp, values) {
|
|
9822
|
-
const entryPath =
|
|
9917
|
+
const entryPath = path19.join(tmp, "index.html");
|
|
9823
9918
|
const original = await readFile13(entryPath, "utf-8");
|
|
9824
9919
|
const { output, missing } = substituteVariables(original, values);
|
|
9825
9920
|
if (missing.length > 0) {
|
|
@@ -10833,7 +10928,7 @@ var videoLipsyncNode = delegated({
|
|
|
10833
10928
|
// src/engine/nodes/remote/videoTranscribe.ts
|
|
10834
10929
|
import { mkdtemp as mkdtemp7, readFile as readFile14, rm as rm7 } from "fs/promises";
|
|
10835
10930
|
import { tmpdir as tmpdir7 } from "os";
|
|
10836
|
-
import
|
|
10931
|
+
import path20 from "path";
|
|
10837
10932
|
import { z as z37 } from "zod";
|
|
10838
10933
|
|
|
10839
10934
|
// src/engine/nodes/local/lib/ffmpeg.ts
|
|
@@ -11161,8 +11256,8 @@ async function tryExtractAudio(inputs, ctx) {
|
|
|
11161
11256
|
ctx.log("video_transcribe: no audio track detected, sending full video");
|
|
11162
11257
|
return null;
|
|
11163
11258
|
}
|
|
11164
|
-
tmpDir = await mkdtemp7(
|
|
11165
|
-
const audioPath =
|
|
11259
|
+
tmpDir = await mkdtemp7(path20.join(tmpdir7(), "vtx-"));
|
|
11260
|
+
const audioPath = path20.join(tmpDir, "audio.mp3");
|
|
11166
11261
|
ctx.log("video_transcribe: extracting audio (mono 16kHz mp3)");
|
|
11167
11262
|
await runFfmpeg(
|
|
11168
11263
|
["-i", video.path, "-vn", "-ac", "1", "-ar", "16000", "-b:a", "64k", "-f", "mp3", "-y", audioPath],
|
|
@@ -11360,14 +11455,14 @@ function catalogCost(def) {
|
|
|
11360
11455
|
// src/engine/storage/cache-store.ts
|
|
11361
11456
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
11362
11457
|
import { mkdir as mkdir3, readFile as readFile15, rename as rename2, writeFile as writeFile9 } from "fs/promises";
|
|
11363
|
-
import
|
|
11458
|
+
import path21 from "path";
|
|
11364
11459
|
var LocalCacheStore = class {
|
|
11365
11460
|
rootDir;
|
|
11366
11461
|
constructor(rootDir) {
|
|
11367
11462
|
this.rootDir = rootDir;
|
|
11368
11463
|
}
|
|
11369
11464
|
filePath(cacheKey) {
|
|
11370
|
-
return
|
|
11465
|
+
return path21.join(this.rootDir, `${cacheKey}.json`);
|
|
11371
11466
|
}
|
|
11372
11467
|
async get(cacheKey) {
|
|
11373
11468
|
try {
|
|
@@ -11380,7 +11475,7 @@ var LocalCacheStore = class {
|
|
|
11380
11475
|
}
|
|
11381
11476
|
async put(entry) {
|
|
11382
11477
|
const dest = this.filePath(entry.cacheKey);
|
|
11383
|
-
await mkdir3(
|
|
11478
|
+
await mkdir3(path21.dirname(dest), { recursive: true });
|
|
11384
11479
|
const tmp = `${dest}.tmp-${process.pid}-${randomUUID2()}`;
|
|
11385
11480
|
await writeFile9(tmp, JSON.stringify(entry, null, 0));
|
|
11386
11481
|
await rename2(tmp, dest);
|
|
@@ -11438,12 +11533,12 @@ function defaultRegistry() {
|
|
|
11438
11533
|
}
|
|
11439
11534
|
function createEngineFromEnv(opts = {}) {
|
|
11440
11535
|
const cwd = opts.cwd ?? process.cwd();
|
|
11441
|
-
const cacheDir = opts.cacheDir ??
|
|
11442
|
-
const outputsDir = opts.outputsDir ??
|
|
11536
|
+
const cacheDir = opts.cacheDir ?? path22.join(cwd, "canvas", ".cache");
|
|
11537
|
+
const outputsDir = opts.outputsDir ?? path22.join(cwd, "canvas");
|
|
11443
11538
|
const connection = requireConnection();
|
|
11444
11539
|
const client = new BackendClient({ baseUrl: connection.BAKER_API_URL, apiKey: connection.BAKER_API_KEY });
|
|
11445
|
-
const assets = new LocalAssetStore(
|
|
11446
|
-
const localCache = new LocalCacheStore(
|
|
11540
|
+
const assets = new LocalAssetStore(path22.join(cacheDir, "assets"));
|
|
11541
|
+
const localCache = new LocalCacheStore(path22.join(cacheDir, "index"));
|
|
11447
11542
|
const remoteCacheEnabled = opts.remoteCache ?? remoteCacheEnabledFromEnv();
|
|
11448
11543
|
const cache = remoteCacheEnabled ? new LayeredCacheStore({
|
|
11449
11544
|
local: localCache,
|
|
@@ -11565,4 +11660,4 @@ export {
|
|
|
11565
11660
|
defaultRegistry,
|
|
11566
11661
|
createEngineFromEnv
|
|
11567
11662
|
};
|
|
11568
|
-
//# sourceMappingURL=chunk-
|
|
11663
|
+
//# sourceMappingURL=chunk-X7PLV5QH.js.map
|