@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 +1 -1
- package/dist/{chunk-APTNJ2EY.js → chunk-CYZ7H4F5.js} +54 -6
- package/dist/chunk-CYZ7H4F5.js.map +1 -0
- package/dist/cli.js +38 -12
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-APTNJ2EY.js.map +0 -1
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-
|
|
18622
|
+
//# sourceMappingURL=chunk-CYZ7H4F5.js.map
|