@koda-sl/baker-cli 0.120.0-dev.3b02f951b → 0.120.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,25 +1,19 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- BackendClient,
4
3
  ELEVENLABS_MAX_MUSIC_LENGTH_MS,
5
4
  IMAGE_GENERATE_MODELS,
6
5
  LayerExecutionError,
7
6
  MODEL_REGISTRY,
8
7
  SEEDANCE_DURATIONS,
9
8
  ValidationError,
10
- collectAssetRefLikes,
11
9
  createEngineFromEnv,
12
10
  defaultRegistry,
13
11
  describeFailureReason,
14
12
  elementMentionKeywords,
15
13
  generateCatalog,
16
- isPersistedAssetRef,
17
- requireCredentialsFromEnv,
18
14
  resolveConcurrency,
19
- sha256Hex,
20
- ulid,
21
15
  validateCanvasDeep
22
- } from "./chunk-AWSEBYP4.js";
16
+ } from "./chunk-IWPAXJC3.js";
23
17
  import {
24
18
  csvOrJson,
25
19
  daysAgoIso,
@@ -4670,11 +4664,11 @@ function rawTextEntries(value) {
4670
4664
  const values = Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
4671
4665
  return values.filter((v) => typeof v === "string").flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
4672
4666
  }
4673
- function rawFileEntries(path14) {
4674
- if (typeof path14 !== "string" || path14.length === 0) {
4667
+ function rawFileEntries(path12) {
4668
+ if (typeof path12 !== "string" || path12.length === 0) {
4675
4669
  return [];
4676
4670
  }
4677
- return readFileSync2(path14, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
4671
+ return readFileSync2(path12, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
4678
4672
  }
4679
4673
  function keywordEntries(args) {
4680
4674
  const defaultMatch = typeof args["match-type"] === "string" ? args["match-type"].toUpperCase() : void 0;
@@ -4697,19 +4691,19 @@ function keywordEntries(args) {
4697
4691
  }
4698
4692
  return entries;
4699
4693
  }
4700
- function loadJsonFileArg(path14) {
4701
- if (typeof path14 !== "string" || path14.length === 0) {
4694
+ function loadJsonFileArg(path12) {
4695
+ if (typeof path12 !== "string" || path12.length === 0) {
4702
4696
  return {};
4703
4697
  }
4704
4698
  try {
4705
- const parsed = JSON.parse(readFileSync2(path14, "utf8"));
4699
+ const parsed = JSON.parse(readFileSync2(path12, "utf8"));
4706
4700
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
4707
- failWriteValidation(`${path14} must contain a JSON object`);
4701
+ failWriteValidation(`${path12} must contain a JSON object`);
4708
4702
  }
4709
4703
  return parsed;
4710
4704
  } catch (err) {
4711
4705
  if (err instanceof SyntaxError) {
4712
- failWriteValidation(`${path14} is not valid JSON: ${err.message}`);
4706
+ failWriteValidation(`${path12} is not valid JSON: ${err.message}`);
4713
4707
  }
4714
4708
  throw err;
4715
4709
  }
@@ -4820,10 +4814,10 @@ async function stageUpdate(kind, customerId, target, payload) {
4820
4814
  async function stageTarget(kind, customerId, target) {
4821
4815
  await stageGoogleOp({ kind, customerId, target });
4822
4816
  }
4823
- async function draftAction(path14, body) {
4817
+ async function draftAction(path12, body) {
4824
4818
  try {
4825
4819
  const chatId = requireChatId();
4826
- const response = await apiPost(path14, { chatId, ...body });
4820
+ const response = await apiPost(path12, { chatId, ...body });
4827
4821
  writeJsonEnvelope(response);
4828
4822
  } catch (err) {
4829
4823
  handleGoogleError(err);
@@ -8578,19 +8572,19 @@ function failWriteValidation2(message) {
8578
8572
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
8579
8573
  process.exit(1);
8580
8574
  }
8581
- function loadJsonFileArg2(path14) {
8582
- if (typeof path14 !== "string" || path14.length === 0) {
8575
+ function loadJsonFileArg2(path12) {
8576
+ if (typeof path12 !== "string" || path12.length === 0) {
8583
8577
  return {};
8584
8578
  }
8585
8579
  try {
8586
- const parsed = JSON.parse(readFileSync6(path14, "utf8"));
8580
+ const parsed = JSON.parse(readFileSync6(path12, "utf8"));
8587
8581
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
8588
- failWriteValidation2(`${path14} must contain a JSON object`);
8582
+ failWriteValidation2(`${path12} must contain a JSON object`);
8589
8583
  }
8590
8584
  return parsed;
8591
8585
  } catch (err) {
8592
8586
  if (err instanceof SyntaxError) {
8593
- failWriteValidation2(`${path14} is not valid JSON: ${err.message}`);
8587
+ failWriteValidation2(`${path12} is not valid JSON: ${err.message}`);
8594
8588
  }
8595
8589
  throw err;
8596
8590
  }
@@ -8675,15 +8669,15 @@ function parseLocaleFlag(value) {
8675
8669
  }
8676
8670
  return { language: match[1], country: match[2].toUpperCase() };
8677
8671
  }
8678
- function loadTargetingFileArg(path14) {
8679
- if (typeof path14 !== "string" || path14.length === 0) {
8672
+ function loadTargetingFileArg(path12) {
8673
+ if (typeof path12 !== "string" || path12.length === 0) {
8680
8674
  return void 0;
8681
8675
  }
8682
- const parsed = loadJsonFileArg2(path14);
8676
+ const parsed = loadJsonFileArg2(path12);
8683
8677
  const criteria = parsed.targetingCriteria ?? parsed;
8684
8678
  if (!criteria.include) {
8685
8679
  failWriteValidation2(
8686
- `${path14} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
8680
+ `${path12} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
8687
8681
  );
8688
8682
  }
8689
8683
  return criteria;
@@ -8718,14 +8712,14 @@ function parseCsvLine(line) {
8718
8712
  cells.push(current);
8719
8713
  return cells.map((cell) => cell.trim());
8720
8714
  }
8721
- function parseListFileArg(path14, maxRows) {
8722
- if (typeof path14 !== "string" || path14.length === 0) {
8715
+ function parseListFileArg(path12, maxRows) {
8716
+ if (typeof path12 !== "string" || path12.length === 0) {
8723
8717
  return void 0;
8724
8718
  }
8725
- const raw = readFileSync6(path14, "utf8");
8719
+ const raw = readFileSync6(path12, "utf8");
8726
8720
  const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
8727
8721
  if (lines.length < 2) {
8728
- failWriteValidation2(`${path14} needs a header row and at least one data row`);
8722
+ failWriteValidation2(`${path12} needs a header row and at least one data row`);
8729
8723
  }
8730
8724
  const columns = parseCsvLine(lines[0]).map((column) => column.trim());
8731
8725
  const rows = [];
@@ -8744,7 +8738,7 @@ function parseListFileArg(path14, maxRows) {
8744
8738
  }
8745
8739
  }
8746
8740
  if (rows.length > maxRows) {
8747
- failWriteValidation2(`${path14} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
8741
+ failWriteValidation2(`${path12} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
8748
8742
  }
8749
8743
  return { columns, rows };
8750
8744
  }
@@ -10827,11 +10821,11 @@ var updateStatusSchema = z9.enum(UPDATE_STATUSES);
10827
10821
  function currencyMinimums2(currencyCode) {
10828
10822
  return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
10829
10823
  }
10830
- function validateDailyBudgetFloor(money, ctx, path14) {
10824
+ function validateDailyBudgetFloor(money, ctx, path12) {
10831
10825
  if (money?.currencyCode) {
10832
10826
  const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
10833
10827
  if (Number(money.amount) < min) {
10834
- ctx.addIssue({ code: "custom", path: path14, message: `below the ${min} ${money.currencyCode} daily minimum` });
10828
+ ctx.addIssue({ code: "custom", path: path12, message: `below the ${min} ${money.currencyCode} daily minimum` });
10835
10829
  }
10836
10830
  }
10837
10831
  }
@@ -11319,19 +11313,19 @@ function failWriteValidation3(message) {
11319
11313
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
11320
11314
  process.exit(1);
11321
11315
  }
11322
- function loadJsonFileArg3(path14) {
11323
- if (typeof path14 !== "string" || path14.length === 0) {
11316
+ function loadJsonFileArg3(path12) {
11317
+ if (typeof path12 !== "string" || path12.length === 0) {
11324
11318
  return {};
11325
11319
  }
11326
11320
  try {
11327
- const parsed = JSON.parse(readFileSync8(path14, "utf8"));
11321
+ const parsed = JSON.parse(readFileSync8(path12, "utf8"));
11328
11322
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
11329
- failWriteValidation3(`${path14} must contain a JSON object`);
11323
+ failWriteValidation3(`${path12} must contain a JSON object`);
11330
11324
  }
11331
11325
  return parsed;
11332
11326
  } catch (err) {
11333
11327
  if (err instanceof SyntaxError) {
11334
- failWriteValidation3(`${path14} is not valid JSON: ${err.message}`);
11328
+ failWriteValidation3(`${path12} is not valid JSON: ${err.message}`);
11335
11329
  }
11336
11330
  throw err;
11337
11331
  }
@@ -14394,7 +14388,7 @@ async function probeDuration(filePath) {
14394
14388
 
14395
14389
  // src/commands/canvas/run.ts
14396
14390
  import { readFile as readFile2 } from "fs/promises";
14397
- import path5 from "path";
14391
+ import path4 from "path";
14398
14392
  import { defineCommand as defineCommand88 } from "citty";
14399
14393
 
14400
14394
  // src/commands/canvas/placeholders.ts
@@ -14438,102 +14432,9 @@ function isResolvableRelative(value) {
14438
14432
  return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !path2.isAbsolute(value);
14439
14433
  }
14440
14434
 
14441
- // src/commands/canvas/run-record.ts
14442
- import path3 from "path";
14443
- var MAX_RUN_NODES = 200;
14444
- var MAX_OUTPUTS_PER_NODE = 10;
14445
- var MAX_FINAL_OUTPUTS = 10;
14446
- var MAX_CREATIVE_SLUG_LENGTH = 100;
14447
- function creativeSlugFromCanvasPath(filePath) {
14448
- const normalized = filePath.split(path3.sep).join("/");
14449
- const match = normalized.match(/(?:^|\/)src\/creatives\/([a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\//);
14450
- const slug = match?.[1] ?? null;
14451
- return slug && slug.length <= MAX_CREATIVE_SLUG_LENGTH ? slug : null;
14452
- }
14453
- var OUTPUT_KINDS = /* @__PURE__ */ new Set(["image", "video", "audio", "json", "text", "font"]);
14454
- function toRecordOutput(slot, value) {
14455
- const refs = collectAssetRefLikes(value);
14456
- const ref = refs.length === 1 ? refs[0] : null;
14457
- if (!ref || !isPersistedAssetRef(ref)) return null;
14458
- const kind = typeof ref.kind === "string" && OUTPUT_KINDS.has(ref.kind) ? ref.kind : null;
14459
- if (!kind) return null;
14460
- return {
14461
- slot,
14462
- kind,
14463
- sha256: ref.sha256,
14464
- url: ref.url,
14465
- mime: ref.mime,
14466
- width: typeof ref.width === "number" ? ref.width : void 0,
14467
- height: typeof ref.height === "number" ? ref.height : void 0,
14468
- durationMs: typeof ref.duration_ms === "number" ? ref.duration_ms : void 0
14469
- };
14470
- }
14471
- function nodeOutputsToRecord(nodeOutputs) {
14472
- const out = [];
14473
- for (const [slot, value] of Object.entries(nodeOutputs)) {
14474
- if (Array.isArray(value)) {
14475
- value.forEach((item, i) => {
14476
- const rec = toRecordOutput(`${slot}#${i}`, item);
14477
- if (rec) out.push(rec);
14478
- });
14479
- } else {
14480
- const rec = toRecordOutput(slot, value);
14481
- if (rec) out.push(rec);
14482
- }
14483
- }
14484
- return out.slice(0, MAX_OUTPUTS_PER_NODE);
14485
- }
14486
- function finalOutputsToRecord(output) {
14487
- if (Array.isArray(output)) {
14488
- return output.map((item, i) => toRecordOutput(`final#${i}`, item)).filter((rec2) => rec2 !== null).slice(0, MAX_FINAL_OUTPUTS);
14489
- }
14490
- const rec = toRecordOutput("final", output);
14491
- return rec ? [rec] : [];
14492
- }
14493
- function buildRunRecord(result, meta) {
14494
- const nodes = result.node_runs.slice(0, MAX_RUN_NODES).map((run) => ({
14495
- nodeId: run.node_id,
14496
- nodeType: run.node_type,
14497
- cached: run.cached,
14498
- credits: run.credits,
14499
- durationMs: run.duration_ms,
14500
- outputs: nodeOutputsToRecord(result.outputs_by_node[run.node_id] ?? {})
14501
- }));
14502
- const finalOutputs = finalOutputsToRecord(result.output);
14503
- return {
14504
- runId: result.run_id,
14505
- creativeSlug: meta.creativeSlug,
14506
- canvasPath: meta.canvasPath,
14507
- canvasSha: meta.canvasSha,
14508
- chatId: meta.chatId,
14509
- status: "completed",
14510
- stats: {
14511
- totalNodes: result.stats.total_nodes,
14512
- cachedNodes: result.stats.cached_nodes,
14513
- totalCredits: result.stats.total_credits,
14514
- durationMs: result.stats.duration_ms
14515
- },
14516
- nodes,
14517
- finalOutputs: finalOutputs.length > 0 ? finalOutputs : void 0
14518
- };
14519
- }
14520
- function buildFailedRunRecord(runId, errorMessage, meta) {
14521
- return {
14522
- runId,
14523
- creativeSlug: meta.creativeSlug,
14524
- canvasPath: meta.canvasPath,
14525
- canvasSha: meta.canvasSha,
14526
- chatId: meta.chatId,
14527
- status: "failed",
14528
- errorMessage: errorMessage.slice(0, 2e3),
14529
- stats: { totalNodes: 0, cachedNodes: 0, totalCredits: 0, durationMs: 0 },
14530
- nodes: []
14531
- };
14532
- }
14533
-
14534
14435
  // src/commands/canvas/run-retention.ts
14535
14436
  import { rm } from "fs/promises";
14536
- import path4 from "path";
14437
+ import path3 from "path";
14537
14438
  function runDirsToPrune(entries, keep, currentRunId) {
14538
14439
  const runs = entries.filter((e) => /^r_[0-9A-Za-z]+$/.test(e) && e !== currentRunId).sort();
14539
14440
  if (keep <= 0) return runs;
@@ -14550,7 +14451,7 @@ async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
14550
14451
  const toPrune = runDirsToPrune(entries, keep, currentRunId);
14551
14452
  if (toPrune.length === 0) return;
14552
14453
  for (const dir of toPrune) {
14553
- await rm(path4.join(outputsDir, dir), { recursive: true, force: true }).catch(
14454
+ await rm(path3.join(outputsDir, dir), { recursive: true, force: true }).catch(
14554
14455
  (e) => log(`[prune ] could not remove ${dir}: ${e.message}`)
14555
14456
  );
14556
14457
  }
@@ -14577,22 +14478,10 @@ var runCommand = defineCommand88({
14577
14478
  "keep-runs": {
14578
14479
  type: "string",
14579
14480
  description: "After the run, prune old r_* run dirs, keeping the N newest (off by default)"
14580
- },
14581
- "remote-cache": {
14582
- type: "string",
14583
- description: "on | off \u2014 company-scoped remote cache + durable asset persistence (default on; env BAKER_CANVAS_REMOTE_CACHE)"
14584
- },
14585
- // citty consumes any `--no-<flag>` as a negation of `<flag>`, so the
14586
- // opt-out spelling `--no-record` requires the flag to be named `record`
14587
- // (a literal "no-record" arg would never receive a value).
14588
- record: {
14589
- type: "boolean",
14590
- default: true,
14591
- description: "Post the durable run-history record to Baker (disable with --no-record)"
14592
14481
  }
14593
14482
  },
14594
14483
  async run({ args }) {
14595
- const filePath = path5.resolve(String(args.file));
14484
+ const filePath = path4.resolve(String(args.file));
14596
14485
  const raw = await readFile2(filePath, "utf8");
14597
14486
  let parsed;
14598
14487
  try {
@@ -14603,7 +14492,7 @@ var runCommand = defineCommand88({
14603
14492
  `);
14604
14493
  process.exit(2);
14605
14494
  }
14606
- parsed = resolveRelativeCanvasPaths(parsed, path5.dirname(filePath));
14495
+ parsed = resolveRelativeCanvasPaths(parsed, path4.dirname(filePath));
14607
14496
  const pending = unsuppliedPlaceholderAssets(parsed);
14608
14497
  if (pending.length > 0) {
14609
14498
  process.stderr.write(
@@ -14623,26 +14512,16 @@ var runCommand = defineCommand88({
14623
14512
  );
14624
14513
  process.exit(2);
14625
14514
  }
14626
- const remoteCache = args["remote-cache"] !== void 0 ? String(args["remote-cache"]) !== "off" : void 0;
14627
14515
  const engine = createEngineFromEnv({
14628
14516
  cacheDir: args["cache-dir"] ? String(args["cache-dir"]) : void 0,
14629
14517
  outputsDir: args["outputs-dir"] ? String(args["outputs-dir"]) : void 0,
14630
14518
  log: (line) => process.stdout.write(`${line}
14631
- `),
14632
- remoteCache
14519
+ `)
14633
14520
  });
14634
- const runId = args["run-id"] ? String(args["run-id"]) : `r_${ulid()}`;
14635
- const recordMeta = {
14636
- creativeSlug: creativeSlugFromCanvasPath(filePath) ?? void 0,
14637
- canvasPath: path5.relative(process.cwd(), filePath) || void 0,
14638
- canvasSha: sha256Hex(Buffer.from(raw)),
14639
- chatId: getEnv().BAKER_CHAT_ID || void 0
14640
- };
14641
- const record = args.record === false ? null : buildRecorder();
14642
14521
  try {
14643
14522
  const policy = args["cache-policy"] ?? "read_write";
14644
14523
  const result = await engine.run(parsed, {
14645
- run_id: runId,
14524
+ run_id: args["run-id"] ? String(args["run-id"]) : void 0,
14646
14525
  cache_policy: policy,
14647
14526
  concurrency: resolveConcurrency(
14648
14527
  // --concurrency wins; --parallel is the discoverable alias for the same bound.
@@ -14650,10 +14529,9 @@ var runCommand = defineCommand88({
14650
14529
  process.env.BAKER_CANVAS_CONCURRENCY
14651
14530
  )
14652
14531
  });
14653
- if (record) await record(buildRunRecord(result, recordMeta));
14654
14532
  const keepRuns = args["keep-runs"] !== void 0 ? Number(args["keep-runs"]) : void 0;
14655
14533
  if (keepRuns !== void 0 && Number.isFinite(keepRuns)) {
14656
- const outputsDir = args["outputs-dir"] ? path5.resolve(String(args["outputs-dir"])) : path5.resolve("canvas");
14534
+ const outputsDir = args["outputs-dir"] ? path4.resolve(String(args["outputs-dir"])) : path4.resolve("canvas");
14657
14535
  await pruneOldRuns(outputsDir, keepRuns, result.run_id, (line) => process.stdout.write(`${line}
14658
14536
  `));
14659
14537
  }
@@ -14681,7 +14559,6 @@ var runCommand = defineCommand88({
14681
14559
  }
14682
14560
  if (e instanceof LayerExecutionError) {
14683
14561
  const failures = e.failures.map((f) => ({ node_id: f.nodeId, message: describeFailureReason(f.reason) }));
14684
- if (record) await record(buildFailedRunRecord(runId, e.message, recordMeta));
14685
14562
  process.stderr.write(
14686
14563
  `${JSON.stringify({ ok: false, error: { code: "runtime", message: e.message, failures } }, null, 2)}
14687
14564
  `
@@ -14689,30 +14566,16 @@ var runCommand = defineCommand88({
14689
14566
  process.exit(1);
14690
14567
  }
14691
14568
  const msg = e instanceof Error ? e.message : String(e);
14692
- if (record) await record(buildFailedRunRecord(runId, msg, recordMeta));
14693
14569
  process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "runtime", message: msg } }, null, 2)}
14694
14570
  `);
14695
14571
  process.exit(1);
14696
14572
  }
14697
14573
  }
14698
14574
  });
14699
- function buildRecorder() {
14700
- return async (payload) => {
14701
- try {
14702
- const creds = requireCredentialsFromEnv();
14703
- const client = new BackendClient({ baseUrl: creds.url, apiKey: creds.apiKey });
14704
- await client.recordRun(payload);
14705
- } catch (e) {
14706
- const msg = e instanceof Error ? e.message : String(e);
14707
- process.stderr.write(`[warn] run record not persisted (${msg})
14708
- `);
14709
- }
14710
- };
14711
- }
14712
14575
 
14713
14576
  // src/commands/canvas/scaffold-static-ad.ts
14714
- import { access, cp, mkdir, readFile as readFile3, writeFile } from "fs/promises";
14715
- import path8 from "path";
14577
+ import { readFile as readFile3, writeFile } from "fs/promises";
14578
+ import path6 from "path";
14716
14579
  import { defineCommand as defineCommand89 } from "citty";
14717
14580
 
14718
14581
  // src/engine/scaffold/staticAd.ts
@@ -14898,106 +14761,18 @@ function staticAdReport(input, elementsInput, opts) {
14898
14761
  };
14899
14762
  }
14900
14763
 
14901
- // src/commands/canvas/creative-definition.ts
14902
- import path6 from "path";
14903
- var PLATFORM_VALUES = ["meta", "google", "linkedin", "tiktok", "youtube", "x", "other"];
14904
- var FORMAT_VALUES = ["1:1", "4:5", "9:16", "16:9", "1.91:1"];
14905
- function titleFromSlug(slug) {
14906
- const title = slug.split("-").filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
14907
- return title || slug;
14908
- }
14909
- function resolvePlatform(platform) {
14910
- const value = platform?.trim();
14911
- return value && PLATFORM_VALUES.includes(value) ? value : "meta";
14912
- }
14913
- function resolveFormats(aspect) {
14914
- const value = aspect?.trim();
14915
- return value && FORMAT_VALUES.includes(value) ? [value] : ["4:5"];
14916
- }
14917
- function referenceRelativePath(kind, ext) {
14918
- const name = kind === "video" ? "source" : "original";
14919
- return `references/${name}${ext}`;
14920
- }
14921
- function sourceExtension(source, isUrl, kind) {
14922
- const raw = isUrl ? urlPathname(source) : source;
14923
- const ext = path6.extname(raw).toLowerCase();
14924
- if (/^\.[a-z0-9]{1,5}$/.test(ext)) return ext;
14925
- return kind === "video" ? ".mp4" : ".jpg";
14926
- }
14927
- function urlPathname(source) {
14928
- try {
14929
- return new URL(source).pathname;
14930
- } catch {
14931
- return source;
14932
- }
14933
- }
14934
- function describeBlueprintIntent(blueprint) {
14935
- const intent = blueprint?.ad_intent;
14936
- if (typeof intent === "string" && intent.trim()) return intent.trim();
14937
- if (intent && typeof intent === "object") {
14938
- const summary = intent.summary ?? intent.feeling;
14939
- if (typeof summary === "string" && summary.trim()) return summary.trim();
14940
- }
14941
- return void 0;
14942
- }
14943
- function yamlScalar(value) {
14944
- return JSON.stringify(value);
14945
- }
14946
- function buildCreativeDefinition(input) {
14947
- const lines = ["---", `title: ${yamlScalar(input.title)}`, `kind: ${input.kind}`, `platform: ${input.platform}`];
14948
- lines.push(`formats: [${input.formats.map(yamlScalar).join(", ")}]`);
14949
- lines.push(`status: ${input.status ?? "draft"}`);
14950
- if (input.sourceReferenceUrl) lines.push(`sourceReferenceUrl: ${yamlScalar(input.sourceReferenceUrl)}`);
14951
- if (input.sourceAdvertiser) lines.push(`sourceAdvertiser: ${yamlScalar(input.sourceAdvertiser)}`);
14952
- if (input.sourceKind) lines.push(`sourceKind: ${input.sourceKind}`);
14953
- if (input.sourcePath) lines.push(`sourcePath: ${yamlScalar(input.sourcePath)}`);
14954
- lines.push("---", "");
14955
- lines.push(input.description?.trim() || `${input.title} \u2014 canvas-built ${input.kind} ad for ${input.platform}.`);
14956
- lines.push("");
14957
- return lines.join("\n");
14958
- }
14959
-
14960
14764
  // src/commands/canvas/scaffold-static-ad-paths.ts
14961
- import path7 from "path";
14962
- function resolveScaffoldStaticAdPaths(rawFile, out, cwd = process.cwd(), slug) {
14765
+ import path5 from "path";
14766
+ function resolveScaffoldStaticAdPaths(rawFile, out, cwd = process.cwd()) {
14963
14767
  const file = rawFile.trim();
14964
14768
  const imageIsUrl = /^https?:\/\//i.test(file);
14965
- const imageSource = imageIsUrl ? file : path7.resolve(cwd, file);
14966
- const outPath = out ? path7.resolve(cwd, out) : slug ? path7.join(cwd, "src", "creatives", slug, `${slug}.canvas.json`) : imageIsUrl ? path7.join(cwd, "static-ad.canvas.json") : path7.join(path7.dirname(imageSource), "static-ad.canvas.json");
14967
- const blueprintPath = path7.join(path7.dirname(outPath), "prompt.json");
14968
- const creativeDir = slug ? path7.dirname(outPath) : null;
14969
- const definitionPath = creativeDir ? path7.join(creativeDir, "_definition.md") : null;
14970
- const referencesDir = creativeDir ? path7.join(creativeDir, "references") : null;
14971
- return { imageIsUrl, imageSource, outPath, blueprintPath, creativeDir, definitionPath, referencesDir };
14972
- }
14973
- var SCAFFOLD_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
14974
- var SCAFFOLD_SLUG_MAX_LENGTH = 100;
14975
- function isValidScaffoldSlug(slug) {
14976
- return slug.length <= SCAFFOLD_SLUG_MAX_LENGTH && SCAFFOLD_SLUG_PATTERN.test(slug);
14769
+ const imageSource = imageIsUrl ? file : path5.resolve(cwd, file);
14770
+ const outPath = out ? path5.resolve(cwd, out) : imageIsUrl ? path5.join(cwd, "static-ad.canvas.json") : path5.join(path5.dirname(imageSource), "static-ad.canvas.json");
14771
+ const blueprintPath = path5.join(path5.dirname(outPath), "prompt.json");
14772
+ return { imageIsUrl, imageSource, outPath, blueprintPath };
14977
14773
  }
14978
14774
 
14979
14775
  // src/commands/canvas/scaffold-static-ad.ts
14980
- async function fileExists(target) {
14981
- try {
14982
- await access(target);
14983
- return true;
14984
- } catch {
14985
- return false;
14986
- }
14987
- }
14988
- async function copySourceIntoReferences(source, isUrl, referencesDir) {
14989
- await mkdir(referencesDir, { recursive: true });
14990
- const relPath = referenceRelativePath("image", sourceExtension(source, isUrl, "image"));
14991
- const dest = path8.join(referencesDir, path8.basename(relPath));
14992
- if (isUrl) {
14993
- const res = await fetch(source);
14994
- if (!res.ok) throw new Error(`failed to download source image (${res.status})`);
14995
- await writeFile(dest, Buffer.from(await res.arrayBuffer()));
14996
- } else {
14997
- await cp(source, dest);
14998
- }
14999
- return relPath;
15000
- }
15001
14776
  function resolveModel(kind, preferred) {
15002
14777
  const ids = Object.keys(MODEL_REGISTRY[kind]);
15003
14778
  return ids.includes(preferred) ? preferred : ids[0] ?? preferred;
@@ -15157,16 +14932,6 @@ var scaffoldStaticAdCommand = defineCommand89({
15157
14932
  file: { type: "positional", required: true, description: "Path or http(s) URL to the source/inspiration image" },
15158
14933
  context: { type: "string", description: "Known provenance (advertiser, category, market) to ground the describe" },
15159
14934
  out: { type: "string", description: "Output canvas path (default <image-dir>/static-ad.canvas.json)" },
15160
- slug: {
15161
- type: "string",
15162
- description: "Creative slug \u2014 writes the canvas to src/creatives/<slug>/<slug>.canvas.json (repo convention)"
15163
- },
15164
- title: { type: "string", description: "Creative title for _definition.md (default: title-cased slug)" },
15165
- platform: {
15166
- type: "string",
15167
- description: "Ad platform for _definition.md (meta|google|linkedin|tiktok|youtube|x|other; default meta)"
15168
- },
15169
- advertiser: { type: "string", description: "Source advertiser recorded in _definition.md" },
15170
14935
  "describe-model": { type: "string", description: "Override the image_describe model id" },
15171
14936
  "select-model": { type: "string", description: "Override the text_generate model id for element selection" },
15172
14937
  "layout-model": { type: "string", description: "Override the text_generate model id for the layout pass" },
@@ -15175,21 +14940,10 @@ var scaffoldStaticAdCommand = defineCommand89({
15175
14940
  "skip-font": { type: "boolean", description: "Skip the brand-font \u2192 type-specimen slot" }
15176
14941
  },
15177
14942
  async run({ args }) {
15178
- const slug = args.slug ? String(args.slug) : void 0;
15179
- if (slug && !isValidScaffoldSlug(slug)) {
15180
- process.stderr.write(
15181
- `${JSON.stringify({ ok: false, error: { code: "invalid_slug", message: "--slug must be lowercase kebab (a-z, 0-9, hyphens), max 100 chars" } }, null, 2)}
15182
- `
15183
- );
15184
- process.exit(2);
15185
- }
15186
- const { imageIsUrl, imageSource, outPath, blueprintPath, definitionPath, referencesDir } = resolveScaffoldStaticAdPaths(
14943
+ const { imageIsUrl, imageSource, outPath, blueprintPath } = resolveScaffoldStaticAdPaths(
15187
14944
  String(args.file),
15188
- args.out ? String(args.out) : void 0,
15189
- process.cwd(),
15190
- slug
14945
+ args.out ? String(args.out) : void 0
15191
14946
  );
15192
- await mkdir(path8.dirname(outPath), { recursive: true });
15193
14947
  const { describeModel, selectModel, layoutModel, genModel } = resolveModels(args);
15194
14948
  const describeCanvas = buildDescribeCanvas(
15195
14949
  imageSource,
@@ -15206,21 +14960,11 @@ var scaffoldStaticAdCommand = defineCommand89({
15206
14960
  }
15207
14961
  await writeFile(blueprintPath, `${JSON.stringify(annotated, null, 2)}
15208
14962
  `, "utf8");
15209
- let canvasImagePath = imageSource;
15210
- let canvasImageIsUrl = imageIsUrl;
15211
- let canvasBlueprintPath = blueprintPath;
15212
- let sourceRelPath;
15213
- if (referencesDir) {
15214
- sourceRelPath = await copySourceIntoReferences(imageSource, imageIsUrl, referencesDir);
15215
- canvasImagePath = sourceRelPath;
15216
- canvasImageIsUrl = false;
15217
- canvasBlueprintPath = "./prompt.json";
15218
- }
15219
14963
  const opts = {
15220
14964
  genModel,
15221
- imagePath: canvasImagePath,
15222
- imageIsUrl: canvasImageIsUrl,
15223
- blueprintPath: canvasBlueprintPath,
14965
+ imagePath: imageSource,
14966
+ imageIsUrl,
14967
+ blueprintPath,
15224
14968
  aspectRatio: args.aspect ? String(args.aspect) : void 0,
15225
14969
  includeFont: !args["skip-font"]
15226
14970
  };
@@ -15242,31 +14986,12 @@ var scaffoldStaticAdCommand = defineCommand89({
15242
14986
  }
15243
14987
  await writeFile(outPath, `${JSON.stringify(canvas, null, 2)}
15244
14988
  `, "utf8");
15245
- if (definitionPath && !await fileExists(definitionPath)) {
15246
- await writeFile(
15247
- definitionPath,
15248
- buildCreativeDefinition({
15249
- title: args.title ? String(args.title) : titleFromSlug(slug ?? ""),
15250
- kind: "static",
15251
- platform: resolvePlatform(args.platform ? String(args.platform) : void 0),
15252
- formats: resolveFormats(args.aspect ? String(args.aspect) : report.aspect_ratio),
15253
- sourceReferenceUrl: imageIsUrl ? imageSource : void 0,
15254
- sourceAdvertiser: args.advertiser ? String(args.advertiser) : args.context ? String(args.context) : void 0,
15255
- sourceKind: "image",
15256
- sourcePath: sourceRelPath,
15257
- description: describeBlueprintIntent(blueprint)
15258
- }),
15259
- "utf8"
15260
- );
15261
- }
15262
14989
  process.stdout.write(
15263
14990
  `${JSON.stringify(
15264
14991
  {
15265
14992
  ok: true,
15266
14993
  canvas_path: outPath,
15267
14994
  prompt_path: blueprintPath,
15268
- definition_path: definitionPath ?? void 0,
15269
- source_reference: sourceRelPath ?? void 0,
15270
14995
  output: canvas.output,
15271
14996
  models: { describe: describeModel, select: selectModel, layout: layoutModel, gen: opts.genModel },
15272
14997
  aspect_ratio: report.aspect_ratio,
@@ -15277,7 +15002,7 @@ var scaffoldStaticAdCommand = defineCommand89({
15277
15002
  run_estimated_credits: validation.estimatedCredits
15278
15003
  },
15279
15004
  checklist: {
15280
- edit_prompt: `Edit ${path8.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.`,
15005
+ edit_prompt: `Edit ${path6.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.`,
15281
15006
  assets_to_supply: report.elements,
15282
15007
  font_slot: report.includes_font ? "Drop a brand font at the [TODO] brandfont path, or delete the brandfont + type_ref nodes to skip it." : "skipped (--skip-font)",
15283
15008
  note: "Replace every [TODO] ingest path with a real file, then `baker canvas validate` and `baker canvas run`. Running generates a billed image \u2014 it is not free."
@@ -15292,8 +15017,8 @@ var scaffoldStaticAdCommand = defineCommand89({
15292
15017
  });
15293
15018
 
15294
15019
  // src/commands/canvas/scaffold-video.ts
15295
- import { cp as cp2, mkdir as mkdir2, readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
15296
- import path11 from "path";
15020
+ import { cp, mkdir, readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
15021
+ import path9 from "path";
15297
15022
  import { defineCommand as defineCommand90 } from "citty";
15298
15023
 
15299
15024
  // src/engine/nodes/local/lib/sceneDetect.ts
@@ -18401,23 +18126,23 @@ function videoReport(input, elementsInput) {
18401
18126
 
18402
18127
  // src/commands/canvas/composition-path.ts
18403
18128
  import { existsSync as existsSync3 } from "fs";
18404
- import path9 from "path";
18129
+ import path7 from "path";
18405
18130
  function resolveShippedCanvasDir(name, startDir, exists = existsSync3, maxDepth = 8) {
18406
- const rel = path9.join("canvas", name);
18131
+ const rel = path7.join("canvas", name);
18407
18132
  let dir = startDir;
18408
18133
  for (let i = 0; i < maxDepth; i++) {
18409
- const candidate = path9.join(dir, rel);
18410
- if (exists(path9.join(candidate, "meta.json"))) return candidate;
18411
- const parent = path9.dirname(dir);
18134
+ const candidate = path7.join(dir, rel);
18135
+ if (exists(path7.join(candidate, "meta.json"))) return candidate;
18136
+ const parent = path7.dirname(dir);
18412
18137
  if (parent === dir) break;
18413
18138
  dir = parent;
18414
18139
  }
18415
- return path9.resolve(startDir, "../../../", rel);
18140
+ return path7.resolve(startDir, "../../../", rel);
18416
18141
  }
18417
18142
 
18418
18143
  // src/commands/canvas/gitignore.ts
18419
18144
  import { appendFile, readFile as readFile5 } from "fs/promises";
18420
- import path10 from "path";
18145
+ import path8 from "path";
18421
18146
  function missingGitignoreEntries(existing, entries) {
18422
18147
  const present = new Set(
18423
18148
  existing.split("\n").map((l) => l.trim().replace(/\/+$/, "")).filter((l) => l.length > 0 && !l.startsWith("#"))
@@ -18425,7 +18150,7 @@ function missingGitignoreEntries(existing, entries) {
18425
18150
  return entries.filter((e) => !present.has(e.trim().replace(/\/+$/, "")));
18426
18151
  }
18427
18152
  async function ensureGitignore(dir, entries) {
18428
- const file = path10.join(dir, ".gitignore");
18153
+ const file = path8.join(dir, ".gitignore");
18429
18154
  let existing;
18430
18155
  try {
18431
18156
  existing = await readFile5(file, "utf8");
@@ -18486,8 +18211,8 @@ async function loadTranscriptBestEffort(ref) {
18486
18211
  async function stageCaptions(outDir, transcript) {
18487
18212
  const text = transcript?.trim();
18488
18213
  if (!text || text === "[]") return {};
18489
- const compositionPath = path11.join(outDir, "tiktok-captions-composition");
18490
- await cp2(SHIPPED_CAPTIONS_DIR, compositionPath, { recursive: true });
18214
+ const compositionPath = path9.join(outDir, "tiktok-captions-composition");
18215
+ await cp(SHIPPED_CAPTIONS_DIR, compositionPath, { recursive: true });
18491
18216
  return { compositionPath };
18492
18217
  }
18493
18218
  function patchCompositionMeta(metaJson, dims) {
@@ -18504,10 +18229,10 @@ function patchCompositionHtml(html, dims) {
18504
18229
  return html.replace(/(<meta\s+name="viewport"\s+content="width=)\d+(,\s*height=)\d+(")/i, `$1${dims.w}$2${dims.h}$3`).replace(/(width:\s*)\d+(px;\s*height:\s*)\d+(px;)/i, `$1${dims.w}$2${dims.h}$3`).replace(/(data-width=")\d+(")/i, `$1${dims.w}$2`).replace(/(data-height=")\d+(")/i, `$1${dims.h}$2`);
18505
18230
  }
18506
18231
  async function stampCompositionDims(compositionDir, dims) {
18507
- const metaPath = path11.join(compositionDir, "meta.json");
18232
+ const metaPath = path9.join(compositionDir, "meta.json");
18508
18233
  const rawMeta = await readFile6(metaPath, "utf8");
18509
18234
  await writeFile2(metaPath, patchCompositionMeta(rawMeta, dims), "utf8");
18510
- const htmlPath = path11.join(compositionDir, "index.html");
18235
+ const htmlPath = path9.join(compositionDir, "index.html");
18511
18236
  const rawHtml = await readFile6(htmlPath, "utf8");
18512
18237
  await writeFile2(htmlPath, patchCompositionHtml(rawHtml, dims), "utf8");
18513
18238
  }
@@ -18647,10 +18372,6 @@ var scaffoldVideoCommand = defineCommand90({
18647
18372
  args: {
18648
18373
  file: { type: "positional", required: true, description: "Path to the reference video" },
18649
18374
  out: { type: "string", description: "Output canvas path (default <video-dir>/<name>.video.canvas.json)" },
18650
- slug: {
18651
- type: "string",
18652
- description: "Creative slug \u2014 writes the canvas to src/creatives/<slug>/<slug>.canvas.json (repo convention)"
18653
- },
18654
18375
  frames: { type: "string", description: '"generate" (default, anchored regen) or "reuse" (wire real frames in)' },
18655
18376
  ambient: {
18656
18377
  type: "boolean",
@@ -18677,19 +18398,11 @@ var scaffoldVideoCommand = defineCommand90({
18677
18398
  }
18678
18399
  },
18679
18400
  async run({ args }) {
18680
- const videoPath = path11.resolve(String(args.file));
18681
- const base = path11.basename(videoPath, path11.extname(videoPath));
18682
- const slug = args.slug ? String(args.slug) : void 0;
18683
- if (slug && !isValidScaffoldSlug(slug)) {
18684
- process.stderr.write(
18685
- `${JSON.stringify({ ok: false, error: { code: "invalid_slug", message: "--slug must be lowercase kebab (a-z, 0-9, hyphens), max 100 chars" } }, null, 2)}
18686
- `
18687
- );
18688
- process.exit(2);
18689
- }
18690
- const outPath = args.out ? path11.resolve(String(args.out)) : slug ? path11.join(process.cwd(), "src", "creatives", slug, `${slug}.canvas.json`) : path11.join(path11.dirname(videoPath), `${base}.video.canvas.json`);
18691
- const outDir = path11.dirname(outPath);
18692
- const blueprintPath = path11.join(outDir, "prompt.json");
18401
+ const videoPath = path9.resolve(String(args.file));
18402
+ const base = path9.basename(videoPath, path9.extname(videoPath));
18403
+ const outPath = args.out ? path9.resolve(String(args.out)) : path9.join(path9.dirname(videoPath), `${base}.video.canvas.json`);
18404
+ const outDir = path9.dirname(outPath);
18405
+ const blueprintPath = path9.join(outDir, "prompt.json");
18693
18406
  const frames = args.frames === "reuse" ? "reuse" : "generate";
18694
18407
  const maxScenes = args["max-scenes"] ? Number(args["max-scenes"]) : void 0;
18695
18408
  if (Number.isFinite(maxScenes)) {
@@ -18708,7 +18421,7 @@ var scaffoldVideoCommand = defineCommand90({
18708
18421
  shotCuts
18709
18422
  });
18710
18423
  const { blueprint, elements, transcript, creditsSpent } = await runAnalysisPasses(deconstructCanvas, selectModel);
18711
- await mkdir2(outDir, { recursive: true });
18424
+ await mkdir(outDir, { recursive: true });
18712
18425
  const annotated = annotateBlueprintWithElements(blueprint, elements);
18713
18426
  await writeFile2(blueprintPath, `${JSON.stringify(annotated, null, 2)}
18714
18427
  `, "utf8");
@@ -18729,10 +18442,10 @@ var scaffoldVideoCommand = defineCommand90({
18729
18442
  `
18730
18443
  );
18731
18444
  }
18732
- const compositionDest = path11.join(outDir, "video-overlay-composition");
18733
- await cp2(SHIPPED_COMPOSITION_DIR, compositionDest, { recursive: true });
18445
+ const compositionDest = path9.join(outDir, "video-overlay-composition");
18446
+ await cp(SHIPPED_COMPOSITION_DIR, compositionDest, { recursive: true });
18734
18447
  await stampCompositionDims(compositionDest, outDims);
18735
- const indexPath = path11.join(compositionDest, "index.html");
18448
+ const indexPath = path9.join(compositionDest, "index.html");
18736
18449
  const overlayHtml = buildOverlayHtml(blueprint, { captionsActive: Boolean(transcript) });
18737
18450
  const indexHtml = await readFile6(indexPath, "utf8");
18738
18451
  const injected = indexHtml.replace("<!--OVERLAYS-->", () => overlayHtml);
@@ -18748,9 +18461,9 @@ var scaffoldVideoCommand = defineCommand90({
18748
18461
  const opts = {
18749
18462
  imageModel,
18750
18463
  videoModel,
18751
- overlayCompositionPath: path11.relative(outDir, compositionDest),
18752
- captionsCompositionPath: captions.compositionPath ? path11.relative(outDir, captions.compositionPath) : void 0,
18753
- blueprintPath: path11.relative(outDir, blueprintPath),
18464
+ overlayCompositionPath: path9.relative(outDir, compositionDest),
18465
+ captionsCompositionPath: captions.compositionPath ? path9.relative(outDir, captions.compositionPath) : void 0,
18466
+ blueprintPath: path9.relative(outDir, blueprintPath),
18754
18467
  frames,
18755
18468
  ambient: Boolean(args.ambient),
18756
18469
  ...args.aspect ? { aspect: String(args.aspect) } : {},
@@ -18808,7 +18521,7 @@ var scaffoldVideoCommand = defineCommand90({
18808
18521
  run_estimated_credits: validation.estimatedCredits
18809
18522
  },
18810
18523
  checklist: {
18811
- edit_prompt: `Edit ${path11.basename(blueprintPath)} \u2014 the blueprint deconstructed from your video; rewrite it into the ad you want (cast, palette, copy, claims). Every scene frame reads it via target_blueprint.`,
18524
+ edit_prompt: `Edit ${path9.basename(blueprintPath)} \u2014 the blueprint deconstructed from your video; rewrite it into the ad you want (cast, palette, copy, claims). Every scene frame reads it via target_blueprint.`,
18812
18525
  recurring_elements_to_supply: report.elements,
18813
18526
  voices_to_confirm: report.dialogue.map((d) => ({
18814
18527
  scene: d.scene,
@@ -18835,7 +18548,7 @@ var scaffoldVideoCommand = defineCommand90({
18835
18548
 
18836
18549
  // src/commands/canvas/set-prompt.ts
18837
18550
  import { readFile as readFile7, writeFile as writeFile3 } from "fs/promises";
18838
- import path12 from "path";
18551
+ import path10 from "path";
18839
18552
  import { defineCommand as defineCommand91 } from "citty";
18840
18553
  function setNodePrompt(canvas, nodeId, text) {
18841
18554
  const nodes = canvas?.nodes;
@@ -18863,7 +18576,7 @@ var setPromptCommand = defineCommand91({
18863
18576
  "text-file": { type: "string", description: "Read the new prompt from a UTF-8 file (preserves accents/newlines)" }
18864
18577
  },
18865
18578
  async run({ args }) {
18866
- const filePath = path12.resolve(String(args.file));
18579
+ const filePath = path10.resolve(String(args.file));
18867
18580
  let canvas;
18868
18581
  try {
18869
18582
  canvas = JSON.parse(await readFile7(filePath, "utf8"));
@@ -18873,7 +18586,7 @@ var setPromptCommand = defineCommand91({
18873
18586
  process.exit(2);
18874
18587
  }
18875
18588
  let text;
18876
- if (args["text-file"]) text = await readFile7(path12.resolve(String(args["text-file"])), "utf8");
18589
+ if (args["text-file"]) text = await readFile7(path10.resolve(String(args["text-file"])), "utf8");
18877
18590
  else if (args.text !== void 0) text = String(args.text);
18878
18591
  else {
18879
18592
  process.stderr.write(
@@ -18894,7 +18607,7 @@ var setPromptCommand = defineCommand91({
18894
18607
  process.exit(2);
18895
18608
  return;
18896
18609
  }
18897
- const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated, path12.dirname(filePath)), defaultRegistry());
18610
+ const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated, path10.dirname(filePath)), defaultRegistry());
18898
18611
  if (!validation.ok) {
18899
18612
  process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "validation", issues: validation.issues } }, null, 2)}
18900
18613
  `);
@@ -18910,7 +18623,7 @@ var setPromptCommand = defineCommand91({
18910
18623
 
18911
18624
  // src/commands/canvas/validate.ts
18912
18625
  import { readFile as readFile8 } from "fs/promises";
18913
- import path13 from "path";
18626
+ import path11 from "path";
18914
18627
  import { defineCommand as defineCommand92 } from "citty";
18915
18628
  var validateCommand = defineCommand92({
18916
18629
  meta: {
@@ -18919,7 +18632,7 @@ var validateCommand = defineCommand92({
18919
18632
  },
18920
18633
  args: { file: { type: "positional", required: true, description: "Path to canvas JSON" } },
18921
18634
  async run({ args }) {
18922
- const filePath = path13.resolve(String(args.file));
18635
+ const filePath = path11.resolve(String(args.file));
18923
18636
  const raw = await readFile8(filePath, "utf8");
18924
18637
  let parsed;
18925
18638
  try {
@@ -18930,7 +18643,7 @@ var validateCommand = defineCommand92({
18930
18643
  `);
18931
18644
  process.exit(2);
18932
18645
  }
18933
- parsed = resolveRelativeCanvasPaths(parsed, path13.dirname(filePath));
18646
+ parsed = resolveRelativeCanvasPaths(parsed, path11.dirname(filePath));
18934
18647
  const result = await validateCanvasDeep(parsed, defaultRegistry());
18935
18648
  if (!result.ok) {
18936
18649
  process.stderr.write(`${JSON.stringify({ ok: false, issues: result.issues }, null, 2)}
@@ -19067,16 +18780,6 @@ registerSchema({
19067
18780
  type: "string",
19068
18781
  description: "Optional URL of the original reference ad",
19069
18782
  required: false
19070
- },
19071
- slug: {
19072
- type: "string",
19073
- description: "Creative slug (src/creatives/<slug>/) \u2014 attaches the image to that creative's row",
19074
- required: false
19075
- },
19076
- runId: {
19077
- type: "string",
19078
- description: "Canvas run id (r_\u2026) of the approved generation to pin as published",
19079
- required: false
19080
18783
  }
19081
18784
  }
19082
18785
  });
@@ -19086,13 +18789,6 @@ function detectCreativeContentType(filePath) {
19086
18789
  unsupportedMessage: "Unsupported creative image extension. Use PNG, JPG, or WebP."
19087
18790
  });
19088
18791
  }
19089
- function chatIdFromEnv() {
19090
- try {
19091
- return getEnv().BAKER_CHAT_ID || void 0;
19092
- } catch {
19093
- return void 0;
19094
- }
19095
- }
19096
18792
  function parseOptionalUrl(value) {
19097
18793
  if (value === void 0 || value.trim() === "") {
19098
18794
  return void 0;
@@ -19123,11 +18819,7 @@ async function publishCreative(args, deps = defaultImageApiDeps) {
19123
18819
  return publishImageAsCreative(deps, {
19124
18820
  imageId: upload.imageId,
19125
18821
  title,
19126
- sourceReferenceUrl,
19127
- slug: args.slug,
19128
- runId: args.runId,
19129
- // Attribute the publish to the driving chat (injected by the bridge).
19130
- chatId: chatIdFromEnv()
18822
+ sourceReferenceUrl
19131
18823
  });
19132
18824
  }
19133
18825
  var publishCommand = defineCommand94({
@@ -19143,16 +18835,6 @@ var publishCommand = defineCommand94({
19143
18835
  type: "string",
19144
18836
  description: "Optional URL of the original reference ad",
19145
18837
  required: false
19146
- },
19147
- slug: {
19148
- type: "string",
19149
- description: "Creative slug (src/creatives/<slug>/) \u2014 attaches the image to that creative's row",
19150
- required: false
19151
- },
19152
- runId: {
19153
- type: "string",
19154
- description: "Canvas run id (r_\u2026) of the approved generation to pin as published",
19155
- required: false
19156
18838
  }
19157
18839
  },
19158
18840
  run: async ({ args }) => {
@@ -19171,9 +18853,7 @@ var publishCommand = defineCommand94({
19171
18853
  file,
19172
18854
  title,
19173
18855
  context: args.context,
19174
- sourceReferenceUrl: args.sourceReferenceUrl,
19175
- slug: args.slug,
19176
- runId: args.runId
18856
+ sourceReferenceUrl: args.sourceReferenceUrl
19177
18857
  });
19178
18858
  writeJson({ ok: true, data });
19179
18859
  } catch (err) {
@@ -20071,9 +19751,9 @@ async function readImageBuffer(pathOrUrl) {
20071
19751
  }
20072
19752
  return readFile10(pathOrUrl);
20073
19753
  }
20074
- async function isDirectory(path14) {
19754
+ async function isDirectory(path12) {
20075
19755
  try {
20076
- const s = await stat2(path14);
19756
+ const s = await stat2(path12);
20077
19757
  return s.isDirectory();
20078
19758
  } catch {
20079
19759
  return false;