@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/README.md +6 -3
- package/dist/{chunk-UBFU3E7L.js → chunk-CIF62V7L.js} +52 -16
- package/dist/chunk-CIF62V7L.js.map +1 -0
- package/dist/cli.js +36 -26
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-UBFU3E7L.js.map +0 -1
package/README.md
CHANGED
|
@@ -3361,7 +3361,7 @@ Ref-image MIMEs: `image/png`, `image/jpeg`, `image/webp`, `image/gif` (via OpenR
|
|
|
3361
3361
|
> - **gpt-image** (default frames): clean-plate exclusions placed **LAST** (OpenAI weights early text as composition), an explicit `photorealistic` cue, identity-critical reference **first**, and `quality=high` (gpt-image-2 forces high input fidelity automatically — the `input_fidelity` param is deliberately **not** sent). Gemini keeps exclusions inline; Recraft drops the photoreal cue.
|
|
3362
3362
|
> - New advisories: `VIDEO_RAW_FACE_KEYFRAME` (a Seedance clip animating a RAW ingested image — real-person 422 risk), `IMAGE_PROMPT_PROFILE_MISSING`, `VIDEO_PROMPT_PROFILE_MISSING`.
|
|
3363
3363
|
|
|
3364
|
-
> **Content-policy blocks are deterministic, not flaky.** ByteDance's Seedance rejects any first/last frame that reads as a real-person likeness (even an AI-generated face) — surfaced as `content_policy_blocked` (HTTP 422, **non-retryable**). This is ByteDance's upstream filter, so it fires on **any** reseller (Replicate or otherwise) — a provider swap does **not** route around it.
|
|
3364
|
+
> **Content-policy blocks are deterministic, not flaky — and now auto-recover.** ByteDance's Seedance rejects any first/last frame that reads as a real-person likeness (even an AI-generated face) — surfaced as `content_policy_blocked` (HTTP 422/`E005` "flagged as sensitive", **non-retryable on the same model**). This is ByteDance's upstream filter, so it fires on **any** reseller (Replicate or otherwise) — a provider swap does **not** route around it. **When a Seedance `video_generate` clip is blocked, the backend automatically re-renders that same clip on `google/veo-3.1-fast` (`person_generation: allow_adult`) — the one curated model that clears the filter — so the run still completes.** The Seedance attempt is never billed (its output was never finalized); only the Veo render is charged. To skip that wasted first attempt entirely (and control look/cost), scaffold a photoreal-cast ad directly on Veo up front (`--real-face`, which also covers AI-generated photoreal faces), or make the source frame less photorealistic.
|
|
3365
3365
|
|
|
3366
3366
|
---
|
|
3367
3367
|
|
|
@@ -3966,7 +3966,7 @@ baker canvas run ./reference-ad.video.canvas.json
|
|
|
3966
3966
|
| `--select-model <id>` | `~google/gemini-flash-latest` | Override the element-selection `text_generate` model. |
|
|
3967
3967
|
| `--image-model <id>` | `openai/gpt-5.4-image-2` | Override the per-frame `image_generate` model (defaults to the strongest, matching `scaffold-static-ad`). |
|
|
3968
3968
|
| `--video-model <id>` | scored router | Override the `video_generate` model **and skip the router**. Curated roster: `bytedance/seedance-2.0` (workhorse), `google/veo-3.1` (cine ceiling + real-face), `google/veo-3.1-fast` (cheap Veo), `kwaivgi/kling-v3.0-pro` (motion-transfer). |
|
|
3969
|
-
| `--real-face` |
|
|
3969
|
+
| `--real-face` | auto-detected | Force the Veo route for a photoreal human presenter (dodges the ByteDance real-person filter). **Usually unnecessary** — the scaffold auto-detects a photoreal on-camera person/animal cast from the deconstruct and routes it to Veo on its own; set this only to force it when the cast isn't detected. Covers AI-generated photoreal faces too, not just real ones. |
|
|
3970
3970
|
| `--motion-transfer` | off | Motion driven from a reference / hyper-dynamic → the router picks Kling. |
|
|
3971
3971
|
| `--identity` | off | Same character/product across clips → the router picks the Seedance workhorse. |
|
|
3972
3972
|
| `--budget <tier>` | `standard` | Router cost posture: `economy` (cheap Veo-fast tier) / `standard` / `premium`. |
|
|
@@ -3975,7 +3975,10 @@ baker canvas run ./reference-ad.video.canvas.json
|
|
|
3975
3975
|
**Scored model router.** When `--video-model` is omitted, a small weighted scorer picks from the curated
|
|
3976
3976
|
roster and prints the choice as `models.video_route_reason` in the run report (mirroring Higgsfield's
|
|
3977
3977
|
`models_explore`). Real-face → Veo, motion-transfer → Kling, else the Seedance workhorse; `--budget economy`
|
|
3978
|
-
shifts a Veo pick to the fast tier. The
|
|
3978
|
+
shifts a Veo pick to the fast tier. **The router runs after the deconstruct, so a photoreal on-camera
|
|
3979
|
+
person/animal cast is auto-detected and routed to Veo up front** — that cast would be blocked on Seedance by
|
|
3980
|
+
ByteDance's real-person filter, so picking Seedance would only burn a wasted attempt before the runtime
|
|
3981
|
+
auto-fallback re-renders it on Veo anyway. The scaffolder also bakes **per-intent param recipes** so the hero/reveal
|
|
3979
3982
|
beat claims the 1080p cine ceiling automatically and a Kling hook beat maxes prompt adherence.
|
|
3980
3983
|
|
|
3981
3984
|
Each scene is captured in a **shoot mode** — `ugc_selfie` (talking heads, the default look), `ugc_broll`, `studio_product` (pack shot), `lifestyle_cinematic`, or `screen_ui`. The scaffold derives one per scene (UGC by default; the cinematic and screen lanes are opt-in) and bakes its capture block into the frame and a camera default into the clip; override per scene with a `shoot_mode` field in that scene's `scenes/sNN.json`. Capture aesthetic + depth-of-field follow the mode (UGC stays flat; studio/lifestyle allow shallow DoF). Clips also carry **diegetic native audio** — the scene's own ambience described in the Seedance prompt, never music (the music bed is a separate, ducked track); set a scene's `ambient` field to steer it.
|
|
@@ -2488,6 +2488,11 @@ import { readFile as readFile2 } from "fs/promises";
|
|
|
2488
2488
|
import path3 from "path";
|
|
2489
2489
|
import { z as z2 } from "zod";
|
|
2490
2490
|
|
|
2491
|
+
// src/engine/lib/url.ts
|
|
2492
|
+
function looksLikeHttpUrl(value) {
|
|
2493
|
+
return typeof value === "string" && /^https?:\/\//i.test(value.trim());
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2491
2496
|
// src/engine/scaffold/lib/prompt-profiles.ts
|
|
2492
2497
|
var VEO_PERSON_GENERATION = "allow_adult";
|
|
2493
2498
|
var VEO_NEGATIVE_PROMPT = "subtitles, captions, on-screen text, watermark, logo, warped face, distorted hands, extra fingers, low quality";
|
|
@@ -2720,7 +2725,8 @@ var STAGE_CODES = {
|
|
|
2720
2725
|
ODD_DIMENSIONS: "VIDEO_ODD_DIMENSIONS",
|
|
2721
2726
|
REGION_DROPPED: "VIDEO_REGION_DROPPED",
|
|
2722
2727
|
OVERLAY_OUT_OF_BOUNDS: "VIDEO_OVERLAY_OUT_OF_BOUNDS",
|
|
2723
|
-
ORPHAN_NODE: "ORPHAN_NODE"
|
|
2728
|
+
ORPHAN_NODE: "ORPHAN_NODE",
|
|
2729
|
+
INGEST_PATH_URL_HEALED: "INGEST_PATH_URL_HEALED"
|
|
2724
2730
|
};
|
|
2725
2731
|
var SPAN_MODEL_SLACK_S = 0.25;
|
|
2726
2732
|
var VIDEO_TIME_SLACK_S = 0.75;
|
|
@@ -2777,6 +2783,7 @@ function validateCanvas(input, registry) {
|
|
|
2777
2783
|
checkUnknownNodeTypes(ctx);
|
|
2778
2784
|
if (issues.some((i) => i.code === STAGE_CODES.UNKNOWN_NODE)) return { ok: false, issues };
|
|
2779
2785
|
checkAllParams(ctx);
|
|
2786
|
+
checkIngestPathUrlHeals(ctx);
|
|
2780
2787
|
checkAllModelParams(ctx);
|
|
2781
2788
|
checkAllRefs(ctx);
|
|
2782
2789
|
checkAllModelInputs(ctx);
|
|
@@ -2899,6 +2906,22 @@ function checkAllParams(ctx) {
|
|
|
2899
2906
|
pushZodIssues(ctx.issues, parsed.error, `nodes[${i}].params`, STAGE_CODES.PARAMS, n.id, n.type);
|
|
2900
2907
|
}
|
|
2901
2908
|
}
|
|
2909
|
+
function checkIngestPathUrlHeals(ctx) {
|
|
2910
|
+
for (let i = 0; i < ctx.canvas.nodes.length; i++) {
|
|
2911
|
+
const n = ctx.canvas.nodes[i];
|
|
2912
|
+
if (!n || n.type !== "ingest") continue;
|
|
2913
|
+
const params = n.params ?? {};
|
|
2914
|
+
if (params.source !== "path" || !looksLikeHttpUrl(params.path)) continue;
|
|
2915
|
+
ctx.issues.push({
|
|
2916
|
+
path: `nodes[${i}].params.source`,
|
|
2917
|
+
code: STAGE_CODES.INGEST_PATH_URL_HEALED,
|
|
2918
|
+
message: `ingest "${n.id}" declares source:"path" but its value is a URL \u2014 running it as source:"url". Update the canvas JSON to source:"url" so it matches what baker runs.`,
|
|
2919
|
+
severity: "warning",
|
|
2920
|
+
node_id: n.id,
|
|
2921
|
+
node_type: n.type
|
|
2922
|
+
});
|
|
2923
|
+
}
|
|
2924
|
+
}
|
|
2902
2925
|
function checkAllModelParams(ctx) {
|
|
2903
2926
|
for (let i = 0; i < ctx.canvas.nodes.length; i++) {
|
|
2904
2927
|
const n = ctx.canvas.nodes[i];
|
|
@@ -4534,18 +4557,30 @@ function mapClientError(ctx, e) {
|
|
|
4534
4557
|
// src/engine/nodes/ingest.ts
|
|
4535
4558
|
var execFile = promisify(execFileCb);
|
|
4536
4559
|
var ExpectEnum = z5.enum(["image", "video", "audio", "text", "json", "font"]);
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4560
|
+
function coercePathUrlToUrl(input) {
|
|
4561
|
+
if (!input || typeof input !== "object") return input;
|
|
4562
|
+
const obj = input;
|
|
4563
|
+
if (obj.source === "path" && looksLikeHttpUrl(obj.path)) {
|
|
4564
|
+
const { path: _path, ...rest } = obj;
|
|
4565
|
+
return { ...rest, source: "url", url: obj.path.trim() };
|
|
4566
|
+
}
|
|
4567
|
+
return input;
|
|
4568
|
+
}
|
|
4569
|
+
var IngestParams = z5.preprocess(
|
|
4570
|
+
coercePathUrlToUrl,
|
|
4571
|
+
z5.discriminatedUnion("source", [
|
|
4572
|
+
z5.object({
|
|
4573
|
+
source: z5.literal("url"),
|
|
4574
|
+
url: z5.string().url(),
|
|
4575
|
+
expect: ExpectEnum
|
|
4576
|
+
}).strict(),
|
|
4577
|
+
z5.object({
|
|
4578
|
+
source: z5.literal("path"),
|
|
4579
|
+
path: z5.string().min(1),
|
|
4580
|
+
expect: ExpectEnum
|
|
4581
|
+
}).strict()
|
|
4582
|
+
])
|
|
4583
|
+
);
|
|
4549
4584
|
var IngestInputs = z5.object({}).strict();
|
|
4550
4585
|
var IngestOutputs = z5.object({ asset: AssetRef }).strict();
|
|
4551
4586
|
var RAW_TEXT_EXTENSIONS = [".txt", ".md"];
|
|
@@ -7272,8 +7307,8 @@ var videoGenerateNode = delegated({
|
|
|
7272
7307
|
id: "video_generate",
|
|
7273
7308
|
version: "2.0.0",
|
|
7274
7309
|
category: "video",
|
|
7275
|
-
summary: "Generate video for ad creatives. Curated roster: `bytedance/seedance-2.0` (identity/product workhorse), `google/veo-3.1` (photoreal cine ceiling +
|
|
7276
|
-
when_to_use: "Use `bytedance/seedance-2.0` for identity/product output.
|
|
7310
|
+
summary: "Generate video for ad creatives. Curated roster: `bytedance/seedance-2.0` (identity/product workhorse, NO photoreal human faces), `google/veo-3.1` (photoreal cine ceiling + the human-face model), `google/veo-3.1-fast` (cheap Veo iteration), `kwaivgi/kling-3.0` (motion-transfer/dynamic). Async with polling.",
|
|
7311
|
+
when_to_use: "Use `bytedance/seedance-2.0` for identity/product output WITHOUT a photoreal human face on camera. Any clip whose frame shows a photoreal human face \u2014 a UGC creator, presenter, or testimonial speaker, REAL OR AI-GENERATED \u2014 must use `google/veo-3.1`: ByteDance's filter rejects photoreal human faces on Seedance (content_policy_blocked/E005), and a synthetic AI face does NOT clear it. Use `google/veo-3.1-fast` while iterating to keep cost low; `kwaivgi/kling-3.0` for motion-transfer/hyper-dynamic beats. `baker canvas scaffold-video` auto-routes a photoreal cast to Veo; a Seedance clip blocked at runtime also auto-recovers on Veo. Each model gates its own durations/resolutions/aspect ratios in the registry \u2014 see the README per-model section.",
|
|
7277
7312
|
inputs: z28.object({
|
|
7278
7313
|
first_frame: ImageRef.optional(),
|
|
7279
7314
|
last_frame: ImageRef.optional(),
|
|
@@ -7744,6 +7779,7 @@ export {
|
|
|
7744
7779
|
REF_PREFIX,
|
|
7745
7780
|
parseRefExpr,
|
|
7746
7781
|
sha256Hex,
|
|
7782
|
+
looksLikeHttpUrl,
|
|
7747
7783
|
SEEDANCE_PROFILE,
|
|
7748
7784
|
clipProfileFor,
|
|
7749
7785
|
clipParamRecipe,
|
|
@@ -7762,4 +7798,4 @@ export {
|
|
|
7762
7798
|
defaultRegistry,
|
|
7763
7799
|
createEngineFromEnv
|
|
7764
7800
|
};
|
|
7765
|
-
//# sourceMappingURL=chunk-
|
|
7801
|
+
//# sourceMappingURL=chunk-CIF62V7L.js.map
|