@koda-sl/baker-cli 0.400.0-dev.7f8839959 → 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.
@@ -20,9 +20,9 @@ import {
20
20
  shouldEscalate
21
21
  } from "./chunk-N72QYDJY.js";
22
22
 
23
- // ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/766ad107c42df28eeadaf0ac2f9089c8a9e200f6ba0b2b1a817b8d536cbdcc49/node_modules/safe-stable-stringify/index.js
23
+ // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js
24
24
  var require_safe_stable_stringify = __commonJS({
25
- "../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/766ad107c42df28eeadaf0ac2f9089c8a9e200f6ba0b2b1a817b8d536cbdcc49/node_modules/safe-stable-stringify/index.js"(exports, module) {
25
+ "../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js"(exports, module) {
26
26
  "use strict";
27
27
  var { hasOwnProperty } = Object.prototype;
28
28
  var stringify = configure2();
@@ -617,7 +617,7 @@ ${originalIndentation}`;
617
617
  });
618
618
 
619
619
  // src/engine/index.ts
620
- import path21 from "path";
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(path22, body, signal) {
671
- return await this.requestJson("POST", path22, body, signal);
670
+ async postJson(path23, body, signal) {
671
+ return await this.requestJson("POST", path23, body, signal);
672
672
  }
673
- async putJson(path22, body, signal) {
674
- return await this.requestJson("PUT", path22, body, signal);
673
+ async putJson(path23, body, signal) {
674
+ return await this.requestJson("PUT", path23, body, signal);
675
675
  }
676
- async getJson(path22, signal) {
677
- return await this.requestJson("GET", path22, void 0, signal);
676
+ async getJson(path23, signal) {
677
+ return await this.requestJson("GET", path23, void 0, signal);
678
678
  }
679
- async requestJson(method, path22, body, signal) {
680
- const url = `${this.baseUrl}${path22.startsWith("/") ? path22 : `/${path22}`}`;
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 path22 = `/api/canvas/jobs/${encodeURIComponent(jobId)}`;
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(path22, signal);
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 path22 = version ? `/api/canvas/artifacts/${encodeURIComponent(kind)}/${encodeURIComponent(name)}/${encodeURIComponent(version)}` : `/api/canvas/artifacts/${encodeURIComponent(kind)}/${encodeURIComponent(name)}`;
957
- return this.http.getJson(path22, signal);
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
 
@@ -1144,7 +1144,7 @@ function resolveAdaptFormats(params) {
1144
1144
  return params.formats ?? [];
1145
1145
  }
1146
1146
 
1147
- // ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/766ad107c42df28eeadaf0ac2f9089c8a9e200f6ba0b2b1a817b8d536cbdcc49/node_modules/safe-stable-stringify/esm/wrapper.js
1147
+ // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/esm/wrapper.js
1148
1148
  var import__ = __toESM(require_safe_stable_stringify(), 1);
1149
1149
  var configure = import__.default.configure;
1150
1150
  var wrapper_default = import__.default;
@@ -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, path22 = "") {
3282
+ function forEachString(value, visit, path23 = "") {
3283
3283
  if (typeof value === "string") {
3284
- visit(value, path22);
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, path22 ? `${path22}[${i}]` : `[${i}]`);
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, path22 ? `${path22}.${k}` : k);
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({ rawParams: n.params, rawInputs: n.inputs, nodeId: n.id, inputKindOf });
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 path22 = pathPrefix ? tail2 ? `${pathPrefix}.${tail2}` : pathPrefix : tail2;
6084
+ const path23 = pathPrefix ? tail2 ? `${pathPrefix}.${tail2}` : pathPrefix : tail2;
6065
6085
  issues.push({
6066
- path: path22,
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(path22) {
6076
- return path22.map((p) => typeof p === "number" ? `[${p}]` : `.${String(p)}`).join("").replace(/^\./, "");
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, path22) => {
6080
- if (s.startsWith(REF_PREFIX)) cb(s, path22);
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 path7 from "path";
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 path6 from "path";
6967
+ import path7 from "path";
6948
6968
 
6949
6969
  // src/lib/vimeoCookie.ts
6950
6970
  import { writeFile as writeFile3 } from "fs/promises";
6951
- import path5 from "path";
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 = path5.join(workDir, "vimeo-cookies.txt");
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 = path6.join(args.workDir, "out.%(ext)s");
7027
- const infoPath = path6.join(args.workDir, "out.info.json");
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: path6.join(args.workDir, downloaded), info, tier, reducedQuality };
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 (path7.isAbsolute(input)) return input;
7541
- return path7.resolve(process.cwd(), input);
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 = path7.extname(absPath).slice(1).toLowerCase();
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: path7.basename(args.absPath),
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(path7.join(tmpdir(), "ingest-yt-"));
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 path8 from "path";
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 = path8.extname(ref.path);
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 = path8.join(tmpDir, `in_${slot}_${i}${extForAssetRef(ref)}`);
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 = path8.join(tmpDir, `in_${slot}${extForAssetRef(ref)}`);
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 = path8.join(tmpDir, `out_${name}${ext}`);
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 = path8.resolve(substituted);
8060
- if (!resolved.startsWith(`${stagingDir}${path8.sep}`) && resolved !== 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(path8.join(tmpdir2(), `cli-${bin.replace(/[^a-z0-9]/gi, "")}-`));
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 path10 from "path";
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 path9 from "path";
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 = path9.join(destDir, filename);
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(path10.join(tmpdir3(), "font-specimen-"));
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 = path10.join(tmp, "index.html");
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 stat5, writeFile as writeFile7 } from "fs/promises";
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 path17 from "path";
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 path11 from "path";
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 = path11.join(current, name);
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 = path11.relative(root, abs).split(path11.sep).join("/");
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 path12 from "path";
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 = path12.join(compositionDir, "meta.json");
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 path13 from "path";
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 = path13.basename(src);
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, path13.join(dir, "gsap.min.js"));
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 path16 from "path";
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 path14 from "path";
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(path14.join(dir, "index.html"), "utf-8").catch(() => "");
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(path14.join(dir, "snapshots", "descriptions.md"), "utf-8").catch(() => "");
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(path14.join(dir, "index.html"), "utf-8").catch(() => "");
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 path15 from "path";
9209
+ import path16 from "path";
9183
9210
  async function ensureHyperframesMetaJson(tmp, nodeId, meta, duration) {
9184
- const metaPath = path15.join(tmp, "meta.json");
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(path16.join(args.dir, "index.html"), "utf-8").catch(() => null);
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 lintIssues(args));
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 lintIssues(args) {
9342
+ async function gateIssues(args) {
9316
9343
  if (!await isHyperframesAvailable()) return [];
9317
- const tmp = await mkdtemp4(path16.join(tmpdir4(), "hf-validate-"));
9344
+ const tmp = await mkdtemp4(path17.join(tmpdir4(), "hf-validate-"));
9318
9345
  try {
9319
- await copyComposition(args.dir, tmp);
9320
- await vendorGsap(tmp, { log: () => void 0 });
9321
- await stagePlaceholderInputs(tmp, args.meta, args.rawInputs);
9322
- const entry = path16.join(tmp, "index.html");
9323
- const html = await readFile11(entry, "utf-8");
9324
- await writeFile6(entry, substituteVariables(html, substitutionValues(args.meta, args.compositionParams)).output);
9325
- await ensureHyperframesMetaJson(tmp, args.nodeId ?? args.meta.id, args.meta, args.meta.default_duration);
9326
- const blockers = await lintPreparedComposition(tmp, args.lintTimeoutMs);
9327
- return blockers.map((b) => ({
9328
- path: "params.composition",
9329
- message: `pre-render gate would fail: [${b.code}] ${b.message}`
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
- async function stagePlaceholderInputs(dir, meta, rawInputs) {
9336
- const inputs = rawInputs && typeof rawInputs === "object" ? rawInputs : {};
9337
- for (const [key, spec] of Object.entries(meta.inputs)) {
9338
- if (!Object.hasOwn(inputs, key)) continue;
9339
- const filename = spec.staged_as ?? defaultFilenameForInput(key, spec.kind);
9340
- await writeFile6(path16.join(dir, filename), spec.kind === "json" ? "{}" : "");
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(path17.join(tmpdir5(), "hf-render-"));
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 = path17.join(tmp, `output.${params.format}`);
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 = path17.isAbsolute(composition) ? composition : path17.resolve(process.cwd(), composition);
9468
- const s = await stat5(compositionPath);
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 path17.dirname(compositionPath);
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
- lintTimeoutMs: 2e4
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(path17.join(tmp, filename));
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 = path17.join(tmp, "index.html");
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 ${path17.basename(tmp)}`);
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 path18 from "path";
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
- validateExtra: (args) => validateCompositionNode(args, NODE_OWNED_PARAM_KEYS2),
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(path18.join(tmpdir6(), "hf-snap-"));
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 = path18.join(tmp, "index.html");
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 = path18.join(tmp, "index.html");
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 path19 from "path";
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(path19.join(tmpdir7(), "vtx-"));
11165
- const audioPath = path19.join(tmpDir, "audio.mp3");
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 path20 from "path";
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 path20.join(this.rootDir, `${cacheKey}.json`);
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(path20.dirname(dest), { recursive: true });
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 ?? path21.join(cwd, "canvas", ".cache");
11442
- const outputsDir = opts.outputsDir ?? path21.join(cwd, "canvas");
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(path21.join(cacheDir, "assets"));
11446
- const localCache = new LocalCacheStore(path21.join(cacheDir, "index"));
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-LOG6SURL.js.map
11657
+ //# sourceMappingURL=chunk-U4OKU5EF.js.map