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

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,7 +42,6 @@ import {
42
42
  isAudioOnly,
43
43
  isPersistedAssetRef,
44
44
  isVimeoAuthFailure,
45
- loadCompositionMeta,
46
45
  looksLikeHttpUrl,
47
46
  maxInputReferences,
48
47
  maxInputSlot,
@@ -69,7 +68,7 @@ import {
69
68
  validateCanvasDeep,
70
69
  withoutCastName,
71
70
  ytDlpBlockSignal
72
- } from "./chunk-Q2VR3FVM.js";
71
+ } from "./chunk-B7MLH3K6.js";
73
72
  import {
74
73
  csvOrJson,
75
74
  daysAgoIso,
@@ -16799,7 +16798,7 @@ import { defineCommand as defineCommand31 } from "citty";
16799
16798
 
16800
16799
  // src/commands/ads/google/ad-copy-flags.ts
16801
16800
  var AD_COPY_LIST_FLAGS = ["headlines", "descriptions", "long-headlines"];
16802
- var AD_COPY_LIST_USAGE = `repeat the flag once per item, or pass one comma-separated list and wrap an item that contains a comma in double quotes: '"Fast, free quotes",Book today'. A flag given once is read as a list, so a lone item with a comma needs its double quotes too: '"Fast, free quotes"'`;
16801
+ var AD_COPY_LIST_USAGE = `repeat the flag once per item, or pass one comma-separated list and wrap an item that contains a comma in double quotes: '"Fast, free quotes",Book today' (or escape its comma: 'Fast\\, free quotes,Book today'). A flag given once is read as a list, so a lone item with a comma needs its double quotes too: '"Fast, free quotes"'`;
16803
16802
  function skipBlanks(value, at) {
16804
16803
  let i = at;
16805
16804
  while (value[i] === " " || value[i] === " ") i++;
@@ -16823,6 +16822,20 @@ function readQuotedField(value, open, flag) {
16823
16822
  }
16824
16823
  return { text: text2, next: after + 1 };
16825
16824
  }
16825
+ function readUnquotedField(value, start) {
16826
+ let text2 = "";
16827
+ let j = start;
16828
+ while (j < value.length && value[j] !== ",") {
16829
+ if (value[j] === "\\" && value[j + 1] === ",") {
16830
+ text2 += ",";
16831
+ j += 2;
16832
+ } else {
16833
+ text2 += value[j];
16834
+ j++;
16835
+ }
16836
+ }
16837
+ return { text: text2, next: j + 1 };
16838
+ }
16826
16839
  function splitQuotedList(value, flag) {
16827
16840
  const fields = [];
16828
16841
  let i = 0;
@@ -16833,10 +16846,9 @@ function splitQuotedList(value, flag) {
16833
16846
  fields.push({ text: text2, quoted: true });
16834
16847
  i = next;
16835
16848
  } else {
16836
- const comma = value.indexOf(",", start);
16837
- const end = comma === -1 ? value.length : comma;
16838
- fields.push({ text: value.slice(start, end), quoted: false });
16839
- i = end + 1;
16849
+ const { text: text2, next } = readUnquotedField(value, start);
16850
+ fields.push({ text: text2, quoted: false });
16851
+ i = next;
16840
16852
  }
16841
16853
  }
16842
16854
  const several = fields.length > 1;
@@ -16854,7 +16866,7 @@ function jsonStringArray(value) {
16854
16866
  function parseCopyList(value, flag) {
16855
16867
  let items;
16856
16868
  if (Array.isArray(value)) {
16857
- items = value.filter((v) => typeof v === "string").map((v) => ({ text: v.trim(), splitAtComma: false }));
16869
+ items = value.filter((v) => typeof v === "string").map((v) => ({ text: v.replaceAll("\\,", ",").trim(), splitAtComma: false }));
16858
16870
  } else if (typeof value === "string") {
16859
16871
  const trimmed = value.trim();
16860
16872
  const json = jsonStringArray(trimmed);
@@ -24818,12 +24830,7 @@ var metaDraftAdvisorySchema = z34.object({
24818
24830
  message: z34.string()
24819
24831
  });
24820
24832
  var metaDraftListResponseSchema = z34.object({
24821
- /**
24822
- * `applied` means the publish finished with no op failed or skipped — when `mode` is `simulated`
24823
- * nothing reached Meta. `partial` means the publish finished but at least one op failed or was
24824
- * skipped — read each op's `result` for which one and why.
24825
- */
24826
- status: z34.enum(["active", "publishing", "applied", "partial", "discarded", "none"]),
24833
+ status: z34.enum(["active", "publishing", "applied", "discarded", "none"]),
24827
24834
  mode: metaWriteModeSchema,
24828
24835
  count: z34.number(),
24829
24836
  ops: z34.array(metaDraftOpViewSchema),
@@ -35532,49 +35539,7 @@ import { defineCommand as defineCommand119 } from "citty";
35532
35539
 
35533
35540
  // src/commands/canvas/catalog.ts
35534
35541
  import { defineCommand as defineCommand108 } from "citty";
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.";
35542
+ 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`.";
35578
35543
  var ARGS = {
35579
35544
  node: {
35580
35545
  type: "string",
@@ -35593,16 +35558,12 @@ var ARGS = {
35593
35558
  description: "Print full JSON Schemas instead of the one-line index (every node, or the --category)."
35594
35559
  }
35595
35560
  };
35596
- async function canvasCatalog(opts) {
35597
- const compositions = await listShippedCompositions(import.meta.dirname);
35598
- return catalogView(generateCatalog(defaultRegistry(), { compositions }), opts);
35599
- }
35600
35561
  registerSchema({ command: "canvas.catalog", description: DESCRIPTION, args: ARGS });
35601
35562
  var catalogCommand = defineCommand108({
35602
35563
  meta: { name: "catalog", description: DESCRIPTION },
35603
35564
  args: ARGS,
35604
35565
  async run({ args: args5 }) {
35605
- const view = await canvasCatalog({
35566
+ const view = catalogView(generateCatalog(defaultRegistry()), {
35606
35567
  node: typeof args5.node === "string" ? args5.node : void 0,
35607
35568
  category: typeof args5.category === "string" ? args5.category : void 0,
35608
35569
  full: args5.full === true
@@ -35615,7 +35576,7 @@ var catalogCommand = defineCommand108({
35615
35576
 
35616
35577
  // src/commands/canvas/critique.ts
35617
35578
  import { readFile as readFile3 } from "fs/promises";
35618
- import path4 from "path";
35579
+ import path3 from "path";
35619
35580
  import { defineCommand as defineCommand109 } from "citty";
35620
35581
 
35621
35582
  // src/engine/scaffold/lib/critique.ts
@@ -35743,7 +35704,7 @@ var critiqueCommand = defineCommand109({
35743
35704
  },
35744
35705
  args: { file: { type: "positional", required: true, description: "Path to canvas JSON" } },
35745
35706
  async run({ args: args5 }) {
35746
- const filePath = path4.resolve(String(args5.file));
35707
+ const filePath = path3.resolve(String(args5.file));
35747
35708
  const raw = await readFile3(filePath, "utf8");
35748
35709
  let parsed;
35749
35710
  try {
@@ -35775,8 +35736,8 @@ var critiqueCommand = defineCommand109({
35775
35736
 
35776
35737
  // src/commands/canvas/inspect.ts
35777
35738
  import { execFile } from "child_process";
35778
- import { readdir as readdir3, readFile as readFile4, stat } from "fs/promises";
35779
- import path5 from "path";
35739
+ import { readdir as readdir2, readFile as readFile4, stat } from "fs/promises";
35740
+ import path4 from "path";
35780
35741
  import { promisify } from "util";
35781
35742
  import { defineCommand as defineCommand110 } from "citty";
35782
35743
  var execFileAsync = promisify(execFile);
@@ -35794,7 +35755,7 @@ var inspectCommand = defineCommand110({
35794
35755
  }
35795
35756
  },
35796
35757
  async run({ args: args5 }) {
35797
- const outputsDir = path5.resolve(String(args5["outputs-dir"] ?? "canvas"));
35758
+ const outputsDir = path4.resolve(String(args5["outputs-dir"] ?? "canvas"));
35798
35759
  const runArg = String(args5.run);
35799
35760
  const runDir = await resolveRunDir(runArg, outputsDir);
35800
35761
  const manifest = await loadManifest(runDir);
@@ -35806,7 +35767,7 @@ var inspectCommand = defineCommand110({
35806
35767
  }
35807
35768
  const summary = {
35808
35769
  ok: true,
35809
- run_id: manifest.run_id ?? path5.basename(runDir),
35770
+ run_id: manifest.run_id ?? path4.basename(runDir),
35810
35771
  run_dir: runDir,
35811
35772
  stats: manifest.stats ?? null,
35812
35773
  output: manifest.output ?? null,
@@ -35819,18 +35780,18 @@ var inspectCommand = defineCommand110({
35819
35780
  }
35820
35781
  });
35821
35782
  async function resolveRunDir(run, outputsDir) {
35822
- if (path5.isAbsolute(run)) {
35783
+ if (path4.isAbsolute(run)) {
35823
35784
  const s2 = await stat(run).catch(() => null);
35824
35785
  if (s2?.isDirectory()) return run;
35825
35786
  throw new Error(`inspect: ${run} is not a directory`);
35826
35787
  }
35827
- const candidate = path5.join(outputsDir, run);
35788
+ const candidate = path4.join(outputsDir, run);
35828
35789
  const s = await stat(candidate).catch(() => null);
35829
35790
  if (s?.isDirectory()) return candidate;
35830
35791
  throw new Error(`inspect: no run directory at ${candidate}`);
35831
35792
  }
35832
35793
  async function loadManifest(runDir) {
35833
- const manifestPath = path5.join(runDir, "manifest.json");
35794
+ const manifestPath = path4.join(runDir, "manifest.json");
35834
35795
  try {
35835
35796
  const raw = await readFile4(manifestPath, "utf-8");
35836
35797
  return JSON.parse(raw);
@@ -35840,9 +35801,9 @@ async function loadManifest(runDir) {
35840
35801
  }
35841
35802
  async function listRunFiles(runDir) {
35842
35803
  const out = [];
35843
- const names = await readdir3(runDir);
35804
+ const names = await readdir2(runDir);
35844
35805
  for (const name of names) {
35845
- const abs = path5.join(runDir, name);
35806
+ const abs = path4.join(runDir, name);
35846
35807
  const s = await stat(abs).catch(() => null);
35847
35808
  if (!s?.isFile()) continue;
35848
35809
  out.push({ name, path: abs, size: s.size });
@@ -35887,58 +35848,58 @@ async function probeDuration(filePath) {
35887
35848
  }
35888
35849
 
35889
35850
  // src/commands/canvas/rerun.ts
35890
- import path18 from "path";
35851
+ import path17 from "path";
35891
35852
  import { defineCommand as defineCommand112 } from "citty";
35892
35853
 
35893
35854
  // src/commands/canvas/run.ts
35894
35855
  import { readFile as readFile12 } from "fs/promises";
35895
- import path17 from "path";
35856
+ import path16 from "path";
35896
35857
  import { defineCommand as defineCommand111 } from "citty";
35897
35858
 
35898
35859
  // src/commands/canvas/normalize-paths.ts
35899
- import { existsSync as existsSync5, realpathSync } from "fs";
35860
+ import { existsSync as existsSync4, realpathSync } from "fs";
35900
35861
  import { writeFile as writeFile2 } from "fs/promises";
35901
- import path6 from "path";
35902
- function findWorkspaceRoot(startDir, exists2 = existsSync5, maxDepth = 12) {
35903
- let dir = path6.resolve(startDir);
35862
+ import path5 from "path";
35863
+ function findWorkspaceRoot(startDir, exists2 = existsSync4, maxDepth = 12) {
35864
+ let dir = path5.resolve(startDir);
35904
35865
  for (let i = 0; i < maxDepth; i++) {
35905
- if (exists2(path6.join(dir, "package.json"))) return dir;
35906
- const parent = path6.dirname(dir);
35866
+ if (exists2(path5.join(dir, "package.json"))) return dir;
35867
+ const parent = path5.dirname(dir);
35907
35868
  if (parent === dir) break;
35908
35869
  dir = parent;
35909
35870
  }
35910
35871
  return null;
35911
35872
  }
35912
35873
  function canonicalize(target) {
35913
- const abs = path6.resolve(target);
35874
+ const abs = path5.resolve(target);
35914
35875
  let dir = abs;
35915
35876
  for (; ; ) {
35916
35877
  try {
35917
35878
  const real = realpathSync(dir);
35918
- return dir === abs ? real : path6.join(real, path6.relative(dir, abs));
35879
+ return dir === abs ? real : path5.join(real, path5.relative(dir, abs));
35919
35880
  } catch {
35920
- const parent = path6.dirname(dir);
35881
+ const parent = path5.dirname(dir);
35921
35882
  if (parent === dir) return abs;
35922
35883
  dir = parent;
35923
35884
  }
35924
35885
  }
35925
35886
  }
35926
35887
  function isInside(root, target) {
35927
- const rel = path6.relative(root, target);
35928
- return rel !== "" && !rel.startsWith("..") && !path6.isAbsolute(rel);
35888
+ const rel = path5.relative(root, target);
35889
+ return rel !== "" && !rel.startsWith("..") && !path5.isAbsolute(rel);
35929
35890
  }
35930
35891
  function toCanvasRelative(canvasDir, target) {
35931
- return path6.relative(canvasDir, target).split(path6.sep).join("/");
35892
+ return path5.relative(canvasDir, target).split(path5.sep).join("/");
35932
35893
  }
35933
35894
  var RUNTIME_WORKSPACE_ROOT = "/home/user/repo";
35934
35895
  function rewriteTarget(value, workspaceRoot) {
35935
35896
  if (typeof value !== "string" || value.length === 0) return null;
35936
- if (value.includes("[TODO") || looksLikeHttpUrl(value) || !path6.isAbsolute(value)) return null;
35897
+ if (value.includes("[TODO") || looksLikeHttpUrl(value) || !path5.isAbsolute(value)) return null;
35937
35898
  const target = canonicalize(value);
35938
35899
  if (isInside(workspaceRoot, target)) return target;
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);
35900
+ const fromRuntime = path5.relative(RUNTIME_WORKSPACE_ROOT, path5.normalize(value));
35901
+ if (fromRuntime !== "" && !fromRuntime.startsWith("..") && !path5.isAbsolute(fromRuntime)) {
35902
+ return path5.join(workspaceRoot, fromRuntime);
35942
35903
  }
35943
35904
  return null;
35944
35905
  }
@@ -35966,7 +35927,7 @@ function normalizeAbsoluteCanvasPaths(canvas, canvasDir, workspaceRoot) {
35966
35927
  return rewrites.length === 0 ? { canvas, rewrites } : { canvas: { ...canvas, nodes }, rewrites };
35967
35928
  }
35968
35929
  async function healAbsoluteCanvasPaths(filePath, canvas) {
35969
- const canvasDir = path6.dirname(filePath);
35930
+ const canvasDir = path5.dirname(filePath);
35970
35931
  const workspaceRoot = findWorkspaceRoot(canvasDir);
35971
35932
  if (!workspaceRoot) return { canvas, rewrites: [], text: null };
35972
35933
  const normalized = normalizeAbsoluteCanvasPaths(canvas, canvasDir, workspaceRoot);
@@ -35997,7 +35958,7 @@ function unsuppliedPlaceholderAssets(canvas) {
35997
35958
  }
35998
35959
 
35999
35960
  // src/commands/canvas/resolve-paths.ts
36000
- import path7 from "path";
35961
+ import path6 from "path";
36001
35962
  function resolveRelativeCanvasPaths(canvas, baseDir) {
36002
35963
  if (!canvas || typeof canvas !== "object") return canvas;
36003
35964
  const c = canvas;
@@ -36010,24 +35971,24 @@ function resolveNode(node, baseDir) {
36010
35971
  const params = n.params;
36011
35972
  if (!params || typeof params !== "object") return node;
36012
35973
  if (n.type === "ingest" && params.source === "path" && isResolvableRelative(params.path)) {
36013
- return { ...node, params: { ...params, path: path7.resolve(baseDir, params.path) } };
35974
+ return { ...node, params: { ...params, path: path6.resolve(baseDir, params.path) } };
36014
35975
  }
36015
35976
  if (n.type === "hyperframe_render" && isResolvableRelative(params.composition)) {
36016
- return { ...node, params: { ...params, composition: path7.resolve(baseDir, params.composition) } };
35977
+ return { ...node, params: { ...params, composition: path6.resolve(baseDir, params.composition) } };
36017
35978
  }
36018
35979
  return node;
36019
35980
  }
36020
35981
  function isResolvableRelative(value) {
36021
- return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !looksLikeHttpUrl(value) && !path7.isAbsolute(value);
35982
+ return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !looksLikeHttpUrl(value) && !path6.isAbsolute(value);
36022
35983
  }
36023
35984
 
36024
35985
  // src/commands/canvas/source-version.ts
36025
35986
  import { readFile as readFile6 } from "fs/promises";
36026
- import path9 from "path";
35987
+ import path8 from "path";
36027
35988
 
36028
35989
  // src/commands/canvas/scene-files.ts
36029
- import { mkdir as mkdir2, readFile as readFile5, readdir as readdir4, rm, writeFile as writeFile3 } from "fs/promises";
36030
- import path8 from "path";
35990
+ import { mkdir as mkdir2, readFile as readFile5, readdir as readdir3, rm, writeFile as writeFile3 } from "fs/promises";
35991
+ import path7 from "path";
36031
35992
  var SCENES_DIR = "scenes";
36032
35993
  var GLOBAL_PROMPT_FILE = "prompt.json";
36033
35994
  var REBUILD_FILE = "prompt.rebuild.json";
@@ -36044,38 +36005,38 @@ function splitBlueprint(blueprint) {
36044
36005
  }
36045
36006
  async function writeSceneFiles(outDir, blueprint) {
36046
36007
  const { global, scenes } = splitBlueprint(blueprint);
36047
- await writeFile3(path8.join(outDir, GLOBAL_PROMPT_FILE), `${JSON.stringify(global, null, 2)}
36008
+ await writeFile3(path7.join(outDir, GLOBAL_PROMPT_FILE), `${JSON.stringify(global, null, 2)}
36048
36009
  `, "utf8");
36049
- const scenesDir = path8.join(outDir, SCENES_DIR);
36010
+ const scenesDir = path7.join(outDir, SCENES_DIR);
36050
36011
  await mkdir2(scenesDir, { recursive: true });
36051
36012
  const written = /* @__PURE__ */ new Set();
36052
36013
  for (let i = 0; i < scenes.length; i++) {
36053
36014
  const name = sceneFileName(i, scenes.length);
36054
36015
  written.add(name);
36055
- await writeFile3(path8.join(scenesDir, name), `${JSON.stringify(scenes[i], null, 2)}
36016
+ await writeFile3(path7.join(scenesDir, name), `${JSON.stringify(scenes[i], null, 2)}
36056
36017
  `, "utf8");
36057
36018
  }
36058
36019
  for (const name of await listSceneFileNames(scenesDir)) {
36059
- if (!written.has(name)) await rm(path8.join(scenesDir, name), { force: true });
36020
+ if (!written.has(name)) await rm(path7.join(scenesDir, name), { force: true });
36060
36021
  }
36061
36022
  }
36062
36023
  async function listSceneFileNames(scenesDir) {
36063
36024
  let entries;
36064
36025
  try {
36065
- entries = await readdir4(scenesDir);
36026
+ entries = await readdir3(scenesDir);
36066
36027
  } catch {
36067
36028
  return [];
36068
36029
  }
36069
36030
  return entries.filter((n) => /^s\d+\.json$/.test(n)).sort(bySceneIndex);
36070
36031
  }
36071
36032
  async function listSceneFiles(creativeDir) {
36072
- const scenesDir = path8.join(creativeDir, SCENES_DIR);
36073
- return (await listSceneFileNames(scenesDir)).map((n) => path8.join(scenesDir, n));
36033
+ const scenesDir = path7.join(creativeDir, SCENES_DIR);
36034
+ return (await listSceneFileNames(scenesDir)).map((n) => path7.join(scenesDir, n));
36074
36035
  }
36075
36036
  async function reassembleBlueprint(creativeDir) {
36076
36037
  const files = await listSceneFiles(creativeDir);
36077
36038
  if (files.length === 0) return null;
36078
- const globalRaw = await readFile5(path8.join(creativeDir, GLOBAL_PROMPT_FILE), "utf8");
36039
+ const globalRaw = await readFile5(path7.join(creativeDir, GLOBAL_PROMPT_FILE), "utf8");
36079
36040
  const global = JSON.parse(globalRaw);
36080
36041
  const scenes = [];
36081
36042
  for (const file of files) {
@@ -36097,8 +36058,8 @@ async function computeSourceSha(canvasPath) {
36097
36058
  } catch {
36098
36059
  return void 0;
36099
36060
  }
36100
- const canvasDir = path9.dirname(canvasPath);
36101
- const promptPath = path9.join(canvasDir, "prompt.json");
36061
+ const canvasDir = path8.dirname(canvasPath);
36062
+ const promptPath = path8.join(canvasDir, "prompt.json");
36102
36063
  let promptBytes;
36103
36064
  try {
36104
36065
  promptBytes = await readFile6(promptPath);
@@ -36125,7 +36086,7 @@ async function computeSourceSha(canvasPath) {
36125
36086
 
36126
36087
  // src/commands/canvas/scene-projection.ts
36127
36088
  import { readFile as readFile7 } from "fs/promises";
36128
- import path10 from "path";
36089
+ import path9 from "path";
36129
36090
 
36130
36091
  // src/engine/scaffold/video.ts
36131
36092
  import { toCardinal as nwAr } from "n2words/ar-SA";
@@ -39531,12 +39492,12 @@ function nonPromptParamsDiverge(live = {}, rebuilt = {}) {
39531
39492
  return false;
39532
39493
  }
39533
39494
  async function syncSceneNodeParams(canvas, canvasPath, log) {
39534
- const creativeDir = path10.dirname(canvasPath);
39495
+ const creativeDir = path9.dirname(canvasPath);
39535
39496
  const blueprint = await reassembleBlueprint(creativeDir);
39536
39497
  if (!blueprint) return "not_applicable";
39537
39498
  let rebuildRaw;
39538
39499
  try {
39539
- rebuildRaw = await readFile7(path10.join(creativeDir, REBUILD_FILE), "utf8");
39500
+ rebuildRaw = await readFile7(path9.join(creativeDir, REBUILD_FILE), "utf8");
39540
39501
  } catch {
39541
39502
  log(
39542
39503
  `[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.`
@@ -39671,13 +39632,13 @@ ${body}` : header || body || compactJson(record);
39671
39632
  }
39672
39633
 
39673
39634
  // src/commands/canvas/run-record.ts
39674
- import path11 from "path";
39635
+ import path10 from "path";
39675
39636
  var MAX_RUN_NODES = 200;
39676
39637
  var MAX_OUTPUTS_PER_NODE = 10;
39677
39638
  var MAX_FINAL_OUTPUTS = 10;
39678
39639
  var MAX_CREATIVE_SLUG_LENGTH = 100;
39679
39640
  function creativeSlugFromCanvasPath(filePath) {
39680
- const normalized = filePath.split(path11.sep).join("/");
39641
+ const normalized = filePath.split(path10.sep).join("/");
39681
39642
  const match = normalized.match(/(?:^|\/)src\/creatives\/([a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\//);
39682
39643
  const slug = match?.[1] ?? null;
39683
39644
  return slug && slug.length <= MAX_CREATIVE_SLUG_LENGTH ? slug : null;
@@ -39970,24 +39931,24 @@ var RunRecordPoster = class {
39970
39931
 
39971
39932
  // src/commands/canvas/run-retention.ts
39972
39933
  import { rm as rm2 } from "fs/promises";
39973
- import path12 from "path";
39934
+ import path11 from "path";
39974
39935
  function runDirsToPrune(entries, keep, currentRunId) {
39975
39936
  const runs = entries.filter((e) => /^r_[0-9A-Za-z]+$/.test(e) && e !== currentRunId).sort();
39976
39937
  if (keep <= 0) return runs;
39977
39938
  return runs.slice(0, Math.max(0, runs.length - keep));
39978
39939
  }
39979
39940
  async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
39980
- const { readdir: readdir17 } = await import("fs/promises");
39941
+ const { readdir: readdir16 } = await import("fs/promises");
39981
39942
  let entries;
39982
39943
  try {
39983
- entries = await readdir17(outputsDir);
39944
+ entries = await readdir16(outputsDir);
39984
39945
  } catch {
39985
39946
  return;
39986
39947
  }
39987
39948
  const toPrune = runDirsToPrune(entries, keep, currentRunId);
39988
39949
  if (toPrune.length === 0) return;
39989
39950
  for (const dir of toPrune) {
39990
- await rm2(path12.join(outputsDir, dir), { recursive: true, force: true }).catch(
39951
+ await rm2(path11.join(outputsDir, dir), { recursive: true, force: true }).catch(
39991
39952
  (e) => log(`[prune ] could not remove ${dir}: ${e.message}`)
39992
39953
  );
39993
39954
  }
@@ -39995,13 +39956,13 @@ async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
39995
39956
  }
39996
39957
 
39997
39958
  // src/commands/canvas/dirty-marker.ts
39998
- import { mkdir as mkdir3, readdir as readdir5, rm as rm3, writeFile as writeFile5 } from "fs/promises";
39999
- import path13 from "path";
39959
+ import { mkdir as mkdir3, readdir as readdir4, rm as rm3, writeFile as writeFile5 } from "fs/promises";
39960
+ import path12 from "path";
40000
39961
  function creativeDirtyDir(base) {
40001
- return base ?? path13.resolve("canvas", ".dirty");
39962
+ return base ?? path12.resolve("canvas", ".dirty");
40002
39963
  }
40003
39964
  function dirtyMarkerFile(slug, base) {
40004
- return path13.join(creativeDirtyDir(base), `${slug}.json`);
39965
+ return path12.join(creativeDirtyDir(base), `${slug}.json`);
40005
39966
  }
40006
39967
  async function clearCreativeDirty(slug, base) {
40007
39968
  try {
@@ -40012,17 +39973,17 @@ async function clearCreativeDirty(slug, base) {
40012
39973
 
40013
39974
  // src/commands/canvas/run-resume.ts
40014
39975
  import { mkdir as mkdir4, readFile as readFile9, rm as rm4, writeFile as writeFile6 } from "fs/promises";
40015
- import path14 from "path";
39976
+ import path13 from "path";
40016
39977
  function markerKey(canvasPath) {
40017
39978
  const slug = creativeSlugFromCanvasPath(canvasPath);
40018
- const identity = slug ?? path14.relative(process.cwd(), path14.resolve(canvasPath));
39979
+ const identity = slug ?? path13.relative(process.cwd(), path13.resolve(canvasPath));
40019
39980
  return sha256Hex(Buffer.from(identity)).slice(0, 32);
40020
39981
  }
40021
39982
  function legacyMarkerKey(canvasPath) {
40022
- return sha256Hex(Buffer.from(path14.resolve(canvasPath))).slice(0, 32);
39983
+ return sha256Hex(Buffer.from(path13.resolve(canvasPath))).slice(0, 32);
40023
39984
  }
40024
39985
  function markerFile(outputsDir, key) {
40025
- return path14.join(outputsDir, ".inflight", `${key}.json`);
39986
+ return path13.join(outputsDir, ".inflight", `${key}.json`);
40026
39987
  }
40027
39988
  var REMOTE_ADOPT_STALE_MS = 12e4;
40028
39989
  function classifyRemoteRun(run, now) {
@@ -40069,8 +40030,8 @@ async function readMarkerRunId(outputsDir, canvasPath) {
40069
40030
  async function markRunInFlight(outputsDir, canvasPath, runId) {
40070
40031
  try {
40071
40032
  const file = markerFile(outputsDir, markerKey(canvasPath));
40072
- await mkdir4(path14.dirname(file), { recursive: true });
40073
- await writeFile6(file, JSON.stringify({ runId, canvasPath: path14.resolve(canvasPath), startedAt: Date.now() }));
40033
+ await mkdir4(path13.dirname(file), { recursive: true });
40034
+ await writeFile6(file, JSON.stringify({ runId, canvasPath: path13.resolve(canvasPath), startedAt: Date.now() }));
40074
40035
  } catch {
40075
40036
  }
40076
40037
  }
@@ -40084,8 +40045,8 @@ async function clearRunMarker(outputsDir, canvasPath) {
40084
40045
  }
40085
40046
 
40086
40047
  // src/commands/canvas/run-snapshot.ts
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";
40048
+ import { mkdir as mkdir5, readdir as readdir5, readFile as readFile10, stat as stat2, writeFile as writeFile7 } from "fs/promises";
40049
+ import path14 from "path";
40089
40050
  var SNAPSHOT_SCHEMA = "baker-canvas-snapshot/1";
40090
40051
  var MAX_SNAPSHOT_FILE_BYTES = 32 * 1024 * 1024;
40091
40052
  var EXT_TO_MIME = {
@@ -40112,15 +40073,15 @@ var EXT_TO_MIME = {
40112
40073
  woff2: "font/woff2"
40113
40074
  };
40114
40075
  function mimeForFile(filePath) {
40115
- const ext = path15.extname(filePath).slice(1).toLowerCase();
40076
+ const ext = path14.extname(filePath).slice(1).toLowerCase();
40116
40077
  return EXT_TO_MIME[ext] ?? "application/octet-stream";
40117
40078
  }
40118
40079
  function toPosix(p) {
40119
- return p.split(path15.sep).join("/");
40080
+ return p.split(path14.sep).join("/");
40120
40081
  }
40121
40082
  function isInside2(dir, target) {
40122
- const rel = path15.relative(dir, target);
40123
- return !rel.startsWith("..") && !path15.isAbsolute(rel);
40083
+ const rel = path14.relative(dir, target);
40084
+ return !rel.startsWith("..") && !path14.isAbsolute(rel);
40124
40085
  }
40125
40086
  function localPathRefsFromCanvas(parsed) {
40126
40087
  const nodes = parsed?.nodes;
@@ -40145,24 +40106,24 @@ function isSnapshotablePath(value) {
40145
40106
  async function sourceRefsToSnapshot(canvasDir, parsed) {
40146
40107
  const refs = new Set(localPathRefsFromCanvas(parsed));
40147
40108
  for (const sceneFile of await listSceneFiles(canvasDir)) {
40148
- refs.add(toPosix(path15.relative(canvasDir, sceneFile)));
40109
+ refs.add(toPosix(path14.relative(canvasDir, sceneFile)));
40149
40110
  }
40150
40111
  refs.add(REBUILD_FILE);
40151
40112
  return [...refs];
40152
40113
  }
40153
40114
  async function uploadRunSnapshot(client, opts) {
40154
40115
  try {
40155
- const canvasDir = path15.dirname(opts.canvasPath);
40116
+ const canvasDir = path14.dirname(opts.canvasPath);
40156
40117
  const put = (bytes, mime) => putContentAddressed(client, bytes, mime, opts.signal);
40157
40118
  const canvasBytes = Buffer.from(opts.raw);
40158
40119
  const canvasUpload = await put(canvasBytes, "application/json");
40159
40120
  const files = [];
40160
40121
  const skipped = [];
40161
40122
  for (const refPath of await sourceRefsToSnapshot(canvasDir, opts.parsed)) {
40162
- const abs = path15.isAbsolute(refPath) ? refPath : path15.resolve(canvasDir, refPath);
40123
+ const abs = path14.isAbsolute(refPath) ? refPath : path14.resolve(canvasDir, refPath);
40163
40124
  if (!isInside2(canvasDir, abs)) {
40164
40125
  skipped.push({
40165
- path: toPosix(path15.relative(canvasDir, abs)),
40126
+ path: toPosix(path14.relative(canvasDir, abs)),
40166
40127
  reason: "outside the creative folder \u2014 read from the workspace on rerun"
40167
40128
  });
40168
40129
  continue;
@@ -40171,12 +40132,12 @@ async function uploadRunSnapshot(client, opts) {
40171
40132
  try {
40172
40133
  st = await stat2(abs);
40173
40134
  } catch {
40174
- skipped.push({ path: toPosix(path15.relative(canvasDir, abs)), reason: "missing" });
40135
+ skipped.push({ path: toPosix(path14.relative(canvasDir, abs)), reason: "missing" });
40175
40136
  continue;
40176
40137
  }
40177
40138
  const fileList = st.isDirectory() ? await listFilesRecursive(abs) : [abs];
40178
40139
  for (const file of fileList) {
40179
- const rel = toPosix(path15.relative(canvasDir, file));
40140
+ const rel = toPosix(path14.relative(canvasDir, file));
40180
40141
  const size = (await stat2(file)).size;
40181
40142
  if (size > MAX_SNAPSHOT_FILE_BYTES) {
40182
40143
  skipped.push({ path: rel, reason: `too large (${size} bytes)` });
@@ -40191,7 +40152,7 @@ async function uploadRunSnapshot(client, opts) {
40191
40152
  schema: SNAPSHOT_SCHEMA,
40192
40153
  creativeSlug: opts.creativeSlug,
40193
40154
  canvasSha: canvasUpload.sha256,
40194
- canvas: { path: path15.basename(opts.canvasPath), sha256: canvasUpload.sha256, url: canvasUpload.url },
40155
+ canvas: { path: path14.basename(opts.canvasPath), sha256: canvasUpload.sha256, url: canvasUpload.url },
40195
40156
  files,
40196
40157
  skipped: skipped.length > 0 ? skipped : void 0
40197
40158
  };
@@ -40217,8 +40178,8 @@ async function putContentAddressed(client, bytes, mime, signal) {
40217
40178
  return { sha256, url: publicUrl };
40218
40179
  }
40219
40180
  async function listFilesRecursive(dir) {
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));
40181
+ const entries = await readdir5(dir, { recursive: true, withFileTypes: true });
40182
+ return entries.filter((d) => d.isFile()).map((d) => path14.join(d.parentPath, d.name));
40222
40183
  }
40223
40184
  var SnapshotConflictError = class extends Error {
40224
40185
  conflicts;
@@ -40230,16 +40191,16 @@ var SnapshotConflictError = class extends Error {
40230
40191
  };
40231
40192
  async function restoreRunSnapshot(manifest, targetDir, opts = {}) {
40232
40193
  const entries = [manifest.canvas, ...manifest.files];
40233
- const resolvedTarget = path15.resolve(targetDir);
40194
+ const resolvedTarget = path14.resolve(targetDir);
40234
40195
  const planned = [];
40235
40196
  const conflicts = [];
40236
40197
  const upToDate = [];
40237
40198
  for (const entry of entries) {
40238
- if (path15.isAbsolute(entry.path) || entry.path.split("/").includes("..")) {
40199
+ if (path14.isAbsolute(entry.path) || entry.path.split("/").includes("..")) {
40239
40200
  throw new Error(`snapshot entry escapes the creative directory: ${entry.path}`);
40240
40201
  }
40241
- const target = path15.resolve(resolvedTarget, entry.path);
40242
- if (target !== resolvedTarget && !target.startsWith(resolvedTarget + path15.sep)) {
40202
+ const target = path14.resolve(resolvedTarget, entry.path);
40203
+ if (target !== resolvedTarget && !target.startsWith(resolvedTarget + path14.sep)) {
40243
40204
  throw new Error(`snapshot entry escapes the creative directory: ${entry.path}`);
40244
40205
  }
40245
40206
  const existing = await readFile10(target).catch(() => null);
@@ -40264,18 +40225,18 @@ async function restoreRunSnapshot(manifest, targetDir, opts = {}) {
40264
40225
  if (sha256Hex(bytes) !== entry.sha256) {
40265
40226
  throw new Error(`snapshot download for ${entry.path} does not match its recorded sha256`);
40266
40227
  }
40267
- await mkdir5(path15.dirname(target), { recursive: true });
40228
+ await mkdir5(path14.dirname(target), { recursive: true });
40268
40229
  await writeFile7(target, bytes);
40269
40230
  restored.push(entry.path);
40270
40231
  }
40271
- return { canvasPath: path15.resolve(resolvedTarget, manifest.canvas.path), restored, upToDate };
40232
+ return { canvasPath: path14.resolve(resolvedTarget, manifest.canvas.path), restored, upToDate };
40272
40233
  }
40273
40234
 
40274
40235
  // src/engine/nodes/local/lib/render-review.ts
40275
40236
  import { execFile as execFile2 } from "child_process";
40276
- import { mkdtemp, readdir as readdir7, readFile as readFile11, rm as rm5 } from "fs/promises";
40237
+ import { mkdtemp, readdir as readdir6, readFile as readFile11, rm as rm5 } from "fs/promises";
40277
40238
  import { tmpdir } from "os";
40278
- import path16 from "path";
40239
+ import path15 from "path";
40279
40240
  import { promisify as promisify2 } from "util";
40280
40241
  import { z as z39 } from "zod";
40281
40242
  var RENDER_REVIEW_MODEL = "~google/gemini-pro-latest";
@@ -40697,11 +40658,11 @@ async function reviewRenderedVideo(opts) {
40697
40658
  const duration = await videoDuration(opts.video);
40698
40659
  if (duration === null) return null;
40699
40660
  const spent = (usage) => opts.onSpend?.(usage);
40700
- const dir = await mkdtemp(path16.join(tmpdir(), "baker-review-"));
40661
+ const dir = await mkdtemp(path15.join(tmpdir(), "baker-review-"));
40701
40662
  try {
40702
40663
  const grabbed = [];
40703
40664
  for (const [i, at] of reviewFrameTimes(duration, RENDER_REVIEW_FRAMES).entries()) {
40704
- const out = path16.join(dir, `f${String(i).padStart(2, "0")}.jpg`);
40665
+ const out = path15.join(dir, `f${String(i).padStart(2, "0")}.jpg`);
40705
40666
  try {
40706
40667
  await execFileAsync2("ffmpeg", buildFrameGrabArgs(opts.video, at, out), { timeout: 3e4 });
40707
40668
  grabbed.push({ at, image: await readFile11(out, { encoding: "base64" }) });
@@ -40751,7 +40712,7 @@ async function reviewRenderedVideo(opts) {
40751
40712
  }
40752
40713
  }
40753
40714
  async function reviewContextBeside(canvasPath) {
40754
- const raw = await readFile11(path16.join(path16.dirname(canvasPath), "prompt.json"), "utf-8").catch(() => null);
40715
+ const raw = await readFile11(path15.join(path15.dirname(canvasPath), "prompt.json"), "utf-8").catch(() => null);
40755
40716
  if (!raw) return {};
40756
40717
  try {
40757
40718
  const blueprint = JSON.parse(raw);
@@ -40767,12 +40728,12 @@ async function reviewContextBeside(canvasPath) {
40767
40728
  }
40768
40729
  }
40769
40730
  async function sceneWindowsBeside(canvasPath) {
40770
- const dir = path16.join(path16.dirname(canvasPath), "scenes");
40771
- const files = await readdir7(dir).catch(() => null);
40731
+ const dir = path15.join(path15.dirname(canvasPath), "scenes");
40732
+ const files = await readdir6(dir).catch(() => null);
40772
40733
  if (!files) return [];
40773
40734
  const windows = [];
40774
40735
  for (const name of files.filter((f) => f.endsWith(".json")).sort()) {
40775
- const raw = await readFile11(path16.join(dir, name), "utf-8").catch(() => null);
40736
+ const raw = await readFile11(path15.join(dir, name), "utf-8").catch(() => null);
40776
40737
  if (!raw) continue;
40777
40738
  try {
40778
40739
  const scene = JSON.parse(raw);
@@ -40898,7 +40859,7 @@ function stopBeforeKinds(until) {
40898
40859
  return null;
40899
40860
  }
40900
40861
  async function executeCanvasRun(opts) {
40901
- const filePath = path17.resolve(opts.file);
40862
+ const filePath = path16.resolve(opts.file);
40902
40863
  const raw = await readFile12(filePath, "utf8");
40903
40864
  let parsed;
40904
40865
  try {
@@ -40921,7 +40882,7 @@ ${describeRewrites(healed.rewrites)}
40921
40882
  `
40922
40883
  );
40923
40884
  }
40924
- parsed = resolveRelativeCanvasPaths(parsed, path17.dirname(filePath));
40885
+ parsed = resolveRelativeCanvasPaths(parsed, path16.dirname(filePath));
40925
40886
  try {
40926
40887
  await syncStyleProjection(parsed, (line) => process.stderr.write(`${line}
40927
40888
  `));
@@ -41027,7 +40988,7 @@ ${describeRewrites(healed.rewrites)}
41027
40988
  const canvasSha = sha256Hex(Buffer.from(canvasText));
41028
40989
  const creativeSlug = creativeSlugFromCanvasPath(filePath) ?? void 0;
41029
40990
  const client = opts.record === false ? null : buildBackendClient();
41030
- const outputsDir = opts.outputsDir ? path17.resolve(opts.outputsDir) : path17.resolve("canvas");
40991
+ const outputsDir = opts.outputsDir ? path16.resolve(opts.outputsDir) : path16.resolve("canvas");
41031
40992
  const { runId, resumed, source, concurrentRunId } = await resolveRunId({
41032
40993
  explicitRunId: opts.runId,
41033
40994
  fresh: opts.fresh === true,
@@ -41061,7 +41022,7 @@ ${describeRewrites(healed.rewrites)}
41061
41022
  const canvasSnapshotUrl = client && creativeSlug ? await uploadRunSnapshot(client, { canvasPath: filePath, raw: canvasText, creativeSlug, parsed }) ?? void 0 : void 0;
41062
41023
  const recordMeta = {
41063
41024
  creativeSlug,
41064
- canvasPath: path17.relative(process.cwd(), filePath) || void 0,
41025
+ canvasPath: path16.relative(process.cwd(), filePath) || void 0,
41065
41026
  canvasSha,
41066
41027
  // The fingerprint the dashboard compares against the current source to flag
41067
41028
  // "edited since last render". Computed from the on-disk canvas.json +
@@ -41319,7 +41280,7 @@ var rerunCommand = defineCommand112({
41319
41280
  if (latest.canvasSha && manifest.canvasSha !== latest.canvasSha) {
41320
41281
  fail2("snapshot_mismatch", `snapshot manifest for run ${latest.runId} does not match its recorded canvas sha`);
41321
41282
  }
41322
- const targetDir = path18.resolve("src", "creatives", slug);
41283
+ const targetDir = path17.resolve("src", "creatives", slug);
41323
41284
  let restoredCanvasPath;
41324
41285
  try {
41325
41286
  const restore = await restoreRunSnapshot(manifest, targetDir, { force: args5["force-remote"] === true });
@@ -41369,7 +41330,7 @@ async function fetchManifest(url) {
41369
41330
 
41370
41331
  // src/commands/canvas/scaffold-static-ad.ts
41371
41332
  import { access, mkdir as mkdir6, readFile as readFile14, writeFile as writeFile8 } from "fs/promises";
41372
- import path22 from "path";
41333
+ import path21 from "path";
41373
41334
  import { defineCommand as defineCommand114 } from "citty";
41374
41335
 
41375
41336
  // src/engine/scaffold/staticAd.ts
@@ -41657,7 +41618,7 @@ function staticAdReport(input, elementsInput, opts) {
41657
41618
  }
41658
41619
 
41659
41620
  // src/commands/canvas/creative-definition.ts
41660
- import path19 from "path";
41621
+ import path18 from "path";
41661
41622
  var PLATFORM_VALUES = ["meta", "google", "linkedin", "tiktok", "youtube", "x", "other"];
41662
41623
  var FORMAT_VALUES = ["1:1", "4:5", "9:16", "16:9", "1.91:1"];
41663
41624
  function titleFromSlug(slug) {
@@ -41705,16 +41666,16 @@ function buildCreativeDefinition(input) {
41705
41666
  }
41706
41667
 
41707
41668
  // src/commands/canvas/scaffold-static-ad-paths.ts
41708
- import path20 from "path";
41669
+ import path19 from "path";
41709
41670
  function resolveScaffoldStaticAdPaths(rawFile, out, cwd = process.cwd(), slug) {
41710
41671
  const file = rawFile.trim();
41711
41672
  const imageIsUrl = /^https?:\/\//i.test(file);
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;
41673
+ const imageSource = imageIsUrl ? file : path19.resolve(cwd, file);
41674
+ 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");
41675
+ const blueprintPath = path19.join(path19.dirname(outPath), "prompt.json");
41676
+ const creativeDir = slug ? path19.dirname(outPath) : null;
41677
+ const definitionPath = creativeDir ? path19.join(creativeDir, "_definition.md") : null;
41678
+ const referencesDir = creativeDir ? path19.join(creativeDir, "references") : null;
41718
41679
  return { imageIsUrl, imageSource, outPath, blueprintPath, creativeDir, definitionPath, referencesDir };
41719
41680
  }
41720
41681
  var SCAFFOLD_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
@@ -41724,8 +41685,8 @@ function isValidScaffoldSlug(slug) {
41724
41685
  }
41725
41686
 
41726
41687
  // src/commands/canvas/sync-definition.ts
41727
- import { readdir as readdir8, readFile as readFile13, stat as stat3 } from "fs/promises";
41728
- import path21 from "path";
41688
+ import { readdir as readdir7, readFile as readFile13, stat as stat3 } from "fs/promises";
41689
+ import path20 from "path";
41729
41690
  import { defineCommand as defineCommand113 } from "citty";
41730
41691
 
41731
41692
  // src/commands/canvas/definition-graph.ts
@@ -41818,26 +41779,26 @@ async function syncCreativeDefinitionBestEffort(input) {
41818
41779
  }
41819
41780
  }
41820
41781
  async function resolveCanvasPath(inputPath) {
41821
- const resolved = path21.resolve(inputPath);
41782
+ const resolved = path20.resolve(inputPath);
41822
41783
  let dir = resolved;
41823
41784
  try {
41824
41785
  if ((await stat3(resolved)).isFile()) {
41825
41786
  if (resolved.endsWith(".canvas.json")) return resolved;
41826
- dir = path21.dirname(resolved);
41787
+ dir = path20.dirname(resolved);
41827
41788
  }
41828
41789
  } catch {
41829
- dir = resolved.endsWith(".canvas.json") ? path21.dirname(resolved) : resolved;
41790
+ dir = resolved.endsWith(".canvas.json") ? path20.dirname(resolved) : resolved;
41830
41791
  }
41831
41792
  let entries;
41832
41793
  try {
41833
- entries = await readdir8(dir);
41794
+ entries = await readdir7(dir);
41834
41795
  } catch {
41835
41796
  return null;
41836
41797
  }
41837
41798
  const canvases = entries.filter((name) => name.endsWith(".canvas.json"));
41838
41799
  const slug = creativeSlugFromCanvasPath(`${dir}/x/`);
41839
41800
  const chosen = (slug ? canvases.find((name) => name === `${slug}.canvas.json`) : void 0) ?? canvases[0];
41840
- return chosen ? path21.join(dir, chosen) : null;
41801
+ return chosen ? path20.join(dir, chosen) : null;
41841
41802
  }
41842
41803
  var syncDefinitionCommand = defineCommand113({
41843
41804
  meta: {
@@ -42118,7 +42079,7 @@ var scaffoldStaticAdCommand = defineCommand114({
42118
42079
  process.cwd(),
42119
42080
  slug
42120
42081
  );
42121
- await mkdir6(path22.dirname(outPath), { recursive: true });
42082
+ await mkdir6(path21.dirname(outPath), { recursive: true });
42122
42083
  const { describeModel, selectModel, layoutModel, genModel } = resolveModels(args5);
42123
42084
  let durableSourceUrl;
42124
42085
  if (referencesDir) {
@@ -42238,7 +42199,7 @@ var scaffoldStaticAdCommand = defineCommand114({
42238
42199
  run_estimated_credits: validation.estimatedCredits
42239
42200
  },
42240
42201
  checklist: {
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.`,
42202
+ 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.`,
42242
42203
  assets_to_supply: report.elements,
42243
42204
  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)",
42244
42205
  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)",
@@ -43007,8 +42968,8 @@ function injectAdBrandOverlay(indexHtml, overlayHtml) {
43007
42968
  }
43008
42969
 
43009
42970
  // src/engine/scaffold/ad-brand-source.ts
43010
- import { readdir as readdir9, readFile as readFile15 } from "fs/promises";
43011
- import path23 from "path";
42971
+ import { readdir as readdir8, readFile as readFile15 } from "fs/promises";
42972
+ import path22 from "path";
43012
42973
  import sharp from "sharp";
43013
42974
  var BRAND_DIR = "src/brand";
43014
42975
  function paletteFromBrandDoc(markdown) {
@@ -43060,16 +43021,16 @@ function pickBrandMark(files) {
43060
43021
  }
43061
43022
  async function readBrandFromWorkspace(root = ".") {
43062
43023
  const found = {};
43063
- const doc = await readFile15(path23.join(root, BRAND_DIR, "BRAND.md"), "utf-8").catch(() => null);
43024
+ const doc = await readFile15(path22.join(root, BRAND_DIR, "BRAND.md"), "utf-8").catch(() => null);
43064
43025
  if (doc) {
43065
43026
  const palette = paletteFromBrandDoc(doc);
43066
43027
  if (palette.length > 0) found.palette = palette;
43067
43028
  }
43068
- const dir = path23.join(root, BRAND_DIR, "logos");
43069
- const files = await readdir9(dir).catch(() => null);
43029
+ const dir = path22.join(root, BRAND_DIR, "logos");
43030
+ const files = await readdir8(dir).catch(() => null);
43070
43031
  if (files) {
43071
43032
  const mark = pickBrandMark(files);
43072
- if (mark) found.logo = path23.join(BRAND_DIR, "logos", mark);
43033
+ if (mark) found.logo = path22.join(BRAND_DIR, "logos", mark);
43073
43034
  }
43074
43035
  return found;
43075
43036
  }
@@ -43079,20 +43040,20 @@ function svgIsLiveText(svg) {
43079
43040
  async function markIsReal(markPath, root = ".") {
43080
43041
  const brandLogos = await findBrandLogosDir(markPath, root);
43081
43042
  if (brandLogos) return await markDirectoryIsReal(brandLogos);
43082
- return await markDirectoryIsReal(path23.dirname(markPath));
43043
+ return await markDirectoryIsReal(path22.dirname(markPath));
43083
43044
  }
43084
43045
  async function findBrandLogosDir(markPath, root) {
43085
43046
  const candidates = [];
43086
- let dir = path23.resolve(path23.dirname(markPath));
43047
+ let dir = path22.resolve(path22.dirname(markPath));
43087
43048
  for (; ; ) {
43088
- candidates.push(path23.join(dir, BRAND_DIR, "logos"));
43089
- const parent = path23.dirname(dir);
43049
+ candidates.push(path22.join(dir, BRAND_DIR, "logos"));
43050
+ const parent = path22.dirname(dir);
43090
43051
  if (parent === dir) break;
43091
43052
  dir = parent;
43092
43053
  }
43093
- candidates.push(path23.join(root, BRAND_DIR, "logos"));
43054
+ candidates.push(path22.join(root, BRAND_DIR, "logos"));
43094
43055
  for (const candidate of candidates) {
43095
- if (await readdir9(candidate).then(
43056
+ if (await readdir8(candidate).then(
43096
43057
  () => true,
43097
43058
  () => false
43098
43059
  ))
@@ -43101,12 +43062,12 @@ async function findBrandLogosDir(markPath, root) {
43101
43062
  return null;
43102
43063
  }
43103
43064
  async function markDirectoryIsReal(dir) {
43104
- const files = await readdir9(dir).catch(() => null);
43065
+ const files = await readdir8(dir).catch(() => null);
43105
43066
  if (!files) return false;
43106
43067
  const marks = files.filter((f) => /\.(svg|png|webp)$/i.test(f));
43107
43068
  if (marks.length === 0) return false;
43108
43069
  for (const f of marks.filter((f2) => /\.svg$/i.test(f2))) {
43109
- const svg = await readFile15(path23.join(dir, f), "utf-8").catch(() => null);
43070
+ const svg = await readFile15(path22.join(dir, f), "utf-8").catch(() => null);
43110
43071
  if (svg === null || svgIsLiveText(svg)) return false;
43111
43072
  }
43112
43073
  return true;
@@ -43133,6 +43094,22 @@ async function markInkIsLight(markPath) {
43133
43094
  }
43134
43095
  }
43135
43096
 
43097
+ // src/commands/canvas/composition-path.ts
43098
+ import { existsSync as existsSync5 } from "fs";
43099
+ import path23 from "path";
43100
+ function resolveShippedCanvasDir(name, startDir, exists2 = existsSync5, maxDepth = 8) {
43101
+ const rel = path23.join("canvas", name);
43102
+ let dir = startDir;
43103
+ for (let i = 0; i < maxDepth; i++) {
43104
+ const candidate = path23.join(dir, rel);
43105
+ if (exists2(path23.join(candidate, "meta.json"))) return candidate;
43106
+ const parent = path23.dirname(dir);
43107
+ if (parent === dir) break;
43108
+ dir = parent;
43109
+ }
43110
+ return path23.resolve(startDir, "../../../", rel);
43111
+ }
43112
+
43136
43113
  // src/commands/canvas/scaffold-ad.ts
43137
43114
  function pinnedOnAvatar(handle, model) {
43138
43115
  const hint = pinnedModelHint({ avatar: handle ?? void 0, model, generateAudio: true });
@@ -43683,7 +43660,7 @@ function routeVideoModel(input) {
43683
43660
 
43684
43661
  // src/engine/nodes/local/lib/sceneDetect.ts
43685
43662
  import { execFile as execFile3 } from "child_process";
43686
- import { mkdtemp as mkdtemp2, readdir as readdir10, readFile as readFile17, rm as rm6 } from "fs/promises";
43663
+ import { mkdtemp as mkdtemp2, readdir as readdir9, readFile as readFile17, rm as rm6 } from "fs/promises";
43687
43664
  import { tmpdir as tmpdir2 } from "os";
43688
43665
  import { join as join3 } from "path";
43689
43666
  import { promisify as promisify3 } from "util";
@@ -43757,7 +43734,7 @@ async function runSceneDetectOnce(filePath, threshold, minSceneLenS, timeoutMs)
43757
43734
  ],
43758
43735
  { encoding: "utf-8", maxBuffer: 32 * 1024 * 1024, timeout: timeoutMs }
43759
43736
  );
43760
- const csvName = (await readdir10(outDir)).find((f) => f.toLowerCase().endsWith(".csv"));
43737
+ const csvName = (await readdir9(outDir)).find((f) => f.toLowerCase().endsWith(".csv"));
43761
43738
  if (!csvName) return [];
43762
43739
  return parsePySceneDetectCsvCuts(await readFile17(join3(outDir, csvName), "utf-8"));
43763
43740
  } finally {
@@ -45159,11 +45136,11 @@ Full guide: __tooling__/docs/tools/baker/creatives.md`
45159
45136
  import { defineCommand as defineCommand124 } from "citty";
45160
45137
 
45161
45138
  // src/commands/experiment/composition.ts
45162
- import { readdir as readdir12, readFile as readFile24 } from "fs/promises";
45139
+ import { readdir as readdir11, readFile as readFile24 } from "fs/promises";
45163
45140
  import path30 from "path";
45164
45141
 
45165
45142
  // src/commands/landing/import-graph.ts
45166
- import { readdir as readdir11, readFile as readFile23, stat as stat5 } from "fs/promises";
45143
+ import { readdir as readdir10, readFile as readFile23, stat as stat5 } from "fs/promises";
45167
45144
  import path29 from "path";
45168
45145
  var SOURCE_EXT = /\.(astro|ts|tsx|js|jsx|mjs|cjs|vue|svelte)$/;
45169
45146
  var RESOLVE_CANDIDATES = [
@@ -45191,7 +45168,7 @@ async function isFile(p) {
45191
45168
  async function walkFiles(dir) {
45192
45169
  let entries;
45193
45170
  try {
45194
- entries = await readdir11(dir, { withFileTypes: true });
45171
+ entries = await readdir10(dir, { withFileTypes: true });
45195
45172
  } catch {
45196
45173
  return [];
45197
45174
  }
@@ -45294,7 +45271,7 @@ function formsOnlyIn(these, those) {
45294
45271
  }
45295
45272
  async function knownFlows(root) {
45296
45273
  try {
45297
- const entries = await readdir12(path30.join(root, "src/lib/flow-engine/flows"), { withFileTypes: true });
45274
+ const entries = await readdir11(path30.join(root, "src/lib/flow-engine/flows"), { withFileTypes: true });
45298
45275
  return new Set(entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name));
45299
45276
  } catch {
45300
45277
  return /* @__PURE__ */ new Set();
@@ -45315,7 +45292,7 @@ async function readForms(root, slug) {
45315
45292
 
45316
45293
  // src/commands/experiment/fold.ts
45317
45294
  import { statSync } from "fs";
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";
45295
+ 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";
45319
45296
  import path32 from "path";
45320
45297
 
45321
45298
  // ../api/src/experiments/variants.ts
@@ -45390,7 +45367,7 @@ async function isDir(p) {
45390
45367
  async function filesUnder(dir, prefix = "") {
45391
45368
  let entries;
45392
45369
  try {
45393
- entries = await readdir13(dir, { withFileTypes: true });
45370
+ entries = await readdir12(dir, { withFileTypes: true });
45394
45371
  } catch {
45395
45372
  return [];
45396
45373
  }
@@ -55754,7 +55731,7 @@ Full guide: __tooling__/docs/tools/baker/images.md`
55754
55731
  import { defineCommand as defineCommand182 } from "citty";
55755
55732
 
55756
55733
  // src/commands/landing/critique.ts
55757
- import { readdir as readdir15, readFile as readFile30, stat as stat9 } from "fs/promises";
55734
+ import { readdir as readdir14, readFile as readFile30, stat as stat9 } from "fs/promises";
55758
55735
  import path37 from "path";
55759
55736
  import { defineCommand as defineCommand171 } from "citty";
55760
55737
 
@@ -56965,7 +56942,7 @@ async function writeCritiqueSnapshot(projectRoot, snapshot) {
56965
56942
  }
56966
56943
 
56967
56944
  // src/commands/landing/source-version.ts
56968
- import { readdir as readdir14, readFile as readFile29, stat as stat8 } from "fs/promises";
56945
+ import { readdir as readdir13, readFile as readFile29, stat as stat8 } from "fs/promises";
56969
56946
  import path36 from "path";
56970
56947
  var CRITIQUED_ROOTS = ["src/pages/", "src/components/"];
56971
56948
  async function landingSourceRelPaths(root, slug) {
@@ -57021,7 +56998,7 @@ async function isFile2(p) {
57021
56998
  async function walkAstro(dir) {
57022
56999
  let entries;
57023
57000
  try {
57024
- entries = await readdir14(dir, { withFileTypes: true });
57001
+ entries = await readdir13(dir, { withFileTypes: true });
57025
57002
  } catch {
57026
57003
  return [];
57027
57004
  }
@@ -57154,7 +57131,7 @@ async function readCompetitorNames(projectRoot) {
57154
57131
  const dir = path37.join(projectRoot, "src", "content", "competitors");
57155
57132
  let entries;
57156
57133
  try {
57157
- entries = (await readdir15(dir)).filter((f) => f.endsWith(".md"));
57134
+ entries = (await readdir14(dir)).filter((f) => f.endsWith(".md"));
57158
57135
  } catch {
57159
57136
  return [];
57160
57137
  }
@@ -57172,7 +57149,7 @@ async function readCompetitorNames(projectRoot) {
57172
57149
  }
57173
57150
  async function listLandingSlugs(projectRoot) {
57174
57151
  try {
57175
- const entries = await readdir15(path37.join(projectRoot, "src", "pages"), { withFileTypes: true });
57152
+ const entries = await readdir14(path37.join(projectRoot, "src", "pages"), { withFileTypes: true });
57176
57153
  return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).map((e) => e.name).sort();
57177
57154
  } catch {
57178
57155
  return [];
@@ -60365,7 +60342,7 @@ Full guide: __tooling__/docs/tools/baker/landing.md`
60365
60342
 
60366
60343
  // src/commands/landing/variant.ts
60367
60344
  import { randomUUID as randomUUID2 } from "crypto";
60368
- import { mkdir as mkdir14, readdir as readdir16, readFile as readFile31, stat as stat10, writeFile as writeFile19 } from "fs/promises";
60345
+ import { mkdir as mkdir14, readdir as readdir15, readFile as readFile31, stat as stat10, writeFile as writeFile19 } from "fs/promises";
60369
60346
  import path45 from "path";
60370
60347
  import { defineCommand as defineCommand181 } from "citty";
60371
60348
  registerSchema({
@@ -60402,7 +60379,7 @@ async function readInternalId(definitionPath) {
60402
60379
  async function archivedVariantNumbers(root, internalId) {
60403
60380
  if (!internalId) return [];
60404
60381
  try {
60405
- const entries = await readdir16(path45.resolve(root, "src/_variants", internalId), { withFileTypes: true });
60382
+ const entries = await readdir15(path45.resolve(root, "src/_variants", internalId), { withFileTypes: true });
60406
60383
  return entries.filter((entry) => entry.isDirectory()).map((entry) => Number(entry.name)).filter((n) => Number.isInteger(n) && n > 0);
60407
60384
  } catch {
60408
60385
  return [];
@@ -60432,7 +60409,7 @@ async function exists(p) {
60432
60409
  }
60433
60410
  async function listLandingSlugs2(root) {
60434
60411
  try {
60435
- const entries = await readdir16(path45.resolve(root, "src", "pages"), { withFileTypes: true });
60412
+ const entries = await readdir15(path45.resolve(root, "src", "pages"), { withFileTypes: true });
60436
60413
  return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).map((e) => e.name).sort();
60437
60414
  } catch {
60438
60415
  return [];
@@ -60441,7 +60418,7 @@ async function listLandingSlugs2(root) {
60441
60418
  async function listComponents(componentsDir, prefix = "") {
60442
60419
  let entries;
60443
60420
  try {
60444
- entries = await readdir16(componentsDir, { withFileTypes: true });
60421
+ entries = await readdir15(componentsDir, { withFileTypes: true });
60445
60422
  } catch {
60446
60423
  return [];
60447
60424
  }