@koda-sl/baker-cli 0.133.1 → 0.134.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/dist/cli.js
CHANGED
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
toModelSafeImage,
|
|
35
35
|
ulid,
|
|
36
36
|
validateCanvasDeep
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-CIF62V7L.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 defineCommand172, runMain } from "citty";
|
|
77
77
|
|
|
78
78
|
// src/commands/actions/index.ts
|
|
79
79
|
import { defineCommand as defineCommand18 } from "citty";
|
|
@@ -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.
|
|
@@ -20631,20 +20655,6 @@ function parseBudget(raw) {
|
|
|
20631
20655
|
}
|
|
20632
20656
|
function resolveModels2(args) {
|
|
20633
20657
|
const pick = (flag, kind, fallback) => args[flag] ? String(args[flag]) : resolveModel2(kind, fallback);
|
|
20634
|
-
let videoModel;
|
|
20635
|
-
let videoRouteReason;
|
|
20636
|
-
if (args["video-model"]) {
|
|
20637
|
-
videoModel = resolveModel2("video_generate", String(args["video-model"]));
|
|
20638
|
-
} else {
|
|
20639
|
-
const route = routeVideoModel({
|
|
20640
|
-
hasRealFace: Boolean(args["real-face"]),
|
|
20641
|
-
needsIdentity: Boolean(args.identity),
|
|
20642
|
-
needsMotionTransfer: Boolean(args["motion-transfer"]),
|
|
20643
|
-
budget: parseBudget(args.budget)
|
|
20644
|
-
});
|
|
20645
|
-
videoModel = resolveModel2("video_generate", route.model);
|
|
20646
|
-
videoRouteReason = route.reason;
|
|
20647
|
-
}
|
|
20648
20658
|
return {
|
|
20649
20659
|
// Flash by default: ~2-3× faster per call than Pro, which keeps each
|
|
20650
20660
|
// per-scene deconstruct step well inside the action time budget and turns a
|
|
@@ -20655,11 +20665,29 @@ function resolveModels2(args) {
|
|
|
20655
20665
|
// Default to the strongest image model (matches the static-ad scaffold); the
|
|
20656
20666
|
// frame generators need the most faithful text/identity reproduction. Override
|
|
20657
20667
|
// with --image-model for a cheaper/faster pass.
|
|
20658
|
-
imageModel: pick("image-model", "image_generate", "openai/gpt-5.4-image-2")
|
|
20659
|
-
videoModel: videoModel || DEFAULT_VIDEO_GENERATE_MODEL,
|
|
20660
|
-
videoRouteReason
|
|
20668
|
+
imageModel: pick("image-model", "image_generate", "openai/gpt-5.4-image-2")
|
|
20661
20669
|
};
|
|
20662
20670
|
}
|
|
20671
|
+
function hasPhotorealCast(elements) {
|
|
20672
|
+
return Array.isArray(elements) && elements.some((e) => {
|
|
20673
|
+
const type = typeof e === "object" && e !== null ? e.type : void 0;
|
|
20674
|
+
return type === "person" || type === "animal";
|
|
20675
|
+
});
|
|
20676
|
+
}
|
|
20677
|
+
function resolveVideoModel(args, elements) {
|
|
20678
|
+
if (args["video-model"]) {
|
|
20679
|
+
return { videoModel: resolveModel2("video_generate", String(args["video-model"])) };
|
|
20680
|
+
}
|
|
20681
|
+
const photorealCast = hasPhotorealCast(elements);
|
|
20682
|
+
const route = routeVideoModel({
|
|
20683
|
+
hasRealFace: Boolean(args["real-face"]) || photorealCast,
|
|
20684
|
+
needsIdentity: Boolean(args.identity),
|
|
20685
|
+
needsMotionTransfer: Boolean(args["motion-transfer"]),
|
|
20686
|
+
budget: parseBudget(args.budget)
|
|
20687
|
+
});
|
|
20688
|
+
const reason = photorealCast && !args["real-face"] ? `${route.reason} \u2014 detected a photoreal on-camera cast, which Seedance's real-person filter would block` : route.reason;
|
|
20689
|
+
return { videoModel: resolveModel2("video_generate", route.model) || DEFAULT_VIDEO_GENERATE_MODEL, videoRouteReason: reason };
|
|
20690
|
+
}
|
|
20663
20691
|
function buildDeconstructCanvas(videoPath, deconstructModel, opts) {
|
|
20664
20692
|
const deconstructParams = { model: deconstructModel, mode: "full" };
|
|
20665
20693
|
if (typeof opts.maxScenes === "number") deconstructParams.max_scenes = opts.maxScenes;
|
|
@@ -20780,7 +20808,7 @@ var scaffoldVideoCommand = defineCommand92({
|
|
|
20780
20808
|
"video-model": { type: "string", description: "Override the video_generate model id for clips (skips the scored router)" },
|
|
20781
20809
|
"real-face": {
|
|
20782
20810
|
type: "boolean",
|
|
20783
|
-
description: "
|
|
20811
|
+
description: "The ad has a photoreal human face on camera \u2192 the router picks Veo (dodges the ByteDance real-person filter). Set this for ANY photoreal presenter/creator/testimonial cast \u2014 the filter blocks AI-GENERATED photoreal faces too, not just real ones."
|
|
20784
20812
|
},
|
|
20785
20813
|
"motion-transfer": {
|
|
20786
20814
|
type: "boolean",
|
|
@@ -20839,7 +20867,7 @@ var scaffoldVideoCommand = defineCommand92({
|
|
|
20839
20867
|
`
|
|
20840
20868
|
);
|
|
20841
20869
|
}
|
|
20842
|
-
const { deconstructModel, selectModel, imageModel
|
|
20870
|
+
const { deconstructModel, selectModel, imageModel } = resolveModels2(args);
|
|
20843
20871
|
const shotThreshold = args["shot-threshold"] ? Number(args["shot-threshold"]) : void 0;
|
|
20844
20872
|
const shotCuts = await detectShotCutsBestEffort(videoPath, shotThreshold);
|
|
20845
20873
|
const deconstructCanvas = buildDeconstructCanvas(videoPath, deconstructModel, {
|
|
@@ -20849,6 +20877,11 @@ var scaffoldVideoCommand = defineCommand92({
|
|
|
20849
20877
|
shotCuts
|
|
20850
20878
|
});
|
|
20851
20879
|
const { blueprint, elements, transcript, creditsSpent } = await runAnalysisPasses(deconstructCanvas, selectModel);
|
|
20880
|
+
const { videoModel, videoRouteReason } = resolveVideoModel(args, elements);
|
|
20881
|
+
if (videoRouteReason && !args["video-model"] && !args["real-face"] && hasPhotorealCast(elements)) {
|
|
20882
|
+
process.stderr.write(`\u{1F3AC} Photoreal on-camera cast detected \u2192 generating clips on ${videoModel} (dodges Seedance's real-person filter).
|
|
20883
|
+
`);
|
|
20884
|
+
}
|
|
20852
20885
|
await mkdir6(outDir, { recursive: true });
|
|
20853
20886
|
const annotated = annotateBlueprintWithElements(blueprint, elements);
|
|
20854
20887
|
await writeSceneFiles(outDir, annotated);
|
|
@@ -21018,12 +21051,12 @@ var scaffoldVideoCommand = defineCommand92({
|
|
|
21018
21051
|
// on-brand color. The overlays inherit the reference's motion unless the
|
|
21019
21052
|
// operator restyles easing/transition/accent from the brand's motion language.
|
|
21020
21053
|
prompt_discipline: "Rewrite each scene with the six-decision structure (Route / Spec / Beats / Copy / Technique / Negatives): quote exact copy, give every beat a timestamp, and name the moves. Pull easing, transition (cut vs fade), pacing, and the accent moment from BRAND.md \xA7 Brand in Motion so the overlays move like THIS brand \u2014 not the reference's. If BRAND.md has no Brand-in-Motion section, seed it with brand-build first. See the creative-canvas-ads skill: references/prompt-anatomy.md + references/hyperframes/.",
|
|
21021
|
-
//
|
|
21022
|
-
//
|
|
21023
|
-
//
|
|
21024
|
-
//
|
|
21054
|
+
// Photoreal on-camera casts auto-route to Veo above, so this only fires
|
|
21055
|
+
// when `--video-model bytedance/seedance-2.0` was EXPLICITLY forced despite
|
|
21056
|
+
// a person/animal cast — overriding that safety route. Warn that every such
|
|
21057
|
+
// clip will hit ByteDance's real-person filter and burn a wasted attempt.
|
|
21025
21058
|
...report.elements.some((e) => e.type === "person" || e.type === "animal") && /seedance/i.test(videoModel) ? {
|
|
21026
|
-
content_policy_risk: "
|
|
21059
|
+
content_policy_risk: "You FORCED Seedance (`--video-model bytedance/seedance-2.0`) on an ad with a photoreal on-camera cast. ByteDance's real-person filter will reject those clips (content_policy_blocked, E005) \u2014 no prompt change clears it. Each clip auto-recovers on Veo at render time so the run still completes, but you burn a wasted Seedance attempt per clip. Drop `--video-model` to let the scaffold route the cast to Veo up front, or make the frames less photorealistic."
|
|
21027
21060
|
} : {},
|
|
21028
21061
|
note: "Drop ONE real source image at each el_* [TODO] (reused across every frame that element appears in), confirm each voice_select casting, then `baker canvas validate` and `baker canvas run`. Running generates many billed image/video/audio assets \u2014 it is not free."
|
|
21029
21062
|
}
|
|
@@ -27249,7 +27282,7 @@ Examples:
|
|
|
27249
27282
|
});
|
|
27250
27283
|
|
|
27251
27284
|
// src/commands/winning-ads/index.ts
|
|
27252
|
-
import { defineCommand as
|
|
27285
|
+
import { defineCommand as defineCommand171 } from "citty";
|
|
27253
27286
|
|
|
27254
27287
|
// src/commands/winning-ads/advertisers.ts
|
|
27255
27288
|
import { defineCommand as defineCommand161 } from "citty";
|
|
@@ -27444,8 +27477,145 @@ var briefCommand = defineCommand162({
|
|
|
27444
27477
|
}
|
|
27445
27478
|
});
|
|
27446
27479
|
|
|
27447
|
-
// src/commands/winning-ads/
|
|
27480
|
+
// src/commands/winning-ads/feed.ts
|
|
27448
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";
|
|
27449
27619
|
var PLATFORMS = ["meta", "linkedin"];
|
|
27450
27620
|
registerSchema({
|
|
27451
27621
|
command: "winning-ads.follow",
|
|
@@ -27460,7 +27630,7 @@ registerSchema({
|
|
|
27460
27630
|
label: { type: "string", description: "Optional display label (defaults to the resolved name)", required: false }
|
|
27461
27631
|
}
|
|
27462
27632
|
});
|
|
27463
|
-
var followCommand =
|
|
27633
|
+
var followCommand = defineCommand164({
|
|
27464
27634
|
meta: {
|
|
27465
27635
|
name: "follow",
|
|
27466
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'
|
|
@@ -27507,7 +27677,7 @@ var followCommand = defineCommand163({
|
|
|
27507
27677
|
});
|
|
27508
27678
|
|
|
27509
27679
|
// src/commands/winning-ads/following.ts
|
|
27510
|
-
import { defineCommand as
|
|
27680
|
+
import { defineCommand as defineCommand165 } from "citty";
|
|
27511
27681
|
registerSchema({
|
|
27512
27682
|
command: "winning-ads.following",
|
|
27513
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.",
|
|
@@ -27540,7 +27710,7 @@ function followingNormalizer(record, full) {
|
|
|
27540
27710
|
platforms: Array.isArray(record.platforms) ? record.platforms : []
|
|
27541
27711
|
};
|
|
27542
27712
|
}
|
|
27543
|
-
var followingCommand =
|
|
27713
|
+
var followingCommand = defineCommand165({
|
|
27544
27714
|
meta: {
|
|
27545
27715
|
name: "following",
|
|
27546
27716
|
description: "List brands you follow, with status (ready / adding\u2026) and cached counts. Example: baker winning-ads following --output md"
|
|
@@ -27575,7 +27745,7 @@ var followingCommand = defineCommand164({
|
|
|
27575
27745
|
});
|
|
27576
27746
|
|
|
27577
27747
|
// src/commands/winning-ads/patterns.ts
|
|
27578
|
-
import { defineCommand as
|
|
27748
|
+
import { defineCommand as defineCommand166 } from "citty";
|
|
27579
27749
|
registerSchema({
|
|
27580
27750
|
command: "winning-ads.patterns",
|
|
27581
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.",
|
|
@@ -27614,7 +27784,7 @@ function discriminatorRow(record) {
|
|
|
27614
27784
|
top_values_duds: Array.isArray(record.top_values_b) ? record.top_values_b.join(", ") : ""
|
|
27615
27785
|
};
|
|
27616
27786
|
}
|
|
27617
|
-
var patternsCommand =
|
|
27787
|
+
var patternsCommand = defineCommand166({
|
|
27618
27788
|
meta: {
|
|
27619
27789
|
name: "patterns",
|
|
27620
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"
|
|
@@ -27670,7 +27840,7 @@ var patternsCommand = defineCommand165({
|
|
|
27670
27840
|
});
|
|
27671
27841
|
|
|
27672
27842
|
// src/commands/winning-ads/search.ts
|
|
27673
|
-
import { defineCommand as
|
|
27843
|
+
import { defineCommand as defineCommand167 } from "citty";
|
|
27674
27844
|
registerSchema({
|
|
27675
27845
|
command: "winning-ads.search",
|
|
27676
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.",
|
|
@@ -27778,7 +27948,7 @@ function buildSearchBody(args) {
|
|
|
27778
27948
|
}
|
|
27779
27949
|
return body;
|
|
27780
27950
|
}
|
|
27781
|
-
var searchCommand4 =
|
|
27951
|
+
var searchCommand4 = defineCommand167({
|
|
27782
27952
|
meta: {
|
|
27783
27953
|
name: "search",
|
|
27784
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"
|
|
@@ -27893,7 +28063,7 @@ var searchCommand4 = defineCommand166({
|
|
|
27893
28063
|
});
|
|
27894
28064
|
|
|
27895
28065
|
// src/commands/winning-ads/seeds.ts
|
|
27896
|
-
import { defineCommand as
|
|
28066
|
+
import { defineCommand as defineCommand168 } from "citty";
|
|
27897
28067
|
function leanRow(r) {
|
|
27898
28068
|
return {
|
|
27899
28069
|
key: r.key,
|
|
@@ -27921,7 +28091,7 @@ function makeSeedCommand(opts) {
|
|
|
27921
28091
|
limit: { type: "number", description: "Max keys 1-100 (default 20)", required: false, default: 20 }
|
|
27922
28092
|
}
|
|
27923
28093
|
});
|
|
27924
|
-
return
|
|
28094
|
+
return defineCommand168({
|
|
27925
28095
|
meta: { name: opts.name, description: opts.description },
|
|
27926
28096
|
args: {
|
|
27927
28097
|
platform: { type: "string", description: "Single platform to segment on", required: false },
|
|
@@ -27970,7 +28140,7 @@ var formatsCommand = makeSeedCommand({
|
|
|
27970
28140
|
});
|
|
27971
28141
|
|
|
27972
28142
|
// src/commands/winning-ads/unfollow.ts
|
|
27973
|
-
import { defineCommand as
|
|
28143
|
+
import { defineCommand as defineCommand169 } from "citty";
|
|
27974
28144
|
registerSchema({
|
|
27975
28145
|
command: "winning-ads.unfollow",
|
|
27976
28146
|
description: "Stop following a brand \u2014 removes it from your ad-dna library by advertiser id.",
|
|
@@ -27978,7 +28148,7 @@ registerSchema({
|
|
|
27978
28148
|
advertiser: { type: "string", description: "Advertiser id to unfollow", required: true }
|
|
27979
28149
|
}
|
|
27980
28150
|
});
|
|
27981
|
-
var unfollowCommand =
|
|
28151
|
+
var unfollowCommand = defineCommand169({
|
|
27982
28152
|
meta: {
|
|
27983
28153
|
name: "unfollow",
|
|
27984
28154
|
description: "Stop following a brand by advertiser id. Example: baker winning-ads unfollow adv_123"
|
|
@@ -27999,7 +28169,7 @@ var unfollowCommand = defineCommand168({
|
|
|
27999
28169
|
});
|
|
28000
28170
|
|
|
28001
28171
|
// src/commands/winning-ads/winners.ts
|
|
28002
|
-
import { defineCommand as
|
|
28172
|
+
import { defineCommand as defineCommand170 } from "citty";
|
|
28003
28173
|
registerSchema({
|
|
28004
28174
|
command: "winning-ads.winners",
|
|
28005
28175
|
description: "Top winning ads for one advertiser id (from `advertisers` or `following`). Returns lean winner cards; add --full for DNA + longevity.",
|
|
@@ -28009,7 +28179,7 @@ registerSchema({
|
|
|
28009
28179
|
platform: { type: "string", description: "Filter to a single platform: meta|linkedin", required: false }
|
|
28010
28180
|
}
|
|
28011
28181
|
});
|
|
28012
|
-
var winnersCommand =
|
|
28182
|
+
var winnersCommand = defineCommand170({
|
|
28013
28183
|
meta: {
|
|
28014
28184
|
name: "winners",
|
|
28015
28185
|
description: "Top winning ads for a specific advertiser id. Example: baker winning-ads winners adv_123 --top 15 --output md"
|
|
@@ -28059,7 +28229,7 @@ var winnersCommand = defineCommand169({
|
|
|
28059
28229
|
});
|
|
28060
28230
|
|
|
28061
28231
|
// src/commands/winning-ads/index.ts
|
|
28062
|
-
var winningAdsCommand =
|
|
28232
|
+
var winningAdsCommand = defineCommand171({
|
|
28063
28233
|
meta: {
|
|
28064
28234
|
name: "winning-ads",
|
|
28065
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.
|
|
@@ -28071,6 +28241,7 @@ Subcommands:
|
|
|
28071
28241
|
baker winning-ads advertisers "<brand>" \u2014 list corpus brands \u2192 advertiser ids (for --exclude-advertiser / --advertiser-id)
|
|
28072
28242
|
baker winning-ads follow "<domain|url|brand>" --platform meta|linkedin \u2014 add a brand's ads to your library
|
|
28073
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
|
|
28074
28245
|
baker winning-ads winners <advertiser> \u2014 top winners for one advertiser id
|
|
28075
28246
|
baker winning-ads unfollow <advertiser> \u2014 stop following a brand
|
|
28076
28247
|
baker winning-ads brief \u2014 creative brief grounded in similar winners
|
|
@@ -28083,6 +28254,8 @@ Examples:
|
|
|
28083
28254
|
baker winning-ads search "B2B SaaS before/after AI automation" --platform meta --format static --output md
|
|
28084
28255
|
baker winning-ads advertisers "Acme" --output md
|
|
28085
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
|
|
28086
28259
|
baker winning-ads winners adv_123 --top 15 --output md
|
|
28087
28260
|
baker winning-ads hooks --platform meta --awareness problem_aware --industry saas --output md
|
|
28088
28261
|
baker winning-ads search "fintech onboarding" --hook-archetype callout --winner-category winner --output md
|
|
@@ -28093,6 +28266,7 @@ Examples:
|
|
|
28093
28266
|
advertisers: advertisersCommand2,
|
|
28094
28267
|
follow: followCommand,
|
|
28095
28268
|
following: followingCommand,
|
|
28269
|
+
feed: feedCommand,
|
|
28096
28270
|
winners: winnersCommand,
|
|
28097
28271
|
unfollow: unfollowCommand,
|
|
28098
28272
|
brief: briefCommand,
|
|
@@ -28120,7 +28294,7 @@ function getCliVersion() {
|
|
|
28120
28294
|
}
|
|
28121
28295
|
|
|
28122
28296
|
// src/cli.ts
|
|
28123
|
-
var main =
|
|
28297
|
+
var main = defineCommand172({
|
|
28124
28298
|
meta: {
|
|
28125
28299
|
name: "baker",
|
|
28126
28300
|
version: getCliVersion(),
|