@koda-sl/baker-cli 0.400.0 → 0.401.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 +3 -0
- package/dist/{chunk-UW62VPTH.js → chunk-U4OKU5EF.js} +204 -115
- package/dist/chunk-U4OKU5EF.js.map +1 -0
- package/dist/cli.js +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
|
}
|
|
@@ -7023,8 +7043,8 @@ function tail(text, maxLines) {
|
|
|
7023
7043
|
return text.split("\n").slice(-maxLines).join("\n");
|
|
7024
7044
|
}
|
|
7025
7045
|
async function runYtDlp(args) {
|
|
7026
|
-
const outTemplate =
|
|
7027
|
-
const infoPath =
|
|
7046
|
+
const outTemplate = path7.join(args.workDir, "out.%(ext)s");
|
|
7047
|
+
const infoPath = path7.join(args.workDir, "out.info.json");
|
|
7028
7048
|
const argv = [
|
|
7029
7049
|
args.url,
|
|
7030
7050
|
"--no-playlist",
|
|
@@ -7065,7 +7085,7 @@ async function runYtDlp(args) {
|
|
|
7065
7085
|
info = JSON.parse(await readFile4(infoPath, "utf-8"));
|
|
7066
7086
|
} catch {
|
|
7067
7087
|
}
|
|
7068
|
-
return { filePath:
|
|
7088
|
+
return { filePath: path7.join(args.workDir, downloaded), info, tier, reducedQuality };
|
|
7069
7089
|
}
|
|
7070
7090
|
async function probeYtDlp(args) {
|
|
7071
7091
|
const argv = [
|
|
@@ -7537,8 +7557,8 @@ function resolveLocalPath(input) {
|
|
|
7537
7557
|
`ingest: ~ path expansion is not supported (got "${input}"). Use an absolute path or a cwd-relative path.`
|
|
7538
7558
|
);
|
|
7539
7559
|
}
|
|
7540
|
-
if (
|
|
7541
|
-
return
|
|
7560
|
+
if (path8.isAbsolute(input)) return input;
|
|
7561
|
+
return path8.resolve(process.cwd(), input);
|
|
7542
7562
|
}
|
|
7543
7563
|
var EXT_TO_MIME = {
|
|
7544
7564
|
png: "image/png",
|
|
@@ -7586,7 +7606,7 @@ function sniffSvg(buf) {
|
|
|
7586
7606
|
return head.startsWith("<?xml") ? head.includes("<svg") : head.startsWith("<svg");
|
|
7587
7607
|
}
|
|
7588
7608
|
function inferMimeFromPath(absPath, sniffBytes) {
|
|
7589
|
-
const ext =
|
|
7609
|
+
const ext = path8.extname(absPath).slice(1).toLowerCase();
|
|
7590
7610
|
const fromExt = EXT_TO_MIME[ext];
|
|
7591
7611
|
if (fromExt) return fromExt;
|
|
7592
7612
|
const fromBytes = sniffImageMime(sniffBytes);
|
|
@@ -7823,7 +7843,7 @@ function localFileMetadata(args) {
|
|
|
7823
7843
|
strategy: "local_file",
|
|
7824
7844
|
ingested_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7825
7845
|
file_size: args.fileSize,
|
|
7826
|
-
original_filename:
|
|
7846
|
+
original_filename: path8.basename(args.absPath),
|
|
7827
7847
|
...args.rasterizedFrom ? { rasterized_from: args.rasterizedFrom } : {},
|
|
7828
7848
|
...args.durationMs !== void 0 ? { duration_ms: args.durationMs } : {}
|
|
7829
7849
|
};
|
|
@@ -7845,7 +7865,7 @@ async function execYtDlp(params, ctx) {
|
|
|
7845
7865
|
if (params.expect !== "video" && params.expect !== "audio") {
|
|
7846
7866
|
throw new Error(`ingest: yt_dlp only handles video/audio, got expect=${params.expect}`);
|
|
7847
7867
|
}
|
|
7848
|
-
const workDir = await mkdtemp(
|
|
7868
|
+
const workDir = await mkdtemp(path8.join(tmpdir(), "ingest-yt-"));
|
|
7849
7869
|
try {
|
|
7850
7870
|
const { filePath, info, reducedQuality } = await runYtDlpForNode({
|
|
7851
7871
|
url: params.url,
|
|
@@ -7951,7 +7971,7 @@ import { z as z7 } from "zod";
|
|
|
7951
7971
|
import { execFile as execFileCb2, spawn as spawn2 } from "child_process";
|
|
7952
7972
|
import { copyFile as copyFile2, mkdtemp as mkdtemp2, readFile as readFile6, rm as rm2, stat as stat3 } from "fs/promises";
|
|
7953
7973
|
import { tmpdir as tmpdir2 } from "os";
|
|
7954
|
-
import
|
|
7974
|
+
import path9 from "path";
|
|
7955
7975
|
import { promisify as promisify2 } from "util";
|
|
7956
7976
|
var execFile2 = promisify2(execFileCb2);
|
|
7957
7977
|
var DEFAULT_TIMEOUT_MS2 = 10 * 60 * 1e3;
|
|
@@ -7978,7 +7998,7 @@ function mimeForExt(ext) {
|
|
|
7978
7998
|
}
|
|
7979
7999
|
function extForAssetRef(ref) {
|
|
7980
8000
|
if (ref.path) {
|
|
7981
|
-
const e =
|
|
8001
|
+
const e = path9.extname(ref.path);
|
|
7982
8002
|
if (e) return e;
|
|
7983
8003
|
}
|
|
7984
8004
|
const reverse = {
|
|
@@ -8000,14 +8020,14 @@ function planArrayInputSlot(tmpDir, slot, values, lookup, stagedInputs) {
|
|
|
8000
8020
|
const ref = values[i];
|
|
8001
8021
|
if (!ref) continue;
|
|
8002
8022
|
if (!ref.path) throw new Error(`cli-runner: inputs.${slot}[${i}] has no local path`);
|
|
8003
|
-
const dest =
|
|
8023
|
+
const dest = path9.join(tmpDir, `in_${slot}_${i}${extForAssetRef(ref)}`);
|
|
8004
8024
|
stagedInputs.push({ srcPath: ref.path, destPath: dest });
|
|
8005
8025
|
lookup.set(`in.${slot}.${i}`, dest);
|
|
8006
8026
|
}
|
|
8007
8027
|
}
|
|
8008
8028
|
function planSingleInputSlot(tmpDir, slot, ref, lookup, stagedInputs) {
|
|
8009
8029
|
if (!ref.path) throw new Error(`cli-runner: inputs.${slot} has no local path`);
|
|
8010
|
-
const dest =
|
|
8030
|
+
const dest = path9.join(tmpDir, `in_${slot}${extForAssetRef(ref)}`);
|
|
8011
8031
|
stagedInputs.push({ srcPath: ref.path, destPath: dest });
|
|
8012
8032
|
lookup.set(`in.${slot}`, dest);
|
|
8013
8033
|
}
|
|
@@ -8015,7 +8035,7 @@ function planOutputs(tmpDir, outputs, lookup) {
|
|
|
8015
8035
|
const outputPaths = [];
|
|
8016
8036
|
for (const [name, spec] of Object.entries(outputs)) {
|
|
8017
8037
|
const ext = spec.ext.startsWith(".") ? spec.ext : `.${spec.ext}`;
|
|
8018
|
-
const absPath =
|
|
8038
|
+
const absPath = path9.join(tmpDir, `out_${name}${ext}`);
|
|
8019
8039
|
outputPaths.push({ name, absPath, spec });
|
|
8020
8040
|
lookup.set(`out.${name}`, absPath);
|
|
8021
8041
|
}
|
|
@@ -8056,8 +8076,8 @@ function rejectRawPaths(substituted, original, stagingDir) {
|
|
|
8056
8076
|
throw new Error(`cli-runner: home-relative path "${original}" not allowed in args.`);
|
|
8057
8077
|
}
|
|
8058
8078
|
if (substituted.startsWith("/")) {
|
|
8059
|
-
const resolved =
|
|
8060
|
-
if (!resolved.startsWith(`${stagingDir}${
|
|
8079
|
+
const resolved = path9.resolve(substituted);
|
|
8080
|
+
if (!resolved.startsWith(`${stagingDir}${path9.sep}`) && resolved !== stagingDir) {
|
|
8061
8081
|
throw new Error(
|
|
8062
8082
|
`cli-runner: raw filesystem path "${original}" not allowed \u2014 declare an input slot and use {{in.<slot>}} instead.`
|
|
8063
8083
|
);
|
|
@@ -8107,7 +8127,7 @@ function tailLines(text, maxLines) {
|
|
|
8107
8127
|
}
|
|
8108
8128
|
async function runCli(opts) {
|
|
8109
8129
|
const { bin, args, inputs, outputs, ctx, timeoutMs = DEFAULT_TIMEOUT_MS2 } = opts;
|
|
8110
|
-
const tmpDir = await mkdtemp2(
|
|
8130
|
+
const tmpDir = await mkdtemp2(path9.join(tmpdir2(), `cli-${bin.replace(/[^a-z0-9]/gi, "")}-`));
|
|
8111
8131
|
try {
|
|
8112
8132
|
const { lookup, stagedInputs, outputPaths } = planPlaceholders(tmpDir, inputs, outputs);
|
|
8113
8133
|
await stageInputs(stagedInputs);
|
|
@@ -8488,17 +8508,17 @@ var ffmpegNode = defineNode({
|
|
|
8488
8508
|
import { mkdtemp as mkdtemp3, rm as rm3, writeFile as writeFile4 } from "fs/promises";
|
|
8489
8509
|
import { createRequire } from "module";
|
|
8490
8510
|
import { tmpdir as tmpdir3 } from "os";
|
|
8491
|
-
import
|
|
8511
|
+
import path11 from "path";
|
|
8492
8512
|
import { z as z11 } from "zod";
|
|
8493
8513
|
|
|
8494
8514
|
// src/engine/nodes/local/lib/assets.ts
|
|
8495
8515
|
import { copyFile as copyFile3, readFile as readFile7 } from "fs/promises";
|
|
8496
|
-
import
|
|
8516
|
+
import path10 from "path";
|
|
8497
8517
|
async function stageAsset(ref, destDir, filename) {
|
|
8498
8518
|
if (!ref.path) {
|
|
8499
8519
|
throw new Error(`stageAsset: ref (${ref.kind}/${ref.mime}) has no local path`);
|
|
8500
8520
|
}
|
|
8501
|
-
const dest =
|
|
8521
|
+
const dest = path10.join(destDir, filename);
|
|
8502
8522
|
await copyFile3(ref.path, dest);
|
|
8503
8523
|
return dest;
|
|
8504
8524
|
}
|
|
@@ -8575,11 +8595,11 @@ var fontSpecimenNode = defineNode({
|
|
|
8575
8595
|
outputKinds: { image: "image" },
|
|
8576
8596
|
cost: () => ({ credits: 0, seconds_estimate: 5 }),
|
|
8577
8597
|
async execute({ inputs, params, ctx }) {
|
|
8578
|
-
const tmp = await mkdtemp3(
|
|
8598
|
+
const tmp = await mkdtemp3(path11.join(tmpdir3(), "font-specimen-"));
|
|
8579
8599
|
try {
|
|
8580
8600
|
const fontFilename = `font.${extForMime(inputs.font.mime)}`;
|
|
8581
8601
|
await stageAsset(inputs.font, tmp, fontFilename);
|
|
8582
|
-
const entryPath =
|
|
8602
|
+
const entryPath = path11.join(tmp, "index.html");
|
|
8583
8603
|
await writeFile4(entryPath, buildSpecimenHtml(params, fontFilename), "utf-8");
|
|
8584
8604
|
ctx.log(`rendering specimen (${params.font_size}px, ${params.text.split("\n").length} lines)`);
|
|
8585
8605
|
const pwSpecifier = ["play", "wright"].join("");
|
|
@@ -8663,15 +8683,15 @@ var fontSpecimenNode = defineNode({
|
|
|
8663
8683
|
|
|
8664
8684
|
// src/engine/nodes/local/hyperframe.ts
|
|
8665
8685
|
import { execFile as execFile4 } from "child_process";
|
|
8666
|
-
import { mkdtemp as mkdtemp5, readFile as readFile12, rm as rm5, stat as
|
|
8686
|
+
import { mkdtemp as mkdtemp5, readFile as readFile12, rm as rm5, stat as stat6, writeFile as writeFile7 } from "fs/promises";
|
|
8667
8687
|
import { cpus, tmpdir as tmpdir5 } from "os";
|
|
8668
|
-
import
|
|
8688
|
+
import path18 from "path";
|
|
8669
8689
|
import { promisify as promisify4 } from "util";
|
|
8670
8690
|
import { z as z13 } from "zod";
|
|
8671
8691
|
|
|
8672
8692
|
// src/engine/engine/composition-hash.ts
|
|
8673
8693
|
import { readdir as readdir2, readFile as readFile8, stat as stat4 } from "fs/promises";
|
|
8674
|
-
import
|
|
8694
|
+
import path12 from "path";
|
|
8675
8695
|
var SKIP_DIRS = /* @__PURE__ */ new Set([".cache", ".git", "node_modules", "dist", "build", ".next", ".turbo"]);
|
|
8676
8696
|
function isSkippedName(name) {
|
|
8677
8697
|
if (name.startsWith(".")) return true;
|
|
@@ -8688,7 +8708,7 @@ async function collectFiles(root, current) {
|
|
|
8688
8708
|
const names = await readdir2(current);
|
|
8689
8709
|
for (const name of names) {
|
|
8690
8710
|
if (isSkippedName(name)) continue;
|
|
8691
|
-
const abs =
|
|
8711
|
+
const abs = path12.join(current, name);
|
|
8692
8712
|
const s = await stat4(abs);
|
|
8693
8713
|
if (s.isDirectory()) {
|
|
8694
8714
|
out.push(...await collectFiles(root, abs));
|
|
@@ -8696,7 +8716,7 @@ async function collectFiles(root, current) {
|
|
|
8696
8716
|
}
|
|
8697
8717
|
if (!s.isFile()) continue;
|
|
8698
8718
|
const bytes = await readFile8(abs);
|
|
8699
|
-
const relPath =
|
|
8719
|
+
const relPath = path12.relative(root, abs).split(path12.sep).join("/");
|
|
8700
8720
|
out.push({ relPath, contentSha: sha256Hex(bytes) });
|
|
8701
8721
|
}
|
|
8702
8722
|
return out;
|
|
@@ -8704,7 +8724,7 @@ async function collectFiles(root, current) {
|
|
|
8704
8724
|
|
|
8705
8725
|
// src/engine/engine/composition-meta.ts
|
|
8706
8726
|
import { readFile as readFile9 } from "fs/promises";
|
|
8707
|
-
import
|
|
8727
|
+
import path13 from "path";
|
|
8708
8728
|
import { z as z12 } from "zod";
|
|
8709
8729
|
var InputKind = z12.enum(["video", "image", "audio", "json", "font"]);
|
|
8710
8730
|
var InputSpec = z12.object({
|
|
@@ -8781,7 +8801,7 @@ var CompositionMetaSchema = z12.object({
|
|
|
8781
8801
|
params: z12.record(z12.string(), ParamSpec).default({})
|
|
8782
8802
|
}).strict();
|
|
8783
8803
|
async function loadCompositionMeta(compositionDir) {
|
|
8784
|
-
const metaPath =
|
|
8804
|
+
const metaPath = path13.join(compositionDir, "meta.json");
|
|
8785
8805
|
let raw;
|
|
8786
8806
|
try {
|
|
8787
8807
|
raw = await readFile9(metaPath, "utf-8");
|
|
@@ -8864,13 +8884,13 @@ function defaultFilenameForInput(key, kind) {
|
|
|
8864
8884
|
// src/engine/nodes/local/lib/composition-stage.ts
|
|
8865
8885
|
import { copyFile as copyFile4, cp } from "fs/promises";
|
|
8866
8886
|
import { createRequire as createRequire2 } from "module";
|
|
8867
|
-
import
|
|
8887
|
+
import path14 from "path";
|
|
8868
8888
|
var require_2 = createRequire2(import.meta.url);
|
|
8869
8889
|
async function copyComposition(srcDir, destDir) {
|
|
8870
8890
|
await cp(srcDir, destDir, {
|
|
8871
8891
|
recursive: true,
|
|
8872
8892
|
filter: (src) => {
|
|
8873
|
-
const name =
|
|
8893
|
+
const name = path14.basename(src);
|
|
8874
8894
|
if (name === ".cache" || name === "node_modules" || name === ".git") return false;
|
|
8875
8895
|
return true;
|
|
8876
8896
|
}
|
|
@@ -8879,21 +8899,21 @@ async function copyComposition(srcDir, destDir) {
|
|
|
8879
8899
|
async function vendorGsap(dir, ctx) {
|
|
8880
8900
|
try {
|
|
8881
8901
|
const gsapMin = require_2.resolve("gsap/dist/gsap.min.js");
|
|
8882
|
-
await copyFile4(gsapMin,
|
|
8902
|
+
await copyFile4(gsapMin, path14.join(dir, "gsap.min.js"));
|
|
8883
8903
|
} catch (e) {
|
|
8884
8904
|
ctx.log(`warning: could not vendor gsap.min.js (${e.message}); compositions must self-supply`);
|
|
8885
8905
|
}
|
|
8886
8906
|
}
|
|
8887
8907
|
|
|
8888
8908
|
// 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";
|
|
8909
|
+
import { mkdtemp as mkdtemp4, readFile as readFile11, rm as rm4, stat as stat5, writeFile as writeFile6 } from "fs/promises";
|
|
8890
8910
|
import { tmpdir as tmpdir4 } from "os";
|
|
8891
|
-
import
|
|
8911
|
+
import path17 from "path";
|
|
8892
8912
|
|
|
8893
8913
|
// src/engine/nodes/local/lib/hyperframe-check.ts
|
|
8894
8914
|
import { execFile as execFile3 } from "child_process";
|
|
8895
8915
|
import { readFile as readFile10 } from "fs/promises";
|
|
8896
|
-
import
|
|
8916
|
+
import path15 from "path";
|
|
8897
8917
|
import { promisify as promisify3 } from "util";
|
|
8898
8918
|
|
|
8899
8919
|
// src/engine/nodes/local/lib/caption-style.ts
|
|
@@ -9076,6 +9096,13 @@ async function lintPreparedComposition(dir, timeoutMs) {
|
|
|
9076
9096
|
const lintRaw = await runOne(buildLintArgsNoInstall(dir), timeoutMs);
|
|
9077
9097
|
return lintRaw === null ? [] : lintBlockers(lintRaw);
|
|
9078
9098
|
}
|
|
9099
|
+
function layoutBlockers(checkRaw) {
|
|
9100
|
+
return classifyGateOutput(checkRaw).blocking.filter((f) => f.source === "layout").map((f) => ({ code: f.code, message: explainGateFinding(f) }));
|
|
9101
|
+
}
|
|
9102
|
+
async function checkPreparedLayout(dir, timeoutMs) {
|
|
9103
|
+
const checkRaw = await runOne(["--no-install", ...buildCheckArgs(dir, 1)], timeoutMs);
|
|
9104
|
+
return checkRaw === null ? [] : layoutBlockers(checkRaw);
|
|
9105
|
+
}
|
|
9079
9106
|
function buildInspectArgs(dir, samples) {
|
|
9080
9107
|
return ["hyperframes", "inspect", dir, "--json", "--samples", String(samples)];
|
|
9081
9108
|
}
|
|
@@ -9116,7 +9143,7 @@ async function runSnapshotSmoke(args, timeoutMs) {
|
|
|
9116
9143
|
}
|
|
9117
9144
|
async function runNestedCompositionSmoke(opts) {
|
|
9118
9145
|
const { dir, nodeId, ctx, timeoutMs, samples } = opts;
|
|
9119
|
-
const indexHtml = await readFile10(
|
|
9146
|
+
const indexHtml = await readFile10(path15.join(dir, "index.html"), "utf-8").catch(() => "");
|
|
9120
9147
|
if (!indexHtml || !usesNestedCompositions(indexHtml)) return;
|
|
9121
9148
|
const snap = await runSnapshotSmoke(
|
|
9122
9149
|
buildSnapshotArgs(dir, Math.min(samples, 3), hasFrameVisionKey()),
|
|
@@ -9132,7 +9159,7 @@ async function runNestedCompositionSmoke(opts) {
|
|
|
9132
9159
|
${snap.message}`
|
|
9133
9160
|
);
|
|
9134
9161
|
}
|
|
9135
|
-
const described = await readFile10(
|
|
9162
|
+
const described = await readFile10(path15.join(dir, "snapshots", "descriptions.md"), "utf-8").catch(() => "");
|
|
9136
9163
|
for (const line of condenseFrameDescriptions(described)) {
|
|
9137
9164
|
ctx.log(`${nodeId}: frame check \u2014 ${line}`);
|
|
9138
9165
|
}
|
|
@@ -9168,7 +9195,7 @@ async function runHyperframesCheck(opts) {
|
|
|
9168
9195
|
${detail}`
|
|
9169
9196
|
);
|
|
9170
9197
|
}
|
|
9171
|
-
const composition = await readFile10(
|
|
9198
|
+
const composition = await readFile10(path15.join(dir, "index.html"), "utf-8").catch(() => "");
|
|
9172
9199
|
const captionComplaint = fragmentedCaptions(captionTextsFrom(composition));
|
|
9173
9200
|
if (captionComplaint) {
|
|
9174
9201
|
ctx.log(`${nodeId}: caption style \u2014 ${captionComplaint}`);
|
|
@@ -9179,9 +9206,9 @@ ${detail}`
|
|
|
9179
9206
|
|
|
9180
9207
|
// src/engine/nodes/local/lib/hyperframe-meta.ts
|
|
9181
9208
|
import { writeFile as writeFile5 } from "fs/promises";
|
|
9182
|
-
import
|
|
9209
|
+
import path16 from "path";
|
|
9183
9210
|
async function ensureHyperframesMetaJson(tmp, nodeId, meta, duration) {
|
|
9184
|
-
const metaPath =
|
|
9211
|
+
const metaPath = path16.join(tmp, "meta.json");
|
|
9185
9212
|
await writeFile5(
|
|
9186
9213
|
metaPath,
|
|
9187
9214
|
JSON.stringify(
|
|
@@ -9244,11 +9271,11 @@ function extractReferencedTokens(source) {
|
|
|
9244
9271
|
|
|
9245
9272
|
// src/engine/nodes/local/lib/composition-static-check.ts
|
|
9246
9273
|
async function staticCompositionIssues(args) {
|
|
9247
|
-
const html = await readFile11(
|
|
9274
|
+
const html = await readFile11(path17.join(args.dir, "index.html"), "utf-8").catch(() => null);
|
|
9248
9275
|
const issues = inputIssues(args.meta, args.rawInputs, args.inputKindOf);
|
|
9249
9276
|
if (html === null) return issues;
|
|
9250
9277
|
issues.push(...undefinedVariableIssues(html, args.meta, args.compositionParams));
|
|
9251
|
-
issues.push(...await
|
|
9278
|
+
issues.push(...await gateIssues(args));
|
|
9252
9279
|
return issues;
|
|
9253
9280
|
}
|
|
9254
9281
|
function substitutionValues(meta, compositionParams) {
|
|
@@ -9312,33 +9339,91 @@ function kindMismatch(expected, got) {
|
|
|
9312
9339
|
if (got === "value") return "got a plain value, not an asset";
|
|
9313
9340
|
return `got "${got}"`;
|
|
9314
9341
|
}
|
|
9315
|
-
async function
|
|
9342
|
+
async function gateIssues(args) {
|
|
9316
9343
|
if (!await isHyperframesAvailable()) return [];
|
|
9317
|
-
const tmp = await mkdtemp4(
|
|
9344
|
+
const tmp = await mkdtemp4(path17.join(tmpdir4(), "hf-validate-"));
|
|
9318
9345
|
try {
|
|
9319
|
-
await
|
|
9320
|
-
await
|
|
9321
|
-
await
|
|
9322
|
-
|
|
9323
|
-
|
|
9324
|
-
|
|
9325
|
-
|
|
9326
|
-
|
|
9327
|
-
|
|
9328
|
-
|
|
9329
|
-
|
|
9330
|
-
|
|
9346
|
+
const { faithful } = await prepareForGate(tmp, args);
|
|
9347
|
+
const lint = await lintPreparedComposition(tmp, args.lintTimeoutMs);
|
|
9348
|
+
const layout = args.checkLayout && faithful ? await checkPreparedLayout(tmp, LAYOUT_CHECK_TIMEOUT_MS) : [];
|
|
9349
|
+
return [
|
|
9350
|
+
...lint.map((b) => ({
|
|
9351
|
+
path: "params.composition",
|
|
9352
|
+
message: `pre-render gate would fail: [${b.code}] ${b.message}`
|
|
9353
|
+
})),
|
|
9354
|
+
...layout.map((b) => ({
|
|
9355
|
+
path: "params.composition",
|
|
9356
|
+
message: `pre-render gate would fail: [layout/${b.code}] ${b.message} Nothing was rendered or billed.`
|
|
9357
|
+
}))
|
|
9358
|
+
];
|
|
9331
9359
|
} finally {
|
|
9332
9360
|
await rm4(tmp, { recursive: true, force: true }).catch(() => void 0);
|
|
9333
9361
|
}
|
|
9334
9362
|
}
|
|
9335
|
-
|
|
9336
|
-
|
|
9337
|
-
|
|
9338
|
-
|
|
9339
|
-
|
|
9340
|
-
|
|
9363
|
+
var LAYOUT_CHECK_TIMEOUT_MS = 6e4;
|
|
9364
|
+
var MAX_INPUT_BYTES = 20 * 1024 * 1024;
|
|
9365
|
+
var STAND_IN_PICTURE = Buffer.from(
|
|
9366
|
+
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=",
|
|
9367
|
+
"base64"
|
|
9368
|
+
);
|
|
9369
|
+
async function readSource(source) {
|
|
9370
|
+
try {
|
|
9371
|
+
if ("path" in source) {
|
|
9372
|
+
const info = await stat5(source.path);
|
|
9373
|
+
return info.isFile() && info.size <= MAX_INPUT_BYTES ? await readFile11(source.path) : null;
|
|
9374
|
+
}
|
|
9375
|
+
return (await fetchExternalBytes(source.url, { maxBytes: MAX_INPUT_BYTES, timeoutMs: 15e3 })).buffer;
|
|
9376
|
+
} catch {
|
|
9377
|
+
return null;
|
|
9378
|
+
}
|
|
9379
|
+
}
|
|
9380
|
+
function standIn(kind) {
|
|
9381
|
+
if (kind === "image") return STAND_IN_PICTURE;
|
|
9382
|
+
return kind === "json" ? "{}" : "";
|
|
9383
|
+
}
|
|
9384
|
+
async function prepareForGate(target, args) {
|
|
9385
|
+
await copyComposition(args.dir, target);
|
|
9386
|
+
await vendorGsap(target, { log: () => void 0 });
|
|
9387
|
+
const staged = await stageGateInputs(target, args);
|
|
9388
|
+
const filled = fillParamSlots(args.meta, args.compositionParams, staged.slotTexts);
|
|
9389
|
+
const entry = path17.join(target, "index.html");
|
|
9390
|
+
const html = await readFile11(entry, "utf-8");
|
|
9391
|
+
await writeFile6(entry, substituteVariables(html, substitutionValues(args.meta, filled.params)).output);
|
|
9392
|
+
await ensureHyperframesMetaJson(target, args.meta.id, args.meta, args.meta.default_duration);
|
|
9393
|
+
return { faithful: staged.faithful && filled.faithful };
|
|
9394
|
+
}
|
|
9395
|
+
async function stageGateInputs(target, args) {
|
|
9396
|
+
const inputs = args.rawInputs && typeof args.rawInputs === "object" ? args.rawInputs : {};
|
|
9397
|
+
const wired = Object.entries(args.meta.inputs).filter(([key]) => Object.hasOwn(inputs, key));
|
|
9398
|
+
const staged = await Promise.all(
|
|
9399
|
+
wired.map(async ([key, spec]) => {
|
|
9400
|
+
const filename = path17.join(target, spec.staged_as ?? defaultFilenameForInput(key, spec.kind));
|
|
9401
|
+
const source = args.inputSourceOf?.(inputs[key]);
|
|
9402
|
+
const bytes = source ? await readSource(source) : null;
|
|
9403
|
+
await writeFile6(filename, bytes ?? standIn(spec.kind));
|
|
9404
|
+
const faithful = bytes !== null || !source && spec.kind === "image";
|
|
9405
|
+
return { key, faithful, text: bytes && spec.kind === "json" ? bytes.toString("utf8") : null };
|
|
9406
|
+
})
|
|
9407
|
+
);
|
|
9408
|
+
const slotTexts = {};
|
|
9409
|
+
for (const { key, text } of staged) if (text !== null) slotTexts[key] = text;
|
|
9410
|
+
return { faithful: staged.every((s) => s.faithful), slotTexts };
|
|
9411
|
+
}
|
|
9412
|
+
function fillParamSlots(meta, compositionParams, slotTexts) {
|
|
9413
|
+
let faithful = true;
|
|
9414
|
+
const params = {};
|
|
9415
|
+
for (const [name, value] of Object.entries(compositionParams)) {
|
|
9416
|
+
const slots = typeof value === "string" ? extractReferencedTokens(value) : [];
|
|
9417
|
+
if (typeof value !== "string" || slots.length === 0) {
|
|
9418
|
+
params[name] = value;
|
|
9419
|
+
} else if (slots.every((slot) => Object.hasOwn(slotTexts, slot))) {
|
|
9420
|
+
params[name] = renderTemplate(value, slotTexts);
|
|
9421
|
+
} else {
|
|
9422
|
+
faithful = false;
|
|
9423
|
+
params[name] = placeholderFor(meta.params[name]?.kind);
|
|
9424
|
+
}
|
|
9341
9425
|
}
|
|
9426
|
+
return { faithful, params };
|
|
9342
9427
|
}
|
|
9343
9428
|
|
|
9344
9429
|
// src/engine/nodes/local/lib/hyperframe-errors.ts
|
|
@@ -9430,7 +9515,7 @@ var hyperframeRenderNode = defineNode({
|
|
|
9430
9515
|
const compositionDir = await resolveCompositionDir(params.composition);
|
|
9431
9516
|
const meta = await loadCompositionMeta(compositionDir);
|
|
9432
9517
|
const compositionParams = validateAndParseDynamicParams(meta, params);
|
|
9433
|
-
const tmp = await mkdtemp5(
|
|
9518
|
+
const tmp = await mkdtemp5(path18.join(tmpdir5(), "hf-render-"));
|
|
9434
9519
|
try {
|
|
9435
9520
|
await copyComposition(compositionDir, tmp);
|
|
9436
9521
|
await vendorGsap(tmp, ctx);
|
|
@@ -9440,7 +9525,7 @@ var hyperframeRenderNode = defineNode({
|
|
|
9440
9525
|
await substituteCompositionFiles(tmp, substitutionValues2);
|
|
9441
9526
|
await ensureHyperframesMetaJson(tmp, ctx.nodeId, meta, duration);
|
|
9442
9527
|
await runHyperframesCheck({ dir: tmp, nodeId: "hyperframe_render", ctx, timeoutMs: params.timeout_ms });
|
|
9443
|
-
const outputPath =
|
|
9528
|
+
const outputPath = path18.join(tmp, `output.${params.format}`);
|
|
9444
9529
|
await runRender({ tmp, outputPath, params, meta, ctx });
|
|
9445
9530
|
const bytes = await readFile12(outputPath);
|
|
9446
9531
|
ctx.log(`rendered ${bytes.length} bytes`);
|
|
@@ -9464,12 +9549,12 @@ var hyperframeRenderNode = defineNode({
|
|
|
9464
9549
|
}
|
|
9465
9550
|
});
|
|
9466
9551
|
async function resolveCompositionDir(composition) {
|
|
9467
|
-
const compositionPath =
|
|
9468
|
-
const s = await
|
|
9552
|
+
const compositionPath = path18.isAbsolute(composition) ? composition : path18.resolve(process.cwd(), composition);
|
|
9553
|
+
const s = await stat6(compositionPath);
|
|
9469
9554
|
if (s.isDirectory()) return compositionPath;
|
|
9470
|
-
return
|
|
9555
|
+
return path18.dirname(compositionPath);
|
|
9471
9556
|
}
|
|
9472
|
-
async function validateCompositionNode(args, ownedKeys) {
|
|
9557
|
+
async function validateCompositionNode(args, ownedKeys, options = {}) {
|
|
9473
9558
|
const issues = await validateCompositionParams(args.rawParams, ownedKeys);
|
|
9474
9559
|
const params = args.rawParams ?? {};
|
|
9475
9560
|
if (typeof params.composition !== "string") return issues;
|
|
@@ -9485,7 +9570,9 @@ async function validateCompositionNode(args, ownedKeys) {
|
|
|
9485
9570
|
compositionParams,
|
|
9486
9571
|
rawInputs: args.rawInputs,
|
|
9487
9572
|
inputKindOf: args.inputKindOf,
|
|
9488
|
-
|
|
9573
|
+
inputSourceOf: args.inputSourceOf,
|
|
9574
|
+
lintTimeoutMs: 2e4,
|
|
9575
|
+
checkLayout: options.checkLayout
|
|
9489
9576
|
})
|
|
9490
9577
|
);
|
|
9491
9578
|
return issues;
|
|
@@ -9560,7 +9647,7 @@ async function stageInputs2(tmp, inputs, meta, ctx) {
|
|
|
9560
9647
|
await stageAsset(ref, tmp, filename);
|
|
9561
9648
|
ctx.log(`staged ${spec.kind} \u2192 ${filename}`);
|
|
9562
9649
|
if (spec.kind === "video" && primaryDuration === null) {
|
|
9563
|
-
primaryDuration = await probeDurationSeconds(
|
|
9650
|
+
primaryDuration = await probeDurationSeconds(path18.join(tmp, filename));
|
|
9564
9651
|
}
|
|
9565
9652
|
}
|
|
9566
9653
|
return primaryDuration;
|
|
@@ -9606,7 +9693,7 @@ function coerceImageParam(value) {
|
|
|
9606
9693
|
throw new Error("hyperframe_render: image param must be a URL string or AssetRef");
|
|
9607
9694
|
}
|
|
9608
9695
|
async function substituteCompositionFiles(tmp, values) {
|
|
9609
|
-
const entryPath =
|
|
9696
|
+
const entryPath = path18.join(tmp, "index.html");
|
|
9610
9697
|
const original = await readFile12(entryPath, "utf-8");
|
|
9611
9698
|
const { output, missing } = substituteVariables(original, values);
|
|
9612
9699
|
if (missing.length > 0) {
|
|
@@ -9623,7 +9710,7 @@ function workerCount() {
|
|
|
9623
9710
|
async function runRender(opts) {
|
|
9624
9711
|
const { tmp, outputPath, params, meta, ctx } = opts;
|
|
9625
9712
|
const args = buildRenderArgs(tmp, outputPath, meta, params.format);
|
|
9626
|
-
ctx.log(`rendering ${meta.width}x${meta.height}@${meta.fps}fps ${params.format} from ${
|
|
9713
|
+
ctx.log(`rendering ${meta.width}x${meta.height}@${meta.fps}fps ${params.format} from ${path18.basename(tmp)}`);
|
|
9627
9714
|
try {
|
|
9628
9715
|
await execFileAsync2("npx", args, { timeout: params.timeout_ms, maxBuffer: 64 * 1024 * 1024 });
|
|
9629
9716
|
} catch (e) {
|
|
@@ -9670,7 +9757,7 @@ import { execFile as execFile5 } from "child_process";
|
|
|
9670
9757
|
import { mkdtemp as mkdtemp6, readFile as readFile13, rm as rm6, writeFile as writeFile8 } from "fs/promises";
|
|
9671
9758
|
import { createRequire as createRequire3 } from "module";
|
|
9672
9759
|
import { tmpdir as tmpdir6 } from "os";
|
|
9673
|
-
import
|
|
9760
|
+
import path19 from "path";
|
|
9674
9761
|
import { promisify as promisify5 } from "util";
|
|
9675
9762
|
import { z as z14 } from "zod";
|
|
9676
9763
|
var _execFileAsync = promisify5(execFile5);
|
|
@@ -9705,7 +9792,9 @@ var hyperframeSnapshotNode = defineNode({
|
|
|
9705
9792
|
cost: () => ({ credits: 0, seconds_estimate: 3 }),
|
|
9706
9793
|
// The snapshot's own keys (`wait_for`) are not composition params: checked against the
|
|
9707
9794
|
// render node's key set, a canvas that waited on a selector failed validate every time.
|
|
9708
|
-
|
|
9795
|
+
// A still has one frame and its copy is known before the run, so validate lays it out
|
|
9796
|
+
// and refuses colliding lines before a single picture is paid for.
|
|
9797
|
+
validateExtra: (args) => validateCompositionNode(args, NODE_OWNED_PARAM_KEYS2, { checkLayout: true }),
|
|
9709
9798
|
cacheKeyExtras: async ({ params }) => {
|
|
9710
9799
|
const out = {};
|
|
9711
9800
|
const composition = params.composition;
|
|
@@ -9719,7 +9808,7 @@ var hyperframeSnapshotNode = defineNode({
|
|
|
9719
9808
|
const compositionDir = await resolveCompositionDir(params.composition);
|
|
9720
9809
|
const meta = await loadCompositionMeta(compositionDir);
|
|
9721
9810
|
const compositionParams = validateAndParseDynamicParams2(meta, params);
|
|
9722
|
-
const tmp = await mkdtemp6(
|
|
9811
|
+
const tmp = await mkdtemp6(path19.join(tmpdir6(), "hf-snap-"));
|
|
9723
9812
|
try {
|
|
9724
9813
|
await copyComposition(compositionDir, tmp);
|
|
9725
9814
|
await vendorGsap(tmp, ctx);
|
|
@@ -9734,7 +9823,7 @@ var hyperframeSnapshotNode = defineNode({
|
|
|
9734
9823
|
timeoutMs: params.timeout_ms,
|
|
9735
9824
|
samples: 1
|
|
9736
9825
|
});
|
|
9737
|
-
const entryPath =
|
|
9826
|
+
const entryPath = path19.join(tmp, "index.html");
|
|
9738
9827
|
const entryUrl = `file://${entryPath}`;
|
|
9739
9828
|
ctx.log(`snapshotting ${meta.width}x${meta.height}@${DEVICE_SCALE_FACTOR2}x wait=${params.wait_for.kind}`);
|
|
9740
9829
|
const pwSpecifier = ["play", "wright"].join("");
|
|
@@ -9819,7 +9908,7 @@ function coerceImageParam2(value) {
|
|
|
9819
9908
|
throw new Error("hyperframe_snapshot: image param must be a URL string or AssetRef");
|
|
9820
9909
|
}
|
|
9821
9910
|
async function substituteCompositionFiles2(tmp, values) {
|
|
9822
|
-
const entryPath =
|
|
9911
|
+
const entryPath = path19.join(tmp, "index.html");
|
|
9823
9912
|
const original = await readFile13(entryPath, "utf-8");
|
|
9824
9913
|
const { output, missing } = substituteVariables(original, values);
|
|
9825
9914
|
if (missing.length > 0) {
|
|
@@ -10833,7 +10922,7 @@ var videoLipsyncNode = delegated({
|
|
|
10833
10922
|
// src/engine/nodes/remote/videoTranscribe.ts
|
|
10834
10923
|
import { mkdtemp as mkdtemp7, readFile as readFile14, rm as rm7 } from "fs/promises";
|
|
10835
10924
|
import { tmpdir as tmpdir7 } from "os";
|
|
10836
|
-
import
|
|
10925
|
+
import path20 from "path";
|
|
10837
10926
|
import { z as z37 } from "zod";
|
|
10838
10927
|
|
|
10839
10928
|
// src/engine/nodes/local/lib/ffmpeg.ts
|
|
@@ -11161,8 +11250,8 @@ async function tryExtractAudio(inputs, ctx) {
|
|
|
11161
11250
|
ctx.log("video_transcribe: no audio track detected, sending full video");
|
|
11162
11251
|
return null;
|
|
11163
11252
|
}
|
|
11164
|
-
tmpDir = await mkdtemp7(
|
|
11165
|
-
const audioPath =
|
|
11253
|
+
tmpDir = await mkdtemp7(path20.join(tmpdir7(), "vtx-"));
|
|
11254
|
+
const audioPath = path20.join(tmpDir, "audio.mp3");
|
|
11166
11255
|
ctx.log("video_transcribe: extracting audio (mono 16kHz mp3)");
|
|
11167
11256
|
await runFfmpeg(
|
|
11168
11257
|
["-i", video.path, "-vn", "-ac", "1", "-ar", "16000", "-b:a", "64k", "-f", "mp3", "-y", audioPath],
|
|
@@ -11360,14 +11449,14 @@ function catalogCost(def) {
|
|
|
11360
11449
|
// src/engine/storage/cache-store.ts
|
|
11361
11450
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
11362
11451
|
import { mkdir as mkdir3, readFile as readFile15, rename as rename2, writeFile as writeFile9 } from "fs/promises";
|
|
11363
|
-
import
|
|
11452
|
+
import path21 from "path";
|
|
11364
11453
|
var LocalCacheStore = class {
|
|
11365
11454
|
rootDir;
|
|
11366
11455
|
constructor(rootDir) {
|
|
11367
11456
|
this.rootDir = rootDir;
|
|
11368
11457
|
}
|
|
11369
11458
|
filePath(cacheKey) {
|
|
11370
|
-
return
|
|
11459
|
+
return path21.join(this.rootDir, `${cacheKey}.json`);
|
|
11371
11460
|
}
|
|
11372
11461
|
async get(cacheKey) {
|
|
11373
11462
|
try {
|
|
@@ -11380,7 +11469,7 @@ var LocalCacheStore = class {
|
|
|
11380
11469
|
}
|
|
11381
11470
|
async put(entry) {
|
|
11382
11471
|
const dest = this.filePath(entry.cacheKey);
|
|
11383
|
-
await mkdir3(
|
|
11472
|
+
await mkdir3(path21.dirname(dest), { recursive: true });
|
|
11384
11473
|
const tmp = `${dest}.tmp-${process.pid}-${randomUUID2()}`;
|
|
11385
11474
|
await writeFile9(tmp, JSON.stringify(entry, null, 0));
|
|
11386
11475
|
await rename2(tmp, dest);
|
|
@@ -11438,12 +11527,12 @@ function defaultRegistry() {
|
|
|
11438
11527
|
}
|
|
11439
11528
|
function createEngineFromEnv(opts = {}) {
|
|
11440
11529
|
const cwd = opts.cwd ?? process.cwd();
|
|
11441
|
-
const cacheDir = opts.cacheDir ??
|
|
11442
|
-
const outputsDir = opts.outputsDir ??
|
|
11530
|
+
const cacheDir = opts.cacheDir ?? path22.join(cwd, "canvas", ".cache");
|
|
11531
|
+
const outputsDir = opts.outputsDir ?? path22.join(cwd, "canvas");
|
|
11443
11532
|
const connection = requireConnection();
|
|
11444
11533
|
const client = new BackendClient({ baseUrl: connection.BAKER_API_URL, apiKey: connection.BAKER_API_KEY });
|
|
11445
|
-
const assets = new LocalAssetStore(
|
|
11446
|
-
const localCache = new LocalCacheStore(
|
|
11534
|
+
const assets = new LocalAssetStore(path22.join(cacheDir, "assets"));
|
|
11535
|
+
const localCache = new LocalCacheStore(path22.join(cacheDir, "index"));
|
|
11447
11536
|
const remoteCacheEnabled = opts.remoteCache ?? remoteCacheEnabledFromEnv();
|
|
11448
11537
|
const cache = remoteCacheEnabled ? new LayeredCacheStore({
|
|
11449
11538
|
local: localCache,
|
|
@@ -11565,4 +11654,4 @@ export {
|
|
|
11565
11654
|
defaultRegistry,
|
|
11566
11655
|
createEngineFromEnv
|
|
11567
11656
|
};
|
|
11568
|
-
//# sourceMappingURL=chunk-
|
|
11657
|
+
//# sourceMappingURL=chunk-U4OKU5EF.js.map
|