@koda-sl/baker-cli 0.434.0-dev.42b55fa66 → 0.439.0-dev.33cf4ca99

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.
Files changed (27) hide show
  1. package/README.md +2 -1
  2. package/dist/{chunk-RFZYRG2Q.js → chunk-32UJLGZX.js} +3 -3
  3. package/dist/{chunk-GCTR4MDE.js → chunk-5DJPTQU5.js} +2 -2
  4. package/dist/{chunk-MMTPMFFH.js → chunk-APTNJ2EY.js} +19 -12
  5. package/dist/chunk-APTNJ2EY.js.map +1 -0
  6. package/dist/{chunk-PHLFNYGQ.js → chunk-KP33GIDZ.js} +4 -4
  7. package/dist/{chunk-FQOKJYKN.js → chunk-PR3CXBAT.js} +5 -1
  8. package/dist/chunk-PR3CXBAT.js.map +1 -0
  9. package/dist/{chunk-Q6F5UNOU.js → chunk-UKHD423A.js} +3 -3
  10. package/dist/cli.js +139 -33
  11. package/dist/cli.js.map +1 -1
  12. package/dist/{client-GS7T7ETG.js → client-JM3QBGR2.js} +4 -4
  13. package/dist/engine/index.js +3 -3
  14. package/dist/{env-SL22S6CM.js → env-WIAWLTDN.js} +4 -2
  15. package/dist/{output-OFDKEPPJ.js → output-UGMWOFQR.js} +5 -5
  16. package/dist/{shared-XR54KFMH.js → shared-DJTAT7CM.js} +6 -6
  17. package/package.json +1 -1
  18. package/dist/chunk-FQOKJYKN.js.map +0 -1
  19. package/dist/chunk-MMTPMFFH.js.map +0 -1
  20. /package/dist/{chunk-RFZYRG2Q.js.map → chunk-32UJLGZX.js.map} +0 -0
  21. /package/dist/{chunk-GCTR4MDE.js.map → chunk-5DJPTQU5.js.map} +0 -0
  22. /package/dist/{chunk-PHLFNYGQ.js.map → chunk-KP33GIDZ.js.map} +0 -0
  23. /package/dist/{chunk-Q6F5UNOU.js.map → chunk-UKHD423A.js.map} +0 -0
  24. /package/dist/{client-GS7T7ETG.js.map → client-JM3QBGR2.js.map} +0 -0
  25. /package/dist/{env-SL22S6CM.js.map → env-WIAWLTDN.js.map} +0 -0
  26. /package/dist/{output-OFDKEPPJ.js.map → output-UGMWOFQR.js.map} +0 -0
  27. /package/dist/{shared-XR54KFMH.js.map → shared-DJTAT7CM.js.map} +0 -0
package/dist/cli.js CHANGED
@@ -198,7 +198,7 @@ import {
198
198
  withoutCastName,
199
199
  wordCount,
200
200
  ytDlpBlockSignal
201
- } from "./chunk-MMTPMFFH.js";
201
+ } from "./chunk-APTNJ2EY.js";
202
202
  import {
203
203
  NAME_CONTAINS_ARG,
204
204
  csvOrJson,
@@ -209,7 +209,7 @@ import {
209
209
  resolveEffectiveStatus,
210
210
  statusFilterHints,
211
211
  todayIso
212
- } from "./chunk-PHLFNYGQ.js";
212
+ } from "./chunk-KP33GIDZ.js";
213
213
  import {
214
214
  buildQueryCacheKey,
215
215
  cacheGet,
@@ -225,19 +225,19 @@ import {
225
225
  writeAdsJson,
226
226
  writeAdsOutput,
227
227
  writeJsonEnvelope
228
- } from "./chunk-RFZYRG2Q.js";
228
+ } from "./chunk-32UJLGZX.js";
229
229
  import {
230
230
  ApiError,
231
231
  apiGet,
232
232
  apiGetWithHeaders,
233
233
  apiPost,
234
234
  validateConvexId
235
- } from "./chunk-Q6F5UNOU.js";
235
+ } from "./chunk-UKHD423A.js";
236
236
  import {
237
237
  installExitRecord,
238
238
  installStreamTaps,
239
239
  logInvocation
240
- } from "./chunk-GCTR4MDE.js";
240
+ } from "./chunk-5DJPTQU5.js";
241
241
  import {
242
242
  __commonJS,
243
243
  __esm,
@@ -261,6 +261,7 @@ import {
261
261
  nextPlannedRoute,
262
262
  optionalChatId,
263
263
  optionalConnection,
264
+ optionalTurnId,
264
265
  outputFlagForCommand,
265
266
  plannedRoutes,
266
267
  refuseNonPublicUrl,
@@ -275,7 +276,7 @@ import {
275
276
  winningAdNormalizer,
276
277
  writeJson,
277
278
  writeOutput
278
- } from "./chunk-FQOKJYKN.js";
279
+ } from "./chunk-PR3CXBAT.js";
279
280
 
280
281
  // ../../.pnpm-store/v10/links/@/i18n-iso-countries/7.14.0/5e6699c273c94e2e87598072b13ced7dbfb8ba9153290de3d03d5f711e81fac0/node_modules/i18n-iso-countries/langs/af.json
281
282
  var require_af = __commonJS({
@@ -54504,10 +54505,10 @@ Example: baker ads meta ads retag 120252158038400247 --url-tags "utm_source={{si
54504
54505
  }
54505
54506
  },
54506
54507
  run: async ({ args: args8 }) => {
54507
- const { apiPost: apiPost2 } = await import("./client-GS7T7ETG.js");
54508
- const { requireChatId: requireChatId2 } = await import("./env-SL22S6CM.js");
54509
- const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-OFDKEPPJ.js");
54510
- const { handleMetaError: handleMetaError2 } = await import("./shared-XR54KFMH.js");
54508
+ const { apiPost: apiPost2 } = await import("./client-JM3QBGR2.js");
54509
+ const { requireChatId: requireChatId2 } = await import("./env-WIAWLTDN.js");
54510
+ const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-UGMWOFQR.js");
54511
+ const { handleMetaError: handleMetaError2 } = await import("./shared-DJTAT7CM.js");
54511
54512
  try {
54512
54513
  const accountId = bareAccountId2(args8);
54513
54514
  const urlTags = typeof args8["url-tags"] === "string" ? args8["url-tags"] : void 0;
@@ -54658,10 +54659,10 @@ function duplicateCommand2(entity, label) {
54658
54659
  replace: { type: "boolean", description: "Pause the original once the copy publishes" }
54659
54660
  },
54660
54661
  run: async ({ args: args8 }) => {
54661
- const { apiPost: apiPost2 } = await import("./client-GS7T7ETG.js");
54662
- const { requireChatId: requireChatId2 } = await import("./env-SL22S6CM.js");
54663
- const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-OFDKEPPJ.js");
54664
- const { handleMetaError: handleMetaError2 } = await import("./shared-XR54KFMH.js");
54662
+ const { apiPost: apiPost2 } = await import("./client-JM3QBGR2.js");
54663
+ const { requireChatId: requireChatId2 } = await import("./env-WIAWLTDN.js");
54664
+ const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-UGMWOFQR.js");
54665
+ const { handleMetaError: handleMetaError2 } = await import("./shared-DJTAT7CM.js");
54665
54666
  try {
54666
54667
  const accountId = bareAccountId2(args8);
54667
54668
  const chatId = requireChatId2();
@@ -67633,10 +67634,63 @@ function figureSourced(match, knowledge2) {
67633
67634
  return new RegExp(`${number2}[^.!?\\n]{0,60}?${stem}|${stem}[^.!?\\n]{0,60}?${number2}`, "iu").test(knowledge2);
67634
67635
  });
67635
67636
  }
67637
+ var NUMBER_WORDS = {
67638
+ one: 1,
67639
+ two: 2,
67640
+ three: 3,
67641
+ four: 4,
67642
+ five: 5,
67643
+ six: 6,
67644
+ seven: 7,
67645
+ eight: 8,
67646
+ nine: 9,
67647
+ ten: 10,
67648
+ eleven: 11,
67649
+ twelve: 12,
67650
+ fifteen: 15,
67651
+ twenty: 20,
67652
+ thirty: 30,
67653
+ forty: 40,
67654
+ fifty: 50,
67655
+ sixty: 60,
67656
+ ninety: 90,
67657
+ hundred: 100,
67658
+ un: 1,
67659
+ uno: 1,
67660
+ una: 1,
67661
+ dos: 2,
67662
+ tres: 3,
67663
+ cuatro: 4,
67664
+ cinco: 5,
67665
+ seis: 6,
67666
+ siete: 7,
67667
+ ocho: 8,
67668
+ nueve: 9,
67669
+ diez: 10,
67670
+ once: 11,
67671
+ doce: 12,
67672
+ quince: 15,
67673
+ veinte: 20,
67674
+ treinta: 30,
67675
+ cuarenta: 40,
67676
+ cincuenta: 50,
67677
+ sesenta: 60,
67678
+ noventa: 90,
67679
+ cien: 100
67680
+ };
67681
+ var NUMBER_WORD = new RegExp(`(?<![\\p{L}])(${Object.keys(NUMBER_WORDS).join("|")})(?![\\p{L}])`, "giu");
67682
+ function withDigits(text3) {
67683
+ return text3.replace(NUMBER_WORD, (word) => String(NUMBER_WORDS[word.toLowerCase()]));
67684
+ }
67685
+ var SUPERLATIVE = new RegExp("(?<![\\p{L}])(the only|only one|#\\s?1|number one|n[\xBA\xB0o]\\.?\\s?1|the (?:best|fastest|cheapest|biggest|largest|lowest|highest|leading)|fastest|cheapest|el \xFAnico|la \xFAnica|los \xFAnicos|las \xFAnicas|el mejor|la mejor|los mejores|el m\xE1s \\p{L}+|la m\xE1s \\p{L}+|n\xFAmero 1|l\xEDder)(?![\\p{L}])", "giu");
67636
67686
  function unsourcedFigureLines(spec, knowledge2) {
67637
- return spec.copy.flatMap(
67638
- (line) => [...line.text.matchAll(CLAIMED_FIGURE)].some((match) => !figureSourced(match, knowledge2)) ? [line.text] : []
67639
- );
67687
+ const records = withDigits(knowledge2);
67688
+ const lower = knowledge2.toLowerCase();
67689
+ return spec.copy.flatMap((line) => {
67690
+ const figure = [...withDigits(line.text).matchAll(CLAIMED_FIGURE)].some((m) => !figureSourced(m, records));
67691
+ const superlative = [...line.text.matchAll(SUPERLATIVE)].some((m) => !lower.includes(m[0].toLowerCase()));
67692
+ return figure || superlative ? [line.text] : [];
67693
+ });
67640
67694
  }
67641
67695
  function proofProblems(spec, knowledge2) {
67642
67696
  const problems = [];
@@ -67658,7 +67712,7 @@ function proofProblems(spec, knowledge2) {
67658
67712
  }
67659
67713
  for (const text3 of unsourcedFigureLines(spec, knowledge2)) {
67660
67714
  problems.push(
67661
- `"${text3}" promises a figure the company's records (src/content, COMPANY.md) do not hold: say only what they record, or drop the figure.`
67715
+ `"${text3}" promises a figure or a superlative ("the only", "the fastest") the company's records (src/content, COMPANY.md) do not hold: say only what they record, or drop it.`
67662
67716
  );
67663
67717
  }
67664
67718
  return problems;
@@ -74819,6 +74873,10 @@ async function reviewStaticRun(opts) {
74819
74873
  const shape = staticRunShape(opts.parsed);
74820
74874
  const placements = canvasPlacements(opts.parsed) ?? safeAreaPlacements(opts.viewer);
74821
74875
  const masterFormat = staticMasterFormat(opts.parsed) ?? void 0;
74876
+ const glancing = opts.glance === false ? Promise.resolve(null) : glanceAtFinished(targets.images, opts.viewer ?? STRANGER, intended, opts.glance ?? gatewayGlanceModel(opts.onSpend)).catch(
74877
+ () => null
74878
+ );
74879
+ const comparing = opts.previous ? nearIdenticalFindings(targets.images, opts.previous).catch(() => []) : Promise.resolve([]);
74822
74880
  const review = await reviewRenderedStatic({
74823
74881
  images: targets.images,
74824
74882
  copy,
@@ -74839,8 +74897,9 @@ async function reviewStaticRun(opts) {
74839
74897
  ...opts.viewer ? { viewer: describeViewer(opts.viewer) } : {},
74840
74898
  onSpend: opts.onSpend
74841
74899
  });
74842
- const glance = review === null || opts.glance === false ? null : await glanceAtFinished(targets.images, opts.viewer ?? STRANGER, intended, opts.glance ?? gatewayGlanceModel(opts.onSpend));
74843
- const unchanged = review === null || !opts.previous ? [] : await nearIdenticalFindings(targets.images, opts.previous);
74900
+ const [glanced, compared] = await Promise.all([glancing, comparing]);
74901
+ const glance = review === null ? null : glanced;
74902
+ const unchanged = review === null ? [] : compared;
74844
74903
  const fresh = review === null ? null : [...review, ...glance ?? [], ...unchanged];
74845
74904
  const reviewed = fresh === null || !opts.settled ? fresh : carryUnchanged(fresh, opts.settled.review, await samePictureSizes(targets.images, opts.settled.images));
74846
74905
  const verdict2 = staticVerdict(reviewed);
@@ -80878,7 +80937,9 @@ function ideasHints(report) {
80878
80937
  return hints2;
80879
80938
  }
80880
80939
  function buildNext(ideas, count2 = BUILD_NEXT) {
80881
- return ideas.filter((i) => i.status === "idea" && i.problems.length === 0).slice(0, count2).map((i) => i.id);
80940
+ const ready = ideas.filter((i) => i.status === "idea" && i.problems.length === 0);
80941
+ const firstBet = ready.find((i) => i.evidence === "explore");
80942
+ return ready.filter((i) => i.evidence !== "explore" || i === firstBet).slice(0, count2).map((i) => i.id);
80882
80943
  }
80883
80944
  function compactIdea(check) {
80884
80945
  return {
@@ -81827,30 +81888,37 @@ async function viewerTemperature(root, adSet, awareness) {
81827
81888
  return viewerFromKnowledge({ personas: [], awareness }).temperature;
81828
81889
  }
81829
81890
  var asPlatform = (value2) => value2 === "linkedin" || value2 === "tiktok" ? value2 : "meta";
81830
- async function findCandidates(searches) {
81831
- for (const search of searches) {
81832
- const data = await apiPost("/api/ad-library/winners/search", search, {
81891
+ function liveReferenceDeps(root) {
81892
+ return {
81893
+ search: async (body) => (await apiPost("/api/ad-library/winners/search", body, {
81833
81894
  timeoutMs: SEARCH_TIMEOUT_MS2
81834
- }).catch(() => null);
81835
- const candidates = (data?.results ?? []).filter((r) => r.ad_id).slice(0, REFERENCE_CANDIDATES);
81895
+ }).catch(() => null))?.results ?? [],
81896
+ fit: (platform, adId) => fitReference(root, platform, adId)
81897
+ };
81898
+ }
81899
+ async function findCandidates(searches, deps) {
81900
+ const results = await Promise.all(searches.map((search) => deps.search(search).catch(() => [])));
81901
+ for (const found of results) {
81902
+ const candidates = found.filter((r) => r.ad_id).slice(0, REFERENCE_CANDIDATES);
81836
81903
  if (candidates.length > 0) return candidates;
81837
81904
  }
81838
81905
  return [];
81839
81906
  }
81840
- async function pickReference(root, searches) {
81841
- const candidates = (await findCandidates(searches)).slice(0, FITS_TRIED);
81907
+ async function pickReference(root, searches, deps = liveReferenceDeps(root)) {
81908
+ const candidates = (await findCandidates(searches, deps)).slice(0, FITS_TRIED);
81909
+ const fits = await Promise.all(candidates.map((c) => deps.fit(asPlatform(c.platform), String(c.ad_id))));
81842
81910
  let unchecked = null;
81843
81911
  let checked = 0;
81844
81912
  for (const [index, candidate] of candidates.entries()) {
81845
- const platform = asPlatform(candidate.platform);
81846
- const fit = await fitReference(root, platform, String(candidate.ad_id));
81913
+ const fit = fits[index];
81914
+ if (!fit) continue;
81847
81915
  if (!fit.ok) unchecked = fit.error;
81848
81916
  else checked += 1;
81849
81917
  if (!(fit.ok && fitsIdea(fit.fit))) continue;
81850
81918
  const layers = fit.fit.why_it_wins;
81851
81919
  return {
81852
81920
  adId: String(candidate.ad_id),
81853
- platform,
81921
+ platform: asPlatform(candidate.platform),
81854
81922
  ...candidate.advertiser_id ? { advertiserId: candidate.advertiser_id } : {},
81855
81923
  why: [layers.disguise, layers.trigger, layers.logic].filter(Boolean).join("; "),
81856
81924
  tried: index + 1
@@ -82261,6 +82329,11 @@ var ARGS13 = {
82261
82329
  type: "string",
82262
82330
  description: "With --run-id and no file: which of the run's outputs to save when it made several, by label (e.g. 4:5), slot, or number (1 = first).",
82263
82331
  required: false
82332
+ },
82333
+ approved: {
82334
+ type: "boolean",
82335
+ description: `The person's own message in this turn asked to save it ("make it and keep it"). Needed only for a version rendered in this same turn, which they have not seen yet; never pass it on your own judgment.`,
82336
+ required: false
82264
82337
  }
82265
82338
  };
82266
82339
  registerSchema({ command: "creatives.publish", description: DESCRIPTION11, args: ARGS13 });
@@ -82332,6 +82405,23 @@ function chooseOutput(run3, choice) {
82332
82405
  return found;
82333
82406
  }
82334
82407
  var EXTENSION = { "image/png": ".png", "image/jpeg": ".jpg", "image/webp": ".webp" };
82408
+ function turnStartedAt(turnId) {
82409
+ const match = turnId?.match(/:(\d+)$/);
82410
+ return match ? Number(match[1]) : void 0;
82411
+ }
82412
+ function refuseUnseen(run3, turnId, approved) {
82413
+ const started = turnStartedAt(turnId);
82414
+ if (approved || started === void 0 || run3.createdAt < started) return;
82415
+ throw new ApiError(
82416
+ "VALIDATION_ERROR",
82417
+ `Run ${run3.runId} was rendered in this turn, so the person has not seen it yet. Show it and save it once they approve it in a later message; pass --approved only when their own message asked to save it.`
82418
+ );
82419
+ }
82420
+ async function refuseUnseenFile(args8, deps) {
82421
+ if (!args8.runId || args8.turnId === void 0 || args8.approved === true) return;
82422
+ const run3 = await fetchRunRecord(args8.runId, deps.post);
82423
+ if (run3) refuseUnseen(run3, args8.turnId, false);
82424
+ }
82335
82425
  async function uploadRunOutput(args8, deps) {
82336
82426
  const run3 = await fetchRunRecord(args8.runId, deps.post);
82337
82427
  if (!run3) {
@@ -82340,6 +82430,7 @@ async function uploadRunOutput(args8, deps) {
82340
82430
  `No run "${args8.runId}" in this company's run history. Pass the image file instead.`
82341
82431
  );
82342
82432
  }
82433
+ refuseUnseen(run3, args8.turnId, args8.approved);
82343
82434
  const chosen = chooseOutput(run3, args8.output);
82344
82435
  const bytes = await (deps.download ?? downloadBytes)(String(chosen.url));
82345
82436
  if (sha256Hex(bytes) !== chosen.sha256) {
@@ -82369,6 +82460,7 @@ async function publishCreative(args8, deps = defaultImageApiDeps) {
82369
82460
  const descriptionContext = args8.context ?? `Static ad creative: ${title}`;
82370
82461
  let upload;
82371
82462
  if (args8.file) {
82463
+ await refuseUnseenFile(args8, deps);
82372
82464
  upload = await uploadLocalImage(
82373
82465
  {
82374
82466
  file: args8.file,
@@ -82379,7 +82471,16 @@ async function publishCreative(args8, deps = defaultImageApiDeps) {
82379
82471
  deps
82380
82472
  );
82381
82473
  } else if (args8.runId) {
82382
- upload = await uploadRunOutput({ runId: args8.runId, output: args8.output, descriptionContext }, deps);
82474
+ upload = await uploadRunOutput(
82475
+ {
82476
+ runId: args8.runId,
82477
+ output: args8.output,
82478
+ descriptionContext,
82479
+ turnId: args8.turnId,
82480
+ approved: args8.approved === true
82481
+ },
82482
+ deps
82483
+ );
82383
82484
  } else {
82384
82485
  throw new ApiError("VALIDATION_ERROR", "Pass the image file, or --run-id to save the run's own output");
82385
82486
  }
@@ -82465,7 +82566,12 @@ var publishCommand = defineCommand160({
82465
82566
  writeJson(await publishVideoCreative({ ...publishArgs, file }));
82466
82567
  return;
82467
82568
  }
82468
- const data = await publishCreative({ ...publishArgs, output: args8.output });
82569
+ const data = await publishCreative({
82570
+ ...publishArgs,
82571
+ output: args8.output,
82572
+ turnId: optionalTurnId(),
82573
+ approved: args8.approved === true
82574
+ });
82469
82575
  writeJson({ ok: true, data });
82470
82576
  } catch (err) {
82471
82577
  if (err instanceof ApiError) {