@koda-sl/baker-cli 0.151.0-dev.1a051172a → 0.151.0-dev.4932063cd
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 +3 -33
- package/dist/{chunk-JBDSJZBZ.js → chunk-S43JQWI2.js} +92 -14
- package/dist/chunk-S43JQWI2.js.map +1 -0
- package/dist/cli.js +483 -970
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-JBDSJZBZ.js.map +0 -1
package/README.md
CHANGED
|
@@ -300,22 +300,11 @@ When a query fails, the error includes a `fix` object with the exact corrected c
|
|
|
300
300
|
|
|
301
301
|
### `baker ads google changes`
|
|
302
302
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
Google keeps account history in two layers, and neither reaches past 90 days:
|
|
306
|
-
|
|
307
|
-
| Scope | Reach | What you get |
|
|
308
|
-
|-------------|---------|---------------------------------------------------------------------|
|
|
309
|
-
| `detail` | 30 days | What changed, old → new value, and who changed it |
|
|
310
|
-
| `summary` | 90 days | Which resources were added, changed or removed — no values, no user |
|
|
311
|
-
|
|
312
|
-
Beyond 90 days there is no API. Infer the change from a monthly spend trend per campaign
|
|
313
|
-
instead, or ask the user to check the change history in the Google Ads web UI.
|
|
303
|
+
Get recent change logs for an account.
|
|
314
304
|
|
|
315
305
|
```bash
|
|
316
306
|
baker ads google changes --customer-id 1234567890
|
|
317
307
|
baker ads google changes --customer-id 1234567890 --days 14 --resource-type CAMPAIGN
|
|
318
|
-
baker ads google changes --customer-id 1234567890 --days 60 --scope summary
|
|
319
308
|
```
|
|
320
309
|
|
|
321
310
|
**Flags:**
|
|
@@ -323,8 +312,7 @@ baker ads google changes --customer-id 1234567890 --days 60 --scope summary
|
|
|
323
312
|
| Flag | Description |
|
|
324
313
|
|-------------------|---------------------------------------------------------------|
|
|
325
314
|
| `--customer-id` | Google Ads customer ID. Falls back to `BAKER_GOOGLE_ADS_CUSTOMER_ID` env var. |
|
|
326
|
-
| `--
|
|
327
|
-
| `--days` | Lookback days (default 7). Max 30 with `detail`, 90 with `summary` |
|
|
315
|
+
| `--days` | Lookback days (default 7, max 90) |
|
|
328
316
|
| `--resource-type` | Filter: CAMPAIGN, AD_GROUP, AD_GROUP_AD, AD_GROUP_CRITERION |
|
|
329
317
|
| `--limit` | Max results (default 50) |
|
|
330
318
|
| `--output` | Format: `json` \| `csv` \| `jsonl` \| `md` |
|
|
@@ -3408,6 +3396,7 @@ Generate video. Async with polling. Two curated models.
|
|
|
3408
3396
|
| `first_frame` | image | no | Starting keyframe (image-to-video) |
|
|
3409
3397
|
| `last_frame` | image | no | Ending keyframe |
|
|
3410
3398
|
| `reference` | image | no | Alternative to `first_frame` when only one image is given |
|
|
3399
|
+
| `references` | image[] | no | Reference-to-video: several images used as visual guidance (this person, this product) instead of an exact opening frame. **Mutually exclusive with `first_frame`** — when both are wired the frame wins and these are ignored, so pick one mode. |
|
|
3411
3400
|
|
|
3412
3401
|
Accepted ref-image MIMEs vary by model — see per-model sections below.
|
|
3413
3402
|
|
|
@@ -4671,25 +4660,6 @@ baker landing critique spring-offer --full # also print advisory-tier findings
|
|
|
4671
4660
|
|
|
4672
4661
|
Output is the standard envelope `{ ok, data, hints }` with `data = { advisory, slug, overall, counts, dimensions, findings }`. `dimensions` scores seven design families (typography, color, borders_depth, motion, spacing, copy, integrity) 0–1 (higher is better); `counts` is the block/warn/advisory tally.
|
|
4673
4662
|
|
|
4674
|
-
## Brand Fonts (`baker brand fonts`)
|
|
4675
|
-
|
|
4676
|
-
Verifies that a brand's typefaces really load, and self-hosts them. A font that isn't actually available never announces itself — the browser substitutes its nearest fallback, so the page renders fine and is quietly off-brand. Reading a family name off a live site tells you what the CSS *asks for*, never what loads.
|
|
4677
|
-
|
|
4678
|
-
```bash
|
|
4679
|
-
baker brand fonts check # are the brand's fonts real?
|
|
4680
|
-
baker brand fonts fetch "DM Sans" # self-host, weights taken from global.css
|
|
4681
|
-
baker brand fonts fetch "Manrope" --weights 500,700 # self-host specific weights
|
|
4682
|
-
baker brand fonts fetch "Inter" --subsets latin,latin-ext # add accented-glyph coverage
|
|
4683
|
-
```
|
|
4684
|
-
|
|
4685
|
-
- **`check`** asks Google Fonts what it *actually* serves for every family and weight `src/styles/global.css` requests, and reports `requested` / `served` / `missing` plus the available unicode subsets. It exits 2 with `FONT_NOT_SERVED` when the brand asks for something Google won't serve, and distinguishes an unknown family name from a family that exists at other weights — the fix differs.
|
|
4686
|
-
- **Failures carry the numbers, so nothing needs a second call.** `check`'s error keeps the full per-family breakdown at `error.fix.families` (healthy families included, so a multi-family brand shows what not to touch), and both commands probe the standard weights to report the ones that *do* exist at `error.fix.served` — the remediation is "retry with one of these" rather than "run `check`", which would be the command that just failed.
|
|
4687
|
-
- **`fetch`** downloads the family into `src/brand/fonts/` and prints the `@font-face` block to paste above `@theme`. Defaults to the `latin` subset; `--subsets latin,latin-ext` adds accented-glyph coverage for Spanish and Portuguese copy. One file per weight *and* subset, since Google ships them separately and `unicode-range` is carried through verbatim.
|
|
4688
|
-
- **It does not edit `global.css` for you.** Paste the block, then drop that family from the Google `@import` — otherwise the page self-hosts *and* still calls Google. Record the weights in `src/brand/BRAND.md` in the same change.
|
|
4689
|
-
- **Licensing:** Google Fonts are open-licensed and safe to self-host. A client's own commercial typeface is not — confirm before re-hosting one.
|
|
4690
|
-
|
|
4691
|
-
Complements the offline `validate-brand-fonts` check that runs in the scaffold's `verify`: that one compares what `global.css` declares against what provides it, with no network. Only the network can answer whether Google really serves a given family and weight.
|
|
4692
|
-
|
|
4693
4663
|
## Help & Discovery
|
|
4694
4664
|
|
|
4695
4665
|
Every command supports `--help` for usage info:
|
|
@@ -1119,6 +1119,7 @@ var OPENROUTER_IMAGE_SIZE = ["1K", "2K", "4K"];
|
|
|
1119
1119
|
var OPENROUTER_IMAGE_SIZE_EXTENDED = ["0.5K", ...OPENROUTER_IMAGE_SIZE];
|
|
1120
1120
|
var OPENROUTER_IMAGE_QUALITY = ["auto", "low", "medium", "high"];
|
|
1121
1121
|
var SEEDANCE_DURATIONS = [4, 5, 6, 8, 10, 12, 15];
|
|
1122
|
+
var KLING_DURATIONS = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
|
|
1122
1123
|
var ELEVENLABS_OUTPUT_FORMATS = [
|
|
1123
1124
|
"mp3_22050_32",
|
|
1124
1125
|
"mp3_44100_32",
|
|
@@ -1412,7 +1413,7 @@ var MODEL_REGISTRY = {
|
|
|
1412
1413
|
prompt: { kind: "string" },
|
|
1413
1414
|
negative_prompt: { kind: "string" },
|
|
1414
1415
|
aspect_ratio: { kind: "string", enum: ["16:9", "9:16"] },
|
|
1415
|
-
resolution: { kind: "string", enum: ["720p", "1080p"] },
|
|
1416
|
+
resolution: { kind: "string", enum: ["720p", "1080p", "4K"] },
|
|
1416
1417
|
duration: { kind: "number", enum: [4, 6, 8] },
|
|
1417
1418
|
seed: { kind: "number" },
|
|
1418
1419
|
generate_audio: { kind: "boolean" },
|
|
@@ -1424,9 +1425,14 @@ var MODEL_REGISTRY = {
|
|
|
1424
1425
|
"kwaivgi/kling-v3.0-pro": {
|
|
1425
1426
|
// Motion-transfer / dynamic multi-shot beats. Reachable through the default
|
|
1426
1427
|
// OpenRouter gateway (generic video body — no google-vertex block), so it
|
|
1427
|
-
// needs no direct-provider exception.
|
|
1428
|
-
//
|
|
1429
|
-
//
|
|
1428
|
+
// needs no direct-provider exception. `cfg_scale` trades prompt adherence
|
|
1429
|
+
// vs motion freedom; higher = closer to prompt.
|
|
1430
|
+
//
|
|
1431
|
+
// Params below are the ones OpenRouter actually advertises for this model
|
|
1432
|
+
// (GET /api/v1/videos/models). Three were wrong before and each was a free
|
|
1433
|
+
// 400 or a silently unsupported knob: it renders 720p ONLY (1080p was
|
|
1434
|
+
// offered and rejected), it takes ANY duration from 3-15s (we allowed just
|
|
1435
|
+
// 5 and 10), and it does not support `seed` at all.
|
|
1430
1436
|
label: "Kling 3.0",
|
|
1431
1437
|
inputs: [],
|
|
1432
1438
|
optional_inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
|
|
@@ -1436,10 +1442,9 @@ var MODEL_REGISTRY = {
|
|
|
1436
1442
|
// over-length prompt fails validate (free) not the billed call.
|
|
1437
1443
|
prompt: { kind: "string", maxLength: 2500 },
|
|
1438
1444
|
negative_prompt: { kind: "string" },
|
|
1439
|
-
aspect_ratio: { kind: "string", enum: ["
|
|
1440
|
-
resolution: { kind: "string", enum: ["720p"
|
|
1441
|
-
duration: { kind: "number", enum:
|
|
1442
|
-
seed: { kind: "number" },
|
|
1445
|
+
aspect_ratio: { kind: "string", enum: ["16:9", "9:16", "1:1"] },
|
|
1446
|
+
resolution: { kind: "string", enum: ["720p"] },
|
|
1447
|
+
duration: { kind: "number", enum: KLING_DURATIONS },
|
|
1443
1448
|
generate_audio: { kind: "boolean" },
|
|
1444
1449
|
cfg_scale: { kind: "number", min: 0, max: 1 }
|
|
1445
1450
|
}
|
|
@@ -1455,7 +1460,7 @@ var MODEL_REGISTRY = {
|
|
|
1455
1460
|
prompt: { kind: "string" },
|
|
1456
1461
|
negative_prompt: { kind: "string" },
|
|
1457
1462
|
aspect_ratio: { kind: "string", enum: ["16:9", "9:16"] },
|
|
1458
|
-
resolution: { kind: "string", enum: ["720p", "1080p"] },
|
|
1463
|
+
resolution: { kind: "string", enum: ["720p", "1080p", "4K"] },
|
|
1459
1464
|
duration: { kind: "number", enum: [4, 6, 8] },
|
|
1460
1465
|
seed: { kind: "number" },
|
|
1461
1466
|
generate_audio: { kind: "boolean" },
|
|
@@ -1777,6 +1782,58 @@ function validateValue(key, value, schema, model) {
|
|
|
1777
1782
|
}
|
|
1778
1783
|
}
|
|
1779
1784
|
|
|
1785
|
+
// ../canvas-contract/src/videoCost.ts
|
|
1786
|
+
var CREDITS_PER_USD = 100;
|
|
1787
|
+
var SEEDANCE_USD_PER_SECOND = {
|
|
1788
|
+
"480p": 0.18,
|
|
1789
|
+
"720p": 0.5,
|
|
1790
|
+
"1080p": 0.62,
|
|
1791
|
+
"4k": 0.62
|
|
1792
|
+
};
|
|
1793
|
+
var DEFAULT_VIDEO_RESOLUTION = "720p";
|
|
1794
|
+
var DEFAULT_VIDEO_DURATION_S = 5;
|
|
1795
|
+
function isSeedanceModel(model) {
|
|
1796
|
+
return model.startsWith("bytedance/seedance");
|
|
1797
|
+
}
|
|
1798
|
+
var FALLBACK_USD_PER_SECOND = 0.5;
|
|
1799
|
+
function seedanceUsdPerSecond(resolution) {
|
|
1800
|
+
return SEEDANCE_USD_PER_SECOND[resolution ?? DEFAULT_VIDEO_RESOLUTION] ?? FALLBACK_USD_PER_SECOND;
|
|
1801
|
+
}
|
|
1802
|
+
var USD_PER_SECOND = {
|
|
1803
|
+
// Kling publishes one flat rate across every resolution and mode.
|
|
1804
|
+
"kwaivgi/kling-v3.0-pro": { silent: 0.112, audio: 0.168 },
|
|
1805
|
+
// Veo prices 4K far above the base tier — and 4K is a selectable resolution,
|
|
1806
|
+
// so folding it into the base rate under-quotes the dearest clip we can make.
|
|
1807
|
+
"google/veo-3.1": {
|
|
1808
|
+
silent: 0.2,
|
|
1809
|
+
audio: 0.4,
|
|
1810
|
+
byResolution: { "4K": { silent: 0.4, audio: 0.6 } }
|
|
1811
|
+
},
|
|
1812
|
+
"google/veo-3.1-fast": {
|
|
1813
|
+
silent: 0.1,
|
|
1814
|
+
audio: 0.12,
|
|
1815
|
+
byResolution: {
|
|
1816
|
+
"720p": { silent: 0.08, audio: 0.1 },
|
|
1817
|
+
"4K": { silent: 0.25, audio: 0.3 }
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
};
|
|
1821
|
+
function estimateVideoCostUsd({ model, duration, resolution, generateAudio }) {
|
|
1822
|
+
const seconds = duration ?? DEFAULT_VIDEO_DURATION_S;
|
|
1823
|
+
if (isSeedanceModel(model)) return seedanceUsdPerSecond(resolution) * seconds;
|
|
1824
|
+
const published = USD_PER_SECOND[model];
|
|
1825
|
+
if (published) {
|
|
1826
|
+
const rate = (resolution ? published.byResolution?.[resolution] : void 0) ?? published;
|
|
1827
|
+
return (generateAudio ? rate.audio : rate.silent) * seconds;
|
|
1828
|
+
}
|
|
1829
|
+
const dearestKnownRate = Math.max(...Object.values(SEEDANCE_USD_PER_SECOND));
|
|
1830
|
+
return dearestKnownRate * seconds;
|
|
1831
|
+
}
|
|
1832
|
+
function estimateVideoCredits(input) {
|
|
1833
|
+
const credits = estimateVideoCostUsd(input) * CREDITS_PER_USD;
|
|
1834
|
+
return Math.ceil(Number(credits.toFixed(6)));
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1780
1837
|
// src/engine/lib/concurrency.ts
|
|
1781
1838
|
var DEFAULT_CONCURRENCY = 8;
|
|
1782
1839
|
function resolveConcurrency(...candidates) {
|
|
@@ -2573,7 +2630,7 @@ function looksLikeHttpUrl(value) {
|
|
|
2573
2630
|
var VEO_PERSON_GENERATION = "allow_adult";
|
|
2574
2631
|
var VEO_NEGATIVE_PROMPT = "subtitles, captions, on-screen text, watermark, logo, warped face, distorted hands, extra fingers, low quality";
|
|
2575
2632
|
var VEO_DURATIONS = [4, 6, 8];
|
|
2576
|
-
var
|
|
2633
|
+
var KLING_DURATIONS2 = [5, 10];
|
|
2577
2634
|
var KLING_NEGATIVE_PROMPT = "warped face, distorted hands, extra fingers, morphing, flicker, on-screen text, watermark, low quality";
|
|
2578
2635
|
var KLING_CFG_SCALE = 0.7;
|
|
2579
2636
|
var SPEAKS_PROSE = (line) => `The person speaks to camera; lip-sync follows the dialogue verbatim, with delivery and emotion carried in the wording itself (no bracketed cues). Dialogue: "${line}"`;
|
|
@@ -2619,7 +2676,7 @@ var KLING_PROFILE = {
|
|
|
2619
2676
|
// Kling takes a negative_prompt PARAM instead (paramDefaults).
|
|
2620
2677
|
keyframeInstruction: "Preserve the composition and colors of the first frame; animate the motion described.",
|
|
2621
2678
|
wordBudget: 200,
|
|
2622
|
-
durationSet:
|
|
2679
|
+
durationSet: KLING_DURATIONS2,
|
|
2623
2680
|
paramDefaults: { negative_prompt: KLING_NEGATIVE_PROMPT, cfg_scale: KLING_CFG_SCALE }
|
|
2624
2681
|
};
|
|
2625
2682
|
function clipProfileFor(modelId) {
|
|
@@ -7453,12 +7510,33 @@ var videoGenerateNode = delegated({
|
|
|
7453
7510
|
inputs: z28.object({
|
|
7454
7511
|
first_frame: ImageRef.optional(),
|
|
7455
7512
|
last_frame: ImageRef.optional(),
|
|
7456
|
-
reference: ImageRef.optional()
|
|
7513
|
+
reference: ImageRef.optional(),
|
|
7514
|
+
/**
|
|
7515
|
+
* Reference-to-video: several images the model uses as visual guidance
|
|
7516
|
+
* (this person, this product) instead of an exact opening frame. Mutually
|
|
7517
|
+
* exclusive with `first_frame` — OpenRouter treats a request carrying both
|
|
7518
|
+
* as image-to-video and ignores these, so wire one or the other.
|
|
7519
|
+
*/
|
|
7520
|
+
references: z28.array(ImageRef).optional()
|
|
7457
7521
|
}).loose(),
|
|
7458
7522
|
params: VideoGenerateParams,
|
|
7459
7523
|
outputs: z28.object({ video: VideoRef }).strict(),
|
|
7460
7524
|
outputKinds: { video: "video" },
|
|
7461
|
-
|
|
7525
|
+
// Priced from the shared contract, so `validate`'s quote and the charge the
|
|
7526
|
+
// backend applies come from ONE table. A flat number here under-quoted a
|
|
7527
|
+
// 1080p 8s clip by ~10x, and the agent reads this out to the user as "this
|
|
7528
|
+
// will cost N" before spending it.
|
|
7529
|
+
cost: ({ params }) => ({
|
|
7530
|
+
credits: estimateVideoCredits({
|
|
7531
|
+
model: params.model,
|
|
7532
|
+
duration: params.duration,
|
|
7533
|
+
resolution: params.resolution,
|
|
7534
|
+
// Audio bills at a separate, higher rate on every model that offers it
|
|
7535
|
+
// (Veo 3.1 doubles), so omitting it quotes half the real cost.
|
|
7536
|
+
generateAudio: params.generate_audio
|
|
7537
|
+
}),
|
|
7538
|
+
seconds_estimate: 120
|
|
7539
|
+
})
|
|
7462
7540
|
});
|
|
7463
7541
|
|
|
7464
7542
|
// src/engine/nodes/remote/videoBackgroundRemove.ts
|
|
@@ -7941,4 +8019,4 @@ export {
|
|
|
7941
8019
|
defaultRegistry,
|
|
7942
8020
|
createEngineFromEnv
|
|
7943
8021
|
};
|
|
7944
|
-
//# sourceMappingURL=chunk-
|
|
8022
|
+
//# sourceMappingURL=chunk-S43JQWI2.js.map
|