@koda-sl/baker-cli 0.133.3 → 0.135.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 +24 -3
- package/dist/cli.js +191 -26
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2185,7 +2185,7 @@ baker testimonials tags
|
|
|
2185
2185
|
|
|
2186
2186
|
### Winning Ads (`baker winning-ads`)
|
|
2187
2187
|
|
|
2188
|
-
Search the **ad-dna** corpus of scored "winning" competitor ads for reference creatives to reproduce (e.g. with `baker canvas`), and manage the brands your library tracks (`follow` / `following` / `unfollow`). Each result carries a presigned media URL (~1h TTL), the ad's DNA summary, and scores. The CLI authenticates with the normal `BAKER_API_KEY`; the Baker backend proxies the request to the ad-dna service with a server-held token — no extra credential in the sandbox.
|
|
2188
|
+
Search the **ad-dna** corpus of scored "winning" competitor ads for reference creatives to reproduce (e.g. with `baker canvas`), and manage the brands your library tracks (`follow` / `following` / `feed` / `unfollow`). Each result carries a presigned media URL (~1h TTL), the ad's DNA summary, and scores. The CLI authenticates with the normal `BAKER_API_KEY`; the Baker backend proxies the request to the ad-dna service with a server-held token — no extra credential in the sandbox.
|
|
2189
2189
|
|
|
2190
2190
|
> The corpus has **Meta + LinkedIn** connectors, so `--platform` inputs are limited to `meta,linkedin`. (Older result rows may still carry a legacy platform string.)
|
|
2191
2191
|
|
|
@@ -2289,9 +2289,29 @@ List the brands you follow → `GET /api/ad-library/following`. Each row shows `
|
|
|
2289
2289
|
baker winning-ads following --output md
|
|
2290
2290
|
```
|
|
2291
2291
|
|
|
2292
|
+
### `baker winning-ads feed`
|
|
2293
|
+
|
|
2294
|
+
Winners across **every** brand you follow, in one library → `GET /api/ad-library/feed`. The advertiser set is derived server-side from your follows (never a client-supplied list), so this is the "what's winning across everyone I track" view. Start here, then trim to specific brands with `--advertiser adv_1,adv_2`. Capped per advertiser (`--per-advertiser`, default 5, `0` = no cap) so no single brand floods the feed — the cap is enforced server-side, so it holds even when you narrow to one advertiser. Same lean winner cards as `search` / `winners` (add `--full` for DNA + longevity).
|
|
2295
|
+
|
|
2296
|
+
Response `data`: `winners`, `following_count` (how many brands you follow), `advertiser_ids` (the ids actually queried = follows ∩ requested), and — when relevant — `hints` (e.g. you follow nobody yet, or a requested id isn't in your follows and was skipped). In `--output md`/`files` the table is the payload and the hints are written to **stderr** so they still surface without corrupting the output.
|
|
2297
|
+
|
|
2298
|
+
```bash
|
|
2299
|
+
baker winning-ads feed --per-advertiser 5 --output md
|
|
2300
|
+
baker winning-ads feed --advertiser adv_123,adv_456 --platform meta --output md
|
|
2301
|
+
```
|
|
2302
|
+
|
|
2303
|
+
| Flag | Purpose |
|
|
2304
|
+
|---|---|
|
|
2305
|
+
| `--advertiser <ids>` | Trim to a comma-separated subset of your followed advertiser ids (ids you don't follow are skipped and reported) |
|
|
2306
|
+
| `--platform meta\|linkedin` | Filter to a single platform |
|
|
2307
|
+
| `--per-advertiser <n>` | Max winners kept per advertiser 0–50 (`0` = no cap, default 5) |
|
|
2308
|
+
| `--limit <n>` | Total winners across all follows 1–200 (default 40) |
|
|
2309
|
+
| `--winner-category <list>` | Restrict to specific winner categories |
|
|
2310
|
+
| `--format <list>` | Restrict to specific formats (e.g. `static,video`) |
|
|
2311
|
+
|
|
2292
2312
|
### `baker winning-ads winners <advertiser>`
|
|
2293
2313
|
|
|
2294
|
-
Top winning ads for one advertiser id → `GET /api/ad-library/advertiser-winners
|
|
2314
|
+
Top winning ads for one advertiser id → `GET /api/ad-library/advertiser-winners` (use `feed` for all your follows at once). Same lean winner cards as `search` (add `--full` for DNA + longevity). Supports `--top N` and `--platform meta|linkedin`.
|
|
2295
2315
|
|
|
2296
2316
|
```bash
|
|
2297
2317
|
baker winning-ads winners adv_123 --top 15 --output md
|
|
@@ -2487,7 +2507,8 @@ Permissions enforced server-side:
|
|
|
2487
2507
|
|
|
2488
2508
|
- Only `claim`/`release` mutate live state.
|
|
2489
2509
|
- `claim` returns action details (`id`, `name`, `description`) plus `recommendedSkills` — a fast model reads the action's name/description/tags against the local `.claude/skills/` catalog and returns the skills (`{ name, reason }`) most worth loading for the work, echoed as `/skill — reason` lines in `hints`. It is best-effort: if the catalog is absent or the model call fails, the claim still succeeds and falls back to the generic "review and load relevant skills" hint.
|
|
2490
|
-
- `
|
|
2510
|
+
- `complete` and `unlink` require the action to be claimed by the current chat — otherwise the API returns `FORBIDDEN` with a hint to claim first. Completing is the record that the work is done, so it stays claim-gated.
|
|
2511
|
+
- `update` and `discard` do NOT require a claim — a chat may edit or retire an action it never claimed. They are blocked only when another chat currently holds the claim (`CONFLICT` with that chat's title).
|
|
2491
2512
|
- Claiming an action already claimed by another chat returns `CONFLICT` with the other chat's title — pick a different action.
|
|
2492
2513
|
- All staged ops are reverted automatically when the chat is discarded.
|
|
2493
2514
|
|
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 defineCommand172, runMain } from "citty";
|
|
77
77
|
|
|
78
78
|
// src/commands/actions/index.ts
|
|
79
79
|
import { defineCommand as defineCommand18 } from "citty";
|
|
@@ -507,7 +507,7 @@ function readSkillCatalog(startDir) {
|
|
|
507
507
|
// src/commands/actions/claim.ts
|
|
508
508
|
registerSchema({
|
|
509
509
|
command: "actions.claim",
|
|
510
|
-
description: "Claim an action for the current chat (live \u2014 visible to other chats immediately). Returns action details plus a fast-model recommendation of which skills to load for the work (`recommendedSkills`).",
|
|
510
|
+
description: "Claim an action for the current chat (live \u2014 visible to other chats immediately). Claim only what you're actively working on now: it's required before `complete`, but NOT for `update` or `discard` (those stage without a claim). Returns action details plus a fast-model recommendation of which skills to load for the work (`recommendedSkills`).",
|
|
511
511
|
args: {
|
|
512
512
|
id: { type: "string", description: "Action ID", required: true }
|
|
513
513
|
}
|
|
@@ -536,7 +536,7 @@ function buildHints(recommendations) {
|
|
|
536
536
|
var claimCommand = defineCommand({
|
|
537
537
|
meta: {
|
|
538
538
|
name: "claim",
|
|
539
|
-
description: "Claim an action so other chats see you're working on it. Required before update
|
|
539
|
+
description: "Claim an action so other chats see you're working on it. Required before `complete` (update and discard don't need a claim). Example: baker actions claim <action-id>"
|
|
540
540
|
},
|
|
541
541
|
args: {
|
|
542
542
|
id: { type: "positional", description: "Action ID", required: false },
|
|
@@ -1023,6 +1023,30 @@ var advertiserWinnersResponseSchema = z2.object({
|
|
|
1023
1023
|
advertiser_id: z2.string(),
|
|
1024
1024
|
winners: z2.array(winningAdSchema)
|
|
1025
1025
|
});
|
|
1026
|
+
var feedRequestSchema = z2.object({
|
|
1027
|
+
// Optional subset of your followed advertiser ids to narrow to ("trim down
|
|
1028
|
+
// per advertiser"). Ids you don't follow are ignored and echoed back in
|
|
1029
|
+
// `unknown_requested`. Omit to browse winners across every brand you follow.
|
|
1030
|
+
advertiser_ids: z2.array(z2.string()).optional(),
|
|
1031
|
+
platform: adLibraryPlatformSchema.optional(),
|
|
1032
|
+
winner_category: z2.array(z2.string()).optional(),
|
|
1033
|
+
format: z2.array(z2.string()).optional(),
|
|
1034
|
+
// Winners kept per advertiser so no single brand floods the feed. `0` = no
|
|
1035
|
+
// cap. Default applied by the route.
|
|
1036
|
+
per_advertiser: z2.number().int().min(0).max(50).optional(),
|
|
1037
|
+
// Total winners returned across all followed advertisers.
|
|
1038
|
+
limit: z2.number().int().min(1).max(200).optional()
|
|
1039
|
+
});
|
|
1040
|
+
var feedResponseSchema = z2.object({
|
|
1041
|
+
winners: z2.array(winningAdSchema),
|
|
1042
|
+
// How many brands the company follows (regardless of the trim).
|
|
1043
|
+
following_count: z2.number(),
|
|
1044
|
+
// The advertiser ids actually queried (follows ∩ requested subset).
|
|
1045
|
+
advertiser_ids: z2.array(z2.string()),
|
|
1046
|
+
// Requested ids that aren't followed — a hint the caller mistyped or hasn't
|
|
1047
|
+
// followed them yet.
|
|
1048
|
+
unknown_requested: z2.array(z2.string())
|
|
1049
|
+
});
|
|
1026
1050
|
var briefRequestSchema = z2.object({
|
|
1027
1051
|
// Partial DNA describing the target creative (all optional); the service
|
|
1028
1052
|
// pulls its own strategically-similar references.
|
|
@@ -2728,16 +2752,16 @@ var createCommand = defineCommand3({
|
|
|
2728
2752
|
import { defineCommand as defineCommand4 } from "citty";
|
|
2729
2753
|
registerSchema({
|
|
2730
2754
|
command: "actions.discard",
|
|
2731
|
-
description: "Stage discard of
|
|
2755
|
+
description: "Stage discard of an action \u2014 no claim needed; retire any action you're not working on. Applies on chat publish. Blocked only if another chat currently has it claimed.",
|
|
2732
2756
|
args: {
|
|
2733
|
-
id: { type: "string", description: "Action ID
|
|
2757
|
+
id: { type: "string", description: "Action ID", required: true },
|
|
2734
2758
|
reason: { type: "string", description: "Optional reason", required: false }
|
|
2735
2759
|
}
|
|
2736
2760
|
});
|
|
2737
2761
|
var discardCommand = defineCommand4({
|
|
2738
2762
|
meta: {
|
|
2739
2763
|
name: "discard",
|
|
2740
|
-
description: 'Stage discard of
|
|
2764
|
+
description: 'Stage discard of an action (no claim needed). Example: baker actions discard <id> --reason "obsolete"'
|
|
2741
2765
|
},
|
|
2742
2766
|
args: {
|
|
2743
2767
|
id: { type: "positional", description: "Action ID", required: false },
|
|
@@ -3316,9 +3340,9 @@ var unlinkCommand = defineCommand16({
|
|
|
3316
3340
|
import { defineCommand as defineCommand17 } from "citty";
|
|
3317
3341
|
registerSchema({
|
|
3318
3342
|
command: "actions.update",
|
|
3319
|
-
description: "Stage an update on
|
|
3343
|
+
description: "Stage an update on an action (name, description, tags, and/or priority) \u2014 no claim needed; edit any action you're not working on. Applies on publish. Blocked only if another chat currently has it claimed. --tags REPLACES the tag set; pass --tags '' to clear. --priority accepts urgent|high|medium|low or 'none' to clear back to unset (== normal).",
|
|
3320
3344
|
args: {
|
|
3321
|
-
id: { type: "string", description: "Action ID
|
|
3345
|
+
id: { type: "string", description: "Action ID", required: true },
|
|
3322
3346
|
name: { type: "string", description: "New name", required: false },
|
|
3323
3347
|
description: { type: "string", description: "New description", required: false },
|
|
3324
3348
|
tags: {
|
|
@@ -3336,7 +3360,7 @@ registerSchema({
|
|
|
3336
3360
|
var updateCommand = defineCommand17({
|
|
3337
3361
|
meta: {
|
|
3338
3362
|
name: "update",
|
|
3339
|
-
description: 'Stage an update on
|
|
3363
|
+
description: 'Stage an update on an action (no claim needed). Example: baker actions update <id> --name "New name"'
|
|
3340
3364
|
},
|
|
3341
3365
|
args: {
|
|
3342
3366
|
id: { type: "positional", description: "Action ID", required: false },
|
|
@@ -27258,7 +27282,7 @@ Examples:
|
|
|
27258
27282
|
});
|
|
27259
27283
|
|
|
27260
27284
|
// src/commands/winning-ads/index.ts
|
|
27261
|
-
import { defineCommand as
|
|
27285
|
+
import { defineCommand as defineCommand171 } from "citty";
|
|
27262
27286
|
|
|
27263
27287
|
// src/commands/winning-ads/advertisers.ts
|
|
27264
27288
|
import { defineCommand as defineCommand161 } from "citty";
|
|
@@ -27453,8 +27477,145 @@ var briefCommand = defineCommand162({
|
|
|
27453
27477
|
}
|
|
27454
27478
|
});
|
|
27455
27479
|
|
|
27456
|
-
// src/commands/winning-ads/
|
|
27480
|
+
// src/commands/winning-ads/feed.ts
|
|
27457
27481
|
import { defineCommand as defineCommand163 } from "citty";
|
|
27482
|
+
function buildFeedParams(input) {
|
|
27483
|
+
const params = {};
|
|
27484
|
+
const advertiser = splitList(input.advertiser);
|
|
27485
|
+
if (advertiser.length > 0) {
|
|
27486
|
+
params.advertiser = advertiser.join(",");
|
|
27487
|
+
}
|
|
27488
|
+
if (input.platform) {
|
|
27489
|
+
params.platform = input.platform;
|
|
27490
|
+
}
|
|
27491
|
+
if (input.perAdvertiser !== void 0 && input.perAdvertiser !== "") {
|
|
27492
|
+
params.per_advertiser = input.perAdvertiser;
|
|
27493
|
+
}
|
|
27494
|
+
if (input.limit !== void 0 && input.limit !== "") {
|
|
27495
|
+
params.limit = input.limit;
|
|
27496
|
+
}
|
|
27497
|
+
const winnerCategory = splitList(input.winnerCategory);
|
|
27498
|
+
if (winnerCategory.length > 0) {
|
|
27499
|
+
params.winner_category = winnerCategory.join(",");
|
|
27500
|
+
}
|
|
27501
|
+
const format = splitList(input.format);
|
|
27502
|
+
if (format.length > 0) {
|
|
27503
|
+
params.format = format.join(",");
|
|
27504
|
+
}
|
|
27505
|
+
return params;
|
|
27506
|
+
}
|
|
27507
|
+
registerSchema({
|
|
27508
|
+
command: "winning-ads.feed",
|
|
27509
|
+
description: "Winners across EVERY brand you follow, in one library. Start here to review your followed advertisers, then trim to specific ones with --advertiser. Capped per advertiser so no single brand floods the feed. Lean winner cards; add --full for DNA + longevity.",
|
|
27510
|
+
args: {
|
|
27511
|
+
advertiser: {
|
|
27512
|
+
type: "string",
|
|
27513
|
+
description: "Comma-separated followed advertiser ids to narrow to (from `following`). Omit for all follows.",
|
|
27514
|
+
required: false
|
|
27515
|
+
},
|
|
27516
|
+
platform: { type: "string", description: "Filter to a single platform: meta|linkedin", required: false },
|
|
27517
|
+
"per-advertiser": {
|
|
27518
|
+
type: "number",
|
|
27519
|
+
description: "Max winners kept per advertiser 0-50 (0 = no cap, default 5)",
|
|
27520
|
+
required: false,
|
|
27521
|
+
default: 5
|
|
27522
|
+
},
|
|
27523
|
+
limit: {
|
|
27524
|
+
type: "number",
|
|
27525
|
+
description: "Total winners across all follows 1-200 (default 40)",
|
|
27526
|
+
required: false,
|
|
27527
|
+
default: 40
|
|
27528
|
+
},
|
|
27529
|
+
"winner-category": { type: "string", description: "Comma-separated winner categories to include", required: false },
|
|
27530
|
+
format: { type: "string", description: "Comma-separated formats to include (e.g. static,video)", required: false }
|
|
27531
|
+
}
|
|
27532
|
+
});
|
|
27533
|
+
var feedCommand = defineCommand163({
|
|
27534
|
+
meta: {
|
|
27535
|
+
name: "feed",
|
|
27536
|
+
description: "Winners across every brand you follow (browse, then trim per advertiser). Example: baker winning-ads feed --per-advertiser 5 --output md"
|
|
27537
|
+
},
|
|
27538
|
+
args: {
|
|
27539
|
+
advertiser: {
|
|
27540
|
+
type: "string",
|
|
27541
|
+
description: "Comma-separated followed advertiser ids to narrow to",
|
|
27542
|
+
required: false
|
|
27543
|
+
},
|
|
27544
|
+
platform: { type: "string", description: "Filter to a single platform: meta|linkedin", required: false },
|
|
27545
|
+
"per-advertiser": {
|
|
27546
|
+
type: "string",
|
|
27547
|
+
description: "Max winners per advertiser 0-50 (0 = no cap, default 5)",
|
|
27548
|
+
required: false
|
|
27549
|
+
},
|
|
27550
|
+
limit: { type: "string", description: "Total winners 1-200 (default 40)", required: false },
|
|
27551
|
+
"winner-category": { type: "string", description: "Comma-separated winner categories", required: false },
|
|
27552
|
+
format: { type: "string", description: "Comma-separated formats", required: false },
|
|
27553
|
+
output: { type: "string", description: "Output format: json|files|md", required: false, default: "json" },
|
|
27554
|
+
fields: { type: "string", description: "Comma-separated field names to include", required: false },
|
|
27555
|
+
full: {
|
|
27556
|
+
type: "boolean",
|
|
27557
|
+
description: "Include DNA detail (angle, persona, hook) + longevity",
|
|
27558
|
+
required: false,
|
|
27559
|
+
default: false
|
|
27560
|
+
}
|
|
27561
|
+
},
|
|
27562
|
+
run: async ({ args }) => {
|
|
27563
|
+
try {
|
|
27564
|
+
const params = buildFeedParams({
|
|
27565
|
+
advertiser: args.advertiser,
|
|
27566
|
+
platform: args.platform,
|
|
27567
|
+
perAdvertiser: args["per-advertiser"],
|
|
27568
|
+
limit: args.limit,
|
|
27569
|
+
winnerCategory: args["winner-category"],
|
|
27570
|
+
format: args.format
|
|
27571
|
+
});
|
|
27572
|
+
const data = await apiGet("/api/ad-library/feed", params);
|
|
27573
|
+
const output = args.output || "json";
|
|
27574
|
+
const full = args.full;
|
|
27575
|
+
const rawWinners = Array.isArray(data?.winners) ? data.winners : [];
|
|
27576
|
+
const hints = [];
|
|
27577
|
+
if ((data?.following_count ?? 0) === 0) {
|
|
27578
|
+
hints.push(
|
|
27579
|
+
'You don\'t follow any brands yet. Run `baker winning-ads follow "<domain>" --platform meta` first.'
|
|
27580
|
+
);
|
|
27581
|
+
}
|
|
27582
|
+
if (Array.isArray(data?.unknown_requested) && data.unknown_requested.length > 0) {
|
|
27583
|
+
hints.push(
|
|
27584
|
+
`Not in your follows (skipped): ${data.unknown_requested.join(", ")}. Check ids with \`baker winning-ads following\`.`
|
|
27585
|
+
);
|
|
27586
|
+
}
|
|
27587
|
+
if (output === "json") {
|
|
27588
|
+
const winners = rawWinners.map((w) => winningAdNormalizer(w, full));
|
|
27589
|
+
writeJson({
|
|
27590
|
+
ok: true,
|
|
27591
|
+
data: {
|
|
27592
|
+
winners,
|
|
27593
|
+
following_count: data?.following_count ?? 0,
|
|
27594
|
+
advertiser_ids: Array.isArray(data?.advertiser_ids) ? data.advertiser_ids : [],
|
|
27595
|
+
...hints.length > 0 ? { hints } : {}
|
|
27596
|
+
}
|
|
27597
|
+
});
|
|
27598
|
+
return;
|
|
27599
|
+
}
|
|
27600
|
+
writeOutput(
|
|
27601
|
+
{ ok: true, data: rawWinners },
|
|
27602
|
+
output,
|
|
27603
|
+
args.fields ? args.fields.split(",") : void 0,
|
|
27604
|
+
full,
|
|
27605
|
+
winningAdNormalizer
|
|
27606
|
+
);
|
|
27607
|
+
for (const hint of hints) {
|
|
27608
|
+
process.stderr.write(`${hint}
|
|
27609
|
+
`);
|
|
27610
|
+
}
|
|
27611
|
+
} catch (err) {
|
|
27612
|
+
reportError(err);
|
|
27613
|
+
}
|
|
27614
|
+
}
|
|
27615
|
+
});
|
|
27616
|
+
|
|
27617
|
+
// src/commands/winning-ads/follow.ts
|
|
27618
|
+
import { defineCommand as defineCommand164 } from "citty";
|
|
27458
27619
|
var PLATFORMS = ["meta", "linkedin"];
|
|
27459
27620
|
registerSchema({
|
|
27460
27621
|
command: "winning-ads.follow",
|
|
@@ -27469,7 +27630,7 @@ registerSchema({
|
|
|
27469
27630
|
label: { type: "string", description: "Optional display label (defaults to the resolved name)", required: false }
|
|
27470
27631
|
}
|
|
27471
27632
|
});
|
|
27472
|
-
var followCommand =
|
|
27633
|
+
var followCommand = defineCommand164({
|
|
27473
27634
|
meta: {
|
|
27474
27635
|
name: "follow",
|
|
27475
27636
|
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'
|
|
@@ -27516,7 +27677,7 @@ var followCommand = defineCommand163({
|
|
|
27516
27677
|
});
|
|
27517
27678
|
|
|
27518
27679
|
// src/commands/winning-ads/following.ts
|
|
27519
|
-
import { defineCommand as
|
|
27680
|
+
import { defineCommand as defineCommand165 } from "citty";
|
|
27520
27681
|
registerSchema({
|
|
27521
27682
|
command: "winning-ads.following",
|
|
27522
27683
|
description: "List the brands you follow in your ad-dna library, with each one's status (ready vs still adding) and cached ad counts.",
|
|
@@ -27549,7 +27710,7 @@ function followingNormalizer(record, full) {
|
|
|
27549
27710
|
platforms: Array.isArray(record.platforms) ? record.platforms : []
|
|
27550
27711
|
};
|
|
27551
27712
|
}
|
|
27552
|
-
var followingCommand =
|
|
27713
|
+
var followingCommand = defineCommand165({
|
|
27553
27714
|
meta: {
|
|
27554
27715
|
name: "following",
|
|
27555
27716
|
description: "List brands you follow, with status (ready / adding\u2026) and cached counts. Example: baker winning-ads following --output md"
|
|
@@ -27584,7 +27745,7 @@ var followingCommand = defineCommand164({
|
|
|
27584
27745
|
});
|
|
27585
27746
|
|
|
27586
27747
|
// src/commands/winning-ads/patterns.ts
|
|
27587
|
-
import { defineCommand as
|
|
27748
|
+
import { defineCommand as defineCommand166 } from "citty";
|
|
27588
27749
|
registerSchema({
|
|
27589
27750
|
command: "winning-ads.patterns",
|
|
27590
27751
|
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.",
|
|
@@ -27623,7 +27784,7 @@ function discriminatorRow(record) {
|
|
|
27623
27784
|
top_values_duds: Array.isArray(record.top_values_b) ? record.top_values_b.join(", ") : ""
|
|
27624
27785
|
};
|
|
27625
27786
|
}
|
|
27626
|
-
var patternsCommand =
|
|
27787
|
+
var patternsCommand = defineCommand166({
|
|
27627
27788
|
meta: {
|
|
27628
27789
|
name: "patterns",
|
|
27629
27790
|
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"
|
|
@@ -27679,7 +27840,7 @@ var patternsCommand = defineCommand165({
|
|
|
27679
27840
|
});
|
|
27680
27841
|
|
|
27681
27842
|
// src/commands/winning-ads/search.ts
|
|
27682
|
-
import { defineCommand as
|
|
27843
|
+
import { defineCommand as defineCommand167 } from "citty";
|
|
27683
27844
|
registerSchema({
|
|
27684
27845
|
command: "winning-ads.search",
|
|
27685
27846
|
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.",
|
|
@@ -27787,7 +27948,7 @@ function buildSearchBody(args) {
|
|
|
27787
27948
|
}
|
|
27788
27949
|
return body;
|
|
27789
27950
|
}
|
|
27790
|
-
var searchCommand4 =
|
|
27951
|
+
var searchCommand4 = defineCommand167({
|
|
27791
27952
|
meta: {
|
|
27792
27953
|
name: "search",
|
|
27793
27954
|
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"
|
|
@@ -27902,7 +28063,7 @@ var searchCommand4 = defineCommand166({
|
|
|
27902
28063
|
});
|
|
27903
28064
|
|
|
27904
28065
|
// src/commands/winning-ads/seeds.ts
|
|
27905
|
-
import { defineCommand as
|
|
28066
|
+
import { defineCommand as defineCommand168 } from "citty";
|
|
27906
28067
|
function leanRow(r) {
|
|
27907
28068
|
return {
|
|
27908
28069
|
key: r.key,
|
|
@@ -27930,7 +28091,7 @@ function makeSeedCommand(opts) {
|
|
|
27930
28091
|
limit: { type: "number", description: "Max keys 1-100 (default 20)", required: false, default: 20 }
|
|
27931
28092
|
}
|
|
27932
28093
|
});
|
|
27933
|
-
return
|
|
28094
|
+
return defineCommand168({
|
|
27934
28095
|
meta: { name: opts.name, description: opts.description },
|
|
27935
28096
|
args: {
|
|
27936
28097
|
platform: { type: "string", description: "Single platform to segment on", required: false },
|
|
@@ -27979,7 +28140,7 @@ var formatsCommand = makeSeedCommand({
|
|
|
27979
28140
|
});
|
|
27980
28141
|
|
|
27981
28142
|
// src/commands/winning-ads/unfollow.ts
|
|
27982
|
-
import { defineCommand as
|
|
28143
|
+
import { defineCommand as defineCommand169 } from "citty";
|
|
27983
28144
|
registerSchema({
|
|
27984
28145
|
command: "winning-ads.unfollow",
|
|
27985
28146
|
description: "Stop following a brand \u2014 removes it from your ad-dna library by advertiser id.",
|
|
@@ -27987,7 +28148,7 @@ registerSchema({
|
|
|
27987
28148
|
advertiser: { type: "string", description: "Advertiser id to unfollow", required: true }
|
|
27988
28149
|
}
|
|
27989
28150
|
});
|
|
27990
|
-
var unfollowCommand =
|
|
28151
|
+
var unfollowCommand = defineCommand169({
|
|
27991
28152
|
meta: {
|
|
27992
28153
|
name: "unfollow",
|
|
27993
28154
|
description: "Stop following a brand by advertiser id. Example: baker winning-ads unfollow adv_123"
|
|
@@ -28008,7 +28169,7 @@ var unfollowCommand = defineCommand168({
|
|
|
28008
28169
|
});
|
|
28009
28170
|
|
|
28010
28171
|
// src/commands/winning-ads/winners.ts
|
|
28011
|
-
import { defineCommand as
|
|
28172
|
+
import { defineCommand as defineCommand170 } from "citty";
|
|
28012
28173
|
registerSchema({
|
|
28013
28174
|
command: "winning-ads.winners",
|
|
28014
28175
|
description: "Top winning ads for one advertiser id (from `advertisers` or `following`). Returns lean winner cards; add --full for DNA + longevity.",
|
|
@@ -28018,7 +28179,7 @@ registerSchema({
|
|
|
28018
28179
|
platform: { type: "string", description: "Filter to a single platform: meta|linkedin", required: false }
|
|
28019
28180
|
}
|
|
28020
28181
|
});
|
|
28021
|
-
var winnersCommand =
|
|
28182
|
+
var winnersCommand = defineCommand170({
|
|
28022
28183
|
meta: {
|
|
28023
28184
|
name: "winners",
|
|
28024
28185
|
description: "Top winning ads for a specific advertiser id. Example: baker winning-ads winners adv_123 --top 15 --output md"
|
|
@@ -28068,7 +28229,7 @@ var winnersCommand = defineCommand169({
|
|
|
28068
28229
|
});
|
|
28069
28230
|
|
|
28070
28231
|
// src/commands/winning-ads/index.ts
|
|
28071
|
-
var winningAdsCommand =
|
|
28232
|
+
var winningAdsCommand = defineCommand171({
|
|
28072
28233
|
meta: {
|
|
28073
28234
|
name: "winning-ads",
|
|
28074
28235
|
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.
|
|
@@ -28080,6 +28241,7 @@ Subcommands:
|
|
|
28080
28241
|
baker winning-ads advertisers "<brand>" \u2014 list corpus brands \u2192 advertiser ids (for --exclude-advertiser / --advertiser-id)
|
|
28081
28242
|
baker winning-ads follow "<domain|url|brand>" --platform meta|linkedin \u2014 add a brand's ads to your library
|
|
28082
28243
|
baker winning-ads following \u2014 list brands you follow (status + counts)
|
|
28244
|
+
baker winning-ads feed \u2014 winners across EVERY brand you follow; trim with --advertiser
|
|
28083
28245
|
baker winning-ads winners <advertiser> \u2014 top winners for one advertiser id
|
|
28084
28246
|
baker winning-ads unfollow <advertiser> \u2014 stop following a brand
|
|
28085
28247
|
baker winning-ads brief \u2014 creative brief grounded in similar winners
|
|
@@ -28092,6 +28254,8 @@ Examples:
|
|
|
28092
28254
|
baker winning-ads search "B2B SaaS before/after AI automation" --platform meta --format static --output md
|
|
28093
28255
|
baker winning-ads advertisers "Acme" --output md
|
|
28094
28256
|
baker winning-ads follow "deel.com" --platform meta
|
|
28257
|
+
baker winning-ads feed --per-advertiser 5 --output md
|
|
28258
|
+
baker winning-ads feed --advertiser adv_123,adv_456 --platform meta --output md
|
|
28095
28259
|
baker winning-ads winners adv_123 --top 15 --output md
|
|
28096
28260
|
baker winning-ads hooks --platform meta --awareness problem_aware --industry saas --output md
|
|
28097
28261
|
baker winning-ads search "fintech onboarding" --hook-archetype callout --winner-category winner --output md
|
|
@@ -28102,6 +28266,7 @@ Examples:
|
|
|
28102
28266
|
advertisers: advertisersCommand2,
|
|
28103
28267
|
follow: followCommand,
|
|
28104
28268
|
following: followingCommand,
|
|
28269
|
+
feed: feedCommand,
|
|
28105
28270
|
winners: winnersCommand,
|
|
28106
28271
|
unfollow: unfollowCommand,
|
|
28107
28272
|
brief: briefCommand,
|
|
@@ -28129,7 +28294,7 @@ function getCliVersion() {
|
|
|
28129
28294
|
}
|
|
28130
28295
|
|
|
28131
28296
|
// src/cli.ts
|
|
28132
|
-
var main =
|
|
28297
|
+
var main = defineCommand172({
|
|
28133
28298
|
meta: {
|
|
28134
28299
|
name: "baker",
|
|
28135
28300
|
version: getCliVersion(),
|