@koda-sl/baker-cli 0.425.0 → 0.426.0-dev.5af7a82af

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
@@ -1803,6 +1803,22 @@ baker gsc sitemaps --site-url "https://example.com/"
1803
1803
 
1804
1804
  ---
1805
1805
 
1806
+ ### Making ads (`baker creatives brief` / `ideas` / `make`)
1807
+
1808
+ Ads start from what customers said. Three commands carry the process; the agent writes the ideas and the copy.
1809
+
1810
+ ```bash
1811
+ baker creatives brief [--adset <id>] [--account-id act_<id>] # one read: viewer, account bottleneck, what works, taste, customer quotes, ideas on file
1812
+ baker creatives ideas [--full] # check and rank src/creatives/_ideas/*.md; build_next
1813
+ baker creatives make <idea> [--slug <s>] [--adset <id>] [--reference <adId>] [--spec <beats.json>] [--from-idea]
1814
+ baker creatives learn [--days <n>] [--dry-run] # what each idea's ads did, written back onto the idea
1815
+ ```
1816
+
1817
+ - `brief` returns a verdict, not raw numbers: `account.bottleneck` is `hook`, `after_click`, `none` or `too_little_data`. A part that cannot be read says `unavailable`. `market` says what competitors' ads already say (the followed brands, else the library), how sophisticated the market is, and which awareness stages nobody speaks to.
1818
+ - `ideas` is free and local. An idea's `evidence` resolves to `src/content/insights/` entries, or it is an `explore` bet. Numbers must be in the Knowledge or our own customers' quotes (a Reddit, forum or web quote never sources a claim), no two ideas may share an angle and format, and a review or testimonial format needs a quote from our own customer.
1819
+ - `learn` pools each built idea's creatives, judges them against the rest of the account's cost per result and writes `status` (`winner`, `failed`, `inconclusive`, `testing`) and a frozen `result` onto the idea. `ideas` then warns when a new idea repeats a failed one.
1820
+ - `make` builds one idea. A static searches the idea's container for ads made for our viewer, checks the closest three with `winning-ads fit` and scaffolds from the first that fits. A video idea takes its beats spec. Either way it records the idea on `_definition.md`, sets `prompt.json`'s `message` and syncs the definition. Drafted copy lines claiming a figure the company never wrote come back first in `hints`. When no proven ad fits (or with `--from-idea`), a static starts from the idea itself: `prompt.json` holds the message and placeholders, and `canvas run` refuses to render until the scene and copy are written.
1821
+
1806
1822
  ### Competitive Intelligence (`baker research`)
1807
1823
 
1808
1824
  Market and competitor research powered by DataForSEO and AI-powered Google Search grounding. Shows who's competing for keywords, search intent classification, competitor keyword strategies, keyword gaps, landing page performance, and open-ended AI research.
@@ -1934,6 +1950,16 @@ Every search or thread item carries verbatim `text`, `author`, `score`, `created
1934
1950
 
1935
1951
  ---
1936
1952
 
1953
+ ### `baker research customers`
1954
+
1955
+ Finds what real customers say and writes each quote as an insight in `src/content/insights/` (type, quote, source, date, `status: observed`). Sources: the company's reviews library, Reddit, and with `--web` pages from web research. A quote is kept only when it appears word for word in the text that was fetched; the model classifies quotes and never writes them.
1956
+
1957
+ ```bash
1958
+ baker research customers --focus "solar panels" # reviews + Reddit
1959
+ baker research customers --query "payroll mistakes" --web --limit 15
1960
+ baker research customers --dry-run # print, write nothing
1961
+ ```
1962
+
1937
1963
  ### `baker research advertisers "keyword"`
1938
1964
 
1939
1965
  Returns a ranked list of **domains** competing for one keyword in Google, with average SERP position, relevance rating, estimated traffic value and visibility — domain economics, **NOT ad copy**. Despite the name it returns no headlines, descriptions or creative of any kind; for a competitor's actual ad copy use `baker winning-ads content <adId>` (Meta/LinkedIn only — Google SERP ad copy is not available anywhere in Baker).
@@ -24,9 +24,9 @@ import {
24
24
  shouldEscalate
25
25
  } from "./chunk-FQOKJYKN.js";
26
26
 
27
- // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js
27
+ // ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/766ad107c42df28eeadaf0ac2f9089c8a9e200f6ba0b2b1a817b8d536cbdcc49/node_modules/safe-stable-stringify/index.js
28
28
  var require_safe_stable_stringify = __commonJS({
29
- "../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js"(exports, module) {
29
+ "../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/766ad107c42df28eeadaf0ac2f9089c8a9e200f6ba0b2b1a817b8d536cbdcc49/node_modules/safe-stable-stringify/index.js"(exports, module) {
30
30
  "use strict";
31
31
  var { hasOwnProperty } = Object.prototype;
32
32
  var stringify = configure2();
@@ -1408,7 +1408,7 @@ function resolveAdaptFormats(params) {
1408
1408
  return params.formats ?? [];
1409
1409
  }
1410
1410
 
1411
- // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/esm/wrapper.js
1411
+ // ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/766ad107c42df28eeadaf0ac2f9089c8a9e200f6ba0b2b1a817b8d536cbdcc49/node_modules/safe-stable-stringify/esm/wrapper.js
1412
1412
  var import__ = __toESM(require_safe_stable_stringify(), 1);
1413
1413
  var configure = import__.default.configure;
1414
1414
  var wrapper_default = import__.default;
@@ -2826,6 +2826,12 @@ var MODEL_ROLES = {
2826
2826
  * only and asked once per ad and viewer, so Flash; the calibration set (E8) decides.
2827
2827
  */
2828
2828
  viewerCheck: { kind: "text_generate", model: "~google/gemini-flash-latest" },
2829
+ /**
2830
+ * Picks the customer truths out of reviews, testimonials and threads (`baker research
2831
+ * customers`): returns exact spans the code then checks against the source. Text only and
2832
+ * one call per batch, so Flash.
2833
+ */
2834
+ customerInsights: { kind: "text_generate", model: "~google/gemini-flash-latest" },
2829
2835
  /**
2830
2836
  * The same viewer shown the FINISHED static ad at phone size for about three seconds, with no
2831
2837
  * brand and no brief: what is sold, whether it is for them, what to do next, what stopped them
@@ -2867,6 +2873,7 @@ var PLATE_JUDGE_MODEL = MODEL_ROLES.plateJudge.model;
2867
2873
  var AD_DESCRIBE_MODEL = MODEL_ROLES.adDescribe.model;
2868
2874
  var BLUEPRINT_ANALYSIS_MODEL = MODEL_ROLES.blueprintAnalysis.model;
2869
2875
  var VIEWER_CHECK_MODEL = MODEL_ROLES.viewerCheck.model;
2876
+ var CUSTOMER_INSIGHTS_MODEL = MODEL_ROLES.customerInsights.model;
2870
2877
  var GLANCE_CHECK_MODEL = MODEL_ROLES.glanceCheck.model;
2871
2878
  var TEXT_BOX_READER_MODEL = MODEL_ROLES.textBoxReader.model;
2872
2879
  var VIDEO_DECONSTRUCT_MODEL = MODEL_ROLES.videoDeconstruct.model;
@@ -6912,6 +6919,18 @@ function conceptProblems(spec) {
6912
6919
  }
6913
6920
  return problems;
6914
6921
  }
6922
+ var PLACEHOLDER = "[TODO";
6923
+ function unwrittenProblems(spec) {
6924
+ const problems = [];
6925
+ if (spec.scene.description.includes(PLACEHOLDER)) {
6926
+ problems.push("The scene is still a placeholder: write what the viewer sees in `scene.description`.");
6927
+ }
6928
+ const lines = spec.copy.filter((line) => line.text.includes(PLACEHOLDER));
6929
+ if (lines.length > 0) {
6930
+ problems.push(`${lines.length} line(s) of copy are still placeholders: write each as it prints, or drop it.`);
6931
+ }
6932
+ return problems;
6933
+ }
6915
6934
  function readAdSpec(raw) {
6916
6935
  if (isAdSpec(raw)) return AdSpecSchema.parse(raw);
6917
6936
  const advertiser = raw?.reference?.advertiser;
@@ -18385,6 +18404,7 @@ export {
18385
18404
  AD_DESCRIBE_MODEL,
18386
18405
  BLUEPRINT_ANALYSIS_MODEL,
18387
18406
  VIEWER_CHECK_MODEL,
18407
+ CUSTOMER_INSIGHTS_MODEL,
18388
18408
  GLANCE_CHECK_MODEL,
18389
18409
  VIDEO_DECONSTRUCT_MODEL,
18390
18410
  VOICEOVER_MODEL,
@@ -18456,6 +18476,7 @@ export {
18456
18476
  isAdSpec,
18457
18477
  conceptSummary,
18458
18478
  conceptProblems,
18479
+ unwrittenProblems,
18459
18480
  readAdSpec,
18460
18481
  withRenderedLettering,
18461
18482
  conceptClassOf,
@@ -18543,4 +18564,4 @@ export {
18543
18564
  defaultRegistry,
18544
18565
  createEngineFromEnv
18545
18566
  };
18546
- //# sourceMappingURL=chunk-ZH7YAR5N.js.map
18567
+ //# sourceMappingURL=chunk-GTHLEQHU.js.map