@koda-sl/baker-cli 0.443.0-dev.edb8d8767 → 0.445.0-dev.71ff4e44a

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/README.md CHANGED
@@ -5833,7 +5833,7 @@ cart, a trial, a donation, a registration); who it is for is reported but never
5833
5833
  `_definition.md`, else the one its `targetAdSet` reaches (as `baker ads meta adsets --audience` reads it), else
5834
5834
  the persona and `awareness` from the Knowledge, else a cold stranger. Not understood → exit 2 with
5835
5835
  `viewer_check_failed` and a `fix` that starts with the one rewrite answering a missed offer (`Do this: make the biggest words say "<message>"`) and names what the viewer missed. After two failures of one ad in a chat turn the check no longer holds it back: the command answers `ok: true` with `understood: false` and what was missed, and `baker canvas run` renders it, printing the miss. The casting check is asked alongside the viewer. Answers are cached per copy, scene and viewer.
5836
- `baker canvas run` makes the same check on a static ad before it spends (skipped for `--fix`, an autofix round, `--use-variant`, a re-layout and resumed runs, never for an edit of the words;
5836
+ Before either, a static ad whose scene quotes words, or names a price or a share, that the copy (or `scene_text`) does not hold is refused (`scene_words_not_in_copy`): the picture would print them and a correction round would erase them. An unreadable `prompt.json` names each wrong field in a line and shows that field's shape. `baker canvas run` makes the same check on a static ad before it spends (skipped for `--fix`, an autofix round, `--use-variant`, a re-layout and resumed runs, never for an edit of the words;
5837
5837
  `--skip-viewer-check` renders without it; a model outage lets the render through with a warning). `--full` adds
5838
5838
  the viewer's whole answer and how the viewer was chosen.
5839
5839
 
@@ -6931,6 +6931,48 @@ function unwrittenProblems(spec) {
6931
6931
  }
6932
6932
  return problems;
6933
6933
  }
6934
+ var QUOTED = /"([^"]{2,})"|“([^”]{2,})”|(?<![\p{L}\p{N}])['‘]([^'’]{2,}?)['’](?![\p{L}\p{N}])/gu;
6935
+ var FIGURE = /[£$€]\s?\d[\d.,]*|\d+(?:[.,]\d+)?\s?%/g;
6936
+ var comparable = (text2) => text2.normalize("NFD").replace(new RegExp("\\p{M}", "gu"), "").toLowerCase().replace(/[^\p{L}\p{N}£$€%]+/gu, " ").trim();
6937
+ function sceneWordProblems(spec) {
6938
+ const held = [...spec.copy.map((l) => l.text), ...spec.scene_text].map(comparable);
6939
+ const holds = (text2) => {
6940
+ const want = comparable(text2);
6941
+ return want.length === 0 || held.some((h) => h.includes(want));
6942
+ };
6943
+ const scene = [spec.scene.description, spec.scene.layout ?? ""].join(" ");
6944
+ const quoted = [...scene.matchAll(QUOTED)].map((m) => (m[1] ?? m[2] ?? m[3] ?? "").trim()).filter((q) => !holds(q));
6945
+ const figures = (scene.match(FIGURE) ?? []).map((f) => f.trim()).filter((f) => !holds(f));
6946
+ const unheld = [.../* @__PURE__ */ new Set([...quoted, ...figures])];
6947
+ if (unheld.length === 0) return [];
6948
+ return [
6949
+ `The scene asks the picture to show ${unheld.map((w) => `"${w}"`).join(", ")}, which the copy does not hold: the picture would print it and the run would then spend a round erasing it. Put each one the ad needs in \`copy\` as an \`in_scene\` line with \`on\` (the bill, the phone), or describe that surface without words (blank, blurred, face-down).`
6950
+ ];
6951
+ }
6952
+ var FIELD_SHAPES = {
6953
+ copy: '"copy": [{"text": "Book your free survey", "lettering": "designed", "role": "cta"}]',
6954
+ scene: '"scene": {"description": "a family on a sunny roof terrace", "look": "photo"}',
6955
+ colors: '"colors": [{"object": "the button", "name": "deep green", "hex": "#1F5C3A"}]',
6956
+ references: '"references": [{"id": "PRODUCT_1", "role": "product", "what": "the solar panel kit"}]',
6957
+ third_party_brands: '"third_party_brands": [{"name": "Trustpilot", "role": "proof", "logo": "BADGE_1"}]',
6958
+ mechanism: '"mechanism": [{"device": "a before and after", "why_it_works": "the change is seen, not told"}]',
6959
+ viewer: '"viewer": {"who": "homeowners with high energy bills"}'
6960
+ };
6961
+ function adSpecErrorText(e) {
6962
+ if (!(e instanceof z7.ZodError)) return e instanceof Error ? e.message : String(e);
6963
+ const items = /* @__PURE__ */ new Map();
6964
+ for (const issue of e.issues) {
6965
+ const [field2, index, key] = issue.path;
6966
+ const at2 = typeof index === "number" ? `${String(field2)}[${index}]` : issue.path.map(String).join(".") || "the spec";
6967
+ const what = issue.code === "unrecognized_keys" ? `no field ${issue.keys.map((k) => `"${k}"`).join(", ")}` : key !== void 0 && typeof index === "number" ? `"${String(key)}" ${issue.message.replace(/^Invalid input: /, "")}` : issue.message.replace(/^Invalid input: /, "");
6968
+ items.set(at2, [...items.get(at2) ?? [], what]);
6969
+ }
6970
+ const fields = [...new Set(e.issues.map((i) => String(i.path[0] ?? "")))].filter((f) => FIELD_SHAPES[f]);
6971
+ return [
6972
+ ...[...items].map(([at2, whats]) => `${at2}: ${[...new Set(whats)].join("; ")}`),
6973
+ ...fields.map((f) => `Shape: ${FIELD_SHAPES[f]}`)
6974
+ ].join("\n");
6975
+ }
6934
6976
  function readAdSpec(raw) {
6935
6977
  if (isAdSpec(raw)) return AdSpecSchema.parse(raw);
6936
6978
  const advertiser = raw?.reference?.advertiser;
@@ -14988,7 +15030,7 @@ async function videoDuration(video) {
14988
15030
  return null;
14989
15031
  }
14990
15032
  }
14991
- async function askGateway(model, parts, timeoutMs, spent) {
15033
+ async function askGateway(model, parts, timeoutMs, spent, reasoning) {
14992
15034
  const key = openRouterKey();
14993
15035
  if (!key) return null;
14994
15036
  try {
@@ -14998,7 +15040,8 @@ async function askGateway(model, parts, timeoutMs, spent) {
14998
15040
  body: JSON.stringify({
14999
15041
  model,
15000
15042
  messages: [{ role: "user", content: parts }],
15001
- usage: { include: true }
15043
+ usage: { include: true },
15044
+ ...reasoning ? { reasoning } : {}
15002
15045
  }),
15003
15046
  signal: AbortSignal.timeout(timeoutMs)
15004
15047
  });
@@ -15047,7 +15090,7 @@ async function askAboutStills(images, prompt, onSpend) {
15047
15090
  if (!hasOpenRouterKey()) return null;
15048
15091
  return await ask(images, prompt, (usage) => onSpend?.(usage));
15049
15092
  }
15050
- async function askAboutImages(model, images, prompt, onSpend, timeoutMs = 6e4) {
15093
+ async function askAboutImages(model, images, prompt, onSpend, timeoutMs = 6e4, reasoning) {
15051
15094
  if (!hasOpenRouterKey()) return null;
15052
15095
  return await askGateway(
15053
15096
  model,
@@ -15058,7 +15101,8 @@ async function askAboutImages(model, images, prompt, onSpend, timeoutMs = 6e4) {
15058
15101
  )
15059
15102
  ],
15060
15103
  timeoutMs,
15061
- (usage) => onSpend?.(usage)
15104
+ (usage) => onSpend?.(usage),
15105
+ reasoning
15062
15106
  );
15063
15107
  }
15064
15108
  async function askAboutText(model, prompt, onSpend) {
@@ -15222,7 +15266,9 @@ async function readTextBoxes(image, opts = {}) {
15222
15266
  return { status: "not_checked" };
15223
15267
  }
15224
15268
  for (let attempt = 0; attempt < 2; attempt++) {
15225
- const answer = await askAboutImages(TEXT_BOX_READER_MODEL, [jpeg], TEXT_BOX_PROMPT, opts.onSpend);
15269
+ const answer = await askAboutImages(TEXT_BOX_READER_MODEL, [jpeg], TEXT_BOX_PROMPT, opts.onSpend, 6e4, {
15270
+ effort: "minimal"
15271
+ });
15226
15272
  const boxes = textBoxesFromReader(answer);
15227
15273
  if (boxes) return { status: "read", boxes };
15228
15274
  }
@@ -18484,6 +18530,8 @@ export {
18484
18530
  conceptSummary,
18485
18531
  conceptProblems,
18486
18532
  unwrittenProblems,
18533
+ sceneWordProblems,
18534
+ adSpecErrorText,
18487
18535
  readAdSpec,
18488
18536
  withRenderedLettering,
18489
18537
  conceptClassOf,
@@ -18571,4 +18619,4 @@ export {
18571
18619
  defaultRegistry,
18572
18620
  createEngineFromEnv
18573
18621
  };
18574
- //# sourceMappingURL=chunk-APTNJ2EY.js.map
18622
+ //# sourceMappingURL=chunk-CYZ7H4F5.js.map