@koda-sl/baker-cli 0.139.1 → 0.140.1-dev.253d2418a
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 +2 -0
- package/dist/{chunk-TAGQCU36.js → chunk-TXNOPO6P.js} +4 -4
- package/dist/chunk-TXNOPO6P.js.map +1 -0
- package/dist/cli.js +353 -46
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-TAGQCU36.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
toModelSafeImage,
|
|
35
35
|
ulid,
|
|
36
36
|
validateCanvasDeep
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-TXNOPO6P.js";
|
|
38
38
|
import {
|
|
39
39
|
csvOrJson,
|
|
40
40
|
daysAgoIso,
|
|
@@ -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(),
|
|
@@ -3684,7 +3711,8 @@ Examples:
|
|
|
3684
3711
|
baker actions claim <id>
|
|
3685
3712
|
baker actions create --name "Build hero" --tags landing,creative --description "..."
|
|
3686
3713
|
baker actions complete <id>
|
|
3687
|
-
baker actions discard <id> --reason "obsolete"
|
|
3714
|
+
baker actions discard <id> --reason "obsolete"
|
|
3715
|
+
Full guide: __tooling__/docs/tools/baker/actions.md`
|
|
3688
3716
|
},
|
|
3689
3717
|
subCommands: {
|
|
3690
3718
|
list: listCommand2,
|
|
@@ -7657,7 +7685,8 @@ Staged writes (never touch Google until the chat is published):
|
|
|
7657
7685
|
baker ads google budgets create --customer-id 1234567890 --name "Search" --amount 50
|
|
7658
7686
|
baker ads google campaigns create --customer-id 1234567890 --name "Brand" --channel-type SEARCH --budget-ref g_temp_\u2026 --bidding-strategy MANUAL_CPC
|
|
7659
7687
|
baker ads google keyword-lists create --customer-id 1234567890 --name "Brand exclusions"
|
|
7660
|
-
baker ads google draft list \u2014 review staged Google Ads changes
|
|
7688
|
+
baker ads google draft list \u2014 review staged Google Ads changes
|
|
7689
|
+
Full guide: __tooling__/docs/tools/baker/ads-google.md`
|
|
7661
7690
|
},
|
|
7662
7691
|
subCommands: {
|
|
7663
7692
|
accounts: accountsCommand,
|
|
@@ -11117,7 +11146,8 @@ published; if the company's LinkedIn-write flag is off the publish is simulated)
|
|
|
11117
11146
|
|
|
11118
11147
|
Account ID format:
|
|
11119
11148
|
--account-id accepts numeric (503001492) or URN (urn:li:sponsoredAccount:503001492).
|
|
11120
|
-
Set BAKER_LINKEDIN_AD_ACCOUNT_ID env to skip --account-id on every call
|
|
11149
|
+
Set BAKER_LINKEDIN_AD_ACCOUNT_ID env to skip --account-id on every call.
|
|
11150
|
+
Full guide: __tooling__/docs/tools/baker/ads-linkedin.md`
|
|
11121
11151
|
},
|
|
11122
11152
|
subCommands: {
|
|
11123
11153
|
accounts: accountsCommand2,
|
|
@@ -11318,11 +11348,13 @@ var SPECIAL_AD_CATEGORIES = [
|
|
|
11318
11348
|
"NONE",
|
|
11319
11349
|
"HOUSING",
|
|
11320
11350
|
"EMPLOYMENT",
|
|
11351
|
+
/** Deprecated by Meta on 2025-01-14 — replaced by FINANCIAL_PRODUCTS_SERVICES. Still accepted as input and mapped on the wire. */
|
|
11321
11352
|
"CREDIT",
|
|
11322
11353
|
"ISSUES_ELECTIONS_POLITICS",
|
|
11323
11354
|
"FINANCIAL_PRODUCTS_SERVICES",
|
|
11324
11355
|
"ONLINE_GAMBLING_AND_GAMING"
|
|
11325
11356
|
];
|
|
11357
|
+
var SPECIAL_CATEGORIES_REQUIRING_COUNTRY = ["ISSUES_ELECTIONS_POLITICS"];
|
|
11326
11358
|
var BUYING_TYPES = ["AUCTION", "RESERVED"];
|
|
11327
11359
|
var BID_STRATEGIES = [
|
|
11328
11360
|
"LOWEST_COST_WITHOUT_CAP",
|
|
@@ -11331,6 +11363,10 @@ var BID_STRATEGIES = [
|
|
|
11331
11363
|
"LOWEST_COST_WITH_MIN_ROAS"
|
|
11332
11364
|
];
|
|
11333
11365
|
var BID_STRATEGIES_REQUIRING_AMOUNT = ["LOWEST_COST_WITH_BID_CAP", "COST_CAP"];
|
|
11366
|
+
var BID_STRATEGIES_FORBIDDING_AMOUNT = [
|
|
11367
|
+
"LOWEST_COST_WITHOUT_CAP",
|
|
11368
|
+
"LOWEST_COST_WITH_MIN_ROAS"
|
|
11369
|
+
];
|
|
11334
11370
|
var BILLING_EVENTS = [
|
|
11335
11371
|
"APP_INSTALLS",
|
|
11336
11372
|
"CLICKS",
|
|
@@ -11370,6 +11406,9 @@ var OPTIMIZATION_GOALS_REQUIRING_PAGE = [
|
|
|
11370
11406
|
"QUALITY_LEAD",
|
|
11371
11407
|
"PAGE_LIKES"
|
|
11372
11408
|
];
|
|
11409
|
+
var OPTIMIZATION_GOALS_REQUIRING_PIXEL = ["OFFSITE_CONVERSIONS"];
|
|
11410
|
+
var OPTIMIZATION_GOALS_REQUIRING_CONVERSION_SOURCE = ["VALUE"];
|
|
11411
|
+
var OPTIMIZATION_GOALS_REQUIRING_APP = ["APP_INSTALLS"];
|
|
11373
11412
|
var DESTINATION_TYPES = [
|
|
11374
11413
|
"WEBSITE",
|
|
11375
11414
|
"APP",
|
|
@@ -11399,6 +11438,8 @@ var CUSTOM_EVENT_TYPES = [
|
|
|
11399
11438
|
"OTHER"
|
|
11400
11439
|
];
|
|
11401
11440
|
var ATTRIBUTION_EVENT_TYPES = ["CLICK_THROUGH", "VIEW_THROUGH", "ENGAGED_VIDEO_VIEW"];
|
|
11441
|
+
var ADVANTAGE_AUDIENCE_OPEN_AGE_MAX = 65;
|
|
11442
|
+
var ADVANTAGE_AUDIENCE_MAX_HARD_AGE_MIN = 25;
|
|
11402
11443
|
var CTA_TYPES2 = [
|
|
11403
11444
|
"LEARN_MORE",
|
|
11404
11445
|
"SHOP_NOW",
|
|
@@ -11496,6 +11537,44 @@ var metaTargetingSchema = z14.object({
|
|
|
11496
11537
|
device_platforms: z14.array(z14.string()).optional(),
|
|
11497
11538
|
targeting_automation: z14.object({ advantage_audience: z14.union([z14.literal(0), z14.literal(1)]) }).partial().optional()
|
|
11498
11539
|
}).catchall(z14.unknown());
|
|
11540
|
+
var GEO_INCLUSION_KEYS = [
|
|
11541
|
+
"countries",
|
|
11542
|
+
"country_groups",
|
|
11543
|
+
"regions",
|
|
11544
|
+
"cities",
|
|
11545
|
+
"zips",
|
|
11546
|
+
"geo_markets",
|
|
11547
|
+
"places",
|
|
11548
|
+
"custom_locations",
|
|
11549
|
+
"electoral_districts",
|
|
11550
|
+
"subcities",
|
|
11551
|
+
"neighborhoods"
|
|
11552
|
+
];
|
|
11553
|
+
function targetingHasGeo(t) {
|
|
11554
|
+
const geo = t?.geo_locations;
|
|
11555
|
+
return Boolean(
|
|
11556
|
+
geo && GEO_INCLUSION_KEYS.some((key) => Array.isArray(geo[key]) && geo[key].length > 0)
|
|
11557
|
+
);
|
|
11558
|
+
}
|
|
11559
|
+
function targetingHasGeoOrAudience(t) {
|
|
11560
|
+
if (!t) {
|
|
11561
|
+
return false;
|
|
11562
|
+
}
|
|
11563
|
+
return targetingHasGeo(t) || Boolean(t.custom_audiences?.length);
|
|
11564
|
+
}
|
|
11565
|
+
function advantageAudienceSetting(t) {
|
|
11566
|
+
const value = t.targeting_automation?.advantage_audience;
|
|
11567
|
+
return value === 0 || value === 1 ? value : void 0;
|
|
11568
|
+
}
|
|
11569
|
+
function targetingHardLimitsDemographics(t) {
|
|
11570
|
+
if (!t) {
|
|
11571
|
+
return false;
|
|
11572
|
+
}
|
|
11573
|
+
const narrowsAgeMax = typeof t.age_max === "number" && t.age_max < ADVANTAGE_AUDIENCE_OPEN_AGE_MAX;
|
|
11574
|
+
const narrowsAgeMin = typeof t.age_min === "number" && t.age_min > ADVANTAGE_AUDIENCE_MAX_HARD_AGE_MIN;
|
|
11575
|
+
const narrowsGender = Array.isArray(t.genders) && t.genders.length === 1;
|
|
11576
|
+
return narrowsAgeMax || narrowsAgeMin || narrowsGender;
|
|
11577
|
+
}
|
|
11499
11578
|
var specialAdCategoriesSchema = z14.array(z14.enum(SPECIAL_AD_CATEGORIES)).default(["NONE"]);
|
|
11500
11579
|
var campaignCreateSchema3 = z14.object({
|
|
11501
11580
|
name: z14.string().min(1).max(META_LIMITS.campaign.nameMax),
|
|
@@ -11519,6 +11598,14 @@ var campaignCreateSchema3 = z14.object({
|
|
|
11519
11598
|
if (p.stop_time && p.start_time && p.stop_time <= p.start_time) {
|
|
11520
11599
|
ctx.addIssue({ code: "custom", path: ["stop_time"], message: "stop_time must be after start_time" });
|
|
11521
11600
|
}
|
|
11601
|
+
const needsCountry = p.special_ad_categories.some((c) => SPECIAL_CATEGORIES_REQUIRING_COUNTRY.includes(c));
|
|
11602
|
+
if (needsCountry && !p.special_ad_category_country?.length) {
|
|
11603
|
+
ctx.addIssue({
|
|
11604
|
+
code: "custom",
|
|
11605
|
+
path: ["special_ad_category_country"],
|
|
11606
|
+
message: "ISSUES_ELECTIONS_POLITICS campaigns need special_ad_category_country \u2014 pass the 2-letter country code(s) the ads run in"
|
|
11607
|
+
});
|
|
11608
|
+
}
|
|
11522
11609
|
});
|
|
11523
11610
|
var campaignUpdateSchema3 = z14.object({
|
|
11524
11611
|
name: z14.string().min(1).max(META_LIMITS.campaign.nameMax).optional(),
|
|
@@ -11570,8 +11657,41 @@ var adSetFields = {
|
|
|
11570
11657
|
attribution_spec: attributionSpecSchema.optional(),
|
|
11571
11658
|
start_time: z14.number().int().positive().optional(),
|
|
11572
11659
|
end_time: z14.number().int().positive().optional(),
|
|
11573
|
-
targeting: metaTargetingSchema
|
|
11660
|
+
targeting: metaTargetingSchema,
|
|
11661
|
+
/** EU Digital Services Act: who benefits from / pays for the ad. Auto-filled from the account for EU geo when omitted. */
|
|
11662
|
+
dsa_beneficiary: z14.string().min(1).max(100).optional(),
|
|
11663
|
+
dsa_payor: z14.string().min(1).max(100).optional()
|
|
11574
11664
|
};
|
|
11665
|
+
function validateBidStrategy(p, ctx) {
|
|
11666
|
+
const strategy = p.bid_strategy;
|
|
11667
|
+
if (!strategy) {
|
|
11668
|
+
return;
|
|
11669
|
+
}
|
|
11670
|
+
if (BID_STRATEGIES_REQUIRING_AMOUNT.includes(strategy) && !p.bidAmount) {
|
|
11671
|
+
ctx.addIssue({ code: "custom", path: ["bidAmount"], message: `${strategy} requires a bidAmount` });
|
|
11672
|
+
}
|
|
11673
|
+
if (BID_STRATEGIES_FORBIDDING_AMOUNT.includes(strategy) && p.bidAmount) {
|
|
11674
|
+
ctx.addIssue({
|
|
11675
|
+
code: "custom",
|
|
11676
|
+
path: ["bidAmount"],
|
|
11677
|
+
message: `${strategy} must not set a bidAmount \u2014 Meta rejects one (it bids automatically)`
|
|
11678
|
+
});
|
|
11679
|
+
}
|
|
11680
|
+
if (strategy === "COST_CAP" && p.billing_event && p.billing_event !== "IMPRESSIONS") {
|
|
11681
|
+
ctx.addIssue({
|
|
11682
|
+
code: "custom",
|
|
11683
|
+
path: ["billing_event"],
|
|
11684
|
+
message: "COST_CAP requires billing_event IMPRESSIONS"
|
|
11685
|
+
});
|
|
11686
|
+
}
|
|
11687
|
+
if (strategy === "LOWEST_COST_WITH_MIN_ROAS" && p.optimization_goal && p.optimization_goal !== "VALUE") {
|
|
11688
|
+
ctx.addIssue({
|
|
11689
|
+
code: "custom",
|
|
11690
|
+
path: ["bid_strategy"],
|
|
11691
|
+
message: "LOWEST_COST_WITH_MIN_ROAS requires optimization_goal VALUE"
|
|
11692
|
+
});
|
|
11693
|
+
}
|
|
11694
|
+
}
|
|
11575
11695
|
function validateAdSetBudgetAndBid(p, ctx) {
|
|
11576
11696
|
if (p.dailyBudget && p.lifetimeBudget) {
|
|
11577
11697
|
ctx.addIssue({ code: "custom", path: ["dailyBudget"], message: "set only one of dailyBudget or lifetimeBudget" });
|
|
@@ -11580,25 +11700,74 @@ function validateAdSetBudgetAndBid(p, ctx) {
|
|
|
11580
11700
|
if (p.lifetimeBudget && !p.end_time) {
|
|
11581
11701
|
ctx.addIssue({ code: "custom", path: ["end_time"], message: "lifetimeBudget ad sets need an end_time" });
|
|
11582
11702
|
}
|
|
11583
|
-
|
|
11584
|
-
ctx.addIssue({ code: "custom", path: ["bidAmount"], message: `${p.bid_strategy} requires a bidAmount` });
|
|
11585
|
-
}
|
|
11703
|
+
validateBidStrategy(p, ctx);
|
|
11586
11704
|
if (p.end_time && p.start_time && p.end_time <= p.start_time) {
|
|
11587
11705
|
ctx.addIssue({ code: "custom", path: ["end_time"], message: "end_time must be after start_time" });
|
|
11588
11706
|
}
|
|
11589
11707
|
}
|
|
11590
11708
|
function validateAdSetPromotedObject(p, ctx) {
|
|
11591
|
-
|
|
11709
|
+
const goal = p.optimization_goal;
|
|
11710
|
+
if (!goal) {
|
|
11711
|
+
return;
|
|
11712
|
+
}
|
|
11713
|
+
const po = p.promoted_object;
|
|
11714
|
+
if (OPTIMIZATION_GOALS_REQUIRING_PAGE.includes(goal) && !po?.page_id) {
|
|
11592
11715
|
ctx.addIssue({
|
|
11593
11716
|
code: "custom",
|
|
11594
11717
|
path: ["promoted_object", "page_id"],
|
|
11595
|
-
message: `optimization_goal ${
|
|
11718
|
+
message: `optimization_goal ${goal} needs promoted_object.page_id \u2014 pass --page-id with the Facebook Page the leads/likes belong to`
|
|
11719
|
+
});
|
|
11720
|
+
}
|
|
11721
|
+
if (OPTIMIZATION_GOALS_REQUIRING_PIXEL.includes(goal) && !po?.pixel_id) {
|
|
11722
|
+
ctx.addIssue({
|
|
11723
|
+
code: "custom",
|
|
11724
|
+
path: ["promoted_object", "pixel_id"],
|
|
11725
|
+
message: `optimization_goal ${goal} needs promoted_object.pixel_id \u2014 pass --pixel-id with the conversion pixel`
|
|
11726
|
+
});
|
|
11727
|
+
}
|
|
11728
|
+
if (OPTIMIZATION_GOALS_REQUIRING_CONVERSION_SOURCE.includes(goal) && !po?.pixel_id && !po?.application_id) {
|
|
11729
|
+
ctx.addIssue({
|
|
11730
|
+
code: "custom",
|
|
11731
|
+
path: ["promoted_object", "pixel_id"],
|
|
11732
|
+
message: `optimization_goal ${goal} needs a conversion source \u2014 pass promoted_object.pixel_id (web value optimization) or promoted_object.application_id (app value optimization)`
|
|
11733
|
+
});
|
|
11734
|
+
}
|
|
11735
|
+
if ((OPTIMIZATION_GOALS_REQUIRING_PIXEL.includes(goal) || OPTIMIZATION_GOALS_REQUIRING_CONVERSION_SOURCE.includes(goal)) && !po?.custom_event_type) {
|
|
11736
|
+
ctx.addIssue({
|
|
11737
|
+
code: "custom",
|
|
11738
|
+
path: ["promoted_object", "custom_event_type"],
|
|
11739
|
+
message: `optimization_goal ${goal} needs promoted_object.custom_event_type \u2014 pass --custom-event-type (e.g. PURCHASE, LEAD)`
|
|
11740
|
+
});
|
|
11741
|
+
}
|
|
11742
|
+
if (OPTIMIZATION_GOALS_REQUIRING_APP.includes(goal) && !po?.application_id) {
|
|
11743
|
+
ctx.addIssue({
|
|
11744
|
+
code: "custom",
|
|
11745
|
+
path: ["promoted_object", "application_id"],
|
|
11746
|
+
message: `optimization_goal ${goal} needs promoted_object.application_id`
|
|
11747
|
+
});
|
|
11748
|
+
}
|
|
11749
|
+
}
|
|
11750
|
+
function validateAdvantageAudience(p, ctx) {
|
|
11751
|
+
const t = p.targeting;
|
|
11752
|
+
if (t && targetingHardLimitsDemographics(t) && advantageAudienceSetting(t) === 1) {
|
|
11753
|
+
ctx.addIssue({
|
|
11754
|
+
code: "custom",
|
|
11755
|
+
path: ["targeting", "targeting_automation", "advantage_audience"],
|
|
11756
|
+
message: "Advantage+ Audience (advantage_audience: 1) treats age and gender as suggestions, so a hard age/gender limit is rejected \u2014 set advantage_audience: 0 to enforce the limit, or drop the age_max/age_min/gender restriction"
|
|
11596
11757
|
});
|
|
11597
11758
|
}
|
|
11598
11759
|
}
|
|
11599
11760
|
var adSetCreateSchema = z14.object(adSetFields).superRefine((p, ctx) => {
|
|
11600
11761
|
validateAdSetBudgetAndBid(p, ctx);
|
|
11601
11762
|
validateAdSetPromotedObject(p, ctx);
|
|
11763
|
+
validateAdvantageAudience(p, ctx);
|
|
11764
|
+
if (!targetingHasGeoOrAudience(p.targeting)) {
|
|
11765
|
+
ctx.addIssue({
|
|
11766
|
+
code: "custom",
|
|
11767
|
+
path: ["targeting", "geo_locations"],
|
|
11768
|
+
message: 'targeting needs a location \u2014 set targeting.geo_locations (e.g. countries: ["US"]) or include a custom audience; Meta rejects an ad set with no geo'
|
|
11769
|
+
});
|
|
11770
|
+
}
|
|
11602
11771
|
});
|
|
11603
11772
|
var adSetUpdateSchema = z14.object({
|
|
11604
11773
|
name: adSetFields.name.optional(),
|
|
@@ -11613,7 +11782,9 @@ var adSetUpdateSchema = z14.object({
|
|
|
11613
11782
|
attribution_spec: attributionSpecSchema.optional(),
|
|
11614
11783
|
start_time: z14.number().int().positive().optional(),
|
|
11615
11784
|
end_time: z14.number().int().positive().optional(),
|
|
11616
|
-
targeting: metaTargetingSchema.optional()
|
|
11785
|
+
targeting: metaTargetingSchema.optional(),
|
|
11786
|
+
dsa_beneficiary: z14.string().min(1).max(100).optional(),
|
|
11787
|
+
dsa_payor: z14.string().min(1).max(100).optional()
|
|
11617
11788
|
}).superRefine((p, ctx) => {
|
|
11618
11789
|
if (!Object.values(p).some((val) => val !== void 0)) {
|
|
11619
11790
|
ctx.addIssue({ code: "custom", message: "update needs at least one field" });
|
|
@@ -11622,6 +11793,7 @@ var adSetUpdateSchema = z14.object({
|
|
|
11622
11793
|
if (p.optimization_goal) {
|
|
11623
11794
|
validateAdSetPromotedObject(p, ctx);
|
|
11624
11795
|
}
|
|
11796
|
+
validateAdvantageAudience(p, ctx);
|
|
11625
11797
|
});
|
|
11626
11798
|
var messageSchema = z14.string().min(1).max(META_LIMITS.creative.messageHardMax);
|
|
11627
11799
|
var headlineSchema2 = z14.string().min(1).max(META_LIMITS.creative.headlineMax);
|
|
@@ -13400,7 +13572,8 @@ Performance (the workhorse):
|
|
|
13400
13572
|
|
|
13401
13573
|
Audit & review:
|
|
13402
13574
|
baker ads meta activities --account-id act_123 --days 14
|
|
13403
|
-
baker ads meta preview --creative-id 9988 --ad-format MOBILE_FEED_STANDARD --out-file /tmp/p.html
|
|
13575
|
+
baker ads meta preview --creative-id 9988 --ad-format MOBILE_FEED_STANDARD --out-file /tmp/p.html
|
|
13576
|
+
Full guide: __tooling__/docs/tools/baker/ads-meta.md`
|
|
13404
13577
|
},
|
|
13405
13578
|
subCommands: {
|
|
13406
13579
|
accounts: accountsCommand3,
|
|
@@ -14864,7 +15037,8 @@ Examples:
|
|
|
14864
15037
|
--start-time 2026-04-01T00:00:00Z --end-time 2026-05-01T00:00:00Z \\
|
|
14865
15038
|
--metric-groups ENGAGEMENT,BILLING --segmentation-type LOCATIONS
|
|
14866
15039
|
|
|
14867
|
-
The CLI auto-detects --account-id when exactly one X Ads account is connected, or via BAKER_X_ADS_ACCOUNT_ID
|
|
15040
|
+
The CLI auto-detects --account-id when exactly one X Ads account is connected, or via BAKER_X_ADS_ACCOUNT_ID.
|
|
15041
|
+
Full guide: __tooling__/docs/tools/baker/ads-x.md`
|
|
14868
15042
|
},
|
|
14869
15043
|
subCommands: {
|
|
14870
15044
|
accounts: accountsCommand4,
|
|
@@ -14902,7 +15076,8 @@ Examples:
|
|
|
14902
15076
|
baker ads meta insights --object act_123 --level ad --date-preset last_7d --fields impressions,spend,ctr
|
|
14903
15077
|
baker ads linkedin accounts
|
|
14904
15078
|
baker ads x accounts
|
|
14905
|
-
baker ads x stats sync --preset campaign-engagement-7d --entity-ids abc,def
|
|
15079
|
+
baker ads x stats sync --preset campaign-engagement-7d --entity-ids abc,def
|
|
15080
|
+
Full guides: __tooling__/docs/tools/baker/ads-<platform>.md (google|meta|linkedin|x)`
|
|
14906
15081
|
},
|
|
14907
15082
|
subCommands: {
|
|
14908
15083
|
google: googleCommand,
|
|
@@ -21599,7 +21774,8 @@ Subcommands:
|
|
|
21599
21774
|
baker canvas catalog \u2014 print the agent-facing node + composition catalog (JSON Schema)
|
|
21600
21775
|
baker canvas inspect <run_id> \u2014 one-page summary of a completed run
|
|
21601
21776
|
baker canvas scaffold-video <video> \u2014 turn a reference video into a runnable reproduction canvas (deconstruct + recurring-element detection)
|
|
21602
|
-
baker canvas scaffold-static-ad <image> \u2014 turn a source image into a runnable static-ad canvas (describe + element detection)
|
|
21777
|
+
baker canvas scaffold-static-ad <image> \u2014 turn a source image into a runnable static-ad canvas (describe + element detection)
|
|
21778
|
+
Full guide: __tooling__/docs/tools/baker/canvas.md`
|
|
21603
21779
|
},
|
|
21604
21780
|
subCommands: {
|
|
21605
21781
|
run: runCommand,
|
|
@@ -21836,7 +22012,8 @@ var diffCommand = defineCommand96({
|
|
|
21836
22012
|
var chatsCommand = defineCommand96({
|
|
21837
22013
|
meta: {
|
|
21838
22014
|
name: "chats",
|
|
21839
|
-
description:
|
|
22015
|
+
description: `Inspect other Sessions on this account (read-only): list them, view what they produced, read their conversation, and see their real file changes \u2014 so you can reuse past work for a new goal.
|
|
22016
|
+
Full guide: __tooling__/docs/tools/baker/chats.md`
|
|
21840
22017
|
},
|
|
21841
22018
|
subCommands: {
|
|
21842
22019
|
list: listCommand5,
|
|
@@ -22060,7 +22237,8 @@ var creativesCommand3 = defineCommand98({
|
|
|
22060
22237
|
Static creative handoff:
|
|
22061
22238
|
baker creatives publish ./canvas/run/final.png --title "Spring Offer Static Ad"
|
|
22062
22239
|
|
|
22063
|
-
Publishing uploads the image to the Company image library, applies the official creative tag, and returns an image reference for chat previews
|
|
22240
|
+
Publishing uploads the image to the Company image library, applies the official creative tag, and returns an image reference for chat previews.
|
|
22241
|
+
Full guide: __tooling__/docs/tools/baker/creatives.md`
|
|
22064
22242
|
},
|
|
22065
22243
|
subCommands: {
|
|
22066
22244
|
publish: publishCommand
|
|
@@ -22268,7 +22446,8 @@ This command is READ-ONLY and never reveals secret values. Author a Form's struc
|
|
|
22268
22446
|
Examples:
|
|
22269
22447
|
baker flows list # every Form + how many confidential fields still need setup
|
|
22270
22448
|
baker flows show contact # one Form's confidential fields and their status
|
|
22271
|
-
baker flows show contact --full
|
|
22449
|
+
baker flows show contact --full
|
|
22450
|
+
Full guide: __tooling__/docs/tools/baker/flows.md`
|
|
22272
22451
|
},
|
|
22273
22452
|
subCommands: {
|
|
22274
22453
|
list: listCommand6,
|
|
@@ -22677,7 +22856,8 @@ Examples:
|
|
|
22677
22856
|
baker ga4 audit \u2014 full property health check
|
|
22678
22857
|
baker ga4 query --preset tracking-health \u2014 compare GA4 vs GAds data
|
|
22679
22858
|
baker ga4 query --preset lp-performance --days 14 \u2014 landing page UX audit
|
|
22680
|
-
baker ga4 query --dimensions "date" --metrics "sessions" --days 7 \u2014 free-form query
|
|
22859
|
+
baker ga4 query --dimensions "date" --metrics "sessions" --days 7 \u2014 free-form query
|
|
22860
|
+
Full guide: __tooling__/docs/tools/baker/ga4.md`
|
|
22681
22861
|
},
|
|
22682
22862
|
subCommands: {
|
|
22683
22863
|
properties: propertiesCommand,
|
|
@@ -23086,7 +23266,8 @@ Examples:
|
|
|
23086
23266
|
baker gsc query --preset cannibalization \u2014 find PPC-SEO overlap
|
|
23087
23267
|
baker gsc query --preset brand-halo --brand "Acme" --days 90 \u2014 brand search trends
|
|
23088
23268
|
baker gsc query --dimensions "query,page" --days 28 \u2014 free-form query
|
|
23089
|
-
baker gsc sitemaps \u2014 check sitemap health
|
|
23269
|
+
baker gsc sitemaps \u2014 check sitemap health
|
|
23270
|
+
Full guide: __tooling__/docs/tools/baker/gsc.md`
|
|
23090
23271
|
},
|
|
23091
23272
|
subCommands: {
|
|
23092
23273
|
sites: sitesCommand,
|
|
@@ -23200,7 +23381,8 @@ var listCommand7 = defineCommand108({
|
|
|
23200
23381
|
var historyCommand = defineCommand108({
|
|
23201
23382
|
meta: {
|
|
23202
23383
|
name: "history",
|
|
23203
|
-
description:
|
|
23384
|
+
description: `Unified account history (audit log): what changed, who did it, and when.
|
|
23385
|
+
Full guide: __tooling__/docs/tools/baker/history.md`
|
|
23204
23386
|
},
|
|
23205
23387
|
subCommands: { list: listCommand7 }
|
|
23206
23388
|
});
|
|
@@ -25798,7 +25980,8 @@ Taxonomy:
|
|
|
25798
25980
|
baker images tags List available image tag names (defaults + company custom tags)
|
|
25799
25981
|
|
|
25800
25982
|
Paid transforms (run on the Convex backend, cost-tracked):
|
|
25801
|
-
baker images upscale <imageId> Real-ESRGAN super-resolution ($0.05/image, waits for completion)
|
|
25983
|
+
baker images upscale <imageId> Real-ESRGAN super-resolution ($0.05/image, waits for completion)
|
|
25984
|
+
Full guide: __tooling__/docs/tools/baker/images.md`
|
|
25802
25985
|
},
|
|
25803
25986
|
subCommands: {
|
|
25804
25987
|
get: getCommand2,
|
|
@@ -25969,7 +26152,8 @@ Start here:
|
|
|
25969
26152
|
Examples:
|
|
25970
26153
|
baker mcp add --name weather --url https://mcp.example.com/mcp
|
|
25971
26154
|
baker mcp add --name acme --url https://acme.dev/mcp --header "Authorization: Bearer sk-\u2026"
|
|
25972
|
-
baker mcp remove --name weather
|
|
26155
|
+
baker mcp remove --name weather
|
|
26156
|
+
Full guide: __tooling__/docs/tools/baker/mcp.md`
|
|
25973
26157
|
},
|
|
25974
26158
|
subCommands: {
|
|
25975
26159
|
list: listCommand8,
|
|
@@ -26843,7 +27027,8 @@ Examples:
|
|
|
26843
27027
|
baker research advertisers "running shoes"
|
|
26844
27028
|
baker research intent "buy running shoes,best running shoes 2026"
|
|
26845
27029
|
baker research keywords-for-site "competitor.com"
|
|
26846
|
-
baker research keyword-gap "them.com" "us.com"
|
|
27030
|
+
baker research keyword-gap "them.com" "us.com"
|
|
27031
|
+
Full guide: __tooling__/docs/tools/baker/research.md`
|
|
26847
27032
|
},
|
|
26848
27033
|
subCommands: {
|
|
26849
27034
|
web: webCommand,
|
|
@@ -27290,7 +27475,8 @@ Examples:
|
|
|
27290
27475
|
baker scheduled-actions create --name "Weekly report" --description "Prepare weekly report" --cron "0 9 * * MON"
|
|
27291
27476
|
baker scheduled-actions update <id-or-temp_sched_id> --enabled false
|
|
27292
27477
|
baker scheduled-actions delete <id-or-temp_sched_id>
|
|
27293
|
-
baker scheduled-actions trigger <id
|
|
27478
|
+
baker scheduled-actions trigger <id>
|
|
27479
|
+
Full guide: __tooling__/docs/tools/baker/scheduled-actions.md`
|
|
27294
27480
|
},
|
|
27295
27481
|
subCommands: {
|
|
27296
27482
|
list: listCommand9,
|
|
@@ -27326,11 +27512,17 @@ var schemaCommand = defineCommand152({
|
|
|
27326
27512
|
const schema = getSchema(commandName);
|
|
27327
27513
|
if (!schema) {
|
|
27328
27514
|
const available = listSchemas();
|
|
27515
|
+
const segments = commandName.split(".");
|
|
27516
|
+
const family = segments[0] === "ads" && segments[1] ? `ads-${segments[1]}` : segments[0];
|
|
27329
27517
|
writeJson({
|
|
27330
27518
|
ok: false,
|
|
27331
27519
|
error: {
|
|
27332
27520
|
code: "NOT_FOUND",
|
|
27333
|
-
message: `Schema "${commandName}" not found. Available: ${available.join(", ")}
|
|
27521
|
+
message: `Schema "${commandName}" not found. Available: ${available.join(", ")}`,
|
|
27522
|
+
fix: {
|
|
27523
|
+
action: `Run the command with --help for exact args, and read __tooling__/docs/tools/baker/${family}.md`,
|
|
27524
|
+
explanation: "Not every command registers a schema; --help and the family doc are the ground truth for those."
|
|
27525
|
+
}
|
|
27334
27526
|
}
|
|
27335
27527
|
});
|
|
27336
27528
|
process.exit(1);
|
|
@@ -27447,7 +27639,8 @@ Refs: \`baker tags list\` prints each tag's ref \u2014 a real tag id, or tag_tem
|
|
|
27447
27639
|
|
|
27448
27640
|
Examples:
|
|
27449
27641
|
baker tags list # production + staged, full readable config + secret status
|
|
27450
|
-
baker tags draft # review the staged changes awaiting publish
|
|
27642
|
+
baker tags draft # review the staged changes awaiting publish
|
|
27643
|
+
Full guide: __tooling__/docs/tools/baker/tags.md`
|
|
27451
27644
|
},
|
|
27452
27645
|
subCommands: {
|
|
27453
27646
|
list: listCommand10,
|
|
@@ -27730,7 +27923,8 @@ Examples:
|
|
|
27730
27923
|
baker testimonials search "value for money" --rating-min 4
|
|
27731
27924
|
baker testimonials get <testimonial-id>
|
|
27732
27925
|
baker testimonials list --source google --sentiment positive
|
|
27733
|
-
baker testimonials tags
|
|
27926
|
+
baker testimonials tags
|
|
27927
|
+
Full guide: __tooling__/docs/tools/baker/testimonials.md`
|
|
27734
27928
|
},
|
|
27735
27929
|
subCommands: {
|
|
27736
27930
|
get: getCommand4,
|
|
@@ -28005,7 +28199,8 @@ Examples:
|
|
|
28005
28199
|
baker videos get <video-id>
|
|
28006
28200
|
baker videos upload ./demo.mp4
|
|
28007
28201
|
baker videos delete <video-id> --dry-run
|
|
28008
|
-
baker videos tags
|
|
28202
|
+
baker videos tags
|
|
28203
|
+
Full guide: __tooling__/docs/tools/baker/videos.md`
|
|
28009
28204
|
},
|
|
28010
28205
|
subCommands: {
|
|
28011
28206
|
get: getCommand5,
|
|
@@ -28017,7 +28212,7 @@ Examples:
|
|
|
28017
28212
|
});
|
|
28018
28213
|
|
|
28019
28214
|
// src/commands/winning-ads/index.ts
|
|
28020
|
-
import { defineCommand as
|
|
28215
|
+
import { defineCommand as defineCommand174 } from "citty";
|
|
28021
28216
|
|
|
28022
28217
|
// src/commands/winning-ads/advertisers.ts
|
|
28023
28218
|
import { defineCommand as defineCommand163 } from "citty";
|
|
@@ -28411,8 +28606,116 @@ var followCommand = defineCommand166({
|
|
|
28411
28606
|
}
|
|
28412
28607
|
});
|
|
28413
28608
|
|
|
28414
|
-
// src/commands/winning-ads/
|
|
28609
|
+
// src/commands/winning-ads/follow-competitors.ts
|
|
28415
28610
|
import { defineCommand as defineCommand167 } from "citty";
|
|
28611
|
+
var PLATFORMS2 = ["meta", "linkedin"];
|
|
28612
|
+
var BATCH_TIMEOUT_MS = 3e5;
|
|
28613
|
+
function buildFollowBatchBody(input) {
|
|
28614
|
+
const seen = /* @__PURE__ */ new Set();
|
|
28615
|
+
const inputs = [];
|
|
28616
|
+
for (const domain of splitList(input.domains)) {
|
|
28617
|
+
const key = domain.toLowerCase();
|
|
28618
|
+
if (seen.has(key)) {
|
|
28619
|
+
continue;
|
|
28620
|
+
}
|
|
28621
|
+
seen.add(key);
|
|
28622
|
+
inputs.push(domain);
|
|
28623
|
+
}
|
|
28624
|
+
return { inputs, platform: input.platform ?? "meta" };
|
|
28625
|
+
}
|
|
28626
|
+
registerSchema({
|
|
28627
|
+
command: "winning-ads.follow-competitors",
|
|
28628
|
+
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.",
|
|
28629
|
+
args: {
|
|
28630
|
+
domains: {
|
|
28631
|
+
type: "string",
|
|
28632
|
+
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"`,
|
|
28633
|
+
required: true
|
|
28634
|
+
},
|
|
28635
|
+
platform: {
|
|
28636
|
+
type: "string",
|
|
28637
|
+
description: "meta|linkedin \u2014 how to read each input, not a tracking limit (default meta). Domains resolve both.",
|
|
28638
|
+
required: false,
|
|
28639
|
+
default: "meta"
|
|
28640
|
+
}
|
|
28641
|
+
}
|
|
28642
|
+
});
|
|
28643
|
+
var followCompetitorsCommand = defineCommand167({
|
|
28644
|
+
meta: {
|
|
28645
|
+
name: "follow-competitors",
|
|
28646
|
+
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"'
|
|
28647
|
+
},
|
|
28648
|
+
args: {
|
|
28649
|
+
domains: {
|
|
28650
|
+
type: "positional",
|
|
28651
|
+
description: "Comma-separated domains (best), URLs, or brand names",
|
|
28652
|
+
required: true
|
|
28653
|
+
},
|
|
28654
|
+
platform: {
|
|
28655
|
+
type: "string",
|
|
28656
|
+
description: "meta|linkedin \u2014 how to read each input, not a tracking limit (default meta).",
|
|
28657
|
+
required: false,
|
|
28658
|
+
default: "meta"
|
|
28659
|
+
}
|
|
28660
|
+
},
|
|
28661
|
+
run: async ({ args }) => {
|
|
28662
|
+
try {
|
|
28663
|
+
const platform = String(args.platform ?? "meta");
|
|
28664
|
+
if (!PLATFORMS2.includes(platform)) {
|
|
28665
|
+
writeJson({
|
|
28666
|
+
ok: false,
|
|
28667
|
+
error: { code: "VALIDATION_ERROR", message: "--platform must be one of: meta, linkedin" }
|
|
28668
|
+
});
|
|
28669
|
+
process.exit(1);
|
|
28670
|
+
}
|
|
28671
|
+
const body = buildFollowBatchBody({ domains: String(args.domains ?? ""), platform });
|
|
28672
|
+
if (body.inputs.length === 0) {
|
|
28673
|
+
writeJson({
|
|
28674
|
+
ok: false,
|
|
28675
|
+
error: { code: "VALIDATION_ERROR", message: "Pass at least one domain in --domains." }
|
|
28676
|
+
});
|
|
28677
|
+
process.exit(1);
|
|
28678
|
+
}
|
|
28679
|
+
if (body.inputs.length > FOLLOW_BATCH_MAX) {
|
|
28680
|
+
writeJson({
|
|
28681
|
+
ok: false,
|
|
28682
|
+
error: {
|
|
28683
|
+
code: "VALIDATION_ERROR",
|
|
28684
|
+
message: `Too many brands (${body.inputs.length}). Follow at most ${FOLLOW_BATCH_MAX} per call.`
|
|
28685
|
+
}
|
|
28686
|
+
});
|
|
28687
|
+
process.exit(1);
|
|
28688
|
+
}
|
|
28689
|
+
const data = await apiPost("/api/ad-library/follow-batch", body, {
|
|
28690
|
+
timeoutMs: BATCH_TIMEOUT_MS
|
|
28691
|
+
});
|
|
28692
|
+
const hints = [];
|
|
28693
|
+
if (data.failed_count > 0) {
|
|
28694
|
+
const failed = data.results.filter((r) => r.status === "failed").map((r) => r.input);
|
|
28695
|
+
hints.push(
|
|
28696
|
+
`${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\`.`
|
|
28697
|
+
);
|
|
28698
|
+
}
|
|
28699
|
+
if (data.ambiguous_count > 0) {
|
|
28700
|
+
const ambiguous = data.results.filter((r) => r.status === "ambiguous").map((r) => r.input);
|
|
28701
|
+
hints.push(
|
|
28702
|
+
`${data.ambiguous_count} brand(s) matched multiple advertisers: ${ambiguous.join(", ")}. Re-run \`baker winning-ads follow\` with an exact domain/URL to pick one.`
|
|
28703
|
+
);
|
|
28704
|
+
}
|
|
28705
|
+
if (data.added_count > 0) {
|
|
28706
|
+
hints.push(
|
|
28707
|
+
"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`."
|
|
28708
|
+
);
|
|
28709
|
+
}
|
|
28710
|
+
writeJson({ ok: true, data, hints: hints.length > 0 ? hints : void 0 });
|
|
28711
|
+
} catch (err) {
|
|
28712
|
+
reportError(err);
|
|
28713
|
+
}
|
|
28714
|
+
}
|
|
28715
|
+
});
|
|
28716
|
+
|
|
28717
|
+
// src/commands/winning-ads/following.ts
|
|
28718
|
+
import { defineCommand as defineCommand168 } from "citty";
|
|
28416
28719
|
registerSchema({
|
|
28417
28720
|
command: "winning-ads.following",
|
|
28418
28721
|
description: "List the brands you follow in your ad-dna library, with each one's status (ready vs still adding) and cached ad counts.",
|
|
@@ -28445,7 +28748,7 @@ function followingNormalizer(record, full) {
|
|
|
28445
28748
|
platforms: Array.isArray(record.platforms) ? record.platforms : []
|
|
28446
28749
|
};
|
|
28447
28750
|
}
|
|
28448
|
-
var followingCommand =
|
|
28751
|
+
var followingCommand = defineCommand168({
|
|
28449
28752
|
meta: {
|
|
28450
28753
|
name: "following",
|
|
28451
28754
|
description: "List brands you follow, with status (ready / adding\u2026) and cached counts. Example: baker winning-ads following --output md"
|
|
@@ -28480,7 +28783,7 @@ var followingCommand = defineCommand167({
|
|
|
28480
28783
|
});
|
|
28481
28784
|
|
|
28482
28785
|
// src/commands/winning-ads/patterns.ts
|
|
28483
|
-
import { defineCommand as
|
|
28786
|
+
import { defineCommand as defineCommand169 } from "citty";
|
|
28484
28787
|
registerSchema({
|
|
28485
28788
|
command: "winning-ads.patterns",
|
|
28486
28789
|
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.",
|
|
@@ -28519,7 +28822,7 @@ function discriminatorRow(record) {
|
|
|
28519
28822
|
top_values_duds: Array.isArray(record.top_values_b) ? record.top_values_b.join(", ") : ""
|
|
28520
28823
|
};
|
|
28521
28824
|
}
|
|
28522
|
-
var patternsCommand =
|
|
28825
|
+
var patternsCommand = defineCommand169({
|
|
28523
28826
|
meta: {
|
|
28524
28827
|
name: "patterns",
|
|
28525
28828
|
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"
|
|
@@ -28575,7 +28878,7 @@ var patternsCommand = defineCommand168({
|
|
|
28575
28878
|
});
|
|
28576
28879
|
|
|
28577
28880
|
// src/commands/winning-ads/search.ts
|
|
28578
|
-
import { defineCommand as
|
|
28881
|
+
import { defineCommand as defineCommand170 } from "citty";
|
|
28579
28882
|
registerSchema({
|
|
28580
28883
|
command: "winning-ads.search",
|
|
28581
28884
|
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.",
|
|
@@ -28683,7 +28986,7 @@ function buildSearchBody(args) {
|
|
|
28683
28986
|
}
|
|
28684
28987
|
return body;
|
|
28685
28988
|
}
|
|
28686
|
-
var searchCommand4 =
|
|
28989
|
+
var searchCommand4 = defineCommand170({
|
|
28687
28990
|
meta: {
|
|
28688
28991
|
name: "search",
|
|
28689
28992
|
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"
|
|
@@ -28798,7 +29101,7 @@ var searchCommand4 = defineCommand169({
|
|
|
28798
29101
|
});
|
|
28799
29102
|
|
|
28800
29103
|
// src/commands/winning-ads/seeds.ts
|
|
28801
|
-
import { defineCommand as
|
|
29104
|
+
import { defineCommand as defineCommand171 } from "citty";
|
|
28802
29105
|
function leanRow(r) {
|
|
28803
29106
|
return {
|
|
28804
29107
|
key: r.key,
|
|
@@ -28826,7 +29129,7 @@ function makeSeedCommand(opts) {
|
|
|
28826
29129
|
limit: { type: "number", description: "Max keys 1-100 (default 20)", required: false, default: 20 }
|
|
28827
29130
|
}
|
|
28828
29131
|
});
|
|
28829
|
-
return
|
|
29132
|
+
return defineCommand171({
|
|
28830
29133
|
meta: { name: opts.name, description: opts.description },
|
|
28831
29134
|
args: {
|
|
28832
29135
|
platform: { type: "string", description: "Single platform to segment on", required: false },
|
|
@@ -28875,7 +29178,7 @@ var formatsCommand = makeSeedCommand({
|
|
|
28875
29178
|
});
|
|
28876
29179
|
|
|
28877
29180
|
// src/commands/winning-ads/unfollow.ts
|
|
28878
|
-
import { defineCommand as
|
|
29181
|
+
import { defineCommand as defineCommand172 } from "citty";
|
|
28879
29182
|
registerSchema({
|
|
28880
29183
|
command: "winning-ads.unfollow",
|
|
28881
29184
|
description: "Stop following a brand \u2014 removes it from your ad-dna library by advertiser id.",
|
|
@@ -28883,7 +29186,7 @@ registerSchema({
|
|
|
28883
29186
|
advertiser: { type: "string", description: "Advertiser id to unfollow", required: true }
|
|
28884
29187
|
}
|
|
28885
29188
|
});
|
|
28886
|
-
var unfollowCommand =
|
|
29189
|
+
var unfollowCommand = defineCommand172({
|
|
28887
29190
|
meta: {
|
|
28888
29191
|
name: "unfollow",
|
|
28889
29192
|
description: "Stop following a brand by advertiser id. Example: baker winning-ads unfollow adv_123"
|
|
@@ -28904,7 +29207,7 @@ var unfollowCommand = defineCommand171({
|
|
|
28904
29207
|
});
|
|
28905
29208
|
|
|
28906
29209
|
// src/commands/winning-ads/winners.ts
|
|
28907
|
-
import { defineCommand as
|
|
29210
|
+
import { defineCommand as defineCommand173 } from "citty";
|
|
28908
29211
|
registerSchema({
|
|
28909
29212
|
command: "winning-ads.winners",
|
|
28910
29213
|
description: "Top winning ads for one advertiser id (from `advertisers` or `following`). Returns lean winner cards; add --full for DNA + longevity.",
|
|
@@ -28914,7 +29217,7 @@ registerSchema({
|
|
|
28914
29217
|
platform: { type: "string", description: "Filter to a single platform: meta|linkedin", required: false }
|
|
28915
29218
|
}
|
|
28916
29219
|
});
|
|
28917
|
-
var winnersCommand =
|
|
29220
|
+
var winnersCommand = defineCommand173({
|
|
28918
29221
|
meta: {
|
|
28919
29222
|
name: "winners",
|
|
28920
29223
|
description: "Top winning ads for a specific advertiser id. Example: baker winning-ads winners adv_123 --top 15 --output md"
|
|
@@ -28964,7 +29267,7 @@ var winnersCommand = defineCommand172({
|
|
|
28964
29267
|
});
|
|
28965
29268
|
|
|
28966
29269
|
// src/commands/winning-ads/index.ts
|
|
28967
|
-
var winningAdsCommand =
|
|
29270
|
+
var winningAdsCommand = defineCommand174({
|
|
28968
29271
|
meta: {
|
|
28969
29272
|
name: "winning-ads",
|
|
28970
29273
|
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.
|
|
@@ -28975,6 +29278,7 @@ Subcommands:
|
|
|
28975
29278
|
baker winning-ads search "<free text>" \u2014 semantic search across the corpus; lean shortlist (advertiser, summary, scores, media_url)
|
|
28976
29279
|
baker winning-ads advertisers "<brand>" \u2014 list corpus brands \u2192 advertiser ids (for --exclude-advertiser / --advertiser-id)
|
|
28977
29280
|
baker winning-ads follow "<domain|url|brand>" --platform meta|linkedin \u2014 add a brand's ads to your library
|
|
29281
|
+
baker winning-ads follow-competitors "<domain,domain,...>" \u2014 add MANY brands at once (every competitor by domain)
|
|
28978
29282
|
baker winning-ads following \u2014 list brands you follow (status + counts)
|
|
28979
29283
|
baker winning-ads feed \u2014 winners across EVERY brand you follow; trim with --advertiser
|
|
28980
29284
|
baker winning-ads winners <advertiser> \u2014 top winners for one advertiser id
|
|
@@ -28989,17 +29293,20 @@ Examples:
|
|
|
28989
29293
|
baker winning-ads search "B2B SaaS before/after AI automation" --platform meta --format static --output md
|
|
28990
29294
|
baker winning-ads advertisers "Acme" --output md
|
|
28991
29295
|
baker winning-ads follow "deel.com" --platform meta
|
|
29296
|
+
baker winning-ads follow-competitors "deel.com,notion.so,hubspot.com"
|
|
28992
29297
|
baker winning-ads feed --per-advertiser 5 --output md
|
|
28993
29298
|
baker winning-ads feed --advertiser adv_123,adv_456 --platform meta --output md
|
|
28994
29299
|
baker winning-ads winners adv_123 --top 15 --output md
|
|
28995
29300
|
baker winning-ads hooks --platform meta --awareness problem_aware --industry saas --output md
|
|
28996
29301
|
baker winning-ads search "fintech onboarding" --hook-archetype callout --winner-category winner --output md
|
|
28997
|
-
baker winning-ads patterns --winners a_1,a_2 --duds a_9,a_8 --output md
|
|
29302
|
+
baker winning-ads patterns --winners a_1,a_2 --duds a_9,a_8 --output md
|
|
29303
|
+
Full guide: __tooling__/docs/tools/baker/winning-ads.md`
|
|
28998
29304
|
},
|
|
28999
29305
|
subCommands: {
|
|
29000
29306
|
search: searchCommand4,
|
|
29001
29307
|
advertisers: advertisersCommand2,
|
|
29002
29308
|
follow: followCommand,
|
|
29309
|
+
"follow-competitors": followCompetitorsCommand,
|
|
29003
29310
|
following: followingCommand,
|
|
29004
29311
|
feed: feedCommand,
|
|
29005
29312
|
winners: winnersCommand,
|
|
@@ -29029,7 +29336,7 @@ function getCliVersion() {
|
|
|
29029
29336
|
}
|
|
29030
29337
|
|
|
29031
29338
|
// src/cli.ts
|
|
29032
|
-
var main =
|
|
29339
|
+
var main = defineCommand175({
|
|
29033
29340
|
meta: {
|
|
29034
29341
|
name: "baker",
|
|
29035
29342
|
version: getCliVersion(),
|