@koda-sl/baker-cli 0.80.0 → 0.82.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/README.md +4 -0
- package/dist/{chunk-NBNUNCY7.js → chunk-KIL2ZJST.js} +38 -3
- package/dist/chunk-KIL2ZJST.js.map +1 -0
- package/dist/cli.js +33 -7
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.d.ts +1 -0
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-NBNUNCY7.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
defaultRegistry,
|
|
10
10
|
generateCatalog,
|
|
11
11
|
validateCanvasDeep
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-KIL2ZJST.js";
|
|
13
13
|
|
|
14
14
|
// src/cli.ts
|
|
15
15
|
import { defineCommand as defineCommand141, runMain } from "citty";
|
|
@@ -9443,7 +9443,7 @@ function buildMotionBoard(blueprint, sceneTurns) {
|
|
|
9443
9443
|
].sort((a, b) => a.at_s - b.at_s);
|
|
9444
9444
|
return {
|
|
9445
9445
|
scene: i,
|
|
9446
|
-
role: scene
|
|
9446
|
+
role: resolveSceneRole(scene, i, blueprint.scenes.length),
|
|
9447
9447
|
window_s: [round(start_s), round(end_s)],
|
|
9448
9448
|
storyboard_frames: [`s${i}_start`, `s${i}_end`],
|
|
9449
9449
|
spoken,
|
|
@@ -9480,22 +9480,44 @@ function inferNarrativeRole(index, total) {
|
|
|
9480
9480
|
if (index === total - 1) return "cta";
|
|
9481
9481
|
return "body";
|
|
9482
9482
|
}
|
|
9483
|
+
function resolveSceneRole(scene, index, total) {
|
|
9484
|
+
return scene.narrative_role?.trim() || inferNarrativeRole(index, total);
|
|
9485
|
+
}
|
|
9486
|
+
function findHookSceneIndex(blueprint) {
|
|
9487
|
+
const total = blueprint.scenes.length;
|
|
9488
|
+
return blueprint.scenes.findIndex((s, i) => resolveSceneRole(s, i, total) === "hook");
|
|
9489
|
+
}
|
|
9490
|
+
var HOOK_OPENER_CRITERIA = "statement not question; benefit by ~2s; first frame legible SOUND-OFF in ~1s (the feed plays muted); no bait-and-switch (the hook sets up the body)";
|
|
9491
|
+
function recraftTextForRole(role, sceneIndex) {
|
|
9492
|
+
if (role === "hook") {
|
|
9493
|
+
return `[RECRAFT HOOK \u2014 the #1 decision, but usually the LIGHTEST move wins: this hook already worked, so default to KEEPING it and building on top (swap only the specifics for ours). REBUILD only when it doesn't transfer \u2014 a claim we lack or a different funnel/awareness stage \u2014 by reaching for its deeper INNER MECHANIC and delivering that truthfully. DIAGNOSE (device + mechanic + stage) \u2192 DECIDE keep/adapt/rebuild \u2192 hold the opener to criteria: ${HOOK_OPENER_CRITERIA}. It lives on s${sceneIndex}_start (first frame) + the scene-${sceneIndex} overlay. See references/hook-craft.md + meta-ads-playbook \xA710/\xA739.]`;
|
|
9494
|
+
}
|
|
9495
|
+
if (role === "cta") {
|
|
9496
|
+
return "[RECRAFT CTA \u2014 the close: state what to do (where to go) + what to expect (offer/bundle/discount) for OUR brand; soft for top-of-funnel, hard for bottom. Do NOT render the reference's words. See references/script-craft.md.]";
|
|
9497
|
+
}
|
|
9498
|
+
return `[RECRAFT: rewrite this ${role} for OUR brand \u2014 true claims only; do NOT render the reference's words. See references/script-craft.md + meta-ads-playbook.]`;
|
|
9499
|
+
}
|
|
9483
9500
|
function buildScriptRecraft(blueprint) {
|
|
9484
9501
|
const total = blueprint.scenes.length;
|
|
9485
9502
|
return blueprint.scenes.map((scene, i) => {
|
|
9486
|
-
const role = scene
|
|
9503
|
+
const role = resolveSceneRole(scene, i, total);
|
|
9487
9504
|
const original = (scene.dialogue ?? []).map((d) => d.line?.trim()).filter((l) => Boolean(l)).join(" ");
|
|
9488
9505
|
return {
|
|
9489
9506
|
scene: i,
|
|
9490
9507
|
role,
|
|
9491
9508
|
original_line: original || null,
|
|
9492
|
-
recraft:
|
|
9509
|
+
recraft: recraftTextForRole(role, i)
|
|
9493
9510
|
};
|
|
9494
9511
|
});
|
|
9495
9512
|
}
|
|
9496
9513
|
function buildVideoTodo(report, overlayCount, floatingCount, opts, blueprint) {
|
|
9514
|
+
const hookSceneIndex = findHookSceneIndex(blueprint);
|
|
9515
|
+
const h = hookSceneIndex;
|
|
9497
9516
|
return {
|
|
9498
|
-
recraft_the_script_first:
|
|
9517
|
+
recraft_the_script_first: `VIDEO IS INSPIRATION, NOT A CLONE. Before rendering, re-craft the script (hook \u2192 body \u2192 CTA) for OUR brand \u2014 the reference already won in-market, but its hook is targeting and may not transfer.${h >= 0 ? " The HOOK is the #1 decision (see the `hook` todo);" : ""} ${h >= 0 ? "then work" : "Work"} the per-scene \`script_recraft\` checklist. References: references/hook-craft.md (the hook), references/script-craft.md (body/CTA) + the meta-ads-playbook skill.`,
|
|
9518
|
+
...h >= 0 ? {
|
|
9519
|
+
hook: `THE HOOK IS THE HIGHEST-LEVERAGE BEAT \u2014 the first frame + first 3\u20134s decide whether the ad is watched at all, and the hook is TARGETING. But highest-leverage does NOT mean always rewrite: this hook already won, so MOST OF THE TIME you KEEP it and build on top (swap only the specifics). REBUILD is the exception \u2014 only when it doesn't transfer (a claim we lack or a different funnel/awareness stage), and then by reaching for its deeper INNER MECHANIC and delivering that truthfully, not inventing a new opener from nothing. For scene ${h}: DIAGNOSE it (device + mechanic + what stage it targets), DECIDE keep/adapt/rebuild, then hold the opener to the criteria \u2014 ${HOOK_OPENER_CRITERIA}. The hook lives across s${h}_start (the scroll-stopping first frame), the scene-${h} overlay text, the s${h}_clip line, an optional ~0.5s micro-hook, and the ramp into the body. Full diagnose\u2192decide\u2192(keep/adapt/rebuild) discipline + the proven hook-type menu: references/hook-craft.md (+ meta-ads-playbook \xA710/\xA717/\xA739).`
|
|
9520
|
+
} : {},
|
|
9499
9521
|
script_recraft: buildScriptRecraft(blueprint),
|
|
9500
9522
|
edit_frames_in_place: "Each s<i>_start / s<i>_end node has its own editable params.prompt (FRAME DESCRIPTION). Edit per frame; the blueprint is only a shared style reference. Frames are CLEAN PLATES \u2014 they render no on-screen text; all text is the overlay HTML layer.",
|
|
9501
9523
|
frames_mode: opts.frames ?? "generate",
|
|
@@ -9527,7 +9549,7 @@ function buildVideoTodo(report, overlayCount, floatingCount, opts, blueprint) {
|
|
|
9527
9549
|
"Nail the PACK SHOT \u2014 the final product hero sells (motivated camera move, light matched to the rest of the ad).",
|
|
9528
9550
|
"Geometry/objects drifting frame to frame? A MAP beats a paragraph \u2014 drop a high-angle schematic still (marked positions) as an extra el_*/reference rather than adding more words.",
|
|
9529
9551
|
"Before/after (dry\u2192wet, skeptic\u2192believer) = two SEPARATE locked reference images \u2014 don't ask words to transform a subject mid-scene (cheaper and more reliable than re-rolling clips).",
|
|
9530
|
-
"The hook is VISUAL-FIRST: the feed plays muted, so scene
|
|
9552
|
+
"The hook is VISUAL-FIRST: the feed plays muted, so the hook scene's opening frame + its overlay text must read sound-off in ~1 second \u2014 don't bury the hook in the spoken line alone (meta-ads-playbook \xA739 visual-hooks-beat-audio, \xA748 the 1-second/feed-native rule). The hook is also the #1 re-craft decision \u2014 diagnose/decide/rebuild it against criteria in references/hook-craft.md (see the `hook` todo)."
|
|
9531
9553
|
]
|
|
9532
9554
|
},
|
|
9533
9555
|
transitions: "Scene-to-scene cuts the deconstruct flagged as fade/whip/zoom/dissolve/swipe are reproduced as an ffmpeg xfade at the boundary (everything else stays a hard cut). The overlap is consumed from extra generated footage, so the picture stays exactly on the audio timeline. To change a transition, edit the scene's `transition_out.type` in prompt.json and re-scaffold, or hand-edit the `spine` node's ffmpeg args. For a richer HERO cut (whip-pan, glitch, light-leak, gravitational-lens\u2026), the overlay layer can run a Hyperframes shader/CSS transition instead \u2014 see references/hyperframes/blueprints-and-transitions.md (pick 2\u20133 transition types total; the motion IS the handoff).",
|
|
@@ -9664,7 +9686,11 @@ function fail2(code, message) {
|
|
|
9664
9686
|
function resolveModels2(args) {
|
|
9665
9687
|
const pick = (flag, kind, fallback) => args[flag] ? String(args[flag]) : resolveModel2(kind, fallback);
|
|
9666
9688
|
return {
|
|
9667
|
-
|
|
9689
|
+
// Flash by default: ~2-3× faster per call than Pro, which keeps each
|
|
9690
|
+
// per-scene deconstruct step well inside the action time budget and turns a
|
|
9691
|
+
// ~9 min run into ~3-4 min. Override with --deconstruct-model
|
|
9692
|
+
// ~google/gemini-pro-latest for the densest extraction when speed matters less.
|
|
9693
|
+
deconstructModel: pick("deconstruct-model", "video_deconstruct", "~google/gemini-flash-latest"),
|
|
9668
9694
|
selectModel: pick("select-model", "text_generate", "~google/gemini-flash-latest"),
|
|
9669
9695
|
// Default to the strongest image model (matches the static-ad scaffold); the
|
|
9670
9696
|
// frame generators need the most faithful text/identity reproduction. Override
|