@koda-sl/baker-cli 0.151.0-dev.4932063cd → 0.151.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 CHANGED
@@ -300,11 +300,22 @@ 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
- Get recent change logs for an account.
303
+ Read the change history of an account.
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.
304
314
 
305
315
  ```bash
306
316
  baker ads google changes --customer-id 1234567890
307
317
  baker ads google changes --customer-id 1234567890 --days 14 --resource-type CAMPAIGN
318
+ baker ads google changes --customer-id 1234567890 --days 60 --scope summary
308
319
  ```
309
320
 
310
321
  **Flags:**
@@ -312,8 +323,9 @@ baker ads google changes --customer-id 1234567890 --days 14 --resource-type CAMP
312
323
  | Flag | Description |
313
324
  |-------------------|---------------------------------------------------------------|
314
325
  | `--customer-id` | Google Ads customer ID. Falls back to `BAKER_GOOGLE_ADS_CUSTOMER_ID` env var. |
315
- | `--days` | Lookback days (default 7, max 90) |
316
- | `--resource-type` | Filter: CAMPAIGN, AD_GROUP, AD_GROUP_AD, AD_GROUP_CRITERION |
326
+ | `--scope` | `detail` (default, 30 days) or `summary` (90 days) |
327
+ | `--days` | Lookback days, counted inclusive of today (default 7). Max 30 with `detail`, 90 with `summary` |
328
+ | `--resource-type` | Filter: CAMPAIGN, CAMPAIGN_CRITERION, AD_GROUP, AD_GROUP_AD, AD_GROUP_CRITERION |
317
329
  | `--limit` | Max results (default 50) |
318
330
  | `--output` | Format: `json` \| `csv` \| `jsonl` \| `md` |
319
331
 
@@ -3396,7 +3408,6 @@ Generate video. Async with polling. Two curated models.
3396
3408
  | `first_frame` | image | no | Starting keyframe (image-to-video) |
3397
3409
  | `last_frame` | image | no | Ending keyframe |
3398
3410
  | `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. |
3400
3411
 
3401
3412
  Accepted ref-image MIMEs vary by model — see per-model sections below.
3402
3413
 
@@ -4658,8 +4669,29 @@ baker landing critique spring-offer --full # also print advisory-tier findings
4658
4669
  - **BRAND.md is the allowlist.** A font, hue, or ground that the client's `src/brand/BRAND.md` (mirrored into `src/styles/global.css` `@theme`, hex or oklch) commits is a decision, not a tell — matched values downgrade to advisory `brandDrift` so the critic never fights a real brand.
4659
4670
  - **Records a freshness snapshot** to `.cache/landing-critique/<slug>.json` (the source hash it scored). The publish quality gate reads it to enforce that every changed landing was critiqued and ships no block-tier tell. Re-run after edits so the snapshot stays fresh.
4660
4671
 
4672
+ - **Agent washing is a copy tell.** A page that claims autonomy ("fully autonomous", "while you sleep", "no human intervention") and never says anywhere what the buyer approves, overrides, or audits scores an `agent-washing` warn. One signal about oversight of the agent's actions — approval, review, override, undo/rollback, audit log, escalation — anywhere on the page clears it; the rule is page-scope precisely because the hero can defer the trust story to a section below it. Generic privacy boilerplate ("GDPR", "encrypted", "your data") deliberately does **not** clear it, since it appears in most footers and says nothing about who is in charge of the agent.
4673
+
4661
4674
  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.
4662
4675
 
4676
+ ## Brand Fonts (`baker brand fonts`)
4677
+
4678
+ 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.
4679
+
4680
+ ```bash
4681
+ baker brand fonts check # are the brand's fonts real?
4682
+ baker brand fonts fetch "DM Sans" # self-host, weights taken from global.css
4683
+ baker brand fonts fetch "Manrope" --weights 500,700 # self-host specific weights
4684
+ baker brand fonts fetch "Inter" --subsets latin,latin-ext # add accented-glyph coverage
4685
+ ```
4686
+
4687
+ - **`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.
4688
+ - **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.
4689
+ - **`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.
4690
+ - **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.
4691
+ - **Licensing:** Google Fonts are open-licensed and safe to self-host. A client's own commercial typeface is not — confirm before re-hosting one.
4692
+
4693
+ 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.
4694
+
4663
4695
  ## Help & Discovery
4664
4696
 
4665
4697
  Every command supports `--help` for usage info:
@@ -4698,6 +4730,7 @@ This CLI is designed for AI agent consumption. Key patterns:
4698
4730
  - **0.116.0**: `lead-forms create` models the full Campaign Manager form — `locale`, form banner image (`formImageId`/`formImageUrn`), predefined profile-field questions (validated enum) vs custom questions (`SINGLE_LINE_TEXT`/`MULTIPLE_CHOICE` with `options`, ≤3 custom), `privacyPolicyText`, disclosure `consents[]` (≤5), tracking `hiddenFields[]` (≤20), and `thankYou` confirmation CTA + landing/appointment link. Staged preview surfaces best-practice warnings (no qualifying question, no confirmation, no consent). No breaking flag changes.
4699
4731
  - **0.121.0**: `lead-forms create` drops the `privacyPolicyText` field — LinkedIn's versioned lead-form API has no privacy-policy-text slot, so it was silently discarded on publish. Use `legalDisclaimer` (shown under the form) or `consents[]` (disclosure checkboxes) instead. (Companion backend fix: staged lead-form questions were serialized in a shape LinkedIn dropped — they now publish correctly, and the staged preview lists each question.)
4700
4732
  - **0.119.0**: `draft amend`/`draft show` land on both `baker ads google` and `baker ads linkedin` — a generic JSON-merge-patch to update any staged op in place plus a full-payload receipt, replacing remove+recreate as the correction path. Google gains `assets update` and `asset-groups create|update` (Performance Max asset groups are now their own entity — `ads create --format performanceMaxAssetGroup` never worked and is gone); `ads create --format video` moves from a bare YouTube id to `--video-assets` refs (**breaking flag change** — stage the video as an asset first); `--format demandGen` gains `--image-assets`/`--square-image-assets`/`--logo-image-assets` and flag-building for headlines/descriptions. LinkedIn's `draft list` now renders a readable Campaign group ▸ Campaign ▸ Creative tree by default (`--json` for raw), `creatives update` gains `--campaign` (re-parent while staged), and `campaigns update` passes create-only fields (`--group`/`--type`/`--locale`/`--associated-entity`) through when amending a `li_temp_*` staged create instead of always stripping them.
4733
+ - **0.150.0**: `baker landing critique` gains an `agent-washing` rule in the `copy` family — an autonomy claim ("fully autonomous", "while you sleep", "no human intervention") with no signal anywhere on the page about who oversees the agent (approval, review, override, undo/rollback, audit log, escalation) scores a warn. Page-scope, so a hero may defer the trust story to a later section; generic privacy boilerplate does not clear it. `CRITIC_VERSION` bumps to `2`.
4701
4734
 
4702
4735
  ## Publishing
4703
4736
 
@@ -7,9 +7,9 @@ import {
7
7
  __toESM
8
8
  } from "./chunk-RK67WL4O.js";
9
9
 
10
- // ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/810146e81bae4e3a061fe487864f2fde80c4b03b886877dc0f1fffbc6480b67e/node_modules/safe-stable-stringify/index.js
10
+ // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js
11
11
  var require_safe_stable_stringify = __commonJS({
12
- "../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/810146e81bae4e3a061fe487864f2fde80c4b03b886877dc0f1fffbc6480b67e/node_modules/safe-stable-stringify/index.js"(exports, module) {
12
+ "../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js"(exports, module) {
13
13
  "use strict";
14
14
  var { hasOwnProperty } = Object.prototype;
15
15
  var stringify = configure2();
@@ -1070,7 +1070,7 @@ function resolveAdaptFormats(params) {
1070
1070
  return params.formats ?? [];
1071
1071
  }
1072
1072
 
1073
- // ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/810146e81bae4e3a061fe487864f2fde80c4b03b886877dc0f1fffbc6480b67e/node_modules/safe-stable-stringify/esm/wrapper.js
1073
+ // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/esm/wrapper.js
1074
1074
  var import__ = __toESM(require_safe_stable_stringify(), 1);
1075
1075
  var configure = import__.default.configure;
1076
1076
  var wrapper_default = import__.default;
@@ -1119,7 +1119,6 @@ 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];
1123
1122
  var ELEVENLABS_OUTPUT_FORMATS = [
1124
1123
  "mp3_22050_32",
1125
1124
  "mp3_44100_32",
@@ -1413,7 +1412,7 @@ var MODEL_REGISTRY = {
1413
1412
  prompt: { kind: "string" },
1414
1413
  negative_prompt: { kind: "string" },
1415
1414
  aspect_ratio: { kind: "string", enum: ["16:9", "9:16"] },
1416
- resolution: { kind: "string", enum: ["720p", "1080p", "4K"] },
1415
+ resolution: { kind: "string", enum: ["720p", "1080p"] },
1417
1416
  duration: { kind: "number", enum: [4, 6, 8] },
1418
1417
  seed: { kind: "number" },
1419
1418
  generate_audio: { kind: "boolean" },
@@ -1425,14 +1424,9 @@ var MODEL_REGISTRY = {
1425
1424
  "kwaivgi/kling-v3.0-pro": {
1426
1425
  // Motion-transfer / dynamic multi-shot beats. Reachable through the default
1427
1426
  // OpenRouter gateway (generic video body — no google-vertex block), so it
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.
1427
+ // needs no direct-provider exception. Cost is usage-based (known from the
1428
+ // provider response), so it has no pre-flight cost estimate. `cfg_scale`
1429
+ // trades prompt adherence vs motion freedom; higher = closer to prompt.
1436
1430
  label: "Kling 3.0",
1437
1431
  inputs: [],
1438
1432
  optional_inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
@@ -1442,9 +1436,10 @@ var MODEL_REGISTRY = {
1442
1436
  // over-length prompt fails validate (free) not the billed call.
1443
1437
  prompt: { kind: "string", maxLength: 2500 },
1444
1438
  negative_prompt: { kind: "string" },
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 },
1439
+ aspect_ratio: { kind: "string", enum: ["1:1", "16:9", "9:16"] },
1440
+ resolution: { kind: "string", enum: ["720p", "1080p"] },
1441
+ duration: { kind: "number", enum: [5, 10] },
1442
+ seed: { kind: "number" },
1448
1443
  generate_audio: { kind: "boolean" },
1449
1444
  cfg_scale: { kind: "number", min: 0, max: 1 }
1450
1445
  }
@@ -1460,7 +1455,7 @@ var MODEL_REGISTRY = {
1460
1455
  prompt: { kind: "string" },
1461
1456
  negative_prompt: { kind: "string" },
1462
1457
  aspect_ratio: { kind: "string", enum: ["16:9", "9:16"] },
1463
- resolution: { kind: "string", enum: ["720p", "1080p", "4K"] },
1458
+ resolution: { kind: "string", enum: ["720p", "1080p"] },
1464
1459
  duration: { kind: "number", enum: [4, 6, 8] },
1465
1460
  seed: { kind: "number" },
1466
1461
  generate_audio: { kind: "boolean" },
@@ -1782,58 +1777,6 @@ function validateValue(key, value, schema, model) {
1782
1777
  }
1783
1778
  }
1784
1779
 
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
-
1837
1780
  // src/engine/lib/concurrency.ts
1838
1781
  var DEFAULT_CONCURRENCY = 8;
1839
1782
  function resolveConcurrency(...candidates) {
@@ -2630,7 +2573,7 @@ function looksLikeHttpUrl(value) {
2630
2573
  var VEO_PERSON_GENERATION = "allow_adult";
2631
2574
  var VEO_NEGATIVE_PROMPT = "subtitles, captions, on-screen text, watermark, logo, warped face, distorted hands, extra fingers, low quality";
2632
2575
  var VEO_DURATIONS = [4, 6, 8];
2633
- var KLING_DURATIONS2 = [5, 10];
2576
+ var KLING_DURATIONS = [5, 10];
2634
2577
  var KLING_NEGATIVE_PROMPT = "warped face, distorted hands, extra fingers, morphing, flicker, on-screen text, watermark, low quality";
2635
2578
  var KLING_CFG_SCALE = 0.7;
2636
2579
  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}"`;
@@ -2676,7 +2619,7 @@ var KLING_PROFILE = {
2676
2619
  // Kling takes a negative_prompt PARAM instead (paramDefaults).
2677
2620
  keyframeInstruction: "Preserve the composition and colors of the first frame; animate the motion described.",
2678
2621
  wordBudget: 200,
2679
- durationSet: KLING_DURATIONS2,
2622
+ durationSet: KLING_DURATIONS,
2680
2623
  paramDefaults: { negative_prompt: KLING_NEGATIVE_PROMPT, cfg_scale: KLING_CFG_SCALE }
2681
2624
  };
2682
2625
  function clipProfileFor(modelId) {
@@ -7510,33 +7453,12 @@ var videoGenerateNode = delegated({
7510
7453
  inputs: z28.object({
7511
7454
  first_frame: ImageRef.optional(),
7512
7455
  last_frame: 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()
7456
+ reference: ImageRef.optional()
7521
7457
  }).loose(),
7522
7458
  params: VideoGenerateParams,
7523
7459
  outputs: z28.object({ video: VideoRef }).strict(),
7524
7460
  outputKinds: { video: "video" },
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
- })
7461
+ cost: () => ({ credits: 50, seconds_estimate: 120 })
7540
7462
  });
7541
7463
 
7542
7464
  // src/engine/nodes/remote/videoBackgroundRemove.ts
@@ -8019,4 +7941,4 @@ export {
8019
7941
  defaultRegistry,
8020
7942
  createEngineFromEnv
8021
7943
  };
8022
- //# sourceMappingURL=chunk-S43JQWI2.js.map
7944
+ //# sourceMappingURL=chunk-OO5BDH3J.js.map