@koda-sl/baker-cli 0.352.0 → 0.353.0-dev.0a55fe912

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/dist/cli.js CHANGED
@@ -42,6 +42,7 @@ import {
42
42
  isAudioOnly,
43
43
  isPersistedAssetRef,
44
44
  isVimeoAuthFailure,
45
+ loadCompositionMeta,
45
46
  looksLikeHttpUrl,
46
47
  maxInputReferences,
47
48
  maxInputSlot,
@@ -68,7 +69,7 @@ import {
68
69
  validateCanvasDeep,
69
70
  withoutCastName,
70
71
  ytDlpBlockSignal
71
- } from "./chunk-4HRJQGVW.js";
72
+ } from "./chunk-Q2VR3FVM.js";
72
73
  import {
73
74
  csvOrJson,
74
75
  daysAgoIso,
@@ -35531,7 +35532,49 @@ import { defineCommand as defineCommand119 } from "citty";
35531
35532
 
35532
35533
  // src/commands/canvas/catalog.ts
35533
35534
  import { defineCommand as defineCommand108 } from "citty";
35534
- var DESCRIPTION = "The canvas node catalog. Start here: `baker canvas catalog` lists every node by category with one line each (a few KB). Then `--node video_generate` prints that node's full JSON Schema \u2014 params, inputs, outputs, models, when to use it. `--category image` narrows the list; add `--full` for that category's schemas. `--full` alone prints every schema (~160 KB) \u2014 prefer `--node`.";
35535
+
35536
+ // src/commands/canvas/composition-path.ts
35537
+ import { existsSync as existsSync4 } from "fs";
35538
+ import { readdir as readdir2 } from "fs/promises";
35539
+ import path3 from "path";
35540
+ function resolveShippedCanvasDir(name, startDir, exists2 = existsSync4, maxDepth = 8) {
35541
+ const rel = path3.join("canvas", name);
35542
+ let dir = startDir;
35543
+ for (let i = 0; i < maxDepth; i++) {
35544
+ const candidate = path3.join(dir, rel);
35545
+ if (exists2(path3.join(candidate, "meta.json"))) return candidate;
35546
+ const parent = path3.dirname(dir);
35547
+ if (parent === dir) break;
35548
+ dir = parent;
35549
+ }
35550
+ return path3.resolve(startDir, "../../../", rel);
35551
+ }
35552
+ async function listShippedCompositions(startDir, maxDepth = 8) {
35553
+ let dir = startDir;
35554
+ for (let i = 0; i < maxDepth; i++) {
35555
+ const root = path3.join(dir, "canvas");
35556
+ const found = await compositionsIn(root);
35557
+ if (found.length > 0) return found.sort((a, b) => a.id.localeCompare(b.id));
35558
+ const parent = path3.dirname(dir);
35559
+ if (parent === dir) break;
35560
+ dir = parent;
35561
+ }
35562
+ return [];
35563
+ }
35564
+ async function compositionsIn(root) {
35565
+ const children = await readdir2(root, { withFileTypes: true }).catch(() => []);
35566
+ const loaded = await Promise.all(
35567
+ children.filter((child) => child.isDirectory()).map(async (child) => {
35568
+ const compositionDir = path3.join(root, child.name);
35569
+ const meta = await loadCompositionMeta(compositionDir).catch(() => null);
35570
+ return meta ? { id: meta.id, title: meta.title, dir: compositionDir } : null;
35571
+ })
35572
+ );
35573
+ return loaded.filter((c) => c !== null);
35574
+ }
35575
+
35576
+ // src/commands/canvas/catalog.ts
35577
+ var DESCRIPTION = "The canvas node catalog. Start here: `baker canvas catalog` lists every node by category with one line each (a few KB). Then `--node video_generate` prints that node's full JSON Schema \u2014 params, inputs, outputs, models, when to use it. `--category image` narrows the list; add `--full` for that category's schemas. `--full` alone prints every schema (~160 KB) \u2014 prefer `--node`. The unfiltered list also carries `compositions` \u2014 ready-made motion graphics, each with the `dir` to copy next to your canvas.";
35535
35578
  var ARGS = {
35536
35579
  node: {
35537
35580
  type: "string",
@@ -35550,12 +35593,16 @@ var ARGS = {
35550
35593
  description: "Print full JSON Schemas instead of the one-line index (every node, or the --category)."
35551
35594
  }
35552
35595
  };
35596
+ async function canvasCatalog(opts) {
35597
+ const compositions = await listShippedCompositions(import.meta.dirname);
35598
+ return catalogView(generateCatalog(defaultRegistry(), { compositions }), opts);
35599
+ }
35553
35600
  registerSchema({ command: "canvas.catalog", description: DESCRIPTION, args: ARGS });
35554
35601
  var catalogCommand = defineCommand108({
35555
35602
  meta: { name: "catalog", description: DESCRIPTION },
35556
35603
  args: ARGS,
35557
35604
  async run({ args: args5 }) {
35558
- const view = catalogView(generateCatalog(defaultRegistry()), {
35605
+ const view = await canvasCatalog({
35559
35606
  node: typeof args5.node === "string" ? args5.node : void 0,
35560
35607
  category: typeof args5.category === "string" ? args5.category : void 0,
35561
35608
  full: args5.full === true
@@ -35568,7 +35615,7 @@ var catalogCommand = defineCommand108({
35568
35615
 
35569
35616
  // src/commands/canvas/critique.ts
35570
35617
  import { readFile as readFile3 } from "fs/promises";
35571
- import path3 from "path";
35618
+ import path4 from "path";
35572
35619
  import { defineCommand as defineCommand109 } from "citty";
35573
35620
 
35574
35621
  // src/engine/scaffold/lib/critique.ts
@@ -35696,7 +35743,7 @@ var critiqueCommand = defineCommand109({
35696
35743
  },
35697
35744
  args: { file: { type: "positional", required: true, description: "Path to canvas JSON" } },
35698
35745
  async run({ args: args5 }) {
35699
- const filePath = path3.resolve(String(args5.file));
35746
+ const filePath = path4.resolve(String(args5.file));
35700
35747
  const raw = await readFile3(filePath, "utf8");
35701
35748
  let parsed;
35702
35749
  try {
@@ -35728,8 +35775,8 @@ var critiqueCommand = defineCommand109({
35728
35775
 
35729
35776
  // src/commands/canvas/inspect.ts
35730
35777
  import { execFile } from "child_process";
35731
- import { readdir as readdir2, readFile as readFile4, stat } from "fs/promises";
35732
- import path4 from "path";
35778
+ import { readdir as readdir3, readFile as readFile4, stat } from "fs/promises";
35779
+ import path5 from "path";
35733
35780
  import { promisify } from "util";
35734
35781
  import { defineCommand as defineCommand110 } from "citty";
35735
35782
  var execFileAsync = promisify(execFile);
@@ -35747,7 +35794,7 @@ var inspectCommand = defineCommand110({
35747
35794
  }
35748
35795
  },
35749
35796
  async run({ args: args5 }) {
35750
- const outputsDir = path4.resolve(String(args5["outputs-dir"] ?? "canvas"));
35797
+ const outputsDir = path5.resolve(String(args5["outputs-dir"] ?? "canvas"));
35751
35798
  const runArg = String(args5.run);
35752
35799
  const runDir = await resolveRunDir(runArg, outputsDir);
35753
35800
  const manifest = await loadManifest(runDir);
@@ -35759,7 +35806,7 @@ var inspectCommand = defineCommand110({
35759
35806
  }
35760
35807
  const summary = {
35761
35808
  ok: true,
35762
- run_id: manifest.run_id ?? path4.basename(runDir),
35809
+ run_id: manifest.run_id ?? path5.basename(runDir),
35763
35810
  run_dir: runDir,
35764
35811
  stats: manifest.stats ?? null,
35765
35812
  output: manifest.output ?? null,
@@ -35772,18 +35819,18 @@ var inspectCommand = defineCommand110({
35772
35819
  }
35773
35820
  });
35774
35821
  async function resolveRunDir(run, outputsDir) {
35775
- if (path4.isAbsolute(run)) {
35822
+ if (path5.isAbsolute(run)) {
35776
35823
  const s2 = await stat(run).catch(() => null);
35777
35824
  if (s2?.isDirectory()) return run;
35778
35825
  throw new Error(`inspect: ${run} is not a directory`);
35779
35826
  }
35780
- const candidate = path4.join(outputsDir, run);
35827
+ const candidate = path5.join(outputsDir, run);
35781
35828
  const s = await stat(candidate).catch(() => null);
35782
35829
  if (s?.isDirectory()) return candidate;
35783
35830
  throw new Error(`inspect: no run directory at ${candidate}`);
35784
35831
  }
35785
35832
  async function loadManifest(runDir) {
35786
- const manifestPath = path4.join(runDir, "manifest.json");
35833
+ const manifestPath = path5.join(runDir, "manifest.json");
35787
35834
  try {
35788
35835
  const raw = await readFile4(manifestPath, "utf-8");
35789
35836
  return JSON.parse(raw);
@@ -35793,9 +35840,9 @@ async function loadManifest(runDir) {
35793
35840
  }
35794
35841
  async function listRunFiles(runDir) {
35795
35842
  const out = [];
35796
- const names = await readdir2(runDir);
35843
+ const names = await readdir3(runDir);
35797
35844
  for (const name of names) {
35798
- const abs = path4.join(runDir, name);
35845
+ const abs = path5.join(runDir, name);
35799
35846
  const s = await stat(abs).catch(() => null);
35800
35847
  if (!s?.isFile()) continue;
35801
35848
  out.push({ name, path: abs, size: s.size });
@@ -35840,58 +35887,58 @@ async function probeDuration(filePath) {
35840
35887
  }
35841
35888
 
35842
35889
  // src/commands/canvas/rerun.ts
35843
- import path17 from "path";
35890
+ import path18 from "path";
35844
35891
  import { defineCommand as defineCommand112 } from "citty";
35845
35892
 
35846
35893
  // src/commands/canvas/run.ts
35847
35894
  import { readFile as readFile12 } from "fs/promises";
35848
- import path16 from "path";
35895
+ import path17 from "path";
35849
35896
  import { defineCommand as defineCommand111 } from "citty";
35850
35897
 
35851
35898
  // src/commands/canvas/normalize-paths.ts
35852
- import { existsSync as existsSync4, realpathSync } from "fs";
35899
+ import { existsSync as existsSync5, realpathSync } from "fs";
35853
35900
  import { writeFile as writeFile2 } from "fs/promises";
35854
- import path5 from "path";
35855
- function findWorkspaceRoot(startDir, exists2 = existsSync4, maxDepth = 12) {
35856
- let dir = path5.resolve(startDir);
35901
+ import path6 from "path";
35902
+ function findWorkspaceRoot(startDir, exists2 = existsSync5, maxDepth = 12) {
35903
+ let dir = path6.resolve(startDir);
35857
35904
  for (let i = 0; i < maxDepth; i++) {
35858
- if (exists2(path5.join(dir, "package.json"))) return dir;
35859
- const parent = path5.dirname(dir);
35905
+ if (exists2(path6.join(dir, "package.json"))) return dir;
35906
+ const parent = path6.dirname(dir);
35860
35907
  if (parent === dir) break;
35861
35908
  dir = parent;
35862
35909
  }
35863
35910
  return null;
35864
35911
  }
35865
35912
  function canonicalize(target) {
35866
- const abs = path5.resolve(target);
35913
+ const abs = path6.resolve(target);
35867
35914
  let dir = abs;
35868
35915
  for (; ; ) {
35869
35916
  try {
35870
35917
  const real = realpathSync(dir);
35871
- return dir === abs ? real : path5.join(real, path5.relative(dir, abs));
35918
+ return dir === abs ? real : path6.join(real, path6.relative(dir, abs));
35872
35919
  } catch {
35873
- const parent = path5.dirname(dir);
35920
+ const parent = path6.dirname(dir);
35874
35921
  if (parent === dir) return abs;
35875
35922
  dir = parent;
35876
35923
  }
35877
35924
  }
35878
35925
  }
35879
35926
  function isInside(root, target) {
35880
- const rel = path5.relative(root, target);
35881
- return rel !== "" && !rel.startsWith("..") && !path5.isAbsolute(rel);
35927
+ const rel = path6.relative(root, target);
35928
+ return rel !== "" && !rel.startsWith("..") && !path6.isAbsolute(rel);
35882
35929
  }
35883
35930
  function toCanvasRelative(canvasDir, target) {
35884
- return path5.relative(canvasDir, target).split(path5.sep).join("/");
35931
+ return path6.relative(canvasDir, target).split(path6.sep).join("/");
35885
35932
  }
35886
35933
  var RUNTIME_WORKSPACE_ROOT = "/home/user/repo";
35887
35934
  function rewriteTarget(value, workspaceRoot) {
35888
35935
  if (typeof value !== "string" || value.length === 0) return null;
35889
- if (value.includes("[TODO") || looksLikeHttpUrl(value) || !path5.isAbsolute(value)) return null;
35936
+ if (value.includes("[TODO") || looksLikeHttpUrl(value) || !path6.isAbsolute(value)) return null;
35890
35937
  const target = canonicalize(value);
35891
35938
  if (isInside(workspaceRoot, target)) return target;
35892
- const fromRuntime = path5.relative(RUNTIME_WORKSPACE_ROOT, path5.normalize(value));
35893
- if (fromRuntime !== "" && !fromRuntime.startsWith("..") && !path5.isAbsolute(fromRuntime)) {
35894
- return path5.join(workspaceRoot, fromRuntime);
35939
+ const fromRuntime = path6.relative(RUNTIME_WORKSPACE_ROOT, path6.normalize(value));
35940
+ if (fromRuntime !== "" && !fromRuntime.startsWith("..") && !path6.isAbsolute(fromRuntime)) {
35941
+ return path6.join(workspaceRoot, fromRuntime);
35895
35942
  }
35896
35943
  return null;
35897
35944
  }
@@ -35919,7 +35966,7 @@ function normalizeAbsoluteCanvasPaths(canvas, canvasDir, workspaceRoot) {
35919
35966
  return rewrites.length === 0 ? { canvas, rewrites } : { canvas: { ...canvas, nodes }, rewrites };
35920
35967
  }
35921
35968
  async function healAbsoluteCanvasPaths(filePath, canvas) {
35922
- const canvasDir = path5.dirname(filePath);
35969
+ const canvasDir = path6.dirname(filePath);
35923
35970
  const workspaceRoot = findWorkspaceRoot(canvasDir);
35924
35971
  if (!workspaceRoot) return { canvas, rewrites: [], text: null };
35925
35972
  const normalized = normalizeAbsoluteCanvasPaths(canvas, canvasDir, workspaceRoot);
@@ -35950,7 +35997,7 @@ function unsuppliedPlaceholderAssets(canvas) {
35950
35997
  }
35951
35998
 
35952
35999
  // src/commands/canvas/resolve-paths.ts
35953
- import path6 from "path";
36000
+ import path7 from "path";
35954
36001
  function resolveRelativeCanvasPaths(canvas, baseDir) {
35955
36002
  if (!canvas || typeof canvas !== "object") return canvas;
35956
36003
  const c = canvas;
@@ -35963,24 +36010,24 @@ function resolveNode(node, baseDir) {
35963
36010
  const params = n.params;
35964
36011
  if (!params || typeof params !== "object") return node;
35965
36012
  if (n.type === "ingest" && params.source === "path" && isResolvableRelative(params.path)) {
35966
- return { ...node, params: { ...params, path: path6.resolve(baseDir, params.path) } };
36013
+ return { ...node, params: { ...params, path: path7.resolve(baseDir, params.path) } };
35967
36014
  }
35968
36015
  if (n.type === "hyperframe_render" && isResolvableRelative(params.composition)) {
35969
- return { ...node, params: { ...params, composition: path6.resolve(baseDir, params.composition) } };
36016
+ return { ...node, params: { ...params, composition: path7.resolve(baseDir, params.composition) } };
35970
36017
  }
35971
36018
  return node;
35972
36019
  }
35973
36020
  function isResolvableRelative(value) {
35974
- return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !looksLikeHttpUrl(value) && !path6.isAbsolute(value);
36021
+ return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !looksLikeHttpUrl(value) && !path7.isAbsolute(value);
35975
36022
  }
35976
36023
 
35977
36024
  // src/commands/canvas/source-version.ts
35978
36025
  import { readFile as readFile6 } from "fs/promises";
35979
- import path8 from "path";
36026
+ import path9 from "path";
35980
36027
 
35981
36028
  // src/commands/canvas/scene-files.ts
35982
- import { mkdir as mkdir2, readFile as readFile5, readdir as readdir3, rm, writeFile as writeFile3 } from "fs/promises";
35983
- import path7 from "path";
36029
+ import { mkdir as mkdir2, readFile as readFile5, readdir as readdir4, rm, writeFile as writeFile3 } from "fs/promises";
36030
+ import path8 from "path";
35984
36031
  var SCENES_DIR = "scenes";
35985
36032
  var GLOBAL_PROMPT_FILE = "prompt.json";
35986
36033
  var REBUILD_FILE = "prompt.rebuild.json";
@@ -35997,38 +36044,38 @@ function splitBlueprint(blueprint) {
35997
36044
  }
35998
36045
  async function writeSceneFiles(outDir, blueprint) {
35999
36046
  const { global, scenes } = splitBlueprint(blueprint);
36000
- await writeFile3(path7.join(outDir, GLOBAL_PROMPT_FILE), `${JSON.stringify(global, null, 2)}
36047
+ await writeFile3(path8.join(outDir, GLOBAL_PROMPT_FILE), `${JSON.stringify(global, null, 2)}
36001
36048
  `, "utf8");
36002
- const scenesDir = path7.join(outDir, SCENES_DIR);
36049
+ const scenesDir = path8.join(outDir, SCENES_DIR);
36003
36050
  await mkdir2(scenesDir, { recursive: true });
36004
36051
  const written = /* @__PURE__ */ new Set();
36005
36052
  for (let i = 0; i < scenes.length; i++) {
36006
36053
  const name = sceneFileName(i, scenes.length);
36007
36054
  written.add(name);
36008
- await writeFile3(path7.join(scenesDir, name), `${JSON.stringify(scenes[i], null, 2)}
36055
+ await writeFile3(path8.join(scenesDir, name), `${JSON.stringify(scenes[i], null, 2)}
36009
36056
  `, "utf8");
36010
36057
  }
36011
36058
  for (const name of await listSceneFileNames(scenesDir)) {
36012
- if (!written.has(name)) await rm(path7.join(scenesDir, name), { force: true });
36059
+ if (!written.has(name)) await rm(path8.join(scenesDir, name), { force: true });
36013
36060
  }
36014
36061
  }
36015
36062
  async function listSceneFileNames(scenesDir) {
36016
36063
  let entries;
36017
36064
  try {
36018
- entries = await readdir3(scenesDir);
36065
+ entries = await readdir4(scenesDir);
36019
36066
  } catch {
36020
36067
  return [];
36021
36068
  }
36022
36069
  return entries.filter((n) => /^s\d+\.json$/.test(n)).sort(bySceneIndex);
36023
36070
  }
36024
36071
  async function listSceneFiles(creativeDir) {
36025
- const scenesDir = path7.join(creativeDir, SCENES_DIR);
36026
- return (await listSceneFileNames(scenesDir)).map((n) => path7.join(scenesDir, n));
36072
+ const scenesDir = path8.join(creativeDir, SCENES_DIR);
36073
+ return (await listSceneFileNames(scenesDir)).map((n) => path8.join(scenesDir, n));
36027
36074
  }
36028
36075
  async function reassembleBlueprint(creativeDir) {
36029
36076
  const files = await listSceneFiles(creativeDir);
36030
36077
  if (files.length === 0) return null;
36031
- const globalRaw = await readFile5(path7.join(creativeDir, GLOBAL_PROMPT_FILE), "utf8");
36078
+ const globalRaw = await readFile5(path8.join(creativeDir, GLOBAL_PROMPT_FILE), "utf8");
36032
36079
  const global = JSON.parse(globalRaw);
36033
36080
  const scenes = [];
36034
36081
  for (const file of files) {
@@ -36050,8 +36097,8 @@ async function computeSourceSha(canvasPath) {
36050
36097
  } catch {
36051
36098
  return void 0;
36052
36099
  }
36053
- const canvasDir = path8.dirname(canvasPath);
36054
- const promptPath = path8.join(canvasDir, "prompt.json");
36100
+ const canvasDir = path9.dirname(canvasPath);
36101
+ const promptPath = path9.join(canvasDir, "prompt.json");
36055
36102
  let promptBytes;
36056
36103
  try {
36057
36104
  promptBytes = await readFile6(promptPath);
@@ -36078,7 +36125,7 @@ async function computeSourceSha(canvasPath) {
36078
36125
 
36079
36126
  // src/commands/canvas/scene-projection.ts
36080
36127
  import { readFile as readFile7 } from "fs/promises";
36081
- import path9 from "path";
36128
+ import path10 from "path";
36082
36129
 
36083
36130
  // src/engine/scaffold/video.ts
36084
36131
  import { toCardinal as nwAr } from "n2words/ar-SA";
@@ -39484,12 +39531,12 @@ function nonPromptParamsDiverge(live = {}, rebuilt = {}) {
39484
39531
  return false;
39485
39532
  }
39486
39533
  async function syncSceneNodeParams(canvas, canvasPath, log) {
39487
- const creativeDir = path9.dirname(canvasPath);
39534
+ const creativeDir = path10.dirname(canvasPath);
39488
39535
  const blueprint = await reassembleBlueprint(creativeDir);
39489
39536
  if (!blueprint) return "not_applicable";
39490
39537
  let rebuildRaw;
39491
39538
  try {
39492
- rebuildRaw = await readFile7(path9.join(creativeDir, REBUILD_FILE), "utf8");
39539
+ rebuildRaw = await readFile7(path10.join(creativeDir, REBUILD_FILE), "utf8");
39493
39540
  } catch {
39494
39541
  log(
39495
39542
  `[scenes] this creative has scene files but no ${REBUILD_FILE}, so edits to scenes/*.json are NOT reaching the render \u2014 the prompts inlined in the canvas are what renders. Re-scaffold the creative to restore the link, or edit the canvas node prompts directly.`
@@ -39624,13 +39671,13 @@ ${body}` : header || body || compactJson(record);
39624
39671
  }
39625
39672
 
39626
39673
  // src/commands/canvas/run-record.ts
39627
- import path10 from "path";
39674
+ import path11 from "path";
39628
39675
  var MAX_RUN_NODES = 200;
39629
39676
  var MAX_OUTPUTS_PER_NODE = 10;
39630
39677
  var MAX_FINAL_OUTPUTS = 10;
39631
39678
  var MAX_CREATIVE_SLUG_LENGTH = 100;
39632
39679
  function creativeSlugFromCanvasPath(filePath) {
39633
- const normalized = filePath.split(path10.sep).join("/");
39680
+ const normalized = filePath.split(path11.sep).join("/");
39634
39681
  const match = normalized.match(/(?:^|\/)src\/creatives\/([a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\//);
39635
39682
  const slug = match?.[1] ?? null;
39636
39683
  return slug && slug.length <= MAX_CREATIVE_SLUG_LENGTH ? slug : null;
@@ -39923,24 +39970,24 @@ var RunRecordPoster = class {
39923
39970
 
39924
39971
  // src/commands/canvas/run-retention.ts
39925
39972
  import { rm as rm2 } from "fs/promises";
39926
- import path11 from "path";
39973
+ import path12 from "path";
39927
39974
  function runDirsToPrune(entries, keep, currentRunId) {
39928
39975
  const runs = entries.filter((e) => /^r_[0-9A-Za-z]+$/.test(e) && e !== currentRunId).sort();
39929
39976
  if (keep <= 0) return runs;
39930
39977
  return runs.slice(0, Math.max(0, runs.length - keep));
39931
39978
  }
39932
39979
  async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
39933
- const { readdir: readdir16 } = await import("fs/promises");
39980
+ const { readdir: readdir17 } = await import("fs/promises");
39934
39981
  let entries;
39935
39982
  try {
39936
- entries = await readdir16(outputsDir);
39983
+ entries = await readdir17(outputsDir);
39937
39984
  } catch {
39938
39985
  return;
39939
39986
  }
39940
39987
  const toPrune = runDirsToPrune(entries, keep, currentRunId);
39941
39988
  if (toPrune.length === 0) return;
39942
39989
  for (const dir of toPrune) {
39943
- await rm2(path11.join(outputsDir, dir), { recursive: true, force: true }).catch(
39990
+ await rm2(path12.join(outputsDir, dir), { recursive: true, force: true }).catch(
39944
39991
  (e) => log(`[prune ] could not remove ${dir}: ${e.message}`)
39945
39992
  );
39946
39993
  }
@@ -39948,13 +39995,13 @@ async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
39948
39995
  }
39949
39996
 
39950
39997
  // src/commands/canvas/dirty-marker.ts
39951
- import { mkdir as mkdir3, readdir as readdir4, rm as rm3, writeFile as writeFile5 } from "fs/promises";
39952
- import path12 from "path";
39998
+ import { mkdir as mkdir3, readdir as readdir5, rm as rm3, writeFile as writeFile5 } from "fs/promises";
39999
+ import path13 from "path";
39953
40000
  function creativeDirtyDir(base) {
39954
- return base ?? path12.resolve("canvas", ".dirty");
40001
+ return base ?? path13.resolve("canvas", ".dirty");
39955
40002
  }
39956
40003
  function dirtyMarkerFile(slug, base) {
39957
- return path12.join(creativeDirtyDir(base), `${slug}.json`);
40004
+ return path13.join(creativeDirtyDir(base), `${slug}.json`);
39958
40005
  }
39959
40006
  async function clearCreativeDirty(slug, base) {
39960
40007
  try {
@@ -39965,17 +40012,17 @@ async function clearCreativeDirty(slug, base) {
39965
40012
 
39966
40013
  // src/commands/canvas/run-resume.ts
39967
40014
  import { mkdir as mkdir4, readFile as readFile9, rm as rm4, writeFile as writeFile6 } from "fs/promises";
39968
- import path13 from "path";
40015
+ import path14 from "path";
39969
40016
  function markerKey(canvasPath) {
39970
40017
  const slug = creativeSlugFromCanvasPath(canvasPath);
39971
- const identity = slug ?? path13.relative(process.cwd(), path13.resolve(canvasPath));
40018
+ const identity = slug ?? path14.relative(process.cwd(), path14.resolve(canvasPath));
39972
40019
  return sha256Hex(Buffer.from(identity)).slice(0, 32);
39973
40020
  }
39974
40021
  function legacyMarkerKey(canvasPath) {
39975
- return sha256Hex(Buffer.from(path13.resolve(canvasPath))).slice(0, 32);
40022
+ return sha256Hex(Buffer.from(path14.resolve(canvasPath))).slice(0, 32);
39976
40023
  }
39977
40024
  function markerFile(outputsDir, key) {
39978
- return path13.join(outputsDir, ".inflight", `${key}.json`);
40025
+ return path14.join(outputsDir, ".inflight", `${key}.json`);
39979
40026
  }
39980
40027
  var REMOTE_ADOPT_STALE_MS = 12e4;
39981
40028
  function classifyRemoteRun(run, now) {
@@ -40022,8 +40069,8 @@ async function readMarkerRunId(outputsDir, canvasPath) {
40022
40069
  async function markRunInFlight(outputsDir, canvasPath, runId) {
40023
40070
  try {
40024
40071
  const file = markerFile(outputsDir, markerKey(canvasPath));
40025
- await mkdir4(path13.dirname(file), { recursive: true });
40026
- await writeFile6(file, JSON.stringify({ runId, canvasPath: path13.resolve(canvasPath), startedAt: Date.now() }));
40072
+ await mkdir4(path14.dirname(file), { recursive: true });
40073
+ await writeFile6(file, JSON.stringify({ runId, canvasPath: path14.resolve(canvasPath), startedAt: Date.now() }));
40027
40074
  } catch {
40028
40075
  }
40029
40076
  }
@@ -40037,8 +40084,8 @@ async function clearRunMarker(outputsDir, canvasPath) {
40037
40084
  }
40038
40085
 
40039
40086
  // src/commands/canvas/run-snapshot.ts
40040
- import { mkdir as mkdir5, readdir as readdir5, readFile as readFile10, stat as stat2, writeFile as writeFile7 } from "fs/promises";
40041
- import path14 from "path";
40087
+ import { mkdir as mkdir5, readdir as readdir6, readFile as readFile10, stat as stat2, writeFile as writeFile7 } from "fs/promises";
40088
+ import path15 from "path";
40042
40089
  var SNAPSHOT_SCHEMA = "baker-canvas-snapshot/1";
40043
40090
  var MAX_SNAPSHOT_FILE_BYTES = 32 * 1024 * 1024;
40044
40091
  var EXT_TO_MIME = {
@@ -40065,15 +40112,15 @@ var EXT_TO_MIME = {
40065
40112
  woff2: "font/woff2"
40066
40113
  };
40067
40114
  function mimeForFile(filePath) {
40068
- const ext = path14.extname(filePath).slice(1).toLowerCase();
40115
+ const ext = path15.extname(filePath).slice(1).toLowerCase();
40069
40116
  return EXT_TO_MIME[ext] ?? "application/octet-stream";
40070
40117
  }
40071
40118
  function toPosix(p) {
40072
- return p.split(path14.sep).join("/");
40119
+ return p.split(path15.sep).join("/");
40073
40120
  }
40074
40121
  function isInside2(dir, target) {
40075
- const rel = path14.relative(dir, target);
40076
- return !rel.startsWith("..") && !path14.isAbsolute(rel);
40122
+ const rel = path15.relative(dir, target);
40123
+ return !rel.startsWith("..") && !path15.isAbsolute(rel);
40077
40124
  }
40078
40125
  function localPathRefsFromCanvas(parsed) {
40079
40126
  const nodes = parsed?.nodes;
@@ -40098,24 +40145,24 @@ function isSnapshotablePath(value) {
40098
40145
  async function sourceRefsToSnapshot(canvasDir, parsed) {
40099
40146
  const refs = new Set(localPathRefsFromCanvas(parsed));
40100
40147
  for (const sceneFile of await listSceneFiles(canvasDir)) {
40101
- refs.add(toPosix(path14.relative(canvasDir, sceneFile)));
40148
+ refs.add(toPosix(path15.relative(canvasDir, sceneFile)));
40102
40149
  }
40103
40150
  refs.add(REBUILD_FILE);
40104
40151
  return [...refs];
40105
40152
  }
40106
40153
  async function uploadRunSnapshot(client, opts) {
40107
40154
  try {
40108
- const canvasDir = path14.dirname(opts.canvasPath);
40155
+ const canvasDir = path15.dirname(opts.canvasPath);
40109
40156
  const put = (bytes, mime) => putContentAddressed(client, bytes, mime, opts.signal);
40110
40157
  const canvasBytes = Buffer.from(opts.raw);
40111
40158
  const canvasUpload = await put(canvasBytes, "application/json");
40112
40159
  const files = [];
40113
40160
  const skipped = [];
40114
40161
  for (const refPath of await sourceRefsToSnapshot(canvasDir, opts.parsed)) {
40115
- const abs = path14.isAbsolute(refPath) ? refPath : path14.resolve(canvasDir, refPath);
40162
+ const abs = path15.isAbsolute(refPath) ? refPath : path15.resolve(canvasDir, refPath);
40116
40163
  if (!isInside2(canvasDir, abs)) {
40117
40164
  skipped.push({
40118
- path: toPosix(path14.relative(canvasDir, abs)),
40165
+ path: toPosix(path15.relative(canvasDir, abs)),
40119
40166
  reason: "outside the creative folder \u2014 read from the workspace on rerun"
40120
40167
  });
40121
40168
  continue;
@@ -40124,12 +40171,12 @@ async function uploadRunSnapshot(client, opts) {
40124
40171
  try {
40125
40172
  st = await stat2(abs);
40126
40173
  } catch {
40127
- skipped.push({ path: toPosix(path14.relative(canvasDir, abs)), reason: "missing" });
40174
+ skipped.push({ path: toPosix(path15.relative(canvasDir, abs)), reason: "missing" });
40128
40175
  continue;
40129
40176
  }
40130
40177
  const fileList = st.isDirectory() ? await listFilesRecursive(abs) : [abs];
40131
40178
  for (const file of fileList) {
40132
- const rel = toPosix(path14.relative(canvasDir, file));
40179
+ const rel = toPosix(path15.relative(canvasDir, file));
40133
40180
  const size = (await stat2(file)).size;
40134
40181
  if (size > MAX_SNAPSHOT_FILE_BYTES) {
40135
40182
  skipped.push({ path: rel, reason: `too large (${size} bytes)` });
@@ -40144,7 +40191,7 @@ async function uploadRunSnapshot(client, opts) {
40144
40191
  schema: SNAPSHOT_SCHEMA,
40145
40192
  creativeSlug: opts.creativeSlug,
40146
40193
  canvasSha: canvasUpload.sha256,
40147
- canvas: { path: path14.basename(opts.canvasPath), sha256: canvasUpload.sha256, url: canvasUpload.url },
40194
+ canvas: { path: path15.basename(opts.canvasPath), sha256: canvasUpload.sha256, url: canvasUpload.url },
40148
40195
  files,
40149
40196
  skipped: skipped.length > 0 ? skipped : void 0
40150
40197
  };
@@ -40170,8 +40217,8 @@ async function putContentAddressed(client, bytes, mime, signal) {
40170
40217
  return { sha256, url: publicUrl };
40171
40218
  }
40172
40219
  async function listFilesRecursive(dir) {
40173
- const entries = await readdir5(dir, { recursive: true, withFileTypes: true });
40174
- return entries.filter((d) => d.isFile()).map((d) => path14.join(d.parentPath, d.name));
40220
+ const entries = await readdir6(dir, { recursive: true, withFileTypes: true });
40221
+ return entries.filter((d) => d.isFile()).map((d) => path15.join(d.parentPath, d.name));
40175
40222
  }
40176
40223
  var SnapshotConflictError = class extends Error {
40177
40224
  conflicts;
@@ -40183,16 +40230,16 @@ var SnapshotConflictError = class extends Error {
40183
40230
  };
40184
40231
  async function restoreRunSnapshot(manifest, targetDir, opts = {}) {
40185
40232
  const entries = [manifest.canvas, ...manifest.files];
40186
- const resolvedTarget = path14.resolve(targetDir);
40233
+ const resolvedTarget = path15.resolve(targetDir);
40187
40234
  const planned = [];
40188
40235
  const conflicts = [];
40189
40236
  const upToDate = [];
40190
40237
  for (const entry of entries) {
40191
- if (path14.isAbsolute(entry.path) || entry.path.split("/").includes("..")) {
40238
+ if (path15.isAbsolute(entry.path) || entry.path.split("/").includes("..")) {
40192
40239
  throw new Error(`snapshot entry escapes the creative directory: ${entry.path}`);
40193
40240
  }
40194
- const target = path14.resolve(resolvedTarget, entry.path);
40195
- if (target !== resolvedTarget && !target.startsWith(resolvedTarget + path14.sep)) {
40241
+ const target = path15.resolve(resolvedTarget, entry.path);
40242
+ if (target !== resolvedTarget && !target.startsWith(resolvedTarget + path15.sep)) {
40196
40243
  throw new Error(`snapshot entry escapes the creative directory: ${entry.path}`);
40197
40244
  }
40198
40245
  const existing = await readFile10(target).catch(() => null);
@@ -40217,18 +40264,18 @@ async function restoreRunSnapshot(manifest, targetDir, opts = {}) {
40217
40264
  if (sha256Hex(bytes) !== entry.sha256) {
40218
40265
  throw new Error(`snapshot download for ${entry.path} does not match its recorded sha256`);
40219
40266
  }
40220
- await mkdir5(path14.dirname(target), { recursive: true });
40267
+ await mkdir5(path15.dirname(target), { recursive: true });
40221
40268
  await writeFile7(target, bytes);
40222
40269
  restored.push(entry.path);
40223
40270
  }
40224
- return { canvasPath: path14.resolve(resolvedTarget, manifest.canvas.path), restored, upToDate };
40271
+ return { canvasPath: path15.resolve(resolvedTarget, manifest.canvas.path), restored, upToDate };
40225
40272
  }
40226
40273
 
40227
40274
  // src/engine/nodes/local/lib/render-review.ts
40228
40275
  import { execFile as execFile2 } from "child_process";
40229
- import { mkdtemp, readdir as readdir6, readFile as readFile11, rm as rm5 } from "fs/promises";
40276
+ import { mkdtemp, readdir as readdir7, readFile as readFile11, rm as rm5 } from "fs/promises";
40230
40277
  import { tmpdir } from "os";
40231
- import path15 from "path";
40278
+ import path16 from "path";
40232
40279
  import { promisify as promisify2 } from "util";
40233
40280
  import { z as z39 } from "zod";
40234
40281
  var RENDER_REVIEW_MODEL = "~google/gemini-pro-latest";
@@ -40650,11 +40697,11 @@ async function reviewRenderedVideo(opts) {
40650
40697
  const duration = await videoDuration(opts.video);
40651
40698
  if (duration === null) return null;
40652
40699
  const spent = (usage) => opts.onSpend?.(usage);
40653
- const dir = await mkdtemp(path15.join(tmpdir(), "baker-review-"));
40700
+ const dir = await mkdtemp(path16.join(tmpdir(), "baker-review-"));
40654
40701
  try {
40655
40702
  const grabbed = [];
40656
40703
  for (const [i, at] of reviewFrameTimes(duration, RENDER_REVIEW_FRAMES).entries()) {
40657
- const out = path15.join(dir, `f${String(i).padStart(2, "0")}.jpg`);
40704
+ const out = path16.join(dir, `f${String(i).padStart(2, "0")}.jpg`);
40658
40705
  try {
40659
40706
  await execFileAsync2("ffmpeg", buildFrameGrabArgs(opts.video, at, out), { timeout: 3e4 });
40660
40707
  grabbed.push({ at, image: await readFile11(out, { encoding: "base64" }) });
@@ -40704,7 +40751,7 @@ async function reviewRenderedVideo(opts) {
40704
40751
  }
40705
40752
  }
40706
40753
  async function reviewContextBeside(canvasPath) {
40707
- const raw = await readFile11(path15.join(path15.dirname(canvasPath), "prompt.json"), "utf-8").catch(() => null);
40754
+ const raw = await readFile11(path16.join(path16.dirname(canvasPath), "prompt.json"), "utf-8").catch(() => null);
40708
40755
  if (!raw) return {};
40709
40756
  try {
40710
40757
  const blueprint = JSON.parse(raw);
@@ -40720,12 +40767,12 @@ async function reviewContextBeside(canvasPath) {
40720
40767
  }
40721
40768
  }
40722
40769
  async function sceneWindowsBeside(canvasPath) {
40723
- const dir = path15.join(path15.dirname(canvasPath), "scenes");
40724
- const files = await readdir6(dir).catch(() => null);
40770
+ const dir = path16.join(path16.dirname(canvasPath), "scenes");
40771
+ const files = await readdir7(dir).catch(() => null);
40725
40772
  if (!files) return [];
40726
40773
  const windows = [];
40727
40774
  for (const name of files.filter((f) => f.endsWith(".json")).sort()) {
40728
- const raw = await readFile11(path15.join(dir, name), "utf-8").catch(() => null);
40775
+ const raw = await readFile11(path16.join(dir, name), "utf-8").catch(() => null);
40729
40776
  if (!raw) continue;
40730
40777
  try {
40731
40778
  const scene = JSON.parse(raw);
@@ -40851,7 +40898,7 @@ function stopBeforeKinds(until) {
40851
40898
  return null;
40852
40899
  }
40853
40900
  async function executeCanvasRun(opts) {
40854
- const filePath = path16.resolve(opts.file);
40901
+ const filePath = path17.resolve(opts.file);
40855
40902
  const raw = await readFile12(filePath, "utf8");
40856
40903
  let parsed;
40857
40904
  try {
@@ -40874,7 +40921,7 @@ ${describeRewrites(healed.rewrites)}
40874
40921
  `
40875
40922
  );
40876
40923
  }
40877
- parsed = resolveRelativeCanvasPaths(parsed, path16.dirname(filePath));
40924
+ parsed = resolveRelativeCanvasPaths(parsed, path17.dirname(filePath));
40878
40925
  try {
40879
40926
  await syncStyleProjection(parsed, (line) => process.stderr.write(`${line}
40880
40927
  `));
@@ -40980,7 +41027,7 @@ ${describeRewrites(healed.rewrites)}
40980
41027
  const canvasSha = sha256Hex(Buffer.from(canvasText));
40981
41028
  const creativeSlug = creativeSlugFromCanvasPath(filePath) ?? void 0;
40982
41029
  const client = opts.record === false ? null : buildBackendClient();
40983
- const outputsDir = opts.outputsDir ? path16.resolve(opts.outputsDir) : path16.resolve("canvas");
41030
+ const outputsDir = opts.outputsDir ? path17.resolve(opts.outputsDir) : path17.resolve("canvas");
40984
41031
  const { runId, resumed, source, concurrentRunId } = await resolveRunId({
40985
41032
  explicitRunId: opts.runId,
40986
41033
  fresh: opts.fresh === true,
@@ -41014,7 +41061,7 @@ ${describeRewrites(healed.rewrites)}
41014
41061
  const canvasSnapshotUrl = client && creativeSlug ? await uploadRunSnapshot(client, { canvasPath: filePath, raw: canvasText, creativeSlug, parsed }) ?? void 0 : void 0;
41015
41062
  const recordMeta = {
41016
41063
  creativeSlug,
41017
- canvasPath: path16.relative(process.cwd(), filePath) || void 0,
41064
+ canvasPath: path17.relative(process.cwd(), filePath) || void 0,
41018
41065
  canvasSha,
41019
41066
  // The fingerprint the dashboard compares against the current source to flag
41020
41067
  // "edited since last render". Computed from the on-disk canvas.json +
@@ -41272,7 +41319,7 @@ var rerunCommand = defineCommand112({
41272
41319
  if (latest.canvasSha && manifest.canvasSha !== latest.canvasSha) {
41273
41320
  fail2("snapshot_mismatch", `snapshot manifest for run ${latest.runId} does not match its recorded canvas sha`);
41274
41321
  }
41275
- const targetDir = path17.resolve("src", "creatives", slug);
41322
+ const targetDir = path18.resolve("src", "creatives", slug);
41276
41323
  let restoredCanvasPath;
41277
41324
  try {
41278
41325
  const restore = await restoreRunSnapshot(manifest, targetDir, { force: args5["force-remote"] === true });
@@ -41322,7 +41369,7 @@ async function fetchManifest(url) {
41322
41369
 
41323
41370
  // src/commands/canvas/scaffold-static-ad.ts
41324
41371
  import { access, mkdir as mkdir6, readFile as readFile14, writeFile as writeFile8 } from "fs/promises";
41325
- import path21 from "path";
41372
+ import path22 from "path";
41326
41373
  import { defineCommand as defineCommand114 } from "citty";
41327
41374
 
41328
41375
  // src/engine/scaffold/staticAd.ts
@@ -41610,7 +41657,7 @@ function staticAdReport(input, elementsInput, opts) {
41610
41657
  }
41611
41658
 
41612
41659
  // src/commands/canvas/creative-definition.ts
41613
- import path18 from "path";
41660
+ import path19 from "path";
41614
41661
  var PLATFORM_VALUES = ["meta", "google", "linkedin", "tiktok", "youtube", "x", "other"];
41615
41662
  var FORMAT_VALUES = ["1:1", "4:5", "9:16", "16:9", "1.91:1"];
41616
41663
  function titleFromSlug(slug) {
@@ -41658,16 +41705,16 @@ function buildCreativeDefinition(input) {
41658
41705
  }
41659
41706
 
41660
41707
  // src/commands/canvas/scaffold-static-ad-paths.ts
41661
- import path19 from "path";
41708
+ import path20 from "path";
41662
41709
  function resolveScaffoldStaticAdPaths(rawFile, out, cwd = process.cwd(), slug) {
41663
41710
  const file = rawFile.trim();
41664
41711
  const imageIsUrl = /^https?:\/\//i.test(file);
41665
- const imageSource = imageIsUrl ? file : path19.resolve(cwd, file);
41666
- const outPath = out ? path19.resolve(cwd, out) : slug ? path19.join(cwd, "src", "creatives", slug, `${slug}.canvas.json`) : imageIsUrl ? path19.join(cwd, "static-ad.canvas.json") : path19.join(path19.dirname(imageSource), "static-ad.canvas.json");
41667
- const blueprintPath = path19.join(path19.dirname(outPath), "prompt.json");
41668
- const creativeDir = slug ? path19.dirname(outPath) : null;
41669
- const definitionPath = creativeDir ? path19.join(creativeDir, "_definition.md") : null;
41670
- const referencesDir = creativeDir ? path19.join(creativeDir, "references") : null;
41712
+ const imageSource = imageIsUrl ? file : path20.resolve(cwd, file);
41713
+ const outPath = out ? path20.resolve(cwd, out) : slug ? path20.join(cwd, "src", "creatives", slug, `${slug}.canvas.json`) : imageIsUrl ? path20.join(cwd, "static-ad.canvas.json") : path20.join(path20.dirname(imageSource), "static-ad.canvas.json");
41714
+ const blueprintPath = path20.join(path20.dirname(outPath), "prompt.json");
41715
+ const creativeDir = slug ? path20.dirname(outPath) : null;
41716
+ const definitionPath = creativeDir ? path20.join(creativeDir, "_definition.md") : null;
41717
+ const referencesDir = creativeDir ? path20.join(creativeDir, "references") : null;
41671
41718
  return { imageIsUrl, imageSource, outPath, blueprintPath, creativeDir, definitionPath, referencesDir };
41672
41719
  }
41673
41720
  var SCAFFOLD_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
@@ -41677,8 +41724,8 @@ function isValidScaffoldSlug(slug) {
41677
41724
  }
41678
41725
 
41679
41726
  // src/commands/canvas/sync-definition.ts
41680
- import { readdir as readdir7, readFile as readFile13, stat as stat3 } from "fs/promises";
41681
- import path20 from "path";
41727
+ import { readdir as readdir8, readFile as readFile13, stat as stat3 } from "fs/promises";
41728
+ import path21 from "path";
41682
41729
  import { defineCommand as defineCommand113 } from "citty";
41683
41730
 
41684
41731
  // src/commands/canvas/definition-graph.ts
@@ -41771,26 +41818,26 @@ async function syncCreativeDefinitionBestEffort(input) {
41771
41818
  }
41772
41819
  }
41773
41820
  async function resolveCanvasPath(inputPath) {
41774
- const resolved = path20.resolve(inputPath);
41821
+ const resolved = path21.resolve(inputPath);
41775
41822
  let dir = resolved;
41776
41823
  try {
41777
41824
  if ((await stat3(resolved)).isFile()) {
41778
41825
  if (resolved.endsWith(".canvas.json")) return resolved;
41779
- dir = path20.dirname(resolved);
41826
+ dir = path21.dirname(resolved);
41780
41827
  }
41781
41828
  } catch {
41782
- dir = resolved.endsWith(".canvas.json") ? path20.dirname(resolved) : resolved;
41829
+ dir = resolved.endsWith(".canvas.json") ? path21.dirname(resolved) : resolved;
41783
41830
  }
41784
41831
  let entries;
41785
41832
  try {
41786
- entries = await readdir7(dir);
41833
+ entries = await readdir8(dir);
41787
41834
  } catch {
41788
41835
  return null;
41789
41836
  }
41790
41837
  const canvases = entries.filter((name) => name.endsWith(".canvas.json"));
41791
41838
  const slug = creativeSlugFromCanvasPath(`${dir}/x/`);
41792
41839
  const chosen = (slug ? canvases.find((name) => name === `${slug}.canvas.json`) : void 0) ?? canvases[0];
41793
- return chosen ? path20.join(dir, chosen) : null;
41840
+ return chosen ? path21.join(dir, chosen) : null;
41794
41841
  }
41795
41842
  var syncDefinitionCommand = defineCommand113({
41796
41843
  meta: {
@@ -42071,7 +42118,7 @@ var scaffoldStaticAdCommand = defineCommand114({
42071
42118
  process.cwd(),
42072
42119
  slug
42073
42120
  );
42074
- await mkdir6(path21.dirname(outPath), { recursive: true });
42121
+ await mkdir6(path22.dirname(outPath), { recursive: true });
42075
42122
  const { describeModel, selectModel, layoutModel, genModel } = resolveModels(args5);
42076
42123
  let durableSourceUrl;
42077
42124
  if (referencesDir) {
@@ -42191,7 +42238,7 @@ var scaffoldStaticAdCommand = defineCommand114({
42191
42238
  run_estimated_credits: validation.estimatedCredits
42192
42239
  },
42193
42240
  checklist: {
42194
- edit_prompt: `Edit ${path21.basename(blueprintPath)} \u2014 it is the blueprint generated from your image; rewrite it into the ad you want (palette, copy, claims, subjects). It feeds the generator directly.`,
42241
+ edit_prompt: `Edit ${path22.basename(blueprintPath)} \u2014 it is the blueprint generated from your image; rewrite it into the ad you want (palette, copy, claims, subjects). It feeds the generator directly.`,
42195
42242
  assets_to_supply: report.elements,
42196
42243
  font_slot: report.includes_font ? "Drop a brand font at the [TODO] brandfont path (the describe pass recorded the ad's typefaces under `fonts` in prompt.json \u2014 match those). The font is wired into the render as a TYPE SPECIMEN reference so generated text takes the brand letterforms. Delete the brandfont + type_ref nodes to skip it." : "skipped (--skip-font)",
42197
42244
  actor_sheets: report.actor_sheets.length > 0 ? `Each living hero (${report.actor_sheets.join(", ")}) is fused into a generated multi-view reference sheet (image_reference_sheet) that the render grounds on \u2014 so drop ONE clean photo at that hero's ingest and the sheet builds the consistent turnaround. Pass --skip-actor-sheets to ground on the lone photo instead.` : "none (no person/animal heroes detected, or --skip-actor-sheets)",
@@ -42960,8 +43007,8 @@ function injectAdBrandOverlay(indexHtml, overlayHtml) {
42960
43007
  }
42961
43008
 
42962
43009
  // src/engine/scaffold/ad-brand-source.ts
42963
- import { readdir as readdir8, readFile as readFile15 } from "fs/promises";
42964
- import path22 from "path";
43010
+ import { readdir as readdir9, readFile as readFile15 } from "fs/promises";
43011
+ import path23 from "path";
42965
43012
  import sharp from "sharp";
42966
43013
  var BRAND_DIR = "src/brand";
42967
43014
  function paletteFromBrandDoc(markdown) {
@@ -43013,16 +43060,16 @@ function pickBrandMark(files) {
43013
43060
  }
43014
43061
  async function readBrandFromWorkspace(root = ".") {
43015
43062
  const found = {};
43016
- const doc = await readFile15(path22.join(root, BRAND_DIR, "BRAND.md"), "utf-8").catch(() => null);
43063
+ const doc = await readFile15(path23.join(root, BRAND_DIR, "BRAND.md"), "utf-8").catch(() => null);
43017
43064
  if (doc) {
43018
43065
  const palette = paletteFromBrandDoc(doc);
43019
43066
  if (palette.length > 0) found.palette = palette;
43020
43067
  }
43021
- const dir = path22.join(root, BRAND_DIR, "logos");
43022
- const files = await readdir8(dir).catch(() => null);
43068
+ const dir = path23.join(root, BRAND_DIR, "logos");
43069
+ const files = await readdir9(dir).catch(() => null);
43023
43070
  if (files) {
43024
43071
  const mark = pickBrandMark(files);
43025
- if (mark) found.logo = path22.join(BRAND_DIR, "logos", mark);
43072
+ if (mark) found.logo = path23.join(BRAND_DIR, "logos", mark);
43026
43073
  }
43027
43074
  return found;
43028
43075
  }
@@ -43032,20 +43079,20 @@ function svgIsLiveText(svg) {
43032
43079
  async function markIsReal(markPath, root = ".") {
43033
43080
  const brandLogos = await findBrandLogosDir(markPath, root);
43034
43081
  if (brandLogos) return await markDirectoryIsReal(brandLogos);
43035
- return await markDirectoryIsReal(path22.dirname(markPath));
43082
+ return await markDirectoryIsReal(path23.dirname(markPath));
43036
43083
  }
43037
43084
  async function findBrandLogosDir(markPath, root) {
43038
43085
  const candidates = [];
43039
- let dir = path22.resolve(path22.dirname(markPath));
43086
+ let dir = path23.resolve(path23.dirname(markPath));
43040
43087
  for (; ; ) {
43041
- candidates.push(path22.join(dir, BRAND_DIR, "logos"));
43042
- const parent = path22.dirname(dir);
43088
+ candidates.push(path23.join(dir, BRAND_DIR, "logos"));
43089
+ const parent = path23.dirname(dir);
43043
43090
  if (parent === dir) break;
43044
43091
  dir = parent;
43045
43092
  }
43046
- candidates.push(path22.join(root, BRAND_DIR, "logos"));
43093
+ candidates.push(path23.join(root, BRAND_DIR, "logos"));
43047
43094
  for (const candidate of candidates) {
43048
- if (await readdir8(candidate).then(
43095
+ if (await readdir9(candidate).then(
43049
43096
  () => true,
43050
43097
  () => false
43051
43098
  ))
@@ -43054,12 +43101,12 @@ async function findBrandLogosDir(markPath, root) {
43054
43101
  return null;
43055
43102
  }
43056
43103
  async function markDirectoryIsReal(dir) {
43057
- const files = await readdir8(dir).catch(() => null);
43104
+ const files = await readdir9(dir).catch(() => null);
43058
43105
  if (!files) return false;
43059
43106
  const marks = files.filter((f) => /\.(svg|png|webp)$/i.test(f));
43060
43107
  if (marks.length === 0) return false;
43061
43108
  for (const f of marks.filter((f2) => /\.svg$/i.test(f2))) {
43062
- const svg = await readFile15(path22.join(dir, f), "utf-8").catch(() => null);
43109
+ const svg = await readFile15(path23.join(dir, f), "utf-8").catch(() => null);
43063
43110
  if (svg === null || svgIsLiveText(svg)) return false;
43064
43111
  }
43065
43112
  return true;
@@ -43086,22 +43133,6 @@ async function markInkIsLight(markPath) {
43086
43133
  }
43087
43134
  }
43088
43135
 
43089
- // src/commands/canvas/composition-path.ts
43090
- import { existsSync as existsSync5 } from "fs";
43091
- import path23 from "path";
43092
- function resolveShippedCanvasDir(name, startDir, exists2 = existsSync5, maxDepth = 8) {
43093
- const rel = path23.join("canvas", name);
43094
- let dir = startDir;
43095
- for (let i = 0; i < maxDepth; i++) {
43096
- const candidate = path23.join(dir, rel);
43097
- if (exists2(path23.join(candidate, "meta.json"))) return candidate;
43098
- const parent = path23.dirname(dir);
43099
- if (parent === dir) break;
43100
- dir = parent;
43101
- }
43102
- return path23.resolve(startDir, "../../../", rel);
43103
- }
43104
-
43105
43136
  // src/commands/canvas/scaffold-ad.ts
43106
43137
  function pinnedOnAvatar(handle, model) {
43107
43138
  const hint = pinnedModelHint({ avatar: handle ?? void 0, model, generateAudio: true });
@@ -43652,7 +43683,7 @@ function routeVideoModel(input) {
43652
43683
 
43653
43684
  // src/engine/nodes/local/lib/sceneDetect.ts
43654
43685
  import { execFile as execFile3 } from "child_process";
43655
- import { mkdtemp as mkdtemp2, readdir as readdir9, readFile as readFile17, rm as rm6 } from "fs/promises";
43686
+ import { mkdtemp as mkdtemp2, readdir as readdir10, readFile as readFile17, rm as rm6 } from "fs/promises";
43656
43687
  import { tmpdir as tmpdir2 } from "os";
43657
43688
  import { join as join3 } from "path";
43658
43689
  import { promisify as promisify3 } from "util";
@@ -43726,7 +43757,7 @@ async function runSceneDetectOnce(filePath, threshold, minSceneLenS, timeoutMs)
43726
43757
  ],
43727
43758
  { encoding: "utf-8", maxBuffer: 32 * 1024 * 1024, timeout: timeoutMs }
43728
43759
  );
43729
- const csvName = (await readdir9(outDir)).find((f) => f.toLowerCase().endsWith(".csv"));
43760
+ const csvName = (await readdir10(outDir)).find((f) => f.toLowerCase().endsWith(".csv"));
43730
43761
  if (!csvName) return [];
43731
43762
  return parsePySceneDetectCsvCuts(await readFile17(join3(outDir, csvName), "utf-8"));
43732
43763
  } finally {
@@ -45128,11 +45159,11 @@ Full guide: __tooling__/docs/tools/baker/creatives.md`
45128
45159
  import { defineCommand as defineCommand124 } from "citty";
45129
45160
 
45130
45161
  // src/commands/experiment/composition.ts
45131
- import { readdir as readdir11, readFile as readFile24 } from "fs/promises";
45162
+ import { readdir as readdir12, readFile as readFile24 } from "fs/promises";
45132
45163
  import path30 from "path";
45133
45164
 
45134
45165
  // src/commands/landing/import-graph.ts
45135
- import { readdir as readdir10, readFile as readFile23, stat as stat5 } from "fs/promises";
45166
+ import { readdir as readdir11, readFile as readFile23, stat as stat5 } from "fs/promises";
45136
45167
  import path29 from "path";
45137
45168
  var SOURCE_EXT = /\.(astro|ts|tsx|js|jsx|mjs|cjs|vue|svelte)$/;
45138
45169
  var RESOLVE_CANDIDATES = [
@@ -45160,7 +45191,7 @@ async function isFile(p) {
45160
45191
  async function walkFiles(dir) {
45161
45192
  let entries;
45162
45193
  try {
45163
- entries = await readdir10(dir, { withFileTypes: true });
45194
+ entries = await readdir11(dir, { withFileTypes: true });
45164
45195
  } catch {
45165
45196
  return [];
45166
45197
  }
@@ -45263,7 +45294,7 @@ function formsOnlyIn(these, those) {
45263
45294
  }
45264
45295
  async function knownFlows(root) {
45265
45296
  try {
45266
- const entries = await readdir11(path30.join(root, "src/lib/flow-engine/flows"), { withFileTypes: true });
45297
+ const entries = await readdir12(path30.join(root, "src/lib/flow-engine/flows"), { withFileTypes: true });
45267
45298
  return new Set(entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name));
45268
45299
  } catch {
45269
45300
  return /* @__PURE__ */ new Set();
@@ -45284,7 +45315,7 @@ async function readForms(root, slug) {
45284
45315
 
45285
45316
  // src/commands/experiment/fold.ts
45286
45317
  import { statSync } from "fs";
45287
- import { cp as cp3, mkdir as mkdir9, readdir as readdir12, readFile as readFile25, rm as rm8, stat as stat6, writeFile as writeFile12 } from "fs/promises";
45318
+ import { cp as cp3, mkdir as mkdir9, readdir as readdir13, readFile as readFile25, rm as rm8, stat as stat6, writeFile as writeFile12 } from "fs/promises";
45288
45319
  import path32 from "path";
45289
45320
 
45290
45321
  // ../api/src/experiments/variants.ts
@@ -45359,7 +45390,7 @@ async function isDir(p) {
45359
45390
  async function filesUnder(dir, prefix = "") {
45360
45391
  let entries;
45361
45392
  try {
45362
- entries = await readdir12(dir, { withFileTypes: true });
45393
+ entries = await readdir13(dir, { withFileTypes: true });
45363
45394
  } catch {
45364
45395
  return [];
45365
45396
  }
@@ -55723,7 +55754,7 @@ Full guide: __tooling__/docs/tools/baker/images.md`
55723
55754
  import { defineCommand as defineCommand182 } from "citty";
55724
55755
 
55725
55756
  // src/commands/landing/critique.ts
55726
- import { readdir as readdir14, readFile as readFile30, stat as stat9 } from "fs/promises";
55757
+ import { readdir as readdir15, readFile as readFile30, stat as stat9 } from "fs/promises";
55727
55758
  import path37 from "path";
55728
55759
  import { defineCommand as defineCommand171 } from "citty";
55729
55760
 
@@ -56934,7 +56965,7 @@ async function writeCritiqueSnapshot(projectRoot, snapshot) {
56934
56965
  }
56935
56966
 
56936
56967
  // src/commands/landing/source-version.ts
56937
- import { readdir as readdir13, readFile as readFile29, stat as stat8 } from "fs/promises";
56968
+ import { readdir as readdir14, readFile as readFile29, stat as stat8 } from "fs/promises";
56938
56969
  import path36 from "path";
56939
56970
  var CRITIQUED_ROOTS = ["src/pages/", "src/components/"];
56940
56971
  async function landingSourceRelPaths(root, slug) {
@@ -56990,7 +57021,7 @@ async function isFile2(p) {
56990
57021
  async function walkAstro(dir) {
56991
57022
  let entries;
56992
57023
  try {
56993
- entries = await readdir13(dir, { withFileTypes: true });
57024
+ entries = await readdir14(dir, { withFileTypes: true });
56994
57025
  } catch {
56995
57026
  return [];
56996
57027
  }
@@ -57123,7 +57154,7 @@ async function readCompetitorNames(projectRoot) {
57123
57154
  const dir = path37.join(projectRoot, "src", "content", "competitors");
57124
57155
  let entries;
57125
57156
  try {
57126
- entries = (await readdir14(dir)).filter((f) => f.endsWith(".md"));
57157
+ entries = (await readdir15(dir)).filter((f) => f.endsWith(".md"));
57127
57158
  } catch {
57128
57159
  return [];
57129
57160
  }
@@ -57141,7 +57172,7 @@ async function readCompetitorNames(projectRoot) {
57141
57172
  }
57142
57173
  async function listLandingSlugs(projectRoot) {
57143
57174
  try {
57144
- const entries = await readdir14(path37.join(projectRoot, "src", "pages"), { withFileTypes: true });
57175
+ const entries = await readdir15(path37.join(projectRoot, "src", "pages"), { withFileTypes: true });
57145
57176
  return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).map((e) => e.name).sort();
57146
57177
  } catch {
57147
57178
  return [];
@@ -60334,7 +60365,7 @@ Full guide: __tooling__/docs/tools/baker/landing.md`
60334
60365
 
60335
60366
  // src/commands/landing/variant.ts
60336
60367
  import { randomUUID as randomUUID2 } from "crypto";
60337
- import { mkdir as mkdir14, readdir as readdir15, readFile as readFile31, stat as stat10, writeFile as writeFile19 } from "fs/promises";
60368
+ import { mkdir as mkdir14, readdir as readdir16, readFile as readFile31, stat as stat10, writeFile as writeFile19 } from "fs/promises";
60338
60369
  import path45 from "path";
60339
60370
  import { defineCommand as defineCommand181 } from "citty";
60340
60371
  registerSchema({
@@ -60371,7 +60402,7 @@ async function readInternalId(definitionPath) {
60371
60402
  async function archivedVariantNumbers(root, internalId) {
60372
60403
  if (!internalId) return [];
60373
60404
  try {
60374
- const entries = await readdir15(path45.resolve(root, "src/_variants", internalId), { withFileTypes: true });
60405
+ const entries = await readdir16(path45.resolve(root, "src/_variants", internalId), { withFileTypes: true });
60375
60406
  return entries.filter((entry) => entry.isDirectory()).map((entry) => Number(entry.name)).filter((n) => Number.isInteger(n) && n > 0);
60376
60407
  } catch {
60377
60408
  return [];
@@ -60401,7 +60432,7 @@ async function exists(p) {
60401
60432
  }
60402
60433
  async function listLandingSlugs2(root) {
60403
60434
  try {
60404
- const entries = await readdir15(path45.resolve(root, "src", "pages"), { withFileTypes: true });
60435
+ const entries = await readdir16(path45.resolve(root, "src", "pages"), { withFileTypes: true });
60405
60436
  return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).map((e) => e.name).sort();
60406
60437
  } catch {
60407
60438
  return [];
@@ -60410,7 +60441,7 @@ async function listLandingSlugs2(root) {
60410
60441
  async function listComponents(componentsDir, prefix = "") {
60411
60442
  let entries;
60412
60443
  try {
60413
- entries = await readdir15(componentsDir, { withFileTypes: true });
60444
+ entries = await readdir16(componentsDir, { withFileTypes: true });
60414
60445
  } catch {
60415
60446
  return [];
60416
60447
  }