@koda-sl/baker-cli 0.133.0 → 0.133.3

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
@@ -23,6 +23,7 @@ import {
23
23
  generateCatalog,
24
24
  imageProfileFor,
25
25
  isPersistedAssetRef,
26
+ looksLikeHttpUrl,
26
27
  parseRefExpr,
27
28
  platformFormats,
28
29
  requireCredentialsFromEnv,
@@ -33,7 +34,7 @@ import {
33
34
  toModelSafeImage,
34
35
  ulid,
35
36
  validateCanvasDeep
36
- } from "./chunk-UBFU3E7L.js";
37
+ } from "./chunk-CIF62V7L.js";
37
38
  import {
38
39
  csvOrJson,
39
40
  daysAgoIso,
@@ -14862,7 +14863,7 @@ function resolveNode(node, baseDir) {
14862
14863
  return node;
14863
14864
  }
14864
14865
  function isResolvableRelative(value) {
14865
- return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !path3.isAbsolute(value);
14866
+ return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !looksLikeHttpUrl(value) && !path3.isAbsolute(value);
14866
14867
  }
14867
14868
 
14868
14869
  // src/commands/canvas/source-version.ts
@@ -20630,20 +20631,6 @@ function parseBudget(raw) {
20630
20631
  }
20631
20632
  function resolveModels2(args) {
20632
20633
  const pick = (flag, kind, fallback) => args[flag] ? String(args[flag]) : resolveModel2(kind, fallback);
20633
- let videoModel;
20634
- let videoRouteReason;
20635
- if (args["video-model"]) {
20636
- videoModel = resolveModel2("video_generate", String(args["video-model"]));
20637
- } else {
20638
- const route = routeVideoModel({
20639
- hasRealFace: Boolean(args["real-face"]),
20640
- needsIdentity: Boolean(args.identity),
20641
- needsMotionTransfer: Boolean(args["motion-transfer"]),
20642
- budget: parseBudget(args.budget)
20643
- });
20644
- videoModel = resolveModel2("video_generate", route.model);
20645
- videoRouteReason = route.reason;
20646
- }
20647
20634
  return {
20648
20635
  // Flash by default: ~2-3× faster per call than Pro, which keeps each
20649
20636
  // per-scene deconstruct step well inside the action time budget and turns a
@@ -20654,11 +20641,29 @@ function resolveModels2(args) {
20654
20641
  // Default to the strongest image model (matches the static-ad scaffold); the
20655
20642
  // frame generators need the most faithful text/identity reproduction. Override
20656
20643
  // with --image-model for a cheaper/faster pass.
20657
- imageModel: pick("image-model", "image_generate", "openai/gpt-5.4-image-2"),
20658
- videoModel: videoModel || DEFAULT_VIDEO_GENERATE_MODEL,
20659
- videoRouteReason
20644
+ imageModel: pick("image-model", "image_generate", "openai/gpt-5.4-image-2")
20660
20645
  };
20661
20646
  }
20647
+ function hasPhotorealCast(elements) {
20648
+ return Array.isArray(elements) && elements.some((e) => {
20649
+ const type = typeof e === "object" && e !== null ? e.type : void 0;
20650
+ return type === "person" || type === "animal";
20651
+ });
20652
+ }
20653
+ function resolveVideoModel(args, elements) {
20654
+ if (args["video-model"]) {
20655
+ return { videoModel: resolveModel2("video_generate", String(args["video-model"])) };
20656
+ }
20657
+ const photorealCast = hasPhotorealCast(elements);
20658
+ const route = routeVideoModel({
20659
+ hasRealFace: Boolean(args["real-face"]) || photorealCast,
20660
+ needsIdentity: Boolean(args.identity),
20661
+ needsMotionTransfer: Boolean(args["motion-transfer"]),
20662
+ budget: parseBudget(args.budget)
20663
+ });
20664
+ const reason = photorealCast && !args["real-face"] ? `${route.reason} \u2014 detected a photoreal on-camera cast, which Seedance's real-person filter would block` : route.reason;
20665
+ return { videoModel: resolveModel2("video_generate", route.model) || DEFAULT_VIDEO_GENERATE_MODEL, videoRouteReason: reason };
20666
+ }
20662
20667
  function buildDeconstructCanvas(videoPath, deconstructModel, opts) {
20663
20668
  const deconstructParams = { model: deconstructModel, mode: "full" };
20664
20669
  if (typeof opts.maxScenes === "number") deconstructParams.max_scenes = opts.maxScenes;
@@ -20779,7 +20784,7 @@ var scaffoldVideoCommand = defineCommand92({
20779
20784
  "video-model": { type: "string", description: "Override the video_generate model id for clips (skips the scored router)" },
20780
20785
  "real-face": {
20781
20786
  type: "boolean",
20782
- description: "Brief needs a real human likeness preserved \u2192 the router picks Veo (dodges the ByteDance real-person filter)."
20787
+ description: "The ad has a photoreal human face on camera \u2192 the router picks Veo (dodges the ByteDance real-person filter). Set this for ANY photoreal presenter/creator/testimonial cast \u2014 the filter blocks AI-GENERATED photoreal faces too, not just real ones."
20783
20788
  },
20784
20789
  "motion-transfer": {
20785
20790
  type: "boolean",
@@ -20838,7 +20843,7 @@ var scaffoldVideoCommand = defineCommand92({
20838
20843
  `
20839
20844
  );
20840
20845
  }
20841
- const { deconstructModel, selectModel, imageModel, videoModel, videoRouteReason } = resolveModels2(args);
20846
+ const { deconstructModel, selectModel, imageModel } = resolveModels2(args);
20842
20847
  const shotThreshold = args["shot-threshold"] ? Number(args["shot-threshold"]) : void 0;
20843
20848
  const shotCuts = await detectShotCutsBestEffort(videoPath, shotThreshold);
20844
20849
  const deconstructCanvas = buildDeconstructCanvas(videoPath, deconstructModel, {
@@ -20848,6 +20853,11 @@ var scaffoldVideoCommand = defineCommand92({
20848
20853
  shotCuts
20849
20854
  });
20850
20855
  const { blueprint, elements, transcript, creditsSpent } = await runAnalysisPasses(deconstructCanvas, selectModel);
20856
+ const { videoModel, videoRouteReason } = resolveVideoModel(args, elements);
20857
+ if (videoRouteReason && !args["video-model"] && !args["real-face"] && hasPhotorealCast(elements)) {
20858
+ process.stderr.write(`\u{1F3AC} Photoreal on-camera cast detected \u2192 generating clips on ${videoModel} (dodges Seedance's real-person filter).
20859
+ `);
20860
+ }
20851
20861
  await mkdir6(outDir, { recursive: true });
20852
20862
  const annotated = annotateBlueprintWithElements(blueprint, elements);
20853
20863
  await writeSceneFiles(outDir, annotated);
@@ -21017,12 +21027,12 @@ var scaffoldVideoCommand = defineCommand92({
21017
21027
  // on-brand color. The overlays inherit the reference's motion unless the
21018
21028
  // operator restyles easing/transition/accent from the brand's motion language.
21019
21029
  prompt_discipline: "Rewrite each scene with the six-decision structure (Route / Spec / Beats / Copy / Technique / Negatives): quote exact copy, give every beat a timestamp, and name the moves. Pull easing, transition (cut vs fade), pacing, and the accent moment from BRAND.md \xA7 Brand in Motion so the overlays move like THIS brand \u2014 not the reference's. If BRAND.md has no Brand-in-Motion section, seed it with brand-build first. See the creative-canvas-ads skill: references/prompt-anatomy.md + references/hyperframes/.",
21020
- // A photoreal on-camera person/animal on Seedance can trip ByteDance's
21021
- // real-person-likeness filter (422 content_policy_blocked, NON-retryable — no
21022
- // prompt reframe clears it). Surface the escape BEFORE the billed run so a
21023
- // face-heavy ad isn't discovered broken mid-render.
21030
+ // Photoreal on-camera casts auto-route to Veo above, so this only fires
21031
+ // when `--video-model bytedance/seedance-2.0` was EXPLICITLY forced despite
21032
+ // a person/animal cast overriding that safety route. Warn that every such
21033
+ // clip will hit ByteDance's real-person filter and burn a wasted attempt.
21024
21034
  ...report.elements.some((e) => e.type === "person" || e.type === "animal") && /seedance/i.test(videoModel) ? {
21025
- content_policy_risk: "This ad has a photoreal on-camera cast generating on Seedance. ByteDance's real-person-likeness filter can reject a photoreal AI face with a NON-retryable 422 (content_policy_blocked) \u2014 no prompt change clears it. If clips fail that way, regenerate on Veo (re-run with `--video-model google/veo-3.1-fast`) or make the frame less photoreal."
21035
+ content_policy_risk: "You FORCED Seedance (`--video-model bytedance/seedance-2.0`) on an ad with a photoreal on-camera cast. ByteDance's real-person filter will reject those clips (content_policy_blocked, E005) \u2014 no prompt change clears it. Each clip auto-recovers on Veo at render time so the run still completes, but you burn a wasted Seedance attempt per clip. Drop `--video-model` to let the scaffold route the cast to Veo up front, or make the frames less photorealistic."
21026
21036
  } : {},
21027
21037
  note: "Drop ONE real source image at each el_* [TODO] (reused across every frame that element appears in), confirm each voice_select casting, then `baker canvas validate` and `baker canvas run`. Running generates many billed image/video/audio assets \u2014 it is not free."
21028
21038
  }