@koda-sl/baker-cli 0.394.0 → 0.395.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.
@@ -2,13 +2,13 @@ import {
2
2
  handleConnectionError,
3
3
  needsConnectionFix,
4
4
  writeAdsJson
5
- } from "./chunk-ZPQ7L33H.js";
5
+ } from "./chunk-QP7637HG.js";
6
6
  import {
7
7
  ApiError
8
- } from "./chunk-CEVZG46B.js";
8
+ } from "./chunk-Q7RQ3H6Y.js";
9
9
  import {
10
10
  getEnv
11
- } from "./chunk-53ATKV76.js";
11
+ } from "./chunk-BRIJ4OWT.js";
12
12
 
13
13
  // src/commands/ads/meta/shared.ts
14
14
  var DAY_MS = 864e5;
@@ -133,4 +133,4 @@ export {
133
133
  resolveEffectiveStatus,
134
134
  statusFilterHints
135
135
  };
136
- //# sourceMappingURL=chunk-F56XWRCY.js.map
136
+ //# sourceMappingURL=chunk-EEHNRAFA.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  debugLogHttp,
3
3
  readBodyForLog
4
- } from "./chunk-S35KWGIQ.js";
4
+ } from "./chunk-ZWMATKNS.js";
5
5
  import {
6
6
  API_KEY_FORMAT_MESSAGE,
7
7
  DIRECT_ROUTE,
@@ -18,7 +18,7 @@ import {
18
18
  refuseNonPublicUrl,
19
19
  requireConnection,
20
20
  shouldEscalate
21
- } from "./chunk-53ATKV76.js";
21
+ } from "./chunk-BRIJ4OWT.js";
22
22
 
23
23
  // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js
24
24
  var require_safe_stable_stringify = __commonJS({
@@ -11565,4 +11565,4 @@ export {
11565
11565
  defaultRegistry,
11566
11566
  createEngineFromEnv
11567
11567
  };
11568
- //# sourceMappingURL=chunk-VTLHR3BB.js.map
11568
+ //# sourceMappingURL=chunk-LHJ5IXBN.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  debugLogHttp,
3
3
  readBodyForLog
4
- } from "./chunk-S35KWGIQ.js";
4
+ } from "./chunk-ZWMATKNS.js";
5
5
  import {
6
6
  getEnv
7
- } from "./chunk-53ATKV76.js";
7
+ } from "./chunk-BRIJ4OWT.js";
8
8
 
9
9
  // src/client.ts
10
10
  var MAX_RATE_LIMIT_RETRIES = 3;
@@ -208,4 +208,4 @@ export {
208
208
  apiGet,
209
209
  apiPost
210
210
  };
211
- //# sourceMappingURL=chunk-CEVZG46B.js.map
211
+ //# sourceMappingURL=chunk-Q7RQ3H6Y.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  ApiError,
3
3
  apiGet
4
- } from "./chunk-CEVZG46B.js";
4
+ } from "./chunk-Q7RQ3H6Y.js";
5
5
  import {
6
6
  getEnv
7
- } from "./chunk-53ATKV76.js";
7
+ } from "./chunk-BRIJ4OWT.js";
8
8
 
9
9
  // src/error-handler.ts
10
10
  var REQUEST_CONNECTION_PLATFORM = {
@@ -298,4 +298,4 @@ export {
298
298
  writeAdsOutput,
299
299
  resolveCustomerId
300
300
  };
301
- //# sourceMappingURL=chunk-ZPQ7L33H.js.map
301
+ //# sourceMappingURL=chunk-QP7637HG.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  debugLogSetting
3
- } from "./chunk-53ATKV76.js";
3
+ } from "./chunk-BRIJ4OWT.js";
4
4
 
5
5
  // src/debugLog.ts
6
6
  import { appendFileSync, mkdirSync, renameSync, statSync } from "fs";
@@ -173,4 +173,4 @@ export {
173
173
  readBodyForLog,
174
174
  installStreamTaps
175
175
  };
176
- //# sourceMappingURL=chunk-S35KWGIQ.js.map
176
+ //# sourceMappingURL=chunk-ZWMATKNS.js.map
package/dist/cli.js CHANGED
@@ -98,7 +98,7 @@ import {
98
98
  withoutCastName,
99
99
  wordCount,
100
100
  ytDlpBlockSignal
101
- } from "./chunk-VTLHR3BB.js";
101
+ } from "./chunk-LHJ5IXBN.js";
102
102
  import {
103
103
  NAME_CONTAINS_ARG,
104
104
  csvOrJson,
@@ -109,7 +109,7 @@ import {
109
109
  resolveEffectiveStatus,
110
110
  statusFilterHints,
111
111
  todayIso
112
- } from "./chunk-F56XWRCY.js";
112
+ } from "./chunk-EEHNRAFA.js";
113
113
  import {
114
114
  buildQueryCacheKey,
115
115
  cacheGet,
@@ -125,19 +125,19 @@ import {
125
125
  writeAdsJson,
126
126
  writeAdsOutput,
127
127
  writeJsonEnvelope
128
- } from "./chunk-ZPQ7L33H.js";
128
+ } from "./chunk-QP7637HG.js";
129
129
  import {
130
130
  ApiError,
131
131
  apiGet,
132
132
  apiGetWithHeaders,
133
133
  apiPost,
134
134
  validateConvexId
135
- } from "./chunk-CEVZG46B.js";
135
+ } from "./chunk-Q7RQ3H6Y.js";
136
136
  import {
137
137
  installExitRecord,
138
138
  installStreamTaps,
139
139
  logInvocation
140
- } from "./chunk-S35KWGIQ.js";
140
+ } from "./chunk-ZWMATKNS.js";
141
141
  import {
142
142
  __commonJS,
143
143
  __esm,
@@ -172,7 +172,7 @@ import {
172
172
  winningAdNormalizer,
173
173
  writeJson,
174
174
  writeOutput
175
- } from "./chunk-53ATKV76.js";
175
+ } from "./chunk-BRIJ4OWT.js";
176
176
 
177
177
  // ../../node_modules/.pnpm/i18n-iso-countries@7.14.0/node_modules/i18n-iso-countries/langs/af.json
178
178
  var require_af = __commonJS({
@@ -22058,6 +22058,67 @@ var winnersHardFiltersSchema = z2.object({
22058
22058
  first_seen_after: z2.string().optional(),
22059
22059
  first_seen_before: z2.string().optional()
22060
22060
  });
22061
+ var firstSeenBoundSchema = z2.union([z2.iso.date(), z2.iso.datetime({ offset: true })], {
22062
+ error: "first_seen_after/first_seen_before must be an ISO date (2026-01-01) or datetime (2026-01-01T00:00:00Z)"
22063
+ }).transform((value2) => new Date(value2.length === 10 ? `${value2}T00:00:00Z` : value2).toISOString());
22064
+ var adFormatSchema = z2.enum(["video", "static", "carousel"]);
22065
+ var winnerCategorySchema = z2.enum([
22066
+ "winner",
22067
+ "grand_slam_winner",
22068
+ "scaled_winner",
22069
+ "low_profile_winner",
22070
+ "rising",
22071
+ "evergreen",
22072
+ "low_traction_dud",
22073
+ "thrash_iteration",
22074
+ "thrash_family",
22075
+ "false_winner",
22076
+ "untested",
22077
+ "dud"
22078
+ ]);
22079
+ var awarenessStageSchema = z2.enum([
22080
+ "unaware",
22081
+ "problem_aware",
22082
+ "solution_aware",
22083
+ "product_aware",
22084
+ "most_aware"
22085
+ ]);
22086
+ var staticFormatPatternSchema = z2.enum([
22087
+ "clean_product",
22088
+ "lifestyle_photo",
22089
+ "headline_card",
22090
+ "infographic",
22091
+ "chat_screenshot",
22092
+ "tweet_screenshot",
22093
+ "review_screenshot",
22094
+ "before_after_split",
22095
+ "comparison_table",
22096
+ "list_card",
22097
+ "meme_template",
22098
+ "native_post_lookalike",
22099
+ "stock_photo_overlay",
22100
+ "founder_portrait",
22101
+ "testimonial_quote",
22102
+ "packshot_minimalist",
22103
+ "four_panel_lifestyle_grid",
22104
+ "two_panel_split",
22105
+ "notes_app_screenshot",
22106
+ "founder_letter_textonly",
22107
+ "us_vs_them_grid",
22108
+ "benefit_callout_grid",
22109
+ "create_your_own_adventure_meme",
22110
+ "quad_split",
22111
+ "stories_style_casual_static"
22112
+ ]);
22113
+ var validatedHardFiltersSchema = winnersHardFiltersSchema.extend({
22114
+ platform: z2.array(adLibraryPlatformSchema).optional(),
22115
+ format: z2.array(adFormatSchema).optional(),
22116
+ winner_category: z2.array(winnerCategorySchema).optional(),
22117
+ awareness_stage: z2.array(awarenessStageSchema).optional(),
22118
+ static_format_patterns: z2.array(staticFormatPatternSchema).optional(),
22119
+ first_seen_after: firstSeenBoundSchema.optional(),
22120
+ first_seen_before: firstSeenBoundSchema.optional()
22121
+ });
22061
22122
  var winnersSearchFields = z2.object({
22062
22123
  free_text_query: z2.string().max(500).optional(),
22063
22124
  ref_ad_id: z2.string().optional(),
@@ -22082,7 +22143,7 @@ var hasSearchInput = (b) => b.free_text_query !== void 0 || b.ref_ad_id !== void
22082
22143
  var SEARCH_INPUT_MESSAGE = "Provide free_text_query, ref_ad_id, or hard_filters";
22083
22144
  var winnersSearchRequestSchema = winnersSearchFields.refine(hasSearchInput, { message: SEARCH_INPUT_MESSAGE });
22084
22145
  var winnerSearchScopeSchema = z2.enum(["all", "followed", "followed-first"]);
22085
- var scopedWinnersSearchRequestSchema = winnersSearchFields.extend({ scope: winnerSearchScopeSchema.optional() }).refine(hasSearchInput, { message: SEARCH_INPUT_MESSAGE }).refine((b) => b.scope !== "followed-first" || !b.offset, {
22146
+ var scopedWinnersSearchRequestSchema = winnersSearchFields.extend({ scope: winnerSearchScopeSchema.optional(), hard_filters: validatedHardFiltersSchema.optional() }).refine(hasSearchInput, { message: SEARCH_INPUT_MESSAGE }).refine((b) => b.scope !== "followed-first" || !b.offset, {
22086
22147
  message: "offset is not supported with scope followed-first; raise limit instead"
22087
22148
  });
22088
22149
  var winningAdDnaSchema = z2.object({
@@ -22092,6 +22153,10 @@ var winningAdDnaSchema = z2.object({
22092
22153
  audience_temperature: z2.string().nullable(),
22093
22154
  target_persona: z2.string().nullable(),
22094
22155
  hook_archetype: z2.string().nullable(),
22156
+ // The proven hook pattern (`winning-ads hooks` seed) the free-text
22157
+ // `hook_archetype` matches: the value two ads can share. Optional while an
22158
+ // older ad-dna does not send it.
22159
+ hook_seed: z2.string().nullable().optional(),
22095
22160
  creator_type: z2.string().nullable(),
22096
22161
  industry: z2.string().nullable(),
22097
22162
  business_model: z2.string().nullable(),
@@ -22121,6 +22186,9 @@ var winningAdSchema = z2.object({
22121
22186
  // How proven in-market (global creative strength).
22122
22187
  winner_score: z2.number().nullable(),
22123
22188
  winner_category: z2.string().nullable(),
22189
+ // The score ad-dna ranked the result by (relevance blended with winner
22190
+ // score, or the winner score on a browse). Search results only.
22191
+ final_score: z2.number().nullable().optional(),
22124
22192
  days_active: z2.number().nullable(),
22125
22193
  reach: z2.number().nullable(),
22126
22194
  active: z2.boolean().nullable(),
@@ -53375,10 +53443,10 @@ Example: baker ads meta ads retag 120252158038400247 --url-tags "utm_source={{si
53375
53443
  }
53376
53444
  },
53377
53445
  run: async ({ args: args8 }) => {
53378
- const { apiPost: apiPost2 } = await import("./client-ST4W3WRE.js");
53379
- const { requireChatId: requireChatId2 } = await import("./env-HQWFIYZF.js");
53380
- const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-BTGDLTVL.js");
53381
- const { handleMetaError: handleMetaError2 } = await import("./shared-KLQWQWPJ.js");
53446
+ const { apiPost: apiPost2 } = await import("./client-4P6U75EX.js");
53447
+ const { requireChatId: requireChatId2 } = await import("./env-LJHSZSNA.js");
53448
+ const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-HVBFJX4I.js");
53449
+ const { handleMetaError: handleMetaError2 } = await import("./shared-7ZEF4DIX.js");
53382
53450
  try {
53383
53451
  const accountId = bareAccountId2(args8);
53384
53452
  const urlTags = typeof args8["url-tags"] === "string" ? args8["url-tags"] : void 0;
@@ -53529,10 +53597,10 @@ function duplicateCommand2(entity, label) {
53529
53597
  replace: { type: "boolean", description: "Pause the original once the copy publishes" }
53530
53598
  },
53531
53599
  run: async ({ args: args8 }) => {
53532
- const { apiPost: apiPost2 } = await import("./client-ST4W3WRE.js");
53533
- const { requireChatId: requireChatId2 } = await import("./env-HQWFIYZF.js");
53534
- const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-BTGDLTVL.js");
53535
- const { handleMetaError: handleMetaError2 } = await import("./shared-KLQWQWPJ.js");
53600
+ const { apiPost: apiPost2 } = await import("./client-4P6U75EX.js");
53601
+ const { requireChatId: requireChatId2 } = await import("./env-LJHSZSNA.js");
53602
+ const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-HVBFJX4I.js");
53603
+ const { handleMetaError: handleMetaError2 } = await import("./shared-7ZEF4DIX.js");
53536
53604
  try {
53537
53605
  const accountId = bareAccountId2(args8);
53538
53606
  const chatId = requireChatId2();
@@ -98604,7 +98672,7 @@ var patternsCommand = defineCommand267({
98604
98672
  import { defineCommand as defineCommand268 } from "citty";
98605
98673
  registerSchema({
98606
98674
  command: "winning-ads.search",
98607
- description: "Search the ad-dna corpus of scored winning ads. Returns a lean shortlist (advertiser, summary, scores, media_url) to pick a reference to reproduce.",
98675
+ description: "Search the ad-dna corpus of scored winning ads. Returns a lean shortlist (advertiser, summary, scores, media_url, and visual/container/mechanism when known) to pick a reference to reproduce. A value outside a closed list (--platform, --format, --winner-category, --awareness, --format-pattern) is refused with error.fix.validValues.",
98608
98676
  args: {
98609
98677
  query: { type: "string", description: "Free-text natural-language query", required: false },
98610
98678
  scope: {
@@ -98621,7 +98689,7 @@ registerSchema({
98621
98689
  limit: { type: "number", description: "Max results 1-100 (default 10)", required: false, default: 10 },
98622
98690
  "max-per-advertiser": {
98623
98691
  type: "number",
98624
- description: "Cap results per advertiser 1-50 (default 3)",
98692
+ description: "Cap results per advertiser 0-50 (default 3; 0 = no cap), also when the company follows one brand",
98625
98693
  required: false,
98626
98694
  default: 3
98627
98695
  },
@@ -98655,17 +98723,17 @@ registerSchema({
98655
98723
  },
98656
98724
  "exclude-advertiser": {
98657
98725
  type: "string",
98658
- description: "Drop these advertiser ids \u2014 your own brand + already-used references",
98726
+ description: "Drop these advertiser ids, usually your own brand (a reused ad is marked already_adapted instead)",
98659
98727
  required: false
98660
98728
  },
98661
98729
  "first-seen-after": {
98662
98730
  type: "string",
98663
- description: "ISO datetime; only ads first seen after this",
98731
+ description: "ISO date (2026-01-01) or datetime; only ads first seen after this",
98664
98732
  required: false
98665
98733
  },
98666
98734
  "first-seen-before": {
98667
98735
  type: "string",
98668
- description: "ISO datetime; only ads first seen before this",
98736
+ description: "ISO date (2026-01-01) or datetime; only ads first seen before this",
98669
98737
  required: false
98670
98738
  },
98671
98739
  "hook-archetype": {
@@ -98782,17 +98850,68 @@ function reportSearchError(err) {
98782
98850
  }
98783
98851
  reportError2(err);
98784
98852
  }
98785
- function rejectWith(message) {
98786
- writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message } });
98787
- process.exit(1);
98853
+ var FLAG_FOR_FIELD = {
98854
+ limit: "--limit",
98855
+ max_per_advertiser: "--max-per-advertiser",
98856
+ min_relevance: "--min-relevance",
98857
+ platform: "--platform",
98858
+ format: "--format",
98859
+ winner_category: "--winner-category",
98860
+ awareness_stage: "--awareness",
98861
+ static_format_patterns: "--format-pattern",
98862
+ first_seen_after: "--first-seen-after",
98863
+ first_seen_before: "--first-seen-before"
98864
+ };
98865
+ function flagFor(path57) {
98866
+ const field = String(path57[0] === "hard_filters" ? path57[1] : path57[0]);
98867
+ return FLAG_FOR_FIELD[field] ?? field;
98788
98868
  }
98789
- function rejectInvalidSearch(args8, body) {
98869
+ function schemaRejection(body) {
98870
+ const parsed = scopedWinnersSearchRequestSchema.safeParse(body, { reportInput: true });
98871
+ if (parsed.success) {
98872
+ return null;
98873
+ }
98874
+ const [first] = parsed.error.issues;
98875
+ if (!first) {
98876
+ return { message: "Invalid search" };
98877
+ }
98878
+ const flag = flagFor(first.path);
98879
+ if (first.code === "invalid_value") {
98880
+ const sameFlag = parsed.error.issues.filter((i) => i.code === "invalid_value" && flagFor(i.path) === flag);
98881
+ const invalidValues = sameFlag.map((i) => String(i.input));
98882
+ const validValues = first.values.map(String);
98883
+ return {
98884
+ message: `Unknown ${flag} value${invalidValues.length > 1 ? "s" : ""} ${invalidValues.map((v) => `"${v}"`).join(", ")}.`,
98885
+ fix: {
98886
+ action: "retry_with_valid_values",
98887
+ explanation: `Re-run with values from \`validValues\` for ${flag}, or drop the flag.`,
98888
+ flag,
98889
+ invalidValues,
98890
+ validValues
98891
+ }
98892
+ };
98893
+ }
98894
+ return { message: first.path.length > 0 ? `${flag}: ${first.message}` : first.message };
98895
+ }
98896
+ var NUMERIC_FLAGS = [
98897
+ ["--limit", "limit"],
98898
+ ["--max-per-advertiser", "maxPerAdvertiser"],
98899
+ ["--min-relevance", "minRelevance"]
98900
+ ];
98901
+ function searchRejection(args8, body) {
98790
98902
  if (args8.scope !== void 0 && !winnerSearchScopeSchema.safeParse(args8.scope).success) {
98791
- rejectWith(`Unknown --scope "${args8.scope}". Use one of: ${winnerSearchScopeSchema.options.join(", ")}.`);
98903
+ return { message: `Unknown --scope "${args8.scope}". Use one of: ${winnerSearchScopeSchema.options.join(", ")}.` };
98904
+ }
98905
+ for (const [flag, key] of NUMERIC_FLAGS) {
98906
+ const value2 = args8[key];
98907
+ if (value2 !== void 0 && value2 !== "" && Number.isNaN(Number(value2))) {
98908
+ return { message: `${flag} must be a number, got "${value2}".` };
98909
+ }
98792
98910
  }
98793
98911
  if (!("free_text_query" in body || "ref_ad_id" in body || "hard_filters" in body)) {
98794
- rejectWith("Provide a query, --ref-ad-id, or a filter flag");
98912
+ return { message: "Provide a query, --ref-ad-id, or a filter flag" };
98795
98913
  }
98914
+ return schemaRejection(body);
98796
98915
  }
98797
98916
  function writeSearchResult(data, opts) {
98798
98917
  const rawResults = Array.isArray(data?.results) ? data.results : [];
@@ -98817,6 +98936,7 @@ function writeSearchResult(data, opts) {
98817
98936
  }
98818
98937
  writeOutput({ ok: true, data: rawResults, ...withHints2 }, opts.output, opts.fields, opts.full, winningAdNormalizer);
98819
98938
  }
98939
+ var SEARCH_TIMEOUT_MS = 12e4;
98820
98940
  var searchCommand5 = defineCommand268({
98821
98941
  meta: {
98822
98942
  name: "search",
@@ -98838,7 +98958,7 @@ var searchCommand5 = defineCommand268({
98838
98958
  },
98839
98959
  "max-per-advertiser": {
98840
98960
  type: "string",
98841
- description: "Cap results per advertiser 1-50 (default 3)",
98961
+ description: "Cap results per advertiser 0-50 (default 3; 0 = no cap), also when the company follows one brand",
98842
98962
  required: false
98843
98963
  },
98844
98964
  "min-relevance": { type: "string", description: "Relevance floor 0-1", required: false },
@@ -98863,11 +98983,11 @@ var searchCommand5 = defineCommand268({
98863
98983
  "advertiser-id": { type: "string", description: "Restrict to these advertiser ids", required: false },
98864
98984
  "exclude-advertiser": {
98865
98985
  type: "string",
98866
- description: "Drop these advertiser ids (your own + already-used)",
98986
+ description: "Drop these advertiser ids, usually your own brand",
98867
98987
  required: false
98868
98988
  },
98869
- "first-seen-after": { type: "string", description: "ISO datetime lower bound", required: false },
98870
- "first-seen-before": { type: "string", description: "ISO datetime upper bound", required: false },
98989
+ "first-seen-after": { type: "string", description: "ISO date or datetime lower bound", required: false },
98990
+ "first-seen-before": { type: "string", description: "ISO date or datetime upper bound", required: false },
98871
98991
  "hook-archetype": {
98872
98992
  type: "string",
98873
98993
  description: "Comma list of proven hook seeds (from `winning-ads hooks`) to narrow the search",
@@ -98888,7 +99008,7 @@ var searchCommand5 = defineCommand268({
98888
99008
  fields: { type: "string", description: "Comma-separated field names to include", required: false },
98889
99009
  full: {
98890
99010
  type: "boolean",
98891
- description: "Include DNA detail (angle, persona, hook) + longevity",
99011
+ description: "Include DNA detail (angle, persona, hook) + longevity; mechanism is in the default output",
98892
99012
  required: false,
98893
99013
  default: false
98894
99014
  }
@@ -98917,8 +99037,14 @@ var searchCommand5 = defineCommand268({
98917
99037
  diverse: args8.diverse
98918
99038
  };
98919
99039
  const body = buildSearchBody2(searchArgs);
98920
- rejectInvalidSearch(searchArgs, body);
98921
- const data = await apiPost("/api/ad-library/winners/search", body);
99040
+ const rejection = searchRejection(searchArgs, body);
99041
+ if (rejection) {
99042
+ writeJson({ ok: false, error: { code: "VALIDATION_ERROR", ...rejection } });
99043
+ process.exit(1);
99044
+ }
99045
+ const data = await apiPost("/api/ad-library/winners/search", body, {
99046
+ timeoutMs: SEARCH_TIMEOUT_MS
99047
+ });
98922
99048
  writeSearchResult(data, {
98923
99049
  output: args8.output || "json",
98924
99050
  fields: args8.fields ? args8.fields.split(",") : void 0,