@koda-sl/baker-cli 0.139.0 → 0.140.1
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 +1 -0
- package/dist/cli.js +178 -17
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -672,6 +672,7 @@ baker ads meta campaigns create --account-id act_123 --name "Q3 Prospecting" -
|
|
|
672
672
|
baker ads meta adsets create --account-id act_123 --campaign meta_temp_camp --name "US 25-54" \
|
|
673
673
|
--optimization-goal OFFSITE_CONVERSIONS --billing-event IMPRESSIONS --pixel-id 111 --custom-event-type LEAD \
|
|
674
674
|
--targeting-file targeting.json # → meta_temp_as
|
|
675
|
+
# lead-form goals (LEAD_GENERATION / QUALITY_LEAD) and PAGE_LIKES require --page-id (the Facebook Page), else Meta rejects the ad set
|
|
675
676
|
baker ads meta creatives create --account-id act_123 --page 555 --instagram-user 777 \
|
|
676
677
|
--message "Save money on pet insurance" --link https://example.com --headline "Best cover" \
|
|
677
678
|
--image-ref meta_temp_img --cta SHOP_NOW --standard-enhancements on # → meta_temp_cr
|
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 defineCommand175, runMain } from "citty";
|
|
77
77
|
|
|
78
78
|
// src/commands/actions/index.ts
|
|
79
79
|
import { defineCommand as defineCommand18 } from "citty";
|
|
@@ -1008,6 +1008,33 @@ var followResponseSchema = z2.object({
|
|
|
1008
1008
|
preview: resolvePreviewSchema.nullable(),
|
|
1009
1009
|
candidates: z2.array(corpusAdvertiserSchema).nullable()
|
|
1010
1010
|
});
|
|
1011
|
+
var FOLLOW_BATCH_MAX = 50;
|
|
1012
|
+
var followBatchRequestSchema = z2.object({
|
|
1013
|
+
// One entry per brand — a domain (best; resolves both Meta + LinkedIn), a
|
|
1014
|
+
// profile / ad-library URL, or a brand name.
|
|
1015
|
+
inputs: z2.array(z2.string().min(1)).min(1).max(FOLLOW_BATCH_MAX),
|
|
1016
|
+
// How to read every input (not a tracking limit — a domain still resolves
|
|
1017
|
+
// every platform we can). Defaults to reading inputs as Meta identities.
|
|
1018
|
+
platform: adLibraryPlatformSchema.default("meta")
|
|
1019
|
+
});
|
|
1020
|
+
var followBatchResultSchema = z2.object({
|
|
1021
|
+
// Echoes the input so the caller can line results up with what it sent.
|
|
1022
|
+
input: z2.string(),
|
|
1023
|
+
// "following"/"added" mirror the single-follow statuses; "ambiguous" needs a
|
|
1024
|
+
// manual pick; "failed" = we couldn't resolve or add it (see `error`).
|
|
1025
|
+
status: z2.enum(["following", "added", "ambiguous", "failed"]),
|
|
1026
|
+
advertiser: followedAdvertiserSchema.nullable(),
|
|
1027
|
+
// Present only when status is "failed" — a plain-language reason.
|
|
1028
|
+
error: z2.string().nullable()
|
|
1029
|
+
});
|
|
1030
|
+
var followBatchResponseSchema = z2.object({
|
|
1031
|
+
results: z2.array(followBatchResultSchema),
|
|
1032
|
+
// Rollup counts across the batch for a one-glance summary.
|
|
1033
|
+
followed_count: z2.number(),
|
|
1034
|
+
added_count: z2.number(),
|
|
1035
|
+
ambiguous_count: z2.number(),
|
|
1036
|
+
failed_count: z2.number()
|
|
1037
|
+
});
|
|
1011
1038
|
var unfollowRequestSchema = z2.object({
|
|
1012
1039
|
// Accept either the Baker subscription id or the corpus advertiser id.
|
|
1013
1040
|
followed_id: z2.string().optional(),
|
|
@@ -11365,6 +11392,11 @@ var OPTIMIZATION_GOALS = [
|
|
|
11365
11392
|
"CONVERSATIONS",
|
|
11366
11393
|
"DERIVED_EVENTS"
|
|
11367
11394
|
];
|
|
11395
|
+
var OPTIMIZATION_GOALS_REQUIRING_PAGE = [
|
|
11396
|
+
"LEAD_GENERATION",
|
|
11397
|
+
"QUALITY_LEAD",
|
|
11398
|
+
"PAGE_LIKES"
|
|
11399
|
+
];
|
|
11368
11400
|
var DESTINATION_TYPES = [
|
|
11369
11401
|
"WEBSITE",
|
|
11370
11402
|
"APP",
|
|
@@ -11582,8 +11614,18 @@ function validateAdSetBudgetAndBid(p, ctx) {
|
|
|
11582
11614
|
ctx.addIssue({ code: "custom", path: ["end_time"], message: "end_time must be after start_time" });
|
|
11583
11615
|
}
|
|
11584
11616
|
}
|
|
11617
|
+
function validateAdSetPromotedObject(p, ctx) {
|
|
11618
|
+
if (p.optimization_goal && OPTIMIZATION_GOALS_REQUIRING_PAGE.includes(p.optimization_goal) && !p.promoted_object?.page_id) {
|
|
11619
|
+
ctx.addIssue({
|
|
11620
|
+
code: "custom",
|
|
11621
|
+
path: ["promoted_object", "page_id"],
|
|
11622
|
+
message: `optimization_goal ${p.optimization_goal} needs promoted_object.page_id \u2014 pass --page-id with the Facebook Page the leads/likes belong to`
|
|
11623
|
+
});
|
|
11624
|
+
}
|
|
11625
|
+
}
|
|
11585
11626
|
var adSetCreateSchema = z14.object(adSetFields).superRefine((p, ctx) => {
|
|
11586
11627
|
validateAdSetBudgetAndBid(p, ctx);
|
|
11628
|
+
validateAdSetPromotedObject(p, ctx);
|
|
11587
11629
|
});
|
|
11588
11630
|
var adSetUpdateSchema = z14.object({
|
|
11589
11631
|
name: adSetFields.name.optional(),
|
|
@@ -11604,6 +11646,9 @@ var adSetUpdateSchema = z14.object({
|
|
|
11604
11646
|
ctx.addIssue({ code: "custom", message: "update needs at least one field" });
|
|
11605
11647
|
}
|
|
11606
11648
|
validateAdSetBudgetAndBid(p, ctx);
|
|
11649
|
+
if (p.optimization_goal) {
|
|
11650
|
+
validateAdSetPromotedObject(p, ctx);
|
|
11651
|
+
}
|
|
11607
11652
|
});
|
|
11608
11653
|
var messageSchema = z14.string().min(1).max(META_LIMITS.creative.messageHardMax);
|
|
11609
11654
|
var headlineSchema2 = z14.string().min(1).max(META_LIMITS.creative.headlineMax);
|
|
@@ -12191,7 +12236,10 @@ var adSetWriteArgs = {
|
|
|
12191
12236
|
end: { type: "string", description: "End time" },
|
|
12192
12237
|
"targeting-file": { type: "string", description: "JSON file with the full Meta targeting spec" },
|
|
12193
12238
|
"promoted-object-file": { type: "string", description: "JSON file with the promoted_object" },
|
|
12194
|
-
"page-id": {
|
|
12239
|
+
"page-id": {
|
|
12240
|
+
type: "string",
|
|
12241
|
+
description: "promoted_object.page_id shortcut (required for LEAD_GENERATION / QUALITY_LEAD / PAGE_LIKES goals)"
|
|
12242
|
+
},
|
|
12195
12243
|
"pixel-id": { type: "string", description: "promoted_object.pixel_id shortcut" },
|
|
12196
12244
|
"custom-event-type": { type: "string", description: "promoted_object.custom_event_type (PURCHASE|LEAD|\u2026)" },
|
|
12197
12245
|
file: { type: "string", description: "JSON file with the full payload; flags override" }
|
|
@@ -12201,6 +12249,7 @@ var adSetsCreateCommand = defineCommand54({
|
|
|
12201
12249
|
name: "create",
|
|
12202
12250
|
description: `Stage a new ad set. ${STAGED_NOTE2}
|
|
12203
12251
|
Chain to a campaign with --campaign (real id or meta_temp_* ref).
|
|
12252
|
+
Lead-form goals (LEAD_GENERATION, QUALITY_LEAD) and PAGE_LIKES need --page-id (the Facebook Page the leads/likes belong to).
|
|
12204
12253
|
Example: baker ads meta adsets create --campaign meta_temp_ab12 --name "US 25-54" --optimization-goal LINK_CLICKS --billing-event IMPRESSIONS --daily-budget 50 --targeting-file t.json`
|
|
12205
12254
|
},
|
|
12206
12255
|
args: { campaign: { type: "string", description: "Parent campaign id or meta_temp_* ref" }, ...adSetWriteArgs },
|
|
@@ -12214,6 +12263,7 @@ var adSetsUpdateCommand = defineCommand54({
|
|
|
12214
12263
|
meta: {
|
|
12215
12264
|
name: "update",
|
|
12216
12265
|
description: `Stage changes to an ad set. ${STAGED_NOTE2}
|
|
12266
|
+
Switching --optimization-goal to a lead-form goal (LEAD_GENERATION, QUALITY_LEAD) or PAGE_LIKES needs --page-id in the same change.
|
|
12217
12267
|
Example: baker ads meta adsets update 6123 --daily-budget 80`
|
|
12218
12268
|
},
|
|
12219
12269
|
args: { id: { type: "positional", description: "Ad set id or meta_temp_* ref", required: true }, ...adSetWriteArgs },
|
|
@@ -27994,7 +28044,7 @@ Examples:
|
|
|
27994
28044
|
});
|
|
27995
28045
|
|
|
27996
28046
|
// src/commands/winning-ads/index.ts
|
|
27997
|
-
import { defineCommand as
|
|
28047
|
+
import { defineCommand as defineCommand174 } from "citty";
|
|
27998
28048
|
|
|
27999
28049
|
// src/commands/winning-ads/advertisers.ts
|
|
28000
28050
|
import { defineCommand as defineCommand163 } from "citty";
|
|
@@ -28388,8 +28438,116 @@ var followCommand = defineCommand166({
|
|
|
28388
28438
|
}
|
|
28389
28439
|
});
|
|
28390
28440
|
|
|
28391
|
-
// src/commands/winning-ads/
|
|
28441
|
+
// src/commands/winning-ads/follow-competitors.ts
|
|
28392
28442
|
import { defineCommand as defineCommand167 } from "citty";
|
|
28443
|
+
var PLATFORMS2 = ["meta", "linkedin"];
|
|
28444
|
+
var BATCH_TIMEOUT_MS = 3e5;
|
|
28445
|
+
function buildFollowBatchBody(input) {
|
|
28446
|
+
const seen = /* @__PURE__ */ new Set();
|
|
28447
|
+
const inputs = [];
|
|
28448
|
+
for (const domain of splitList(input.domains)) {
|
|
28449
|
+
const key = domain.toLowerCase();
|
|
28450
|
+
if (seen.has(key)) {
|
|
28451
|
+
continue;
|
|
28452
|
+
}
|
|
28453
|
+
seen.add(key);
|
|
28454
|
+
inputs.push(domain);
|
|
28455
|
+
}
|
|
28456
|
+
return { inputs, platform: input.platform ?? "meta" };
|
|
28457
|
+
}
|
|
28458
|
+
registerSchema({
|
|
28459
|
+
command: "winning-ads.follow-competitors",
|
|
28460
|
+
description: "Follow MANY brands at once \u2014 the fast way to add every competitor to your library. Pass a comma-separated list of domains (best \u2014 each resolves both Meta + LinkedIn, every country). One brand failing never blocks the others: the response reports per-brand status (following/added/ambiguous/failed) plus rollup counts. Ideal right after a competitor scan.",
|
|
28461
|
+
args: {
|
|
28462
|
+
domains: {
|
|
28463
|
+
type: "string",
|
|
28464
|
+
description: `Comma-separated domains (best), profile/ad-library URLs, or brand names \u2014 up to ${FOLLOW_BATCH_MAX}. e.g. "deel.com,notion.so,hubspot.com"`,
|
|
28465
|
+
required: true
|
|
28466
|
+
},
|
|
28467
|
+
platform: {
|
|
28468
|
+
type: "string",
|
|
28469
|
+
description: "meta|linkedin \u2014 how to read each input, not a tracking limit (default meta). Domains resolve both.",
|
|
28470
|
+
required: false,
|
|
28471
|
+
default: "meta"
|
|
28472
|
+
}
|
|
28473
|
+
}
|
|
28474
|
+
});
|
|
28475
|
+
var followCompetitorsCommand = defineCommand167({
|
|
28476
|
+
meta: {
|
|
28477
|
+
name: "follow-competitors",
|
|
28478
|
+
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"'
|
|
28479
|
+
},
|
|
28480
|
+
args: {
|
|
28481
|
+
domains: {
|
|
28482
|
+
type: "positional",
|
|
28483
|
+
description: "Comma-separated domains (best), URLs, or brand names",
|
|
28484
|
+
required: true
|
|
28485
|
+
},
|
|
28486
|
+
platform: {
|
|
28487
|
+
type: "string",
|
|
28488
|
+
description: "meta|linkedin \u2014 how to read each input, not a tracking limit (default meta).",
|
|
28489
|
+
required: false,
|
|
28490
|
+
default: "meta"
|
|
28491
|
+
}
|
|
28492
|
+
},
|
|
28493
|
+
run: async ({ args }) => {
|
|
28494
|
+
try {
|
|
28495
|
+
const platform = String(args.platform ?? "meta");
|
|
28496
|
+
if (!PLATFORMS2.includes(platform)) {
|
|
28497
|
+
writeJson({
|
|
28498
|
+
ok: false,
|
|
28499
|
+
error: { code: "VALIDATION_ERROR", message: "--platform must be one of: meta, linkedin" }
|
|
28500
|
+
});
|
|
28501
|
+
process.exit(1);
|
|
28502
|
+
}
|
|
28503
|
+
const body = buildFollowBatchBody({ domains: String(args.domains ?? ""), platform });
|
|
28504
|
+
if (body.inputs.length === 0) {
|
|
28505
|
+
writeJson({
|
|
28506
|
+
ok: false,
|
|
28507
|
+
error: { code: "VALIDATION_ERROR", message: "Pass at least one domain in --domains." }
|
|
28508
|
+
});
|
|
28509
|
+
process.exit(1);
|
|
28510
|
+
}
|
|
28511
|
+
if (body.inputs.length > FOLLOW_BATCH_MAX) {
|
|
28512
|
+
writeJson({
|
|
28513
|
+
ok: false,
|
|
28514
|
+
error: {
|
|
28515
|
+
code: "VALIDATION_ERROR",
|
|
28516
|
+
message: `Too many brands (${body.inputs.length}). Follow at most ${FOLLOW_BATCH_MAX} per call.`
|
|
28517
|
+
}
|
|
28518
|
+
});
|
|
28519
|
+
process.exit(1);
|
|
28520
|
+
}
|
|
28521
|
+
const data = await apiPost("/api/ad-library/follow-batch", body, {
|
|
28522
|
+
timeoutMs: BATCH_TIMEOUT_MS
|
|
28523
|
+
});
|
|
28524
|
+
const hints = [];
|
|
28525
|
+
if (data.failed_count > 0) {
|
|
28526
|
+
const failed = data.results.filter((r) => r.status === "failed").map((r) => r.input);
|
|
28527
|
+
hints.push(
|
|
28528
|
+
`${data.failed_count} brand(s) couldn't be added: ${failed.join(", ")}. Retry each with its website or Facebook/LinkedIn URL via \`baker winning-ads follow\`.`
|
|
28529
|
+
);
|
|
28530
|
+
}
|
|
28531
|
+
if (data.ambiguous_count > 0) {
|
|
28532
|
+
const ambiguous = data.results.filter((r) => r.status === "ambiguous").map((r) => r.input);
|
|
28533
|
+
hints.push(
|
|
28534
|
+
`${data.ambiguous_count} brand(s) matched multiple advertisers: ${ambiguous.join(", ")}. Re-run \`baker winning-ads follow\` with an exact domain/URL to pick one.`
|
|
28535
|
+
);
|
|
28536
|
+
}
|
|
28537
|
+
if (data.added_count > 0) {
|
|
28538
|
+
hints.push(
|
|
28539
|
+
"Newly added brands are ingesting now \u2014 their winners fill in over the next few minutes. Check `baker winning-ads following` or `baker winning-ads feed`."
|
|
28540
|
+
);
|
|
28541
|
+
}
|
|
28542
|
+
writeJson({ ok: true, data, hints: hints.length > 0 ? hints : void 0 });
|
|
28543
|
+
} catch (err) {
|
|
28544
|
+
reportError(err);
|
|
28545
|
+
}
|
|
28546
|
+
}
|
|
28547
|
+
});
|
|
28548
|
+
|
|
28549
|
+
// src/commands/winning-ads/following.ts
|
|
28550
|
+
import { defineCommand as defineCommand168 } from "citty";
|
|
28393
28551
|
registerSchema({
|
|
28394
28552
|
command: "winning-ads.following",
|
|
28395
28553
|
description: "List the brands you follow in your ad-dna library, with each one's status (ready vs still adding) and cached ad counts.",
|
|
@@ -28422,7 +28580,7 @@ function followingNormalizer(record, full) {
|
|
|
28422
28580
|
platforms: Array.isArray(record.platforms) ? record.platforms : []
|
|
28423
28581
|
};
|
|
28424
28582
|
}
|
|
28425
|
-
var followingCommand =
|
|
28583
|
+
var followingCommand = defineCommand168({
|
|
28426
28584
|
meta: {
|
|
28427
28585
|
name: "following",
|
|
28428
28586
|
description: "List brands you follow, with status (ready / adding\u2026) and cached counts. Example: baker winning-ads following --output md"
|
|
@@ -28457,7 +28615,7 @@ var followingCommand = defineCommand167({
|
|
|
28457
28615
|
});
|
|
28458
28616
|
|
|
28459
28617
|
// src/commands/winning-ads/patterns.ts
|
|
28460
|
-
import { defineCommand as
|
|
28618
|
+
import { defineCommand as defineCommand169 } from "citty";
|
|
28461
28619
|
registerSchema({
|
|
28462
28620
|
command: "winning-ads.patterns",
|
|
28463
28621
|
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.",
|
|
@@ -28496,7 +28654,7 @@ function discriminatorRow(record) {
|
|
|
28496
28654
|
top_values_duds: Array.isArray(record.top_values_b) ? record.top_values_b.join(", ") : ""
|
|
28497
28655
|
};
|
|
28498
28656
|
}
|
|
28499
|
-
var patternsCommand =
|
|
28657
|
+
var patternsCommand = defineCommand169({
|
|
28500
28658
|
meta: {
|
|
28501
28659
|
name: "patterns",
|
|
28502
28660
|
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"
|
|
@@ -28552,7 +28710,7 @@ var patternsCommand = defineCommand168({
|
|
|
28552
28710
|
});
|
|
28553
28711
|
|
|
28554
28712
|
// src/commands/winning-ads/search.ts
|
|
28555
|
-
import { defineCommand as
|
|
28713
|
+
import { defineCommand as defineCommand170 } from "citty";
|
|
28556
28714
|
registerSchema({
|
|
28557
28715
|
command: "winning-ads.search",
|
|
28558
28716
|
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.",
|
|
@@ -28660,7 +28818,7 @@ function buildSearchBody(args) {
|
|
|
28660
28818
|
}
|
|
28661
28819
|
return body;
|
|
28662
28820
|
}
|
|
28663
|
-
var searchCommand4 =
|
|
28821
|
+
var searchCommand4 = defineCommand170({
|
|
28664
28822
|
meta: {
|
|
28665
28823
|
name: "search",
|
|
28666
28824
|
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"
|
|
@@ -28775,7 +28933,7 @@ var searchCommand4 = defineCommand169({
|
|
|
28775
28933
|
});
|
|
28776
28934
|
|
|
28777
28935
|
// src/commands/winning-ads/seeds.ts
|
|
28778
|
-
import { defineCommand as
|
|
28936
|
+
import { defineCommand as defineCommand171 } from "citty";
|
|
28779
28937
|
function leanRow(r) {
|
|
28780
28938
|
return {
|
|
28781
28939
|
key: r.key,
|
|
@@ -28803,7 +28961,7 @@ function makeSeedCommand(opts) {
|
|
|
28803
28961
|
limit: { type: "number", description: "Max keys 1-100 (default 20)", required: false, default: 20 }
|
|
28804
28962
|
}
|
|
28805
28963
|
});
|
|
28806
|
-
return
|
|
28964
|
+
return defineCommand171({
|
|
28807
28965
|
meta: { name: opts.name, description: opts.description },
|
|
28808
28966
|
args: {
|
|
28809
28967
|
platform: { type: "string", description: "Single platform to segment on", required: false },
|
|
@@ -28852,7 +29010,7 @@ var formatsCommand = makeSeedCommand({
|
|
|
28852
29010
|
});
|
|
28853
29011
|
|
|
28854
29012
|
// src/commands/winning-ads/unfollow.ts
|
|
28855
|
-
import { defineCommand as
|
|
29013
|
+
import { defineCommand as defineCommand172 } from "citty";
|
|
28856
29014
|
registerSchema({
|
|
28857
29015
|
command: "winning-ads.unfollow",
|
|
28858
29016
|
description: "Stop following a brand \u2014 removes it from your ad-dna library by advertiser id.",
|
|
@@ -28860,7 +29018,7 @@ registerSchema({
|
|
|
28860
29018
|
advertiser: { type: "string", description: "Advertiser id to unfollow", required: true }
|
|
28861
29019
|
}
|
|
28862
29020
|
});
|
|
28863
|
-
var unfollowCommand =
|
|
29021
|
+
var unfollowCommand = defineCommand172({
|
|
28864
29022
|
meta: {
|
|
28865
29023
|
name: "unfollow",
|
|
28866
29024
|
description: "Stop following a brand by advertiser id. Example: baker winning-ads unfollow adv_123"
|
|
@@ -28881,7 +29039,7 @@ var unfollowCommand = defineCommand171({
|
|
|
28881
29039
|
});
|
|
28882
29040
|
|
|
28883
29041
|
// src/commands/winning-ads/winners.ts
|
|
28884
|
-
import { defineCommand as
|
|
29042
|
+
import { defineCommand as defineCommand173 } from "citty";
|
|
28885
29043
|
registerSchema({
|
|
28886
29044
|
command: "winning-ads.winners",
|
|
28887
29045
|
description: "Top winning ads for one advertiser id (from `advertisers` or `following`). Returns lean winner cards; add --full for DNA + longevity.",
|
|
@@ -28891,7 +29049,7 @@ registerSchema({
|
|
|
28891
29049
|
platform: { type: "string", description: "Filter to a single platform: meta|linkedin", required: false }
|
|
28892
29050
|
}
|
|
28893
29051
|
});
|
|
28894
|
-
var winnersCommand =
|
|
29052
|
+
var winnersCommand = defineCommand173({
|
|
28895
29053
|
meta: {
|
|
28896
29054
|
name: "winners",
|
|
28897
29055
|
description: "Top winning ads for a specific advertiser id. Example: baker winning-ads winners adv_123 --top 15 --output md"
|
|
@@ -28941,7 +29099,7 @@ var winnersCommand = defineCommand172({
|
|
|
28941
29099
|
});
|
|
28942
29100
|
|
|
28943
29101
|
// src/commands/winning-ads/index.ts
|
|
28944
|
-
var winningAdsCommand =
|
|
29102
|
+
var winningAdsCommand = defineCommand174({
|
|
28945
29103
|
meta: {
|
|
28946
29104
|
name: "winning-ads",
|
|
28947
29105
|
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.
|
|
@@ -28952,6 +29110,7 @@ Subcommands:
|
|
|
28952
29110
|
baker winning-ads search "<free text>" \u2014 semantic search across the corpus; lean shortlist (advertiser, summary, scores, media_url)
|
|
28953
29111
|
baker winning-ads advertisers "<brand>" \u2014 list corpus brands \u2192 advertiser ids (for --exclude-advertiser / --advertiser-id)
|
|
28954
29112
|
baker winning-ads follow "<domain|url|brand>" --platform meta|linkedin \u2014 add a brand's ads to your library
|
|
29113
|
+
baker winning-ads follow-competitors "<domain,domain,...>" \u2014 add MANY brands at once (every competitor by domain)
|
|
28955
29114
|
baker winning-ads following \u2014 list brands you follow (status + counts)
|
|
28956
29115
|
baker winning-ads feed \u2014 winners across EVERY brand you follow; trim with --advertiser
|
|
28957
29116
|
baker winning-ads winners <advertiser> \u2014 top winners for one advertiser id
|
|
@@ -28966,6 +29125,7 @@ Examples:
|
|
|
28966
29125
|
baker winning-ads search "B2B SaaS before/after AI automation" --platform meta --format static --output md
|
|
28967
29126
|
baker winning-ads advertisers "Acme" --output md
|
|
28968
29127
|
baker winning-ads follow "deel.com" --platform meta
|
|
29128
|
+
baker winning-ads follow-competitors "deel.com,notion.so,hubspot.com"
|
|
28969
29129
|
baker winning-ads feed --per-advertiser 5 --output md
|
|
28970
29130
|
baker winning-ads feed --advertiser adv_123,adv_456 --platform meta --output md
|
|
28971
29131
|
baker winning-ads winners adv_123 --top 15 --output md
|
|
@@ -28977,6 +29137,7 @@ Examples:
|
|
|
28977
29137
|
search: searchCommand4,
|
|
28978
29138
|
advertisers: advertisersCommand2,
|
|
28979
29139
|
follow: followCommand,
|
|
29140
|
+
"follow-competitors": followCompetitorsCommand,
|
|
28980
29141
|
following: followingCommand,
|
|
28981
29142
|
feed: feedCommand,
|
|
28982
29143
|
winners: winnersCommand,
|
|
@@ -29006,7 +29167,7 @@ function getCliVersion() {
|
|
|
29006
29167
|
}
|
|
29007
29168
|
|
|
29008
29169
|
// src/cli.ts
|
|
29009
|
-
var main =
|
|
29170
|
+
var main = defineCommand175({
|
|
29010
29171
|
meta: {
|
|
29011
29172
|
name: "baker",
|
|
29012
29173
|
version: getCliVersion(),
|