@koda-sl/baker-cli 0.142.0 → 0.144.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 +15 -1
- package/dist/cli.js +240 -24
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2132,7 +2132,11 @@ baker videos search "tutorial" --tags explainer,ugc --limit 5
|
|
|
2132
2132
|
|
|
2133
2133
|
### `baker videos get <id>`
|
|
2134
2134
|
|
|
2135
|
-
Get a single video by ID.
|
|
2135
|
+
Get a single video by ID. `--full` includes the auto-generated **transcript** (Baker transcribes every upload with speech-to-text), a `transcript_segment_count`, and the titled/timestamped **scene breakdown** — so you can read what a clip says and shows without watching it. Default JSON also returns the raw `transcript` + timed `transcriptSegments`; `--full` is what surfaces them in `--output md`/`files` too.
|
|
2136
|
+
|
|
2137
|
+
```bash
|
|
2138
|
+
baker videos get j571abc123 --full --output md
|
|
2139
|
+
```
|
|
2136
2140
|
|
|
2137
2141
|
### `baker videos upload <file>`
|
|
2138
2142
|
|
|
@@ -2326,6 +2330,16 @@ Top winning ads for one advertiser id → `GET /api/ad-library/advertiser-winner
|
|
|
2326
2330
|
baker winning-ads winners adv_123 --top 15 --output md
|
|
2327
2331
|
```
|
|
2328
2332
|
|
|
2333
|
+
### `baker winning-ads content <ad-id>`
|
|
2334
|
+
|
|
2335
|
+
Read what's **inside** one ad → `GET /api/ad-library/ad-content`. `search`/`winners`/`feed` return a lean shortlist; this opens a single `ad_id` so you can understand a reference before reproducing it. For a **video** it returns the spoken `transcript`, the `on_screen_text` overlays, and the ad `copy` (`primary_text`/`headline`/`cta`); a **static** ad returns only the copy. Add `--full` for speech (voiceover style, speaker count, direct-address), pacing (scene count, shot length, key timeline moments), any recognised soundtrack, and each on-screen overlay's role + position (e.g. `GLOBAL PAYROLL @0.5s [hook, top]`) so you can place text faithfully. `--platform meta|linkedin` selects which platform the id is on (default `meta`).
|
|
2336
|
+
|
|
2337
|
+
```bash
|
|
2338
|
+
baker winning-ads content adg_123 # transcript + on-screen text + copy
|
|
2339
|
+
baker winning-ads content adg_123 --platform meta --full # + speech, pacing, soundtrack
|
|
2340
|
+
baker winning-ads content adg_123 --full --output md
|
|
2341
|
+
```
|
|
2342
|
+
|
|
2329
2343
|
### `baker winning-ads unfollow <advertiser>`
|
|
2330
2344
|
|
|
2331
2345
|
Stop following a brand by advertiser id → `POST /api/ad-library/unfollow`. Returns `{ removed }`.
|
package/dist/cli.js
CHANGED
|
@@ -73,7 +73,7 @@ import {
|
|
|
73
73
|
} from "./chunk-RK67WL4O.js";
|
|
74
74
|
|
|
75
75
|
// src/cli.ts
|
|
76
|
-
import { defineCommand as
|
|
76
|
+
import { defineCommand as defineCommand178, runMain } from "citty";
|
|
77
77
|
|
|
78
78
|
// src/commands/actions/index.ts
|
|
79
79
|
import { defineCommand as defineCommand18 } from "citty";
|
|
@@ -145,6 +145,22 @@ function compactVideo(video) {
|
|
|
145
145
|
status: String(video.status ?? "")
|
|
146
146
|
};
|
|
147
147
|
}
|
|
148
|
+
function sceneLines(value) {
|
|
149
|
+
if (!Array.isArray(value)) {
|
|
150
|
+
return [];
|
|
151
|
+
}
|
|
152
|
+
return value.flatMap((s) => {
|
|
153
|
+
const scene = asRecord(s);
|
|
154
|
+
const title = typeof scene.title === "string" ? scene.title : "";
|
|
155
|
+
if (!title) {
|
|
156
|
+
return [];
|
|
157
|
+
}
|
|
158
|
+
const start = round2(scene.startSecond);
|
|
159
|
+
const end = round2(scene.endSecond);
|
|
160
|
+
const range = start !== null && end !== null ? ` (${start}-${end}s)` : "";
|
|
161
|
+
return [`${title}${range}`];
|
|
162
|
+
});
|
|
163
|
+
}
|
|
148
164
|
function fullVideo(video) {
|
|
149
165
|
const compact = compactVideo(video);
|
|
150
166
|
return {
|
|
@@ -152,6 +168,12 @@ function fullVideo(video) {
|
|
|
152
168
|
duration: video.duration ?? null,
|
|
153
169
|
muxPlaybackId: String(video.muxPlaybackId ?? ""),
|
|
154
170
|
source: String(video.source ?? ""),
|
|
171
|
+
// The spoken transcript + AI scene breakdown of the client's own clip — the
|
|
172
|
+
// "understand what's in this video" payload. Kept out of the compact/search
|
|
173
|
+
// projection (too large for a list) and surfaced here on --full.
|
|
174
|
+
transcript: video.transcript ?? null,
|
|
175
|
+
transcript_segment_count: Array.isArray(video.transcriptSegments) ? video.transcriptSegments.length : 0,
|
|
176
|
+
scenes: sceneLines(video.scenes),
|
|
155
177
|
createdAt: video.createdAt ?? null
|
|
156
178
|
};
|
|
157
179
|
}
|
|
@@ -243,6 +265,76 @@ function winningAdNormalizer(record, full) {
|
|
|
243
265
|
}
|
|
244
266
|
return compactWinningAd(record);
|
|
245
267
|
}
|
|
268
|
+
function overlayLines(value, detailed = false) {
|
|
269
|
+
if (!Array.isArray(value)) {
|
|
270
|
+
return [];
|
|
271
|
+
}
|
|
272
|
+
return value.flatMap((o) => {
|
|
273
|
+
const item = asRecord(o);
|
|
274
|
+
const text = typeof item.text === "string" ? item.text : "";
|
|
275
|
+
if (!text) {
|
|
276
|
+
return [];
|
|
277
|
+
}
|
|
278
|
+
const at = round2(item.appears_at_s);
|
|
279
|
+
let line = at !== null ? `${text} @${at}s` : text;
|
|
280
|
+
if (detailed) {
|
|
281
|
+
const tags = [item.role, item.position].filter((t) => typeof t === "string" && t.length > 0);
|
|
282
|
+
if (tags.length) {
|
|
283
|
+
line += ` [${tags.join(", ")}]`;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return [line];
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
function compactAdContent(record) {
|
|
290
|
+
return {
|
|
291
|
+
ad_id: record.ad_id ?? null,
|
|
292
|
+
advertiser: record.advertiser ?? null,
|
|
293
|
+
format: record.format ?? null,
|
|
294
|
+
media_kind: record.media_kind ?? null,
|
|
295
|
+
media_url: record.media_url ?? null,
|
|
296
|
+
summary: record.summary ?? null,
|
|
297
|
+
transcript: record.transcript ?? null,
|
|
298
|
+
on_screen_text: overlayLines(record.on_screen_text),
|
|
299
|
+
has_captions: typeof record.has_captions === "boolean" ? record.has_captions : null,
|
|
300
|
+
primary_text: record.primary_text ?? null,
|
|
301
|
+
headline: record.headline ?? null,
|
|
302
|
+
cta: record.cta ?? null
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
function fullAdContent(record) {
|
|
306
|
+
const speech = asRecord(record.speech);
|
|
307
|
+
const pacing = asRecord(record.pacing);
|
|
308
|
+
const music = asRecord(record.music);
|
|
309
|
+
return {
|
|
310
|
+
...compactAdContent(record),
|
|
311
|
+
platform: record.platform ?? null,
|
|
312
|
+
// Re-derive with role/position tags — the lean compact version dropped them.
|
|
313
|
+
on_screen_text: overlayLines(record.on_screen_text, true),
|
|
314
|
+
winner_score: round2(record.winner_score),
|
|
315
|
+
winner_category: record.winner_category ?? null,
|
|
316
|
+
angle: record.angle ?? null,
|
|
317
|
+
hook_archetype: record.hook_archetype ?? null,
|
|
318
|
+
caption_style: record.caption_style ?? null,
|
|
319
|
+
has_speech: typeof record.has_speech === "boolean" ? record.has_speech : null,
|
|
320
|
+
speech_pct_of_runtime: round2(speech.speech_pct_of_runtime),
|
|
321
|
+
speaker_count: speech.speaker_count ?? null,
|
|
322
|
+
voiceover_vs_sync: speech.voiceover_vs_sync ?? null,
|
|
323
|
+
is_direct_address: typeof speech.is_direct_address === "boolean" ? speech.is_direct_address : null,
|
|
324
|
+
speech_emotion_dominant: speech.speech_emotion_dominant ?? null,
|
|
325
|
+
scene_count: pacing.scene_count ?? null,
|
|
326
|
+
avg_shot_length_s: round2(pacing.avg_shot_length_s),
|
|
327
|
+
pacing_shape: pacing.pacing_shape ?? null,
|
|
328
|
+
hook_ends_at_s: round2(pacing.hook_ends_at_s),
|
|
329
|
+
cta_first_shown_at_s: round2(pacing.cta_first_shown_at_s),
|
|
330
|
+
product_first_appears_at_s: round2(pacing.product_first_appears_at_s),
|
|
331
|
+
music_track_title: music.track_title ?? null,
|
|
332
|
+
music_track_artist: music.track_artist ?? null
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
function adContentNormalizer(record, full) {
|
|
336
|
+
return full ? fullAdContent(record) : compactAdContent(record);
|
|
337
|
+
}
|
|
246
338
|
function applyFieldMask(data, fields) {
|
|
247
339
|
const result = {};
|
|
248
340
|
for (const field of fields) {
|
|
@@ -1135,6 +1227,65 @@ var seedCatalogResponseSchema = z2.object({
|
|
|
1135
1227
|
segment: seedCatalogSegmentSchema.nullable(),
|
|
1136
1228
|
patterns: z2.array(patternSeedSchema)
|
|
1137
1229
|
});
|
|
1230
|
+
var adContentRequestSchema = z2.object({
|
|
1231
|
+
ad_id: z2.string().min(1),
|
|
1232
|
+
platform: adLibraryPlatformSchema.optional()
|
|
1233
|
+
});
|
|
1234
|
+
var adContentOverlaySchema = z2.object({
|
|
1235
|
+
text: z2.string(),
|
|
1236
|
+
appears_at_s: z2.number().nullable(),
|
|
1237
|
+
position: z2.string().nullable(),
|
|
1238
|
+
role: z2.string().nullable()
|
|
1239
|
+
});
|
|
1240
|
+
var adContentSpeechSchema = z2.object({
|
|
1241
|
+
speech_pct_of_runtime: z2.number().nullable(),
|
|
1242
|
+
speaker_count: z2.number().nullable(),
|
|
1243
|
+
voiceover_vs_sync: z2.string().nullable(),
|
|
1244
|
+
is_direct_address: z2.boolean().nullable(),
|
|
1245
|
+
speech_emotion_dominant: z2.string().nullable()
|
|
1246
|
+
});
|
|
1247
|
+
var adContentPacingSchema = z2.object({
|
|
1248
|
+
scene_count: z2.number().nullable(),
|
|
1249
|
+
avg_shot_length_s: z2.number().nullable(),
|
|
1250
|
+
pacing_shape: z2.string().nullable(),
|
|
1251
|
+
hook_ends_at_s: z2.number().nullable(),
|
|
1252
|
+
cta_first_shown_at_s: z2.number().nullable(),
|
|
1253
|
+
product_first_appears_at_s: z2.number().nullable()
|
|
1254
|
+
});
|
|
1255
|
+
var adContentMusicSchema = z2.object({
|
|
1256
|
+
track_title: z2.string().nullable(),
|
|
1257
|
+
track_artist: z2.string().nullable()
|
|
1258
|
+
});
|
|
1259
|
+
var adContentSchema = z2.object({
|
|
1260
|
+
ad_id: z2.string().nullable(),
|
|
1261
|
+
advertiser: z2.string().nullable(),
|
|
1262
|
+
advertiser_id: z2.string().nullable(),
|
|
1263
|
+
platform: z2.string().nullable(),
|
|
1264
|
+
format: z2.string().nullable(),
|
|
1265
|
+
media_kind: z2.string().nullable(),
|
|
1266
|
+
media_url: z2.string().nullable(),
|
|
1267
|
+
winner_score: z2.number().nullable(),
|
|
1268
|
+
winner_category: z2.string().nullable(),
|
|
1269
|
+
summary: z2.string().nullable(),
|
|
1270
|
+
angle: z2.string().nullable(),
|
|
1271
|
+
hook_archetype: z2.string().nullable(),
|
|
1272
|
+
// Spoken words (video only; null when the ad has no speech track).
|
|
1273
|
+
transcript: z2.string().nullable(),
|
|
1274
|
+
has_speech: z2.boolean().nullable(),
|
|
1275
|
+
speech: adContentSpeechSchema,
|
|
1276
|
+
// On-screen text / captions.
|
|
1277
|
+
has_captions: z2.boolean().nullable(),
|
|
1278
|
+
caption_style: z2.string().nullable(),
|
|
1279
|
+
on_screen_text: z2.array(adContentOverlaySchema),
|
|
1280
|
+
// Copy the viewer reads outside the media.
|
|
1281
|
+
primary_text: z2.string().nullable(),
|
|
1282
|
+
headline: z2.string().nullable(),
|
|
1283
|
+
cta: z2.string().nullable(),
|
|
1284
|
+
// Structure + soundtrack.
|
|
1285
|
+
pacing: adContentPacingSchema,
|
|
1286
|
+
music: adContentMusicSchema
|
|
1287
|
+
});
|
|
1288
|
+
var adContentResponseSchema = z2.object({ ad: adContentSchema });
|
|
1138
1289
|
|
|
1139
1290
|
// ../api/src/ads-linkedin/limits.ts
|
|
1140
1291
|
var LINKEDIN_LIMITS = {
|
|
@@ -4923,7 +5074,7 @@ var demandGenAdSchema = z12.object({
|
|
|
4923
5074
|
squareImageAssets: z12.array(refSchema).optional(),
|
|
4924
5075
|
logoImageAssets: z12.array(refSchema).optional()
|
|
4925
5076
|
});
|
|
4926
|
-
var
|
|
5077
|
+
var adContentSchema2 = z12.discriminatedUnion("format", [
|
|
4927
5078
|
responsiveSearchAdSchema,
|
|
4928
5079
|
responsiveDisplayAdSchema,
|
|
4929
5080
|
callAdSchema,
|
|
@@ -4934,7 +5085,7 @@ var adContentSchema = z12.discriminatedUnion("format", [
|
|
|
4934
5085
|
var adCreateSchema = z12.object({
|
|
4935
5086
|
adGroup: refSchema,
|
|
4936
5087
|
status: stageableStatusSchema2.default("PAUSED"),
|
|
4937
|
-
content:
|
|
5088
|
+
content: adContentSchema2
|
|
4938
5089
|
});
|
|
4939
5090
|
var adUpdateSchema = z12.object({
|
|
4940
5091
|
status: z12.enum(["ENABLED", "PAUSED", "REMOVED"]).optional(),
|
|
@@ -29434,7 +29585,7 @@ Full guide: __tooling__/docs/tools/baker/videos.md`
|
|
|
29434
29585
|
});
|
|
29435
29586
|
|
|
29436
29587
|
// src/commands/winning-ads/index.ts
|
|
29437
|
-
import { defineCommand as
|
|
29588
|
+
import { defineCommand as defineCommand177 } from "citty";
|
|
29438
29589
|
|
|
29439
29590
|
// src/commands/winning-ads/advertisers.ts
|
|
29440
29591
|
import { defineCommand as defineCommand165 } from "citty";
|
|
@@ -29629,8 +29780,70 @@ var briefCommand = defineCommand166({
|
|
|
29629
29780
|
}
|
|
29630
29781
|
});
|
|
29631
29782
|
|
|
29632
|
-
// src/commands/winning-ads/
|
|
29783
|
+
// src/commands/winning-ads/content.ts
|
|
29633
29784
|
import { defineCommand as defineCommand167 } from "citty";
|
|
29785
|
+
registerSchema({
|
|
29786
|
+
command: "winning-ads.content",
|
|
29787
|
+
description: "Read what's INSIDE one winning ad: the spoken transcript, the on-screen text, and the ad copy. Use this after `search`/`winners`/`feed` return a shortlist \u2014 pass an ad_id to understand a reference before reproducing it. Add --full for speech, pacing, and soundtrack detail. Video ads carry the transcript/on-screen text; static ads carry only the copy.",
|
|
29788
|
+
args: {
|
|
29789
|
+
"ad-id": { type: "string", description: "The ad id to open (from search/winners/feed results)", required: true },
|
|
29790
|
+
platform: {
|
|
29791
|
+
type: "string",
|
|
29792
|
+
description: "Which platform the ad id is on: meta|linkedin (default meta)",
|
|
29793
|
+
required: false
|
|
29794
|
+
}
|
|
29795
|
+
}
|
|
29796
|
+
});
|
|
29797
|
+
var contentCommand = defineCommand167({
|
|
29798
|
+
meta: {
|
|
29799
|
+
name: "content",
|
|
29800
|
+
description: "Read the transcript + on-screen text + copy of one winning ad. Example: baker winning-ads content adg_123 --platform meta --full --output md"
|
|
29801
|
+
},
|
|
29802
|
+
args: {
|
|
29803
|
+
"ad-id": { type: "positional", description: "Ad id (from search/winners/feed)", required: true },
|
|
29804
|
+
platform: {
|
|
29805
|
+
type: "string",
|
|
29806
|
+
description: "Platform the ad id is on: meta|linkedin (default meta)",
|
|
29807
|
+
required: false
|
|
29808
|
+
},
|
|
29809
|
+
output: { type: "string", description: "Output format: json|files|md", required: false, default: "json" },
|
|
29810
|
+
fields: { type: "string", description: "Comma-separated field names to include", required: false },
|
|
29811
|
+
full: {
|
|
29812
|
+
type: "boolean",
|
|
29813
|
+
description: "Include speech, pacing, and soundtrack detail",
|
|
29814
|
+
required: false,
|
|
29815
|
+
default: false
|
|
29816
|
+
}
|
|
29817
|
+
},
|
|
29818
|
+
run: async ({ args }) => {
|
|
29819
|
+
try {
|
|
29820
|
+
const params = { id: String(args["ad-id"]) };
|
|
29821
|
+
if (args.platform) {
|
|
29822
|
+
params.platform = String(args.platform);
|
|
29823
|
+
}
|
|
29824
|
+
const data = await apiGet("/api/ad-library/ad-content", params);
|
|
29825
|
+
const output = args.output || "json";
|
|
29826
|
+
const full = args.full;
|
|
29827
|
+
const ad = data?.ad ?? {};
|
|
29828
|
+
if (output === "json") {
|
|
29829
|
+
writeJson({ ok: true, data: { ad: adContentNormalizer(ad, full) } });
|
|
29830
|
+
return;
|
|
29831
|
+
}
|
|
29832
|
+
writeOutput(
|
|
29833
|
+
{ ok: true, data: ad },
|
|
29834
|
+
output,
|
|
29835
|
+
args.fields ? args.fields.split(",") : void 0,
|
|
29836
|
+
full,
|
|
29837
|
+
adContentNormalizer
|
|
29838
|
+
);
|
|
29839
|
+
} catch (err) {
|
|
29840
|
+
reportError(err);
|
|
29841
|
+
}
|
|
29842
|
+
}
|
|
29843
|
+
});
|
|
29844
|
+
|
|
29845
|
+
// src/commands/winning-ads/feed.ts
|
|
29846
|
+
import { defineCommand as defineCommand168 } from "citty";
|
|
29634
29847
|
function buildFeedParams(input) {
|
|
29635
29848
|
const params = {};
|
|
29636
29849
|
const advertiser = splitList(input.advertiser);
|
|
@@ -29682,7 +29895,7 @@ registerSchema({
|
|
|
29682
29895
|
format: { type: "string", description: "Comma-separated formats to include (e.g. static,video)", required: false }
|
|
29683
29896
|
}
|
|
29684
29897
|
});
|
|
29685
|
-
var feedCommand =
|
|
29898
|
+
var feedCommand = defineCommand168({
|
|
29686
29899
|
meta: {
|
|
29687
29900
|
name: "feed",
|
|
29688
29901
|
description: "Winners across every brand you follow (browse, then trim per advertiser). Example: baker winning-ads feed --per-advertiser 5 --output md"
|
|
@@ -29767,7 +29980,7 @@ var feedCommand = defineCommand167({
|
|
|
29767
29980
|
});
|
|
29768
29981
|
|
|
29769
29982
|
// src/commands/winning-ads/follow.ts
|
|
29770
|
-
import { defineCommand as
|
|
29983
|
+
import { defineCommand as defineCommand169 } from "citty";
|
|
29771
29984
|
var PLATFORMS = ["meta", "linkedin"];
|
|
29772
29985
|
registerSchema({
|
|
29773
29986
|
command: "winning-ads.follow",
|
|
@@ -29782,7 +29995,7 @@ registerSchema({
|
|
|
29782
29995
|
label: { type: "string", description: "Optional display label (defaults to the resolved name)", required: false }
|
|
29783
29996
|
}
|
|
29784
29997
|
});
|
|
29785
|
-
var followCommand =
|
|
29998
|
+
var followCommand = defineCommand169({
|
|
29786
29999
|
meta: {
|
|
29787
30000
|
name: "follow",
|
|
29788
30001
|
description: 'Follow a brand to track ALL its ads \u2014 every platform and country. --platform is how we read your input, not a limit. A domain tracks both Meta + LinkedIn. Example: baker winning-ads follow "deel.com" --platform meta'
|
|
@@ -29829,7 +30042,7 @@ var followCommand = defineCommand168({
|
|
|
29829
30042
|
});
|
|
29830
30043
|
|
|
29831
30044
|
// src/commands/winning-ads/follow-competitors.ts
|
|
29832
|
-
import { defineCommand as
|
|
30045
|
+
import { defineCommand as defineCommand170 } from "citty";
|
|
29833
30046
|
var PLATFORMS2 = ["meta", "linkedin"];
|
|
29834
30047
|
var BATCH_TIMEOUT_MS = 3e5;
|
|
29835
30048
|
function buildFollowBatchBody(input) {
|
|
@@ -29862,7 +30075,7 @@ registerSchema({
|
|
|
29862
30075
|
}
|
|
29863
30076
|
}
|
|
29864
30077
|
});
|
|
29865
|
-
var followCompetitorsCommand =
|
|
30078
|
+
var followCompetitorsCommand = defineCommand170({
|
|
29866
30079
|
meta: {
|
|
29867
30080
|
name: "follow-competitors",
|
|
29868
30081
|
description: 'Follow many brands at once by domain \u2014 add every competitor in one call. Example: baker winning-ads follow-competitors "deel.com,notion.so,hubspot.com"'
|
|
@@ -29937,7 +30150,7 @@ var followCompetitorsCommand = defineCommand169({
|
|
|
29937
30150
|
});
|
|
29938
30151
|
|
|
29939
30152
|
// src/commands/winning-ads/following.ts
|
|
29940
|
-
import { defineCommand as
|
|
30153
|
+
import { defineCommand as defineCommand171 } from "citty";
|
|
29941
30154
|
registerSchema({
|
|
29942
30155
|
command: "winning-ads.following",
|
|
29943
30156
|
description: "List the brands you follow in your ad-dna library, with each one's status (ready vs still adding) and cached ad counts.",
|
|
@@ -29970,7 +30183,7 @@ function followingNormalizer(record, full) {
|
|
|
29970
30183
|
platforms: Array.isArray(record.platforms) ? record.platforms : []
|
|
29971
30184
|
};
|
|
29972
30185
|
}
|
|
29973
|
-
var followingCommand =
|
|
30186
|
+
var followingCommand = defineCommand171({
|
|
29974
30187
|
meta: {
|
|
29975
30188
|
name: "following",
|
|
29976
30189
|
description: "List brands you follow, with status (ready / adding\u2026) and cached counts. Example: baker winning-ads following --output md"
|
|
@@ -30005,7 +30218,7 @@ var followingCommand = defineCommand170({
|
|
|
30005
30218
|
});
|
|
30006
30219
|
|
|
30007
30220
|
// src/commands/winning-ads/patterns.ts
|
|
30008
|
-
import { defineCommand as
|
|
30221
|
+
import { defineCommand as defineCommand172 } from "citty";
|
|
30009
30222
|
registerSchema({
|
|
30010
30223
|
command: "winning-ads.patterns",
|
|
30011
30224
|
description: "Mine what separates two cohorts of ads: pass a comma-list of winning ad ids (--winners) and a comma-list of weaker ad ids (--duds). Returns the discriminating DNA fields.",
|
|
@@ -30044,7 +30257,7 @@ function discriminatorRow(record) {
|
|
|
30044
30257
|
top_values_duds: Array.isArray(record.top_values_b) ? record.top_values_b.join(", ") : ""
|
|
30045
30258
|
};
|
|
30046
30259
|
}
|
|
30047
|
-
var patternsCommand =
|
|
30260
|
+
var patternsCommand = defineCommand172({
|
|
30048
30261
|
meta: {
|
|
30049
30262
|
name: "patterns",
|
|
30050
30263
|
description: "Discover what separates winning ads from weak ones. Example: baker winning-ads patterns --winners a_1,a_2,a_3 --duds a_9,a_8 --output md"
|
|
@@ -30100,7 +30313,7 @@ var patternsCommand = defineCommand171({
|
|
|
30100
30313
|
});
|
|
30101
30314
|
|
|
30102
30315
|
// src/commands/winning-ads/search.ts
|
|
30103
|
-
import { defineCommand as
|
|
30316
|
+
import { defineCommand as defineCommand173 } from "citty";
|
|
30104
30317
|
registerSchema({
|
|
30105
30318
|
command: "winning-ads.search",
|
|
30106
30319
|
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.",
|
|
@@ -30208,7 +30421,7 @@ function buildSearchBody(args) {
|
|
|
30208
30421
|
}
|
|
30209
30422
|
return body;
|
|
30210
30423
|
}
|
|
30211
|
-
var searchCommand4 =
|
|
30424
|
+
var searchCommand4 = defineCommand173({
|
|
30212
30425
|
meta: {
|
|
30213
30426
|
name: "search",
|
|
30214
30427
|
description: "Search winning reference ads. Example: baker winning-ads search 'B2B SaaS before/after AI automation' --platform meta --format static --winner-category winner --exclude-advertiser adv_123 --output md"
|
|
@@ -30323,7 +30536,7 @@ var searchCommand4 = defineCommand172({
|
|
|
30323
30536
|
});
|
|
30324
30537
|
|
|
30325
30538
|
// src/commands/winning-ads/seeds.ts
|
|
30326
|
-
import { defineCommand as
|
|
30539
|
+
import { defineCommand as defineCommand174 } from "citty";
|
|
30327
30540
|
function leanRow(r) {
|
|
30328
30541
|
return {
|
|
30329
30542
|
key: r.key,
|
|
@@ -30351,7 +30564,7 @@ function makeSeedCommand(opts) {
|
|
|
30351
30564
|
limit: { type: "number", description: "Max keys 1-100 (default 20)", required: false, default: 20 }
|
|
30352
30565
|
}
|
|
30353
30566
|
});
|
|
30354
|
-
return
|
|
30567
|
+
return defineCommand174({
|
|
30355
30568
|
meta: { name: opts.name, description: opts.description },
|
|
30356
30569
|
args: {
|
|
30357
30570
|
platform: { type: "string", description: "Single platform to segment on", required: false },
|
|
@@ -30400,7 +30613,7 @@ var formatsCommand = makeSeedCommand({
|
|
|
30400
30613
|
});
|
|
30401
30614
|
|
|
30402
30615
|
// src/commands/winning-ads/unfollow.ts
|
|
30403
|
-
import { defineCommand as
|
|
30616
|
+
import { defineCommand as defineCommand175 } from "citty";
|
|
30404
30617
|
registerSchema({
|
|
30405
30618
|
command: "winning-ads.unfollow",
|
|
30406
30619
|
description: "Stop following a brand \u2014 removes it from your ad-dna library by advertiser id.",
|
|
@@ -30408,7 +30621,7 @@ registerSchema({
|
|
|
30408
30621
|
advertiser: { type: "string", description: "Advertiser id to unfollow", required: true }
|
|
30409
30622
|
}
|
|
30410
30623
|
});
|
|
30411
|
-
var unfollowCommand =
|
|
30624
|
+
var unfollowCommand = defineCommand175({
|
|
30412
30625
|
meta: {
|
|
30413
30626
|
name: "unfollow",
|
|
30414
30627
|
description: "Stop following a brand by advertiser id. Example: baker winning-ads unfollow adv_123"
|
|
@@ -30429,7 +30642,7 @@ var unfollowCommand = defineCommand174({
|
|
|
30429
30642
|
});
|
|
30430
30643
|
|
|
30431
30644
|
// src/commands/winning-ads/winners.ts
|
|
30432
|
-
import { defineCommand as
|
|
30645
|
+
import { defineCommand as defineCommand176 } from "citty";
|
|
30433
30646
|
registerSchema({
|
|
30434
30647
|
command: "winning-ads.winners",
|
|
30435
30648
|
description: "Top winning ads for one advertiser id (from `advertisers` or `following`). Returns lean winner cards; add --full for DNA + longevity.",
|
|
@@ -30439,7 +30652,7 @@ registerSchema({
|
|
|
30439
30652
|
platform: { type: "string", description: "Filter to a single platform: meta|linkedin", required: false }
|
|
30440
30653
|
}
|
|
30441
30654
|
});
|
|
30442
|
-
var winnersCommand =
|
|
30655
|
+
var winnersCommand = defineCommand176({
|
|
30443
30656
|
meta: {
|
|
30444
30657
|
name: "winners",
|
|
30445
30658
|
description: "Top winning ads for a specific advertiser id. Example: baker winning-ads winners adv_123 --top 15 --output md"
|
|
@@ -30489,7 +30702,7 @@ var winnersCommand = defineCommand175({
|
|
|
30489
30702
|
});
|
|
30490
30703
|
|
|
30491
30704
|
// src/commands/winning-ads/index.ts
|
|
30492
|
-
var winningAdsCommand =
|
|
30705
|
+
var winningAdsCommand = defineCommand177({
|
|
30493
30706
|
meta: {
|
|
30494
30707
|
name: "winning-ads",
|
|
30495
30708
|
description: `Search the ad-dna corpus of scored "winning" ads for reference creatives to reproduce, and manage the brands your library tracks. Proxied through the Baker backend (BAKER_API_KEY) \u2014 no separate token needed.
|
|
@@ -30504,6 +30717,7 @@ Subcommands:
|
|
|
30504
30717
|
baker winning-ads following \u2014 list brands you follow (status + counts)
|
|
30505
30718
|
baker winning-ads feed \u2014 winners across EVERY brand you follow; trim with --advertiser
|
|
30506
30719
|
baker winning-ads winners <advertiser> \u2014 top winners for one advertiser id
|
|
30720
|
+
baker winning-ads content <ad-id> \u2014 read ONE ad's transcript + on-screen text + copy (understand a reference before reproducing it)
|
|
30507
30721
|
baker winning-ads unfollow <advertiser> \u2014 stop following a brand
|
|
30508
30722
|
baker winning-ads brief \u2014 creative brief grounded in similar winners
|
|
30509
30723
|
baker winning-ads patterns --winners \u2026 --duds \u2026 \u2014 what separates a winning cohort from a weak one
|
|
@@ -30519,6 +30733,7 @@ Examples:
|
|
|
30519
30733
|
baker winning-ads feed --per-advertiser 5 --output md
|
|
30520
30734
|
baker winning-ads feed --advertiser adv_123,adv_456 --platform meta --output md
|
|
30521
30735
|
baker winning-ads winners adv_123 --top 15 --output md
|
|
30736
|
+
baker winning-ads content adg_123 --full --output md
|
|
30522
30737
|
baker winning-ads hooks --platform meta --awareness problem_aware --industry saas --output md
|
|
30523
30738
|
baker winning-ads search "fintech onboarding" --hook-archetype callout --winner-category winner --output md
|
|
30524
30739
|
baker winning-ads patterns --winners a_1,a_2 --duds a_9,a_8 --output md
|
|
@@ -30532,6 +30747,7 @@ Full guide: __tooling__/docs/tools/baker/winning-ads.md`
|
|
|
30532
30747
|
following: followingCommand,
|
|
30533
30748
|
feed: feedCommand,
|
|
30534
30749
|
winners: winnersCommand,
|
|
30750
|
+
content: contentCommand,
|
|
30535
30751
|
unfollow: unfollowCommand,
|
|
30536
30752
|
brief: briefCommand,
|
|
30537
30753
|
patterns: patternsCommand,
|
|
@@ -30558,7 +30774,7 @@ function getCliVersion() {
|
|
|
30558
30774
|
}
|
|
30559
30775
|
|
|
30560
30776
|
// src/cli.ts
|
|
30561
|
-
var main =
|
|
30777
|
+
var main = defineCommand178({
|
|
30562
30778
|
meta: {
|
|
30563
30779
|
name: "baker",
|
|
30564
30780
|
version: getCliVersion(),
|