@koda-sl/baker-cli 0.358.0 → 0.359.0-dev.5dbf6338c

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
@@ -69,7 +69,7 @@ import {
69
69
  validateCanvasDeep,
70
70
  withoutCastName,
71
71
  ytDlpBlockSignal
72
- } from "./chunk-AI4HWQVN.js";
72
+ } from "./chunk-K2IKLMCM.js";
73
73
  import {
74
74
  csvOrJson,
75
75
  daysAgoIso,
@@ -36644,9 +36644,134 @@ var critiqueCommand = defineCommand109({
36644
36644
  // src/commands/canvas/inspect.ts
36645
36645
  import { execFile } from "child_process";
36646
36646
  import { readdir as readdir2, readFile as readFile4, stat } from "fs/promises";
36647
- import path4 from "path";
36647
+ import path6 from "path";
36648
36648
  import { promisify } from "util";
36649
36649
  import { defineCommand as defineCommand110 } from "citty";
36650
+
36651
+ // src/commands/canvas/normalize-paths.ts
36652
+ import { existsSync as existsSync4, realpathSync } from "fs";
36653
+ import { writeFile as writeFile2 } from "fs/promises";
36654
+ import path5 from "path";
36655
+
36656
+ // src/commands/canvas/resolve-paths.ts
36657
+ import path4 from "path";
36658
+ function resolveRelativeCanvasPaths(canvas, baseDir) {
36659
+ if (!canvas || typeof canvas !== "object") return canvas;
36660
+ const c = canvas;
36661
+ if (!Array.isArray(c.nodes)) return canvas;
36662
+ return { ...canvas, nodes: c.nodes.map((n) => resolveNode(n, baseDir)) };
36663
+ }
36664
+ function localPathParam(node) {
36665
+ if (node.type === "ingest") return node.params?.source === "path" ? "path" : null;
36666
+ if (node.type === "hyperframe_render" || node.type === "hyperframe_snapshot") return "composition";
36667
+ return null;
36668
+ }
36669
+ function resolveNode(node, baseDir) {
36670
+ if (!node || typeof node !== "object") return node;
36671
+ const n = node;
36672
+ const params = n.params;
36673
+ if (!params || typeof params !== "object") return node;
36674
+ const key = localPathParam(n);
36675
+ if (key && isResolvableRelative(params[key])) {
36676
+ return { ...node, params: { ...params, [key]: path4.resolve(baseDir, params[key]) } };
36677
+ }
36678
+ return node;
36679
+ }
36680
+ function isResolvableRelative(value) {
36681
+ return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !looksLikeHttpUrl(value) && !path4.isAbsolute(value);
36682
+ }
36683
+
36684
+ // src/commands/canvas/normalize-paths.ts
36685
+ function findWorkspaceRoot(startDir, exists2 = existsSync4, maxDepth = 12) {
36686
+ let dir = path5.resolve(startDir);
36687
+ for (let i = 0; i < maxDepth; i++) {
36688
+ if (exists2(path5.join(dir, "package.json"))) return dir;
36689
+ const parent = path5.dirname(dir);
36690
+ if (parent === dir) break;
36691
+ dir = parent;
36692
+ }
36693
+ return null;
36694
+ }
36695
+ function canvasOutputsRoot(canvasFile, cwd = process.cwd(), exists2 = existsSync4) {
36696
+ const root = findWorkspaceRoot(path5.dirname(path5.resolve(cwd, canvasFile)), exists2) ?? cwd;
36697
+ return path5.join(root, "canvas");
36698
+ }
36699
+ function canonicalize(target2) {
36700
+ const abs = path5.resolve(target2);
36701
+ let dir = abs;
36702
+ for (; ; ) {
36703
+ try {
36704
+ const real = realpathSync(dir);
36705
+ return dir === abs ? real : path5.join(real, path5.relative(dir, abs));
36706
+ } catch {
36707
+ const parent = path5.dirname(dir);
36708
+ if (parent === dir) return abs;
36709
+ dir = parent;
36710
+ }
36711
+ }
36712
+ }
36713
+ function isInside(root, target2) {
36714
+ const rel = path5.relative(root, target2);
36715
+ return rel !== "" && !rel.startsWith("..") && !path5.isAbsolute(rel);
36716
+ }
36717
+ function toCanvasRelative(canvasDir, target2) {
36718
+ return path5.relative(canvasDir, target2).split(path5.sep).join("/");
36719
+ }
36720
+ var RUNTIME_WORKSPACE_ROOT = "/home/user/repo";
36721
+ function rewriteTarget(value, workspaceRoot) {
36722
+ if (typeof value !== "string" || value.length === 0) return null;
36723
+ if (value.includes("[TODO") || looksLikeHttpUrl(value) || !path5.isAbsolute(value)) return null;
36724
+ const target2 = canonicalize(value);
36725
+ if (isInside(workspaceRoot, target2)) return target2;
36726
+ const fromRuntime = path5.relative(RUNTIME_WORKSPACE_ROOT, path5.normalize(value));
36727
+ if (fromRuntime !== "" && !fromRuntime.startsWith("..") && !path5.isAbsolute(fromRuntime)) {
36728
+ return path5.join(workspaceRoot, fromRuntime);
36729
+ }
36730
+ return null;
36731
+ }
36732
+ function normalizeCanvasPaths(canvas, canvasDir, workspaceRoot) {
36733
+ if (!canvas || typeof canvas !== "object") return { canvas, rewrites: [] };
36734
+ const c = canvas;
36735
+ if (!Array.isArray(c.nodes)) return { canvas, rewrites: [] };
36736
+ const root = canonicalize(workspaceRoot);
36737
+ const dir = canonicalize(canvasDir);
36738
+ const rewrites = [];
36739
+ const nodes = c.nodes.map((node) => {
36740
+ if (!node || typeof node !== "object") return node;
36741
+ const n = node;
36742
+ const params = n.params;
36743
+ if (!params || typeof params !== "object") return node;
36744
+ const nodeId = typeof n.id === "string" ? n.id : "?";
36745
+ if (n.type === "ingest" && params.source === "path" && looksLikeHttpUrl(params.path)) {
36746
+ rewrites.push({ nodeId, param: "source", from: "path", to: "url" });
36747
+ return { ...node, params: coercePathUrlToUrl(params) };
36748
+ }
36749
+ const key = localPathParam(n);
36750
+ if (!key) return node;
36751
+ const target2 = rewriteTarget(params[key], root);
36752
+ if (target2 === null) return node;
36753
+ const to = toCanvasRelative(dir, target2);
36754
+ rewrites.push({ nodeId, param: key, from: params[key], to });
36755
+ return { ...node, params: { ...params, [key]: to } };
36756
+ });
36757
+ return rewrites.length === 0 ? { canvas, rewrites } : { canvas: { ...canvas, nodes }, rewrites };
36758
+ }
36759
+ async function healCanvasPaths(filePath, canvas) {
36760
+ const canvasDir = path5.dirname(filePath);
36761
+ const workspaceRoot = findWorkspaceRoot(canvasDir);
36762
+ if (!workspaceRoot) return { canvas, rewrites: [], text: null };
36763
+ const normalized = normalizeCanvasPaths(canvas, canvasDir, workspaceRoot);
36764
+ if (normalized.rewrites.length === 0) return { ...normalized, text: null };
36765
+ const text2 = `${JSON.stringify(normalized.canvas, null, 2)}
36766
+ `;
36767
+ await writeFile2(filePath, text2, "utf8");
36768
+ return { ...normalized, text: text2 };
36769
+ }
36770
+ function describeRewrites(rewrites) {
36771
+ return rewrites.map((r) => ` ${r.nodeId}.${r.param}: ${r.from} \u2192 ${r.to}`).join("\n");
36772
+ }
36773
+
36774
+ // src/commands/canvas/inspect.ts
36650
36775
  var execFileAsync = promisify(execFile);
36651
36776
  var inspectCommand = defineCommand110({
36652
36777
  meta: {
@@ -36655,14 +36780,15 @@ var inspectCommand = defineCommand110({
36655
36780
  },
36656
36781
  args: {
36657
36782
  run: { type: "positional", required: true, description: "Run id (e.g. r_01K...) or absolute run directory" },
36658
- "outputs-dir": { type: "string", description: "Per-run outputs root (default ./canvas)" },
36783
+ "outputs-dir": { type: "string", description: "Per-run outputs root (default <workspace root>/canvas, where `canvas run` writes)" },
36659
36784
  thumbnails: {
36660
36785
  type: "boolean",
36661
36786
  description: "Extract start/middle/end frames from every video output (requires ffmpeg)"
36662
36787
  }
36663
36788
  },
36664
36789
  async run({ args: args5 }) {
36665
- const outputsDir = path4.resolve(String(args5["outputs-dir"] ?? "canvas"));
36790
+ const cwd = process.cwd();
36791
+ const outputsDir = args5["outputs-dir"] ? path6.resolve(String(args5["outputs-dir"])) : path6.join(findWorkspaceRoot(cwd) ?? cwd, "canvas");
36666
36792
  const runArg = String(args5.run);
36667
36793
  const runDir = await resolveRunDir(runArg, outputsDir);
36668
36794
  const manifest = await loadManifest(runDir);
@@ -36674,7 +36800,7 @@ var inspectCommand = defineCommand110({
36674
36800
  }
36675
36801
  const summary = {
36676
36802
  ok: true,
36677
- run_id: manifest.run_id ?? path4.basename(runDir),
36803
+ run_id: manifest.run_id ?? path6.basename(runDir),
36678
36804
  run_dir: runDir,
36679
36805
  stats: manifest.stats ?? null,
36680
36806
  output: manifest.output ?? null,
@@ -36687,18 +36813,18 @@ var inspectCommand = defineCommand110({
36687
36813
  }
36688
36814
  });
36689
36815
  async function resolveRunDir(run, outputsDir) {
36690
- if (path4.isAbsolute(run)) {
36816
+ if (path6.isAbsolute(run)) {
36691
36817
  const s2 = await stat(run).catch(() => null);
36692
36818
  if (s2?.isDirectory()) return run;
36693
36819
  throw new Error(`inspect: ${run} is not a directory`);
36694
36820
  }
36695
- const candidate = path4.join(outputsDir, run);
36821
+ const candidate = path6.join(outputsDir, run);
36696
36822
  const s = await stat(candidate).catch(() => null);
36697
36823
  if (s?.isDirectory()) return candidate;
36698
36824
  throw new Error(`inspect: no run directory at ${candidate}`);
36699
36825
  }
36700
36826
  async function loadManifest(runDir) {
36701
- const manifestPath = path4.join(runDir, "manifest.json");
36827
+ const manifestPath = path6.join(runDir, "manifest.json");
36702
36828
  try {
36703
36829
  const raw = await readFile4(manifestPath, "utf-8");
36704
36830
  return JSON.parse(raw);
@@ -36710,7 +36836,7 @@ async function listRunFiles(runDir) {
36710
36836
  const out = [];
36711
36837
  const names = await readdir2(runDir);
36712
36838
  for (const name of names) {
36713
- const abs = path4.join(runDir, name);
36839
+ const abs = path6.join(runDir, name);
36714
36840
  const s = await stat(abs).catch(() => null);
36715
36841
  if (!s?.isFile()) continue;
36716
36842
  out.push({ name, path: abs, size: s.size });
@@ -36763,95 +36889,6 @@ import { readFile as readFile12 } from "fs/promises";
36763
36889
  import path16 from "path";
36764
36890
  import { defineCommand as defineCommand111 } from "citty";
36765
36891
 
36766
- // src/commands/canvas/normalize-paths.ts
36767
- import { existsSync as existsSync4, realpathSync } from "fs";
36768
- import { writeFile as writeFile2 } from "fs/promises";
36769
- import path5 from "path";
36770
- function findWorkspaceRoot(startDir, exists2 = existsSync4, maxDepth = 12) {
36771
- let dir = path5.resolve(startDir);
36772
- for (let i = 0; i < maxDepth; i++) {
36773
- if (exists2(path5.join(dir, "package.json"))) return dir;
36774
- const parent = path5.dirname(dir);
36775
- if (parent === dir) break;
36776
- dir = parent;
36777
- }
36778
- return null;
36779
- }
36780
- function canonicalize(target2) {
36781
- const abs = path5.resolve(target2);
36782
- let dir = abs;
36783
- for (; ; ) {
36784
- try {
36785
- const real = realpathSync(dir);
36786
- return dir === abs ? real : path5.join(real, path5.relative(dir, abs));
36787
- } catch {
36788
- const parent = path5.dirname(dir);
36789
- if (parent === dir) return abs;
36790
- dir = parent;
36791
- }
36792
- }
36793
- }
36794
- function isInside(root, target2) {
36795
- const rel = path5.relative(root, target2);
36796
- return rel !== "" && !rel.startsWith("..") && !path5.isAbsolute(rel);
36797
- }
36798
- function toCanvasRelative(canvasDir, target2) {
36799
- return path5.relative(canvasDir, target2).split(path5.sep).join("/");
36800
- }
36801
- var RUNTIME_WORKSPACE_ROOT = "/home/user/repo";
36802
- function rewriteTarget(value, workspaceRoot) {
36803
- if (typeof value !== "string" || value.length === 0) return null;
36804
- if (value.includes("[TODO") || looksLikeHttpUrl(value) || !path5.isAbsolute(value)) return null;
36805
- const target2 = canonicalize(value);
36806
- if (isInside(workspaceRoot, target2)) return target2;
36807
- const fromRuntime = path5.relative(RUNTIME_WORKSPACE_ROOT, path5.normalize(value));
36808
- if (fromRuntime !== "" && !fromRuntime.startsWith("..") && !path5.isAbsolute(fromRuntime)) {
36809
- return path5.join(workspaceRoot, fromRuntime);
36810
- }
36811
- return null;
36812
- }
36813
- function normalizeCanvasPaths(canvas, canvasDir, workspaceRoot) {
36814
- if (!canvas || typeof canvas !== "object") return { canvas, rewrites: [] };
36815
- const c = canvas;
36816
- if (!Array.isArray(c.nodes)) return { canvas, rewrites: [] };
36817
- const root = canonicalize(workspaceRoot);
36818
- const dir = canonicalize(canvasDir);
36819
- const rewrites = [];
36820
- const nodes = c.nodes.map((node) => {
36821
- if (!node || typeof node !== "object") return node;
36822
- const n = node;
36823
- const params = n.params;
36824
- if (!params || typeof params !== "object") return node;
36825
- const nodeId = typeof n.id === "string" ? n.id : "?";
36826
- if (n.type === "ingest" && params.source === "path" && looksLikeHttpUrl(params.path)) {
36827
- rewrites.push({ nodeId, param: "source", from: "path", to: "url" });
36828
- return { ...node, params: coercePathUrlToUrl(params) };
36829
- }
36830
- const key = n.type === "ingest" && params.source === "path" ? "path" : n.type === "hyperframe_render" ? "composition" : null;
36831
- if (!key) return node;
36832
- const target2 = rewriteTarget(params[key], root);
36833
- if (target2 === null) return node;
36834
- const to = toCanvasRelative(dir, target2);
36835
- rewrites.push({ nodeId, param: key, from: params[key], to });
36836
- return { ...node, params: { ...params, [key]: to } };
36837
- });
36838
- return rewrites.length === 0 ? { canvas, rewrites } : { canvas: { ...canvas, nodes }, rewrites };
36839
- }
36840
- async function healCanvasPaths(filePath, canvas) {
36841
- const canvasDir = path5.dirname(filePath);
36842
- const workspaceRoot = findWorkspaceRoot(canvasDir);
36843
- if (!workspaceRoot) return { canvas, rewrites: [], text: null };
36844
- const normalized = normalizeCanvasPaths(canvas, canvasDir, workspaceRoot);
36845
- if (normalized.rewrites.length === 0) return { ...normalized, text: null };
36846
- const text2 = `${JSON.stringify(normalized.canvas, null, 2)}
36847
- `;
36848
- await writeFile2(filePath, text2, "utf8");
36849
- return { ...normalized, text: text2 };
36850
- }
36851
- function describeRewrites(rewrites) {
36852
- return rewrites.map((r) => ` ${r.nodeId}.${r.param}: ${r.from} \u2192 ${r.to}`).join("\n");
36853
- }
36854
-
36855
36892
  // src/commands/canvas/placeholders.ts
36856
36893
  function unsuppliedPlaceholderAssets(canvas) {
36857
36894
  const nodes = canvas?.nodes;
@@ -36868,31 +36905,6 @@ function unsuppliedPlaceholderAssets(canvas) {
36868
36905
  return out;
36869
36906
  }
36870
36907
 
36871
- // src/commands/canvas/resolve-paths.ts
36872
- import path6 from "path";
36873
- function resolveRelativeCanvasPaths(canvas, baseDir) {
36874
- if (!canvas || typeof canvas !== "object") return canvas;
36875
- const c = canvas;
36876
- if (!Array.isArray(c.nodes)) return canvas;
36877
- return { ...canvas, nodes: c.nodes.map((n) => resolveNode(n, baseDir)) };
36878
- }
36879
- function resolveNode(node, baseDir) {
36880
- if (!node || typeof node !== "object") return node;
36881
- const n = node;
36882
- const params = n.params;
36883
- if (!params || typeof params !== "object") return node;
36884
- if (n.type === "ingest" && params.source === "path" && isResolvableRelative(params.path)) {
36885
- return { ...node, params: { ...params, path: path6.resolve(baseDir, params.path) } };
36886
- }
36887
- if (n.type === "hyperframe_render" && isResolvableRelative(params.composition)) {
36888
- return { ...node, params: { ...params, composition: path6.resolve(baseDir, params.composition) } };
36889
- }
36890
- return node;
36891
- }
36892
- function isResolvableRelative(value) {
36893
- return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !looksLikeHttpUrl(value) && !path6.isAbsolute(value);
36894
- }
36895
-
36896
36908
  // src/commands/canvas/source-version.ts
36897
36909
  import { readFile as readFile6 } from "fs/promises";
36898
36910
  import path8 from "path";
@@ -41002,12 +41014,9 @@ function localPathRefsFromCanvas(parsed) {
41002
41014
  const n = node;
41003
41015
  const params = n.params;
41004
41016
  if (!params || typeof params !== "object") continue;
41005
- if (n.type === "ingest" && params.source === "path" && isSnapshotablePath(params.path)) {
41006
- refs.add(params.path);
41007
- }
41008
- if (n.type === "hyperframe_render" && isSnapshotablePath(params.composition)) {
41009
- refs.add(params.composition);
41010
- }
41017
+ const key = localPathParam(n);
41018
+ const value = key ? params[key] : void 0;
41019
+ if (isSnapshotablePath(value)) refs.add(value);
41011
41020
  }
41012
41021
  return [...refs];
41013
41022
  }
@@ -41692,8 +41701,8 @@ var runCommand = defineCommand111({
41692
41701
  type: "string",
41693
41702
  description: "What the person asked for, IN THEIR OWN WORDS \u2014 paste their message, do not summarise it. The review compares the finished video against this and reports what they asked for that is missing or contradicted. Without it the review can only say whether the video is well made, not whether it is the one they wanted: every other check grades the render against the spec, and a spec that misread the request agrees with itself."
41694
41703
  },
41695
- "cache-dir": { type: "string", description: "Cache root (default ./canvas/.cache)" },
41696
- "outputs-dir": { type: "string", description: "Per-run outputs root (default ./canvas)" },
41704
+ "cache-dir": { type: "string", description: "Cache root (default <workspace root>/canvas/.cache, whatever directory you run from)" },
41705
+ "outputs-dir": { type: "string", description: "Per-run outputs root (default <workspace root>/canvas, whatever directory you run from)" },
41697
41706
  "run-id": { type: "string", description: "Override run id (also resumes that run, re-attaching its in-flight jobs)" },
41698
41707
  fresh: {
41699
41708
  type: "boolean",
@@ -41771,6 +41780,7 @@ function stopBeforeKinds(until) {
41771
41780
  }
41772
41781
  async function executeCanvasRun(opts) {
41773
41782
  const filePath = path16.resolve(opts.file);
41783
+ const canvasRoot = canvasOutputsRoot(filePath);
41774
41784
  const raw = await readFile12(filePath, "utf8");
41775
41785
  let parsed;
41776
41786
  try {
@@ -41782,7 +41792,7 @@ async function executeCanvasRun(opts) {
41782
41792
  process.exit(2);
41783
41793
  }
41784
41794
  const attemptedSlug = creativeSlugFromCanvasPath(filePath);
41785
- if (attemptedSlug) await clearCreativeDirty(attemptedSlug);
41795
+ if (attemptedSlug) await clearCreativeDirty(attemptedSlug, path16.join(canvasRoot, ".dirty"));
41786
41796
  const healed = await healCanvasPaths(filePath, parsed);
41787
41797
  parsed = healed.canvas;
41788
41798
  const canvasText = healed.text ?? raw;
@@ -41878,8 +41888,8 @@ ${describeRewrites(healed.rewrites)}
41878
41888
  }
41879
41889
  }
41880
41890
  const engine = createEngineFromEnv({
41881
- cacheDir: opts.cacheDir,
41882
- outputsDir: opts.outputsDir,
41891
+ cacheDir: opts.cacheDir ?? path16.join(canvasRoot, ".cache"),
41892
+ outputsDir: opts.outputsDir ?? canvasRoot,
41883
41893
  log: (line) => process.stdout.write(`${line}
41884
41894
  `),
41885
41895
  remoteCache: opts.remoteCache
@@ -41899,7 +41909,7 @@ ${describeRewrites(healed.rewrites)}
41899
41909
  const canvasSha = sha256Hex(Buffer.from(canvasText));
41900
41910
  const creativeSlug = creativeSlugFromCanvasPath(filePath) ?? void 0;
41901
41911
  const client = opts.record === false ? null : buildBackendClient();
41902
- const outputsDir = opts.outputsDir ? path16.resolve(opts.outputsDir) : path16.resolve("canvas");
41912
+ const outputsDir = opts.outputsDir ? path16.resolve(opts.outputsDir) : canvasRoot;
41903
41913
  const { runId, resumed, source, concurrentRunId } = await resolveRunId({
41904
41914
  explicitRunId: opts.runId,
41905
41915
  fresh: opts.fresh === true,
@@ -41933,7 +41943,7 @@ ${describeRewrites(healed.rewrites)}
41933
41943
  const canvasSnapshotUrl = client && creativeSlug ? await uploadRunSnapshot(client, { canvasPath: filePath, raw: canvasText, creativeSlug, parsed }) ?? void 0 : void 0;
41934
41944
  const recordMeta = {
41935
41945
  creativeSlug,
41936
- canvasPath: path16.relative(process.cwd(), filePath) || void 0,
41946
+ canvasPath: path16.relative(path16.dirname(canvasRoot), filePath) || void 0,
41937
41947
  canvasSha,
41938
41948
  // The fingerprint the dashboard compares against the current source to flag
41939
41949
  // "edited since last render". Computed from the on-disk canvas.json +