@koda-sl/baker-cli 0.105.0 → 0.106.0-dev.a605c0acb

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
@@ -9,10 +9,10 @@ import {
9
9
  defaultRegistry,
10
10
  generateCatalog,
11
11
  validateCanvasDeep
12
- } from "./chunk-3JVYU72O.js";
12
+ } from "./chunk-26K7V346.js";
13
13
 
14
14
  // src/cli.ts
15
- import { defineCommand as defineCommand152, runMain } from "citty";
15
+ import { defineCommand as defineCommand154, runMain } from "citty";
16
16
 
17
17
  // src/commands/actions/index.ts
18
18
  import { defineCommand as defineCommand18 } from "citty";
@@ -935,9 +935,553 @@ var actionsTagsCreateResponseSchema = okResponse(z2.object({ tagId: z2.string()
935
935
  var actionsTagsDeleteRequestSchema = z2.object({ name: z2.string() });
936
936
  var actionsTagsDeleteResponseSchema = okOnlySchema();
937
937
 
938
- // ../api/src/images.ts
938
+ // ../api/src/ads-linkedin/limits.ts
939
+ var LINKEDIN_LIMITS = {
940
+ campaignGroup: {
941
+ nameMax: 100
942
+ },
943
+ campaign: {
944
+ nameMax: 255
945
+ },
946
+ creative: {
947
+ commentarySoftMax: 600,
948
+ // feed truncates with "…see more" beyond this
949
+ commentaryHardMax: 3e3,
950
+ headlineMax: 70,
951
+ descriptionMax: 300,
952
+ textAdHeadlineMax: 25,
953
+ textAdDescriptionMax: 75,
954
+ spotlightHeadlineMax: 70,
955
+ spotlightDescriptionMax: 70,
956
+ spotlightCtaMax: 18,
957
+ carouselCardHeadlineMax: 45,
958
+ carouselCardsMin: 2,
959
+ carouselCardsMax: 10,
960
+ conversationButtonLabelMax: 25
961
+ },
962
+ audience: {
963
+ nameMax: 100,
964
+ minRowsToServe: 300,
965
+ // LinkedIn refuses to serve smaller matched audiences
966
+ inlineRowsMax: 1e4,
967
+ // above this the list must come as a stored file ref
968
+ rowsMax: 3e5
969
+ },
970
+ conversion: {
971
+ nameMax: 255,
972
+ postClickWindows: [1, 7, 30, 90],
973
+ viewThroughWindows: [1, 7, 30]
974
+ },
975
+ leadForm: {
976
+ nameMax: 256,
977
+ headlineMax: 60,
978
+ descriptionMax: 160,
979
+ questionsMax: 12,
980
+ questionsSoftMax: 4,
981
+ // playbook: >4 fields tanks completion rate
982
+ customQuestionsMax: 3,
983
+ thankYouMessageMax: 300
984
+ }
985
+ };
986
+ var CAMPAIGN_TYPES = ["SPONSORED_UPDATES", "TEXT_AD", "SPONSORED_INMAILS", "DYNAMIC"];
987
+ var COST_TYPES = ["CPC", "CPM", "CPV"];
988
+ var OBJECTIVE_TYPES = [
989
+ "BRAND_AWARENESS",
990
+ "ENGAGEMENT",
991
+ "JOB_APPLICANT",
992
+ "LEAD_GENERATION",
993
+ "WEBSITE_CONVERSION",
994
+ "WEBSITE_VISIT",
995
+ "VIDEO_VIEW",
996
+ "TALENT_LEAD"
997
+ ];
998
+ var OBJECTIVE_CAMPAIGN_TYPES = {
999
+ VIDEO_VIEW: ["SPONSORED_UPDATES"],
1000
+ LEAD_GENERATION: ["SPONSORED_UPDATES", "SPONSORED_INMAILS"],
1001
+ ENGAGEMENT: ["SPONSORED_UPDATES", "DYNAMIC"]
1002
+ };
1003
+ var STAGEABLE_CREATE_STATUSES = ["DRAFT", "ACTIVE", "PAUSED"];
1004
+ var CREATIVE_INTENDED_STATUSES = ["ACTIVE", "PAUSED", "DRAFT"];
1005
+ var CTA_TYPES = [
1006
+ "APPLY",
1007
+ "DOWNLOAD",
1008
+ "VIEW_QUOTE",
1009
+ "LEARN_MORE",
1010
+ "SIGN_UP",
1011
+ "SUBSCRIBE",
1012
+ "REGISTER",
1013
+ "JOIN",
1014
+ "ATTEND",
1015
+ "REQUEST_DEMO",
1016
+ "SEE_MORE"
1017
+ ];
1018
+ var CREATIVE_SELECTIONS = ["OPTIMIZED", "ROUND_ROBIN"];
1019
+ var AUDIENCE_TYPES = ["company-list", "user-list", "retargeting", "engagement"];
1020
+ var CONVERSION_TYPES = [
1021
+ "ADD_TO_CART",
1022
+ "DOWNLOAD",
1023
+ "INSTALL",
1024
+ "KEY_PAGE_VIEW",
1025
+ "LEAD",
1026
+ "PURCHASE",
1027
+ "SIGN_UP",
1028
+ "OTHER"
1029
+ ];
1030
+ var CONVERSION_METHODS = ["INSIGHT_TAG", "CONVERSIONS_API"];
1031
+ var ATTRIBUTION_TYPES = ["LAST_TOUCH_BY_CAMPAIGN", "LAST_TOUCH_BY_CONVERSION"];
1032
+ var CURRENCY_MINIMUMS = {
1033
+ USD: { dailyBudgetMin: 10, unitCostMin: 2 },
1034
+ EUR: { dailyBudgetMin: 10, unitCostMin: 2 },
1035
+ GBP: { dailyBudgetMin: 8, unitCostMin: 2 }
1036
+ };
1037
+ var DEFAULT_CURRENCY_MINIMUM = { dailyBudgetMin: 10, unitCostMin: 2 };
1038
+ var TEMP_REF_REGEX = /^li_temp_[A-Za-z0-9_-]{4,}$/;
1039
+ var NUMERIC_ID_REGEX = /^\d+$/;
1040
+ var URN_REGEX = /^urn:li:[a-zA-Z]+:.+$/;
1041
+ var IMAGE_URN_REGEX = /^urn:li:image:.+$/;
1042
+ var VIDEO_URN_REGEX = /^urn:li:video:.+$/;
1043
+ var DOCUMENT_URN_REGEX = /^urn:li:document:.+$/;
1044
+ var POST_URN_REGEX = /^urn:li:(share|ugcPost):\d+$/;
1045
+ var ORGANIZATION_URN_REGEX = /^urn:li:organization:\d+$/;
1046
+ var TARGETING_FACET_URN_REGEX = /^urn:li:adTargetingFacet:[a-zA-Z]+$/;
1047
+
1048
+ // ../api/src/ads-linkedin/ops.ts
939
1049
  import { z as z3 } from "zod";
940
- var imageSourceSchema = z3.enum([
1050
+ var tempRefSchema = z3.string().regex(TEMP_REF_REGEX, "expected a li_temp_* reference");
1051
+ var parentRefSchema = z3.union([
1052
+ z3.string().regex(URN_REGEX, "expected a urn:li:* value"),
1053
+ z3.string().regex(NUMERIC_ID_REGEX, "expected a numeric id"),
1054
+ tempRefSchema
1055
+ ]);
1056
+ var moneySchema = z3.object({
1057
+ amount: z3.string().regex(/^\d+(\.\d{1,2})?$/, "expected a decimal amount like 50 or 50.00").refine((val) => Number(val) > 0, "amount must be greater than zero"),
1058
+ currencyCode: z3.string().length(3)
1059
+ });
1060
+ var runScheduleSchema = z3.object({
1061
+ start: z3.number().int().positive(),
1062
+ end: z3.number().int().positive().optional()
1063
+ }).refine((s) => s.end === void 0 || s.end > s.start, {
1064
+ message: "runSchedule.end must be after runSchedule.start",
1065
+ path: ["end"]
1066
+ });
1067
+ var facetValuesSchema = z3.array(z3.union([z3.string().regex(URN_REGEX), tempRefSchema])).min(1);
1068
+ var targetingCriteriaSchema = z3.object({
1069
+ include: z3.object({
1070
+ and: z3.array(
1071
+ z3.object({
1072
+ or: z3.record(z3.string().regex(TARGETING_FACET_URN_REGEX, "invalid targeting facet URN"), facetValuesSchema)
1073
+ })
1074
+ ).min(1, "targeting needs at least one include facet group")
1075
+ }),
1076
+ exclude: z3.object({
1077
+ or: z3.record(z3.string().regex(TARGETING_FACET_URN_REGEX, "invalid targeting facet URN"), facetValuesSchema)
1078
+ }).optional()
1079
+ });
1080
+ var stageableStatusSchema = z3.enum(STAGEABLE_CREATE_STATUSES);
1081
+ var entityStatusSchema = z3.enum(["ACTIVE", "PAUSED", "ARCHIVED", "CANCELED", "DRAFT", "COMPLETED"]);
1082
+ function currencyMinimums(currencyCode) {
1083
+ return CURRENCY_MINIMUMS[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM;
1084
+ }
1085
+ var campaignGroupCreateSchema = z3.object({
1086
+ name: z3.string().min(1).max(LINKEDIN_LIMITS.campaignGroup.nameMax),
1087
+ runSchedule: runScheduleSchema,
1088
+ totalBudget: moneySchema.optional(),
1089
+ status: stageableStatusSchema.default("DRAFT")
1090
+ });
1091
+ var campaignGroupUpdateSchema = z3.object({
1092
+ name: z3.string().min(1).max(LINKEDIN_LIMITS.campaignGroup.nameMax).optional(),
1093
+ runSchedule: runScheduleSchema.optional(),
1094
+ totalBudget: moneySchema.optional(),
1095
+ status: entityStatusSchema.optional()
1096
+ }).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
1097
+ var campaignFields = {
1098
+ name: z3.string().min(1).max(LINKEDIN_LIMITS.campaign.nameMax),
1099
+ campaignGroup: parentRefSchema,
1100
+ type: z3.enum(CAMPAIGN_TYPES),
1101
+ objectiveType: z3.enum(OBJECTIVE_TYPES).optional(),
1102
+ costType: z3.enum(COST_TYPES),
1103
+ unitCost: moneySchema.optional(),
1104
+ dailyBudget: moneySchema.optional(),
1105
+ totalBudget: moneySchema.optional(),
1106
+ runSchedule: runScheduleSchema.optional(),
1107
+ locale: z3.object({ country: z3.string().length(2), language: z3.string().length(2) }),
1108
+ targetingCriteria: targetingCriteriaSchema,
1109
+ audienceExpansionEnabled: z3.boolean().default(false),
1110
+ offsiteDeliveryEnabled: z3.boolean().default(false),
1111
+ connectedTelevisionOnly: z3.boolean().default(false),
1112
+ creativeSelection: z3.enum(CREATIVE_SELECTIONS).optional(),
1113
+ associatedEntity: z3.string().regex(ORGANIZATION_URN_REGEX).optional(),
1114
+ status: stageableStatusSchema.default("DRAFT")
1115
+ };
1116
+ function validateCampaignBudgets(p, ctx, { requireBudget }) {
1117
+ if (requireBudget && !p.dailyBudget && !p.totalBudget) {
1118
+ ctx.addIssue({ code: "custom", path: ["dailyBudget"], message: "set dailyBudget and/or totalBudget" });
1119
+ }
1120
+ if (p.totalBudget && !p.dailyBudget && !p.runSchedule?.end) {
1121
+ ctx.addIssue({
1122
+ code: "custom",
1123
+ path: ["runSchedule", "end"],
1124
+ message: "totalBudget-only campaigns need runSchedule.end"
1125
+ });
1126
+ }
1127
+ if (p.dailyBudget) {
1128
+ const min = currencyMinimums(p.dailyBudget.currencyCode).dailyBudgetMin;
1129
+ if (Number(p.dailyBudget.amount) < min) {
1130
+ ctx.addIssue({
1131
+ code: "custom",
1132
+ path: ["dailyBudget", "amount"],
1133
+ message: `dailyBudget below the ${min} ${p.dailyBudget.currencyCode} minimum`
1134
+ });
1135
+ }
1136
+ }
1137
+ if (p.unitCost) {
1138
+ const min = currencyMinimums(p.unitCost.currencyCode).unitCostMin;
1139
+ if (Number(p.unitCost.amount) < min) {
1140
+ ctx.addIssue({
1141
+ code: "custom",
1142
+ path: ["unitCost", "amount"],
1143
+ message: `unitCost below the ${min} ${p.unitCost.currencyCode} minimum bid`
1144
+ });
1145
+ }
1146
+ }
1147
+ }
1148
+ var campaignCreateSchema = z3.object(campaignFields).superRefine((p, ctx) => {
1149
+ validateCampaignBudgets(p, ctx, { requireBudget: true });
1150
+ const allowedTypes = p.objectiveType ? OBJECTIVE_CAMPAIGN_TYPES[p.objectiveType] : void 0;
1151
+ if (allowedTypes && !allowedTypes.includes(p.type)) {
1152
+ ctx.addIssue({
1153
+ code: "custom",
1154
+ path: ["type"],
1155
+ message: `objective ${p.objectiveType} only supports campaign types ${allowedTypes.join(", ")}`
1156
+ });
1157
+ }
1158
+ });
1159
+ var campaignUpdateSchema = z3.object({
1160
+ name: campaignFields.name.optional(),
1161
+ objectiveType: campaignFields.objectiveType,
1162
+ unitCost: moneySchema.optional(),
1163
+ dailyBudget: moneySchema.optional(),
1164
+ totalBudget: moneySchema.optional(),
1165
+ runSchedule: runScheduleSchema.optional(),
1166
+ targetingCriteria: targetingCriteriaSchema.optional(),
1167
+ audienceExpansionEnabled: z3.boolean().optional(),
1168
+ offsiteDeliveryEnabled: z3.boolean().optional(),
1169
+ connectedTelevisionOnly: z3.boolean().optional(),
1170
+ creativeSelection: z3.enum(CREATIVE_SELECTIONS).optional(),
1171
+ status: entityStatusSchema.optional()
1172
+ }).superRefine((p, ctx) => {
1173
+ if (!Object.values(p).some((val) => val !== void 0)) {
1174
+ ctx.addIssue({ code: "custom", message: "update needs at least one field" });
1175
+ }
1176
+ validateCampaignBudgets(p, ctx, { requireBudget: false });
1177
+ });
1178
+ var commentarySchema = z3.string().min(1).max(LINKEDIN_LIMITS.creative.commentaryHardMax);
1179
+ var headlineSchema = z3.string().min(1).max(LINKEDIN_LIMITS.creative.headlineMax);
1180
+ var httpsUrlSchema = z3.string().url().refine((u) => u.startsWith("https://"), "landing pages must be https");
1181
+ var bakerMediaIdSchema = z3.string().min(1);
1182
+ var imageCreativeSchema = z3.object({
1183
+ format: z3.literal("image"),
1184
+ commentary: commentarySchema,
1185
+ imageId: bakerMediaIdSchema.optional(),
1186
+ imageUrn: z3.string().regex(IMAGE_URN_REGEX).optional(),
1187
+ headline: headlineSchema,
1188
+ landingUrl: httpsUrlSchema,
1189
+ cta: z3.enum(CTA_TYPES).optional(),
1190
+ mediaTitle: z3.string().max(200).optional()
1191
+ }).refine((p) => p.imageId ? !p.imageUrn : Boolean(p.imageUrn), {
1192
+ message: "provide exactly one of imageId (Baker library) or imageUrn (already on LinkedIn)",
1193
+ path: ["imageId"]
1194
+ });
1195
+ var videoCreativeSchema = z3.object({
1196
+ format: z3.literal("video"),
1197
+ commentary: commentarySchema,
1198
+ videoId: bakerMediaIdSchema.optional(),
1199
+ videoUrn: z3.string().regex(VIDEO_URN_REGEX).optional(),
1200
+ headline: headlineSchema,
1201
+ landingUrl: httpsUrlSchema.optional(),
1202
+ cta: z3.enum(CTA_TYPES).optional(),
1203
+ mediaTitle: z3.string().max(200).optional()
1204
+ }).refine((p) => p.videoId ? !p.videoUrn : Boolean(p.videoUrn), {
1205
+ message: "provide exactly one of videoId (Baker library) or videoUrn (already on LinkedIn)",
1206
+ path: ["videoId"]
1207
+ });
1208
+ var textCreativeSchema = z3.object({
1209
+ format: z3.literal("text"),
1210
+ headline: z3.string().min(1).max(LINKEDIN_LIMITS.creative.textAdHeadlineMax),
1211
+ description: z3.string().min(1).max(LINKEDIN_LIMITS.creative.textAdDescriptionMax),
1212
+ landingUrl: httpsUrlSchema,
1213
+ imageId: bakerMediaIdSchema.optional(),
1214
+ imageUrn: z3.string().regex(IMAGE_URN_REGEX).optional()
1215
+ });
1216
+ var spotlightCreativeSchema = z3.object({
1217
+ format: z3.literal("spotlight"),
1218
+ headline: z3.string().min(1).max(LINKEDIN_LIMITS.creative.spotlightHeadlineMax),
1219
+ description: z3.string().min(1).max(LINKEDIN_LIMITS.creative.spotlightDescriptionMax),
1220
+ landingUrl: httpsUrlSchema,
1221
+ ctaLabel: z3.string().min(1).max(LINKEDIN_LIMITS.creative.spotlightCtaMax),
1222
+ logoImageId: bakerMediaIdSchema.optional(),
1223
+ logoUrn: z3.string().regex(IMAGE_URN_REGEX).optional(),
1224
+ showMemberProfilePhoto: z3.boolean().default(true)
1225
+ });
1226
+ var followerCreativeSchema = z3.object({
1227
+ format: z3.literal("follower"),
1228
+ headline: z3.string().max(LINKEDIN_LIMITS.creative.spotlightHeadlineMax).optional(),
1229
+ description: z3.string().max(LINKEDIN_LIMITS.creative.spotlightDescriptionMax).optional(),
1230
+ logoImageId: bakerMediaIdSchema.optional(),
1231
+ logoUrn: z3.string().regex(IMAGE_URN_REGEX).optional()
1232
+ });
1233
+ var documentCreativeSchema = z3.object({
1234
+ format: z3.literal("document"),
1235
+ commentary: commentarySchema,
1236
+ documentTitle: z3.string().min(1).max(200),
1237
+ documentUrn: z3.string().regex(DOCUMENT_URN_REGEX).optional(),
1238
+ documentId: bakerMediaIdSchema.optional()
1239
+ }).refine((p) => p.documentId ? !p.documentUrn : Boolean(p.documentUrn), {
1240
+ message: "provide exactly one of documentId or documentUrn",
1241
+ path: ["documentId"]
1242
+ });
1243
+ var carouselCreativeSchema = z3.object({
1244
+ format: z3.literal("carousel"),
1245
+ commentary: commentarySchema,
1246
+ cards: z3.array(
1247
+ z3.object({
1248
+ imageId: bakerMediaIdSchema.optional(),
1249
+ imageUrn: z3.string().regex(IMAGE_URN_REGEX).optional(),
1250
+ headline: z3.string().min(1).max(LINKEDIN_LIMITS.creative.carouselCardHeadlineMax),
1251
+ landingUrl: httpsUrlSchema
1252
+ }).refine((card) => card.imageId ? !card.imageUrn : Boolean(card.imageUrn), {
1253
+ message: "each card needs exactly one of imageId or imageUrn",
1254
+ path: ["imageId"]
1255
+ })
1256
+ ).min(LINKEDIN_LIMITS.creative.carouselCardsMin).max(LINKEDIN_LIMITS.creative.carouselCardsMax)
1257
+ });
1258
+ var conversationCreativeSchema = z3.object({
1259
+ format: z3.literal("conversation"),
1260
+ name: z3.string().max(255).optional(),
1261
+ raw: z3.record(z3.string(), z3.unknown())
1262
+ });
1263
+ var tlaCreativeSchema = z3.object({
1264
+ format: z3.literal("tla"),
1265
+ postUrn: z3.string().regex(POST_URN_REGEX, "expected urn:li:share:* or urn:li:ugcPost:*")
1266
+ });
1267
+ var jobsCreativeSchema = z3.object({
1268
+ format: z3.literal("jobs"),
1269
+ organizationName: z3.string().min(1).max(200),
1270
+ logoImageId: bakerMediaIdSchema.optional(),
1271
+ logoUrn: z3.string().regex(IMAGE_URN_REGEX).optional(),
1272
+ headlinePreset: z3.string().min(1),
1273
+ buttonLabelPreset: z3.string().min(1)
1274
+ });
1275
+ var creativeContentSchema = z3.discriminatedUnion("format", [
1276
+ imageCreativeSchema,
1277
+ videoCreativeSchema,
1278
+ textCreativeSchema,
1279
+ spotlightCreativeSchema,
1280
+ followerCreativeSchema,
1281
+ documentCreativeSchema,
1282
+ carouselCreativeSchema,
1283
+ conversationCreativeSchema,
1284
+ tlaCreativeSchema,
1285
+ jobsCreativeSchema
1286
+ ]);
1287
+ var creativeCreateSchema = z3.object({
1288
+ campaign: parentRefSchema,
1289
+ intendedStatus: z3.enum(CREATIVE_INTENDED_STATUSES).default("DRAFT"),
1290
+ content: creativeContentSchema
1291
+ });
1292
+ var creativeUpdateSchema = z3.object({
1293
+ intendedStatus: z3.enum(["ACTIVE", "PAUSED", "ARCHIVED", "DRAFT"]).optional(),
1294
+ name: z3.string().max(255).optional(),
1295
+ headline: headlineSchema.optional(),
1296
+ landingUrl: httpsUrlSchema.optional(),
1297
+ cta: z3.enum(CTA_TYPES).optional()
1298
+ }).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
1299
+ var listRowSchema = z3.record(z3.string(), z3.string());
1300
+ var audienceCreateSchema = z3.object({
1301
+ name: z3.string().min(1).max(LINKEDIN_LIMITS.audience.nameMax),
1302
+ audienceType: z3.enum(AUDIENCE_TYPES),
1303
+ listColumns: z3.array(z3.string().min(1)).optional(),
1304
+ listRows: z3.array(listRowSchema).max(LINKEDIN_LIMITS.audience.inlineRowsMax).optional(),
1305
+ /** Baker file reference (R2) for lists too large to inline. */
1306
+ sourceFileRef: z3.string().optional(),
1307
+ /** Retargeting/engagement source config — structural passthrough, file-first. */
1308
+ raw: z3.record(z3.string(), z3.unknown()).optional()
1309
+ }).superRefine((p, ctx) => {
1310
+ const isList = p.audienceType === "company-list" || p.audienceType === "user-list";
1311
+ if (isList && !p.listRows?.length && !p.sourceFileRef) {
1312
+ ctx.addIssue({
1313
+ code: "custom",
1314
+ path: ["listRows"],
1315
+ message: "list audiences need listRows (or sourceFileRef for large files)"
1316
+ });
1317
+ }
1318
+ if (!isList && !p.raw) {
1319
+ ctx.addIssue({
1320
+ code: "custom",
1321
+ path: ["raw"],
1322
+ message: `${p.audienceType} audiences need a raw source config (use --file)`
1323
+ });
1324
+ }
1325
+ });
1326
+ var audienceUploadListSchema = z3.object({
1327
+ segment: parentRefSchema,
1328
+ listColumns: z3.array(z3.string().min(1)).optional(),
1329
+ listRows: z3.array(listRowSchema).max(LINKEDIN_LIMITS.audience.inlineRowsMax).optional(),
1330
+ sourceFileRef: z3.string().optional()
1331
+ }).refine((p) => Boolean(p.listRows?.length) || Boolean(p.sourceFileRef), {
1332
+ message: "upload needs listRows (or sourceFileRef for large files)",
1333
+ path: ["listRows"]
1334
+ });
1335
+ var postClickWindowSchema = z3.number().refine(
1336
+ (val) => LINKEDIN_LIMITS.conversion.postClickWindows.includes(val),
1337
+ `postClickAttributionWindowSize must be one of ${LINKEDIN_LIMITS.conversion.postClickWindows.join(", ")}`
1338
+ );
1339
+ var viewThroughWindowSchema = z3.number().refine(
1340
+ (val) => LINKEDIN_LIMITS.conversion.viewThroughWindows.includes(val),
1341
+ `viewThroughAttributionWindowSize must be one of ${LINKEDIN_LIMITS.conversion.viewThroughWindows.join(", ")}`
1342
+ );
1343
+ var conversionCreateSchema = z3.object({
1344
+ name: z3.string().min(1).max(LINKEDIN_LIMITS.conversion.nameMax),
1345
+ type: z3.enum(CONVERSION_TYPES),
1346
+ conversionMethod: z3.enum(CONVERSION_METHODS),
1347
+ postClickAttributionWindowSize: postClickWindowSchema.optional(),
1348
+ viewThroughAttributionWindowSize: viewThroughWindowSchema.optional(),
1349
+ attributionType: z3.enum(ATTRIBUTION_TYPES).optional(),
1350
+ /** Insight-tag URL match rules — passthrough validated by LinkedIn. */
1351
+ urlMatchRuleExpression: z3.array(z3.array(z3.record(z3.string(), z3.string()))).optional(),
1352
+ associateAllCampaigns: z3.boolean().optional()
1353
+ });
1354
+ var conversionUpdateSchema = z3.object({
1355
+ name: conversionCreateSchema.shape.name.optional(),
1356
+ postClickAttributionWindowSize: postClickWindowSchema.optional(),
1357
+ viewThroughAttributionWindowSize: viewThroughWindowSchema.optional(),
1358
+ attributionType: z3.enum(ATTRIBUTION_TYPES).optional(),
1359
+ enabled: z3.boolean().optional()
1360
+ }).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
1361
+ var leadFormCreateSchema = z3.object({
1362
+ name: z3.string().min(1).max(LINKEDIN_LIMITS.leadForm.nameMax),
1363
+ headline: z3.string().min(1).max(LINKEDIN_LIMITS.leadForm.headlineMax),
1364
+ description: z3.string().max(LINKEDIN_LIMITS.leadForm.descriptionMax).optional(),
1365
+ privacyPolicyUrl: httpsUrlSchema,
1366
+ questions: z3.array(z3.object({ name: z3.string().min(1), predefinedField: z3.string().optional() })).min(1).max(LINKEDIN_LIMITS.leadForm.questionsMax),
1367
+ thankYou: z3.object({
1368
+ message: z3.string().max(LINKEDIN_LIMITS.leadForm.thankYouMessageMax).optional(),
1369
+ landingUrl: httpsUrlSchema.optional()
1370
+ }).optional(),
1371
+ legalDisclaimer: z3.string().optional(),
1372
+ raw: z3.record(z3.string(), z3.unknown()).optional()
1373
+ });
1374
+ var leadFormUpdateSchema = z3.object({
1375
+ name: leadFormCreateSchema.shape.name.optional(),
1376
+ raw: z3.record(z3.string(), z3.unknown()).optional()
1377
+ }).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
1378
+ var LINKEDIN_DRAFT_OP_KINDS = [
1379
+ "campaignGroup.create",
1380
+ "campaignGroup.update",
1381
+ "campaign.create",
1382
+ "campaign.update",
1383
+ "creative.create",
1384
+ "creative.update",
1385
+ "audience.create",
1386
+ "audience.uploadList",
1387
+ "conversion.create",
1388
+ "conversion.update",
1389
+ "leadForm.create",
1390
+ "leadForm.update"
1391
+ ];
1392
+ var linkedinDraftOpKindSchema = z3.enum(LINKEDIN_DRAFT_OP_KINDS);
1393
+ var accountIdSchema = z3.string().regex(NUMERIC_ID_REGEX, "accountId must be the bare numeric ad account id");
1394
+ var updateTargetSchema = z3.union([z3.string().regex(URN_REGEX), z3.string().regex(NUMERIC_ID_REGEX)]);
1395
+ function createOp(kind, payload) {
1396
+ return z3.object({ kind: z3.literal(kind), accountId: accountIdSchema, payload });
1397
+ }
1398
+ function updateOp(kind, payload) {
1399
+ return z3.object({ kind: z3.literal(kind), accountId: accountIdSchema, target: updateTargetSchema, payload });
1400
+ }
1401
+ var linkedinDraftOpInputSchema = z3.discriminatedUnion("kind", [
1402
+ createOp("campaignGroup.create", campaignGroupCreateSchema),
1403
+ updateOp("campaignGroup.update", campaignGroupUpdateSchema),
1404
+ createOp("campaign.create", campaignCreateSchema),
1405
+ updateOp("campaign.update", campaignUpdateSchema),
1406
+ createOp("creative.create", creativeCreateSchema),
1407
+ updateOp("creative.update", creativeUpdateSchema),
1408
+ createOp("audience.create", audienceCreateSchema),
1409
+ createOp("audience.uploadList", audienceUploadListSchema),
1410
+ createOp("conversion.create", conversionCreateSchema),
1411
+ updateOp("conversion.update", conversionUpdateSchema),
1412
+ createOp("leadForm.create", leadFormCreateSchema),
1413
+ updateOp("leadForm.update", leadFormUpdateSchema)
1414
+ ]);
1415
+
1416
+ // ../api/src/ads-linkedin/wire.ts
1417
+ import { z as z4 } from "zod";
1418
+ var linkedinWriteModeSchema = z4.enum(["live", "simulated"]);
1419
+ var linkedinDraftOpResultSchema = z4.object({
1420
+ status: z4.enum(["applied", "simulated", "failed", "skipped"]),
1421
+ urn: z4.string().optional(),
1422
+ error: z4.string().optional(),
1423
+ skippedBecause: z4.string().optional(),
1424
+ executedAt: z4.number().optional()
1425
+ });
1426
+ var linkedinDraftStageRequestSchema = z4.object({
1427
+ chatId: z4.string(),
1428
+ op: linkedinDraftOpInputSchema
1429
+ });
1430
+ var linkedinDraftStageResponseSchema = z4.object({
1431
+ staged: z4.literal(true),
1432
+ ref: z4.string(),
1433
+ kind: linkedinDraftOpKindSchema,
1434
+ mode: linkedinWriteModeSchema,
1435
+ dependsOn: z4.array(z4.string()),
1436
+ summary: z4.string(),
1437
+ warnings: z4.array(z4.string())
1438
+ });
1439
+ var linkedinDraftOpViewSchema = z4.object({
1440
+ ref: z4.string(),
1441
+ kind: linkedinDraftOpKindSchema,
1442
+ accountId: z4.string(),
1443
+ target: z4.string().optional(),
1444
+ dependsOn: z4.array(z4.string()),
1445
+ summary: z4.string(),
1446
+ stagedAt: z4.number(),
1447
+ result: linkedinDraftOpResultSchema.optional()
1448
+ });
1449
+ var linkedinDraftListRequestSchema = z4.object({
1450
+ chatId: z4.string()
1451
+ });
1452
+ var linkedinDraftListResponseSchema = z4.object({
1453
+ status: z4.enum(["active", "publishing", "applied", "discarded", "none"]),
1454
+ mode: linkedinWriteModeSchema,
1455
+ count: z4.number(),
1456
+ ops: z4.array(linkedinDraftOpViewSchema)
1457
+ });
1458
+ var linkedinDraftRemoveRequestSchema = z4.object({
1459
+ chatId: z4.string(),
1460
+ ref: z4.string()
1461
+ });
1462
+ var linkedinDraftRemoveResponseSchema = z4.object({
1463
+ /** The requested ref plus any dependents removed by cascade. */
1464
+ removed: z4.array(z4.string())
1465
+ });
1466
+ var linkedinDraftClearRequestSchema = z4.object({
1467
+ chatId: z4.string()
1468
+ });
1469
+ var linkedinDraftClearResponseSchema = z4.object({
1470
+ cleared: z4.number()
1471
+ });
1472
+ var linkedinFieldErrorSchema = z4.object({
1473
+ path: z4.string(),
1474
+ message: z4.string()
1475
+ });
1476
+ var linkedinDraftErrorResponseSchema = z4.object({
1477
+ code: z4.string(),
1478
+ error: z4.string(),
1479
+ fields: z4.array(linkedinFieldErrorSchema).optional()
1480
+ });
1481
+
1482
+ // ../api/src/images.ts
1483
+ import { z as z5 } from "zod";
1484
+ var imageSourceSchema = z5.enum([
941
1485
  "uploaded",
942
1486
  "website",
943
1487
  "google_testimonial",
@@ -953,49 +1497,49 @@ var imageSourceSchema = z3.enum([
953
1497
  "pinterest",
954
1498
  "ai_generated"
955
1499
  ]);
956
- var imageStatusSchema = z3.enum(["uploading", "processing", "ready", "error"]);
957
- var upscaleConfigSchema = z3.object({
958
- model: z3.literal("philz1337x/crystal-upscaler"),
959
- input: z3.object({
960
- scale_factor: z3.number(),
961
- creativity: z3.number(),
962
- output_format: z3.string()
1500
+ var imageStatusSchema = z5.enum(["uploading", "processing", "ready", "error"]);
1501
+ var upscaleConfigSchema = z5.object({
1502
+ model: z5.literal("philz1337x/crystal-upscaler"),
1503
+ input: z5.object({
1504
+ scale_factor: z5.number(),
1505
+ creativity: z5.number(),
1506
+ output_format: z5.string()
963
1507
  }),
964
- status: z3.enum(["pending", "completed"])
1508
+ status: z5.enum(["pending", "completed"])
965
1509
  });
966
- var imageDocSchema = z3.object({
967
- _id: z3.string(),
968
- _creationTime: z3.number(),
969
- companyId: z3.string(),
970
- storageKey: z3.string(),
1510
+ var imageDocSchema = z5.object({
1511
+ _id: z5.string(),
1512
+ _creationTime: z5.number(),
1513
+ companyId: z5.string(),
1514
+ storageKey: z5.string(),
971
1515
  upscaleConfig: upscaleConfigSchema.optional(),
972
- upscaledStorageKey: z3.string().optional(),
973
- name: z3.string(),
974
- description: z3.string(),
975
- tags: z3.array(z3.string()),
976
- source: z3.string(),
977
- externalId: z3.string().optional(),
978
- externalUrl: z3.string().optional(),
979
- contentHash: z3.string().optional(),
980
- sourceId: z3.string().optional(),
981
- descriptionContext: z3.string().optional(),
982
- width: z3.number().optional(),
983
- height: z3.number().optional(),
984
- aspectRatio: z3.number().optional(),
985
- dominantColor: z3.string().optional(),
986
- imagePalette: z3.array(z3.string()).optional(),
987
- thumbhashDataUri: z3.string().optional(),
988
- isLightImage: z3.boolean().optional(),
989
- descriptionEmbedding: z3.array(z3.number()).optional(),
990
- imageEmbedding: z3.array(z3.number()).optional(),
991
- searchText: z3.string().optional(),
1516
+ upscaledStorageKey: z5.string().optional(),
1517
+ name: z5.string(),
1518
+ description: z5.string(),
1519
+ tags: z5.array(z5.string()),
1520
+ source: z5.string(),
1521
+ externalId: z5.string().optional(),
1522
+ externalUrl: z5.string().optional(),
1523
+ contentHash: z5.string().optional(),
1524
+ sourceId: z5.string().optional(),
1525
+ descriptionContext: z5.string().optional(),
1526
+ width: z5.number().optional(),
1527
+ height: z5.number().optional(),
1528
+ aspectRatio: z5.number().optional(),
1529
+ dominantColor: z5.string().optional(),
1530
+ imagePalette: z5.array(z5.string()).optional(),
1531
+ thumbhashDataUri: z5.string().optional(),
1532
+ isLightImage: z5.boolean().optional(),
1533
+ descriptionEmbedding: z5.array(z5.number()).optional(),
1534
+ imageEmbedding: z5.array(z5.number()).optional(),
1535
+ searchText: z5.string().optional(),
992
1536
  status: imageStatusSchema,
993
- errorMessage: z3.string().optional(),
994
- createdAt: z3.number(),
995
- updatedAt: z3.number(),
996
- imageUrl: z3.string()
1537
+ errorMessage: z5.string().optional(),
1538
+ createdAt: z5.number(),
1539
+ updatedAt: z5.number(),
1540
+ imageUrl: z5.string()
997
1541
  });
998
- var imageHitSourceSchema = z3.enum([
1542
+ var imageHitSourceSchema = z5.enum([
999
1543
  "library",
1000
1544
  "magnific",
1001
1545
  "google_images",
@@ -1006,374 +1550,374 @@ var imageHitSourceSchema = z3.enum([
1006
1550
  "giphy",
1007
1551
  "pinterest"
1008
1552
  ]);
1009
- var imageHitSchema = z3.object({
1553
+ var imageHitSchema = z5.object({
1010
1554
  source: imageHitSourceSchema,
1011
- url: z3.string(),
1012
- thumbnailUrl: z3.string().optional(),
1013
- width: z3.number().optional(),
1014
- height: z3.number().optional(),
1015
- aspectRatio: z3.number().optional(),
1016
- dominantColor: z3.string().optional(),
1017
- externalId: z3.string().optional(),
1018
- externalUrl: z3.string().optional(),
1019
- providerMeta: z3.record(z3.string(), z3.unknown()).optional(),
1020
- descriptionContext: z3.string().optional(),
1021
- _id: z3.string().optional(),
1022
- name: z3.string().optional(),
1023
- description: z3.string().optional(),
1024
- tags: z3.array(z3.string()).optional(),
1025
- score: z3.number().optional(),
1026
- alsoInLibrary: z3.string().optional(),
1027
- prefetchedBytes: z3.string().optional(),
1028
- prefetchedContentType: z3.string().optional()
1555
+ url: z5.string(),
1556
+ thumbnailUrl: z5.string().optional(),
1557
+ width: z5.number().optional(),
1558
+ height: z5.number().optional(),
1559
+ aspectRatio: z5.number().optional(),
1560
+ dominantColor: z5.string().optional(),
1561
+ externalId: z5.string().optional(),
1562
+ externalUrl: z5.string().optional(),
1563
+ providerMeta: z5.record(z5.string(), z5.unknown()).optional(),
1564
+ descriptionContext: z5.string().optional(),
1565
+ _id: z5.string().optional(),
1566
+ name: z5.string().optional(),
1567
+ description: z5.string().optional(),
1568
+ tags: z5.array(z5.string()).optional(),
1569
+ score: z5.number().optional(),
1570
+ alsoInLibrary: z5.string().optional(),
1571
+ prefetchedBytes: z5.string().optional(),
1572
+ prefetchedContentType: z5.string().optional()
1029
1573
  });
1030
1574
  var ingestedImageHitSchema = imageHitSchema.extend({
1031
- imageId: z3.string().optional(),
1032
- imageUrl: z3.string().optional(),
1033
- deduped: z3.boolean().optional(),
1034
- sourceUrl: z3.string().optional()
1035
- });
1036
- var autoIngestItemSchema = z3.object({
1037
- imageId: z3.string(),
1038
- deduped: z3.boolean(),
1039
- imageUrl: z3.string(),
1040
- sourceUrl: z3.string(),
1041
- externalUrl: z3.string().optional()
1575
+ imageId: z5.string().optional(),
1576
+ imageUrl: z5.string().optional(),
1577
+ deduped: z5.boolean().optional(),
1578
+ sourceUrl: z5.string().optional()
1579
+ });
1580
+ var autoIngestItemSchema = z5.object({
1581
+ imageId: z5.string(),
1582
+ deduped: z5.boolean(),
1583
+ imageUrl: z5.string(),
1584
+ sourceUrl: z5.string(),
1585
+ externalUrl: z5.string().optional()
1042
1586
  });
1043
1587
  function providerHitsResponseSchema() {
1044
- return z3.object({
1045
- hits: z3.array(ingestedImageHitSchema),
1046
- ingested: z3.array(autoIngestItemSchema)
1588
+ return z5.object({
1589
+ hits: z5.array(ingestedImageHitSchema),
1590
+ ingested: z5.array(autoIngestItemSchema)
1047
1591
  });
1048
1592
  }
1049
- var imagesGetRequestSchema = z3.object({ id: z3.string().min(1, "Missing id parameter") });
1050
- var imagesSearchRequestSchema = z3.object({
1051
- query: z3.string().min(1),
1052
- limit: z3.coerce.number().int().positive().max(100).optional(),
1053
- aspectRatio: z3.string().optional(),
1054
- tags: z3.array(z3.string()).optional(),
1055
- source: z3.string().optional(),
1056
- externalUrlHost: z3.string().optional()
1057
- });
1058
- var imageSearchResultSchema = z3.object({
1059
- _id: z3.string(),
1060
- imageUrl: z3.string(),
1061
- name: z3.string(),
1062
- description: z3.string(),
1063
- tags: z3.array(z3.string()),
1064
- width: z3.number().optional(),
1065
- height: z3.number().optional(),
1066
- aspectRatio: z3.number().optional(),
1067
- dominantColor: z3.string().optional(),
1068
- imagePalette: z3.array(z3.string()).optional(),
1069
- source: z3.string(),
1070
- externalUrl: z3.string().optional(),
1071
- score: z3.number()
1072
- });
1073
- var imagesSearchResponseSchema = z3.array(imageSearchResultSchema);
1074
- var imagesUploadRequestSchema = z3.object({
1075
- base64: z3.string().min(1),
1076
- contentType: z3.string().min(1),
1077
- source: z3.string().optional(),
1078
- descriptionContext: z3.string().optional()
1079
- });
1080
- var imagesUploadResponseSchema = z3.object({ imageId: z3.string() });
1081
- var imagesDeleteRequestSchema = z3.object({ id: z3.string().min(1, "Missing image ID") });
1082
- var imagesDeleteResponseSchema = z3.object({ ok: z3.literal(true) });
1083
- var imagesUpscaleRequestSchema = z3.object({ imageId: z3.string().min(1, "Missing image ID") });
1084
- var imagesUpscaleResponseSchema = z3.object({
1085
- imageId: z3.string(),
1086
- status: z3.literal("processing")
1593
+ var imagesGetRequestSchema = z5.object({ id: z5.string().min(1, "Missing id parameter") });
1594
+ var imagesSearchRequestSchema = z5.object({
1595
+ query: z5.string().min(1),
1596
+ limit: z5.coerce.number().int().positive().max(100).optional(),
1597
+ aspectRatio: z5.string().optional(),
1598
+ tags: z5.array(z5.string()).optional(),
1599
+ source: z5.string().optional(),
1600
+ externalUrlHost: z5.string().optional()
1601
+ });
1602
+ var imageSearchResultSchema = z5.object({
1603
+ _id: z5.string(),
1604
+ imageUrl: z5.string(),
1605
+ name: z5.string(),
1606
+ description: z5.string(),
1607
+ tags: z5.array(z5.string()),
1608
+ width: z5.number().optional(),
1609
+ height: z5.number().optional(),
1610
+ aspectRatio: z5.number().optional(),
1611
+ dominantColor: z5.string().optional(),
1612
+ imagePalette: z5.array(z5.string()).optional(),
1613
+ source: z5.string(),
1614
+ externalUrl: z5.string().optional(),
1615
+ score: z5.number()
1616
+ });
1617
+ var imagesSearchResponseSchema = z5.array(imageSearchResultSchema);
1618
+ var imagesUploadRequestSchema = z5.object({
1619
+ base64: z5.string().min(1),
1620
+ contentType: z5.string().min(1),
1621
+ source: z5.string().optional(),
1622
+ descriptionContext: z5.string().optional()
1623
+ });
1624
+ var imagesUploadResponseSchema = z5.object({ imageId: z5.string() });
1625
+ var imagesDeleteRequestSchema = z5.object({ id: z5.string().min(1, "Missing image ID") });
1626
+ var imagesDeleteResponseSchema = z5.object({ ok: z5.literal(true) });
1627
+ var imagesUpscaleRequestSchema = z5.object({ imageId: z5.string().min(1, "Missing image ID") });
1628
+ var imagesUpscaleResponseSchema = z5.object({
1629
+ imageId: z5.string(),
1630
+ status: z5.literal("processing")
1087
1631
  });
1088
1632
  var IMAGES_FIND_SOURCES = ["library", "magnific", "google", "iconify", "giphy", "pinterest"];
1089
- var imagesFindRequestSchema = z3.object({
1090
- query: z3.string().min(1),
1091
- sources: z3.array(z3.enum(IMAGES_FIND_SOURCES)).optional(),
1092
- limit: z3.coerce.number().int().positive().max(50).optional(),
1093
- fallback: z3.boolean().optional(),
1094
- threshold: z3.number().min(0).max(1).optional(),
1095
- autoIngest: z3.coerce.number().int().min(0).max(20).optional(),
1096
- descriptionContext: z3.string().optional()
1097
- });
1098
- var imagesFindResponseSchema = z3.object({
1099
- groups: z3.object({
1100
- library: z3.array(imageHitSchema),
1101
- external: z3.array(ingestedImageHitSchema)
1633
+ var imagesFindRequestSchema = z5.object({
1634
+ query: z5.string().min(1),
1635
+ sources: z5.array(z5.enum(IMAGES_FIND_SOURCES)).optional(),
1636
+ limit: z5.coerce.number().int().positive().max(50).optional(),
1637
+ fallback: z5.boolean().optional(),
1638
+ threshold: z5.number().min(0).max(1).optional(),
1639
+ autoIngest: z5.coerce.number().int().min(0).max(20).optional(),
1640
+ descriptionContext: z5.string().optional()
1641
+ });
1642
+ var imagesFindResponseSchema = z5.object({
1643
+ groups: z5.object({
1644
+ library: z5.array(imageHitSchema),
1645
+ external: z5.array(ingestedImageHitSchema)
1102
1646
  }),
1103
- meta: z3.object({
1104
- counts: z3.record(z3.string(), z3.number()),
1105
- errors: z3.array(z3.object({ source: imageHitSourceSchema, message: z3.string() }))
1647
+ meta: z5.object({
1648
+ counts: z5.record(z5.string(), z5.number()),
1649
+ errors: z5.array(z5.object({ source: imageHitSourceSchema, message: z5.string() }))
1106
1650
  }),
1107
- ingested: z3.array(autoIngestItemSchema)
1108
- });
1109
- var imagesStockRequestSchema = z3.object({
1110
- query: z3.string().min(1),
1111
- orientation: z3.enum(["landscape", "portrait", "square", "panoramic"]).optional(),
1112
- contentType: z3.enum(["photo", "vector", "psd"]).optional(),
1113
- license: z3.enum(["freemium", "premium"]).optional(),
1114
- color: z3.string().optional(),
1115
- aiGenerated: z3.enum(["exclude", "only"]).optional(),
1116
- people: z3.enum(["include", "exclude", "only"]).optional(),
1117
- order: z3.enum(["relevance", "recent"]).optional(),
1118
- limit: z3.coerce.number().int().positive().max(50).optional(),
1119
- page: z3.coerce.number().int().positive().optional(),
1120
- autoIngest: z3.coerce.number().int().min(0).max(20).optional(),
1121
- descriptionContext: z3.string().optional()
1651
+ ingested: z5.array(autoIngestItemSchema)
1652
+ });
1653
+ var imagesStockRequestSchema = z5.object({
1654
+ query: z5.string().min(1),
1655
+ orientation: z5.enum(["landscape", "portrait", "square", "panoramic"]).optional(),
1656
+ contentType: z5.enum(["photo", "vector", "psd"]).optional(),
1657
+ license: z5.enum(["freemium", "premium"]).optional(),
1658
+ color: z5.string().optional(),
1659
+ aiGenerated: z5.enum(["exclude", "only"]).optional(),
1660
+ people: z5.enum(["include", "exclude", "only"]).optional(),
1661
+ order: z5.enum(["relevance", "recent"]).optional(),
1662
+ limit: z5.coerce.number().int().positive().max(50).optional(),
1663
+ page: z5.coerce.number().int().positive().optional(),
1664
+ autoIngest: z5.coerce.number().int().min(0).max(20).optional(),
1665
+ descriptionContext: z5.string().optional()
1122
1666
  });
1123
1667
  var imagesStockResponseSchema = providerHitsResponseSchema();
1124
- var imagesGoogleRequestSchema = z3.object({
1125
- query: z3.string().min(1),
1126
- type: z3.string().optional(),
1127
- size: z3.string().optional(),
1128
- color: z3.string().optional(),
1129
- safe: z3.enum(["off", "active"]).optional(),
1130
- limit: z3.coerce.number().int().positive().max(50).optional(),
1131
- autoIngest: z3.coerce.number().int().min(0).max(20).optional(),
1132
- descriptionContext: z3.string().optional()
1668
+ var imagesGoogleRequestSchema = z5.object({
1669
+ query: z5.string().min(1),
1670
+ type: z5.string().optional(),
1671
+ size: z5.string().optional(),
1672
+ color: z5.string().optional(),
1673
+ safe: z5.enum(["off", "active"]).optional(),
1674
+ limit: z5.coerce.number().int().positive().max(50).optional(),
1675
+ autoIngest: z5.coerce.number().int().min(0).max(20).optional(),
1676
+ descriptionContext: z5.string().optional()
1133
1677
  });
1134
1678
  var imagesGoogleResponseSchema = providerHitsResponseSchema();
1135
- var imagesPinterestRequestSchema = z3.object({
1136
- query: z3.string().min(1),
1137
- limit: z3.coerce.number().int().positive().max(20).optional(),
1138
- autoIngest: z3.coerce.number().int().min(0).max(20).optional(),
1139
- descriptionContext: z3.string().optional()
1679
+ var imagesPinterestRequestSchema = z5.object({
1680
+ query: z5.string().min(1),
1681
+ limit: z5.coerce.number().int().positive().max(20).optional(),
1682
+ autoIngest: z5.coerce.number().int().min(0).max(20).optional(),
1683
+ descriptionContext: z5.string().optional()
1140
1684
  });
1141
1685
  var imagesPinterestResponseSchema = providerHitsResponseSchema();
1142
- var rgbTriple = z3.tuple([
1143
- z3.number().int().min(0).max(255),
1144
- z3.number().int().min(0).max(255),
1145
- z3.number().int().min(0).max(255)
1686
+ var rgbTriple = z5.tuple([
1687
+ z5.number().int().min(0).max(255),
1688
+ z5.number().int().min(0).max(255),
1689
+ z5.number().int().min(0).max(255)
1146
1690
  ]);
1147
- var imageGenerateModelSchema = z3.enum([
1691
+ var imageGenerateModelSchema = z5.enum([
1148
1692
  "openai/gpt-5.4-image-2",
1149
1693
  "google/gemini-3.5-flash",
1150
1694
  "google/gemini-3.1-flash-image-preview",
1151
1695
  "google/gemini-3-pro-image-preview",
1152
1696
  "recraft/recraft-v4.1-pro-vector"
1153
1697
  ]);
1154
- var imagesGenerateRequestSchema = z3.object({
1155
- prompt: z3.string().min(1),
1698
+ var imagesGenerateRequestSchema = z5.object({
1699
+ prompt: z5.string().min(1),
1156
1700
  model: imageGenerateModelSchema.optional(),
1157
1701
  // Aspect ratio + size are validated loosely as strings; the per-model enum
1158
1702
  // lives in canvas-contract and OpenRouter rejects unsupported combinations.
1159
- aspectRatio: z3.string().optional(),
1160
- imageSize: z3.string().optional(),
1703
+ aspectRatio: z5.string().optional(),
1704
+ imageSize: z5.string().optional(),
1161
1705
  // Recraft v4.1 Pro Vector levers (ignored by other models).
1162
- strength: z3.coerce.number().min(0).max(1).optional(),
1163
- rgbColors: z3.array(rgbTriple).optional(),
1706
+ strength: z5.coerce.number().min(0).max(1).optional(),
1707
+ rgbColors: z5.array(rgbTriple).optional(),
1164
1708
  backgroundRgbColor: rgbTriple.optional(),
1165
1709
  // Public image URLs used as visual references (multi-reference, in order).
1166
- referenceUrls: z3.array(z3.string().url()).optional(),
1167
- descriptionContext: z3.string().optional()
1168
- });
1169
- var generatedImageSchema = z3.object({
1170
- imageId: z3.string(),
1171
- deduped: z3.boolean(),
1172
- imageUrl: z3.string(),
1173
- width: z3.number().optional(),
1174
- height: z3.number().optional()
1175
- });
1176
- var imagesGenerateResponseSchema = z3.object({
1177
- model: z3.string(),
1178
- costUsd: z3.number(),
1179
- images: z3.array(generatedImageSchema)
1180
- });
1181
- var imagesLogoRequestSchema = z3.object({
1182
- domain: z3.string().min(1),
1183
- variant: z3.enum(["icon", "logo", "symbol"]).optional(),
1184
- autoIngest: z3.coerce.number().int().min(0).max(5).optional(),
1185
- descriptionContext: z3.string().optional()
1710
+ referenceUrls: z5.array(z5.string().url()).optional(),
1711
+ descriptionContext: z5.string().optional()
1712
+ });
1713
+ var generatedImageSchema = z5.object({
1714
+ imageId: z5.string(),
1715
+ deduped: z5.boolean(),
1716
+ imageUrl: z5.string(),
1717
+ width: z5.number().optional(),
1718
+ height: z5.number().optional()
1719
+ });
1720
+ var imagesGenerateResponseSchema = z5.object({
1721
+ model: z5.string(),
1722
+ costUsd: z5.number(),
1723
+ images: z5.array(generatedImageSchema)
1724
+ });
1725
+ var imagesLogoRequestSchema = z5.object({
1726
+ domain: z5.string().min(1),
1727
+ variant: z5.enum(["icon", "logo", "symbol"]).optional(),
1728
+ autoIngest: z5.coerce.number().int().min(0).max(5).optional(),
1729
+ descriptionContext: z5.string().optional()
1186
1730
  });
1187
1731
  var imagesLogoResponseSchema = providerHitsResponseSchema();
1188
- var imagesIconRequestSchema = z3.object({
1189
- name: z3.string().min(1),
1190
- set: z3.string().optional(),
1191
- color: z3.string().optional(),
1192
- width: z3.coerce.number().int().positive().optional(),
1193
- autoIngest: z3.coerce.number().int().min(0).max(20).optional(),
1194
- descriptionContext: z3.string().optional()
1732
+ var imagesIconRequestSchema = z5.object({
1733
+ name: z5.string().min(1),
1734
+ set: z5.string().optional(),
1735
+ color: z5.string().optional(),
1736
+ width: z5.coerce.number().int().positive().optional(),
1737
+ autoIngest: z5.coerce.number().int().min(0).max(20).optional(),
1738
+ descriptionContext: z5.string().optional()
1195
1739
  });
1196
1740
  var imagesIconResponseSchema = providerHitsResponseSchema();
1197
- var imagesExtractRequestSchema = z3.object({
1198
- url: z3.string().url(),
1199
- waitFor: z3.coerce.number().int().min(0).max(3e4).optional(),
1200
- limit: z3.coerce.number().int().positive().max(50).optional(),
1201
- autoIngest: z3.coerce.number().int().min(0).max(20).optional(),
1202
- descriptionContext: z3.string().optional()
1741
+ var imagesExtractRequestSchema = z5.object({
1742
+ url: z5.string().url(),
1743
+ waitFor: z5.coerce.number().int().min(0).max(3e4).optional(),
1744
+ limit: z5.coerce.number().int().positive().max(50).optional(),
1745
+ autoIngest: z5.coerce.number().int().min(0).max(20).optional(),
1746
+ descriptionContext: z5.string().optional()
1203
1747
  });
1204
1748
  var imagesExtractResponseSchema = providerHitsResponseSchema();
1205
- var imagesScreenshotRequestSchema = z3.object({
1206
- url: z3.string().url(),
1207
- fullPage: z3.boolean().optional(),
1208
- viewportWidth: z3.coerce.number().int().positive().max(3840).optional(),
1209
- viewportHeight: z3.coerce.number().int().positive().max(2160).optional(),
1210
- format: z3.enum(["webp", "png", "jpg"]).optional(),
1211
- descriptionContext: z3.string().optional()
1749
+ var imagesScreenshotRequestSchema = z5.object({
1750
+ url: z5.string().url(),
1751
+ fullPage: z5.boolean().optional(),
1752
+ viewportWidth: z5.coerce.number().int().positive().max(3840).optional(),
1753
+ viewportHeight: z5.coerce.number().int().positive().max(2160).optional(),
1754
+ format: z5.enum(["webp", "png", "jpg"]).optional(),
1755
+ descriptionContext: z5.string().optional()
1212
1756
  });
1213
1757
  var imagesScreenshotResponseSchema = providerHitsResponseSchema();
1214
- var imagesGiphyRequestSchema = z3.object({
1215
- query: z3.string().min(1).optional(),
1216
- trending: z3.coerce.boolean().optional(),
1217
- limit: z3.coerce.number().int().positive().max(50).optional(),
1218
- rating: z3.enum(["g", "pg", "pg-13", "r"]).optional(),
1219
- lang: z3.string().optional(),
1220
- autoIngest: z3.coerce.number().int().min(0).max(20).optional(),
1221
- descriptionContext: z3.string().optional()
1758
+ var imagesGiphyRequestSchema = z5.object({
1759
+ query: z5.string().min(1).optional(),
1760
+ trending: z5.coerce.boolean().optional(),
1761
+ limit: z5.coerce.number().int().positive().max(50).optional(),
1762
+ rating: z5.enum(["g", "pg", "pg-13", "r"]).optional(),
1763
+ lang: z5.string().optional(),
1764
+ autoIngest: z5.coerce.number().int().min(0).max(20).optional(),
1765
+ descriptionContext: z5.string().optional()
1222
1766
  });
1223
1767
  var imagesGifResponseSchema = providerHitsResponseSchema();
1224
1768
  var imagesStickerResponseSchema = providerHitsResponseSchema();
1225
- var imagesIngestRequestSchema = z3.object({
1226
- url: z3.string().url(),
1769
+ var imagesIngestRequestSchema = z5.object({
1770
+ url: z5.string().url(),
1227
1771
  // Validate source at the HTTP boundary so unknown values produce the standard
1228
1772
  // `{ code: "BAD_REQUEST", message }` shape instead of a plain Error from
1229
1773
  // `assertImageSource` inside the action.
1230
1774
  source: imageSourceSchema,
1231
- externalId: z3.string().optional(),
1232
- externalUrl: z3.string().optional(),
1233
- descriptionContext: z3.string().optional()
1775
+ externalId: z5.string().optional(),
1776
+ externalUrl: z5.string().optional(),
1777
+ descriptionContext: z5.string().optional()
1234
1778
  });
1235
- var imagesIngestResponseSchema = z3.object({
1236
- imageId: z3.string(),
1237
- deduped: z3.boolean(),
1238
- contentHash: z3.string()
1779
+ var imagesIngestResponseSchema = z5.object({
1780
+ imageId: z5.string(),
1781
+ deduped: z5.boolean(),
1782
+ contentHash: z5.string()
1239
1783
  });
1240
1784
 
1241
1785
  // ../api/src/testimonials.ts
1242
- import { z as z4 } from "zod";
1243
- var testimonialSourceTypeSchema = z4.enum(["google", "trustpilot"]);
1244
- var testimonialStatusSchema = z4.enum(["pending", "processing", "ready", "error"]);
1245
- var testimonialSentimentSchema = z4.enum(["positive", "neutral", "negative"]);
1246
- var testimonialDocSchema = z4.object({
1247
- _id: z4.string(),
1248
- _creationTime: z4.number(),
1249
- companyId: z4.string(),
1250
- sourceId: z4.string(),
1786
+ import { z as z6 } from "zod";
1787
+ var testimonialSourceTypeSchema = z6.enum(["google", "trustpilot"]);
1788
+ var testimonialStatusSchema = z6.enum(["pending", "processing", "ready", "error"]);
1789
+ var testimonialSentimentSchema = z6.enum(["positive", "neutral", "negative"]);
1790
+ var testimonialDocSchema = z6.object({
1791
+ _id: z6.string(),
1792
+ _creationTime: z6.number(),
1793
+ companyId: z6.string(),
1794
+ sourceId: z6.string(),
1251
1795
  sourceType: testimonialSourceTypeSchema,
1252
- reviewText: z4.string(),
1253
- reviewTitle: z4.string().optional(),
1254
- searchText: z4.string().optional(),
1255
- reviewerName: z4.string().optional(),
1256
- reviewerImageUrl: z4.string().optional(),
1257
- reviewerImageId: z4.string().optional(),
1258
- reviewerLocation: z4.string().optional(),
1259
- rating: z4.number().optional(),
1260
- reviewDate: z4.number().optional(),
1261
- ownerAnswer: z4.string().optional(),
1262
- mediaUrls: z4.array(z4.string()).optional(),
1263
- imageIds: z4.array(z4.string()).optional(),
1264
- videoIds: z4.array(z4.string()).optional(),
1265
- sourceUrl: z4.string().optional(),
1266
- rawData: z4.unknown().optional(),
1267
- tags: z4.array(z4.string()),
1268
- highlight: z4.string().optional(),
1269
- language: z4.string().optional(),
1270
- summary: z4.string().optional(),
1796
+ reviewText: z6.string(),
1797
+ reviewTitle: z6.string().optional(),
1798
+ searchText: z6.string().optional(),
1799
+ reviewerName: z6.string().optional(),
1800
+ reviewerImageUrl: z6.string().optional(),
1801
+ reviewerImageId: z6.string().optional(),
1802
+ reviewerLocation: z6.string().optional(),
1803
+ rating: z6.number().optional(),
1804
+ reviewDate: z6.number().optional(),
1805
+ ownerAnswer: z6.string().optional(),
1806
+ mediaUrls: z6.array(z6.string()).optional(),
1807
+ imageIds: z6.array(z6.string()).optional(),
1808
+ videoIds: z6.array(z6.string()).optional(),
1809
+ sourceUrl: z6.string().optional(),
1810
+ rawData: z6.unknown().optional(),
1811
+ tags: z6.array(z6.string()),
1812
+ highlight: z6.string().optional(),
1813
+ language: z6.string().optional(),
1814
+ summary: z6.string().optional(),
1271
1815
  sentiment: testimonialSentimentSchema.optional(),
1272
- textEmbedding: z4.array(z4.number()).optional(),
1273
- externalId: z4.string().optional(),
1274
- contentHash: z4.string().optional(),
1816
+ textEmbedding: z6.array(z6.number()).optional(),
1817
+ externalId: z6.string().optional(),
1818
+ contentHash: z6.string().optional(),
1275
1819
  status: testimonialStatusSchema,
1276
- errorMessage: z4.string().optional(),
1277
- createdAt: z4.number(),
1278
- updatedAt: z4.number()
1820
+ errorMessage: z6.string().optional(),
1821
+ createdAt: z6.number(),
1822
+ updatedAt: z6.number()
1279
1823
  });
1280
- var testimonialsListRequestSchema = z4.object({
1824
+ var testimonialsListRequestSchema = z6.object({
1281
1825
  source: testimonialSourceTypeSchema.optional(),
1282
- rating_min: z4.coerce.number().int().min(1).max(5).optional(),
1283
- rating_max: z4.coerce.number().int().min(1).max(5).optional(),
1284
- tags: z4.string().transform((s) => s.split(",").filter(Boolean)).optional(),
1826
+ rating_min: z6.coerce.number().int().min(1).max(5).optional(),
1827
+ rating_max: z6.coerce.number().int().min(1).max(5).optional(),
1828
+ tags: z6.string().transform((s) => s.split(",").filter(Boolean)).optional(),
1285
1829
  status: testimonialStatusSchema.optional(),
1286
1830
  sentiment: testimonialSentimentSchema.optional(),
1287
- language: z4.string().min(2).max(5).optional(),
1288
- limit: z4.coerce.number().int().positive().max(200).optional()
1289
- });
1290
- var testimonialsListResponseSchema = z4.array(testimonialDocSchema);
1291
- var testimonialsGetRequestSchema = z4.object({ id: z4.string().min(1, "Missing id parameter") });
1292
- var testimonialsSearchRequestSchema = z4.object({
1293
- query: z4.string().min(1),
1294
- limit: z4.coerce.number().int().positive().max(100).optional(),
1831
+ language: z6.string().min(2).max(5).optional(),
1832
+ limit: z6.coerce.number().int().positive().max(200).optional()
1833
+ });
1834
+ var testimonialsListResponseSchema = z6.array(testimonialDocSchema);
1835
+ var testimonialsGetRequestSchema = z6.object({ id: z6.string().min(1, "Missing id parameter") });
1836
+ var testimonialsSearchRequestSchema = z6.object({
1837
+ query: z6.string().min(1),
1838
+ limit: z6.coerce.number().int().positive().max(100).optional(),
1295
1839
  source: testimonialSourceTypeSchema.optional(),
1296
- rating_min: z4.coerce.number().int().min(1).max(5).optional(),
1297
- rating_max: z4.coerce.number().int().min(1).max(5).optional(),
1298
- tags: z4.array(z4.string()).optional(),
1840
+ rating_min: z6.coerce.number().int().min(1).max(5).optional(),
1841
+ rating_max: z6.coerce.number().int().min(1).max(5).optional(),
1842
+ tags: z6.array(z6.string()).optional(),
1299
1843
  status: testimonialStatusSchema.optional(),
1300
1844
  sentiment: testimonialSentimentSchema.optional(),
1301
- language: z4.string().min(2).max(5).optional()
1845
+ language: z6.string().min(2).max(5).optional()
1302
1846
  }).refine(
1303
1847
  (data) => data.rating_min === void 0 || data.rating_max === void 0 || data.rating_min <= data.rating_max,
1304
1848
  { message: "rating_min must be less than or equal to rating_max" }
1305
1849
  );
1306
- var testimonialsSearchResponseSchema = z4.array(testimonialDocSchema);
1307
- var testimonialsOutscraperWebhookResponseSchema = z4.object({
1308
- ok: z4.literal(true),
1309
- note: z4.string().optional()
1850
+ var testimonialsSearchResponseSchema = z6.array(testimonialDocSchema);
1851
+ var testimonialsOutscraperWebhookResponseSchema = z6.object({
1852
+ ok: z6.literal(true),
1853
+ note: z6.string().optional()
1310
1854
  });
1311
1855
 
1312
1856
  // ../api/src/videos.ts
1313
- import { z as z5 } from "zod";
1314
- var videoStatusSchema = z5.enum(["uploading", "uploaded", "processing", "ready", "error"]);
1315
- var videoTranscriptSegmentSchema = z5.object({
1316
- text: z5.string(),
1317
- startSecond: z5.number(),
1318
- endSecond: z5.number()
1319
- });
1320
- var videoSceneSchema = z5.object({
1321
- title: z5.string(),
1322
- description: z5.string(),
1323
- startSecond: z5.number(),
1324
- endSecond: z5.number(),
1325
- thumbnailTime: z5.number()
1326
- });
1327
- var videoDocSchema = z5.object({
1328
- _id: z5.string(),
1329
- _creationTime: z5.number(),
1330
- companyId: z5.string(),
1331
- muxAssetId: z5.string(),
1332
- muxPlaybackId: z5.string(),
1333
- muxUploadId: z5.string(),
1334
- name: z5.string(),
1335
- description: z5.string(),
1336
- tags: z5.array(z5.string()),
1337
- source: z5.string(),
1338
- externalId: z5.string().optional(),
1339
- sourceId: z5.string().optional(),
1340
- width: z5.number().optional(),
1341
- height: z5.number().optional(),
1342
- aspectRatio: z5.number().optional(),
1343
- duration: z5.number().optional(),
1344
- transcript: z5.string().optional(),
1345
- transcriptSegments: z5.array(videoTranscriptSegmentSchema).optional(),
1346
- scenes: z5.array(videoSceneSchema).optional(),
1347
- descriptionEmbedding: z5.array(z5.number()).optional(),
1348
- searchText: z5.string().optional(),
1857
+ import { z as z7 } from "zod";
1858
+ var videoStatusSchema = z7.enum(["uploading", "uploaded", "processing", "ready", "error"]);
1859
+ var videoTranscriptSegmentSchema = z7.object({
1860
+ text: z7.string(),
1861
+ startSecond: z7.number(),
1862
+ endSecond: z7.number()
1863
+ });
1864
+ var videoSceneSchema = z7.object({
1865
+ title: z7.string(),
1866
+ description: z7.string(),
1867
+ startSecond: z7.number(),
1868
+ endSecond: z7.number(),
1869
+ thumbnailTime: z7.number()
1870
+ });
1871
+ var videoDocSchema = z7.object({
1872
+ _id: z7.string(),
1873
+ _creationTime: z7.number(),
1874
+ companyId: z7.string(),
1875
+ muxAssetId: z7.string(),
1876
+ muxPlaybackId: z7.string(),
1877
+ muxUploadId: z7.string(),
1878
+ name: z7.string(),
1879
+ description: z7.string(),
1880
+ tags: z7.array(z7.string()),
1881
+ source: z7.string(),
1882
+ externalId: z7.string().optional(),
1883
+ sourceId: z7.string().optional(),
1884
+ width: z7.number().optional(),
1885
+ height: z7.number().optional(),
1886
+ aspectRatio: z7.number().optional(),
1887
+ duration: z7.number().optional(),
1888
+ transcript: z7.string().optional(),
1889
+ transcriptSegments: z7.array(videoTranscriptSegmentSchema).optional(),
1890
+ scenes: z7.array(videoSceneSchema).optional(),
1891
+ descriptionEmbedding: z7.array(z7.number()).optional(),
1892
+ searchText: z7.string().optional(),
1349
1893
  status: videoStatusSchema,
1350
- errorMessage: z5.string().optional(),
1351
- createdAt: z5.number(),
1352
- updatedAt: z5.number(),
1353
- thumbnailUrl: z5.string()
1354
- });
1355
- var videosWebhookResponseSchema = z5.object({ ok: z5.literal(true) });
1356
- var videosGetRequestSchema = z5.object({ id: z5.string().min(1, "Missing id parameter") });
1357
- var videosSearchRequestSchema = z5.object({
1358
- query: z5.string().min(1),
1359
- limit: z5.coerce.number().int().positive().max(100).optional(),
1360
- tags: z5.array(z5.string()).optional()
1361
- });
1362
- var videoSearchResultSchema = z5.object({
1363
- _id: z5.string(),
1364
- thumbnailUrl: z5.string(),
1365
- name: z5.string(),
1366
- description: z5.string(),
1367
- tags: z5.array(z5.string()),
1368
- status: z5.string(),
1369
- duration: z5.number().optional(),
1370
- muxPlaybackId: z5.string(),
1371
- createdAt: z5.number()
1372
- });
1373
- var videosSearchResponseSchema = z5.array(videoSearchResultSchema);
1374
- var videosUploadResponseSchema = z5.object({ uploadUrl: z5.string(), videoId: z5.string() });
1375
- var videosDeleteRequestSchema = z5.object({ id: z5.string().min(1, "Missing video ID") });
1376
- var videosDeleteResponseSchema = z5.object({ ok: z5.literal(true) });
1894
+ errorMessage: z7.string().optional(),
1895
+ createdAt: z7.number(),
1896
+ updatedAt: z7.number(),
1897
+ thumbnailUrl: z7.string()
1898
+ });
1899
+ var videosWebhookResponseSchema = z7.object({ ok: z7.literal(true) });
1900
+ var videosGetRequestSchema = z7.object({ id: z7.string().min(1, "Missing id parameter") });
1901
+ var videosSearchRequestSchema = z7.object({
1902
+ query: z7.string().min(1),
1903
+ limit: z7.coerce.number().int().positive().max(100).optional(),
1904
+ tags: z7.array(z7.string()).optional()
1905
+ });
1906
+ var videoSearchResultSchema = z7.object({
1907
+ _id: z7.string(),
1908
+ thumbnailUrl: z7.string(),
1909
+ name: z7.string(),
1910
+ description: z7.string(),
1911
+ tags: z7.array(z7.string()),
1912
+ status: z7.string(),
1913
+ duration: z7.number().optional(),
1914
+ muxPlaybackId: z7.string(),
1915
+ createdAt: z7.number()
1916
+ });
1917
+ var videosSearchResponseSchema = z7.array(videoSearchResultSchema);
1918
+ var videosUploadResponseSchema = z7.object({ uploadUrl: z7.string(), videoId: z7.string() });
1919
+ var videosDeleteRequestSchema = z7.object({ id: z7.string().min(1, "Missing video ID") });
1920
+ var videosDeleteResponseSchema = z7.object({ ok: z7.literal(true) });
1377
1921
 
1378
1922
  // src/commands/actions/complete.ts
1379
1923
  import { defineCommand as defineCommand2 } from "citty";
@@ -2202,7 +2746,7 @@ Examples:
2202
2746
  });
2203
2747
 
2204
2748
  // src/commands/ads/index.ts
2205
- import { defineCommand as defineCommand78 } from "citty";
2749
+ import { defineCommand as defineCommand80 } from "citty";
2206
2750
 
2207
2751
  // src/commands/ads/google/index.ts
2208
2752
  import { defineCommand as defineCommand29 } from "citty";
@@ -4526,7 +5070,7 @@ Examples:
4526
5070
  });
4527
5071
 
4528
5072
  // src/commands/ads/linkedin/index.ts
4529
- import { defineCommand as defineCommand47 } from "citty";
5073
+ import { defineCommand as defineCommand49 } from "citty";
4530
5074
 
4531
5075
  // src/commands/ads/linkedin/schemas.ts
4532
5076
  registerSchema({
@@ -4824,6 +5368,293 @@ registerSchema({
4824
5368
  "skip-cache": { type: "boolean", description: "Bypass cache", required: false }
4825
5369
  }
4826
5370
  });
5371
+ var writeAccountArgs = {
5372
+ "account-id": { type: "string", description: "Numeric account ID or urn:li:sponsoredAccount:N", required: false },
5373
+ "account-urn": { type: "string", description: "Alias for --account-id", required: false }
5374
+ };
5375
+ registerSchema({
5376
+ command: "ads.linkedin.campaign-groups.create",
5377
+ description: "Stage a new campaign group (staged until publish; review with `baker ads linkedin draft`). Returns a li_temp_* ref that later `campaigns create --group` calls can reference.",
5378
+ args: {
5379
+ ...writeAccountArgs,
5380
+ name: { type: "string", description: "Name (\u2264100 chars)", required: true },
5381
+ start: { type: "string", description: "Run schedule start (ISO date or epoch ms)", required: true },
5382
+ end: { type: "string", description: "Run schedule end", required: false },
5383
+ "total-budget": { type: "string", description: "Lifetime budget amount", required: false },
5384
+ currency: { type: "string", description: "3-letter currency code (required with money flags)", required: false },
5385
+ status: { type: "string", description: "DRAFT|ACTIVE|PAUSED (default DRAFT)", required: false },
5386
+ file: { type: "string", description: "JSON payload file; flags override file keys", required: false }
5387
+ }
5388
+ });
5389
+ registerSchema({
5390
+ command: "ads.linkedin.campaign-groups.update",
5391
+ description: "Stage changes to an existing campaign group (name, schedule, budget, status). Captures a before-snapshot for the dashboard diff. Applies on chat publish.",
5392
+ args: {
5393
+ id: { type: "positional", description: "Campaign group id or URN", required: true },
5394
+ ...writeAccountArgs,
5395
+ name: { type: "string", description: "New name", required: false },
5396
+ start: { type: "string", description: "New schedule start", required: false },
5397
+ end: { type: "string", description: "New schedule end", required: false },
5398
+ "total-budget": { type: "string", description: "New lifetime budget", required: false },
5399
+ currency: { type: "string", description: "3-letter currency code", required: false },
5400
+ status: { type: "string", description: "ACTIVE|PAUSED|ARCHIVED", required: false },
5401
+ file: { type: "string", description: "JSON file with fields to change", required: false }
5402
+ }
5403
+ });
5404
+ registerSchema({
5405
+ command: "ads.linkedin.campaigns.create",
5406
+ description: "Stage a new campaign. --group accepts a real id/URN or a li_temp_* ref staged earlier in this chat. Targeting goes in --targeting-file as LinkedIn criteria: {include:{and:[{or:{'urn:li:adTargetingFacet:locations':['urn:li:geo:\u2026']}}]}} \u2014 find facet values with `baker ads linkedin facets values`. Playbook defaults: manual bid (--bid), audience expansion off, LAN off. Staged until publish.",
5407
+ args: {
5408
+ ...writeAccountArgs,
5409
+ name: { type: "string", description: "Name (\u2264255 chars)", required: true },
5410
+ group: { type: "string", description: "Campaign group id/URN or li_temp_* ref", required: true },
5411
+ type: { type: "string", description: "SPONSORED_UPDATES|TEXT_AD|SPONSORED_INMAILS|DYNAMIC", required: true },
5412
+ objective: { type: "string", description: "LEAD_GENERATION|WEBSITE_VISIT|BRAND_AWARENESS|\u2026", required: false },
5413
+ "cost-type": { type: "string", description: "CPC|CPM|CPV", required: true },
5414
+ bid: { type: "string", description: "Manual bid amount (unitCost)", required: false },
5415
+ "daily-budget": { type: "string", description: "Daily budget amount", required: false },
5416
+ "total-budget": { type: "string", description: "Lifetime budget amount", required: false },
5417
+ currency: { type: "string", description: "3-letter currency code (required with money flags)", required: false },
5418
+ start: { type: "string", description: "Run schedule start", required: false },
5419
+ end: { type: "string", description: "Run schedule end", required: false },
5420
+ locale: { type: "string", description: "Profile locale like en_US (default en_US)", required: false },
5421
+ "targeting-file": { type: "string", description: "JSON file with targetingCriteria", required: true },
5422
+ "audience-expansion": { type: "string", description: "on|off (playbook: off; default off)", required: false },
5423
+ lan: {
5424
+ type: "string",
5425
+ description: "LinkedIn Audience Network on|off (playbook: off; default off)",
5426
+ required: false
5427
+ },
5428
+ ctv: { type: "string", description: "Connected TV on|off (default off)", required: false },
5429
+ "creative-selection": { type: "string", description: "OPTIMIZED|ROUND_ROBIN", required: false },
5430
+ "associated-entity": { type: "string", description: "Organization URN", required: false },
5431
+ status: { type: "string", description: "DRAFT|ACTIVE|PAUSED (default DRAFT)", required: false },
5432
+ file: { type: "string", description: "JSON payload file; flags override file keys", required: false }
5433
+ }
5434
+ });
5435
+ registerSchema({
5436
+ command: "ads.linkedin.campaigns.update",
5437
+ description: "Stage changes to an existing campaign \u2014 budget, bid, targeting, schedule, flags, status. Only pass what changes; a before-snapshot powers the dashboard diff. Applies on chat publish.",
5438
+ args: {
5439
+ id: { type: "positional", description: "Campaign id or URN", required: true },
5440
+ ...writeAccountArgs,
5441
+ name: { type: "string", description: "New name", required: false },
5442
+ objective: { type: "string", description: "New objective", required: false },
5443
+ bid: { type: "string", description: "New manual bid", required: false },
5444
+ "daily-budget": { type: "string", description: "New daily budget", required: false },
5445
+ "total-budget": { type: "string", description: "New lifetime budget", required: false },
5446
+ currency: { type: "string", description: "3-letter currency code", required: false },
5447
+ start: { type: "string", description: "New schedule start", required: false },
5448
+ end: { type: "string", description: "New schedule end", required: false },
5449
+ "targeting-file": { type: "string", description: "JSON file with replacement targetingCriteria", required: false },
5450
+ "audience-expansion": { type: "string", description: "on|off", required: false },
5451
+ lan: { type: "string", description: "on|off", required: false },
5452
+ ctv: { type: "string", description: "on|off", required: false },
5453
+ "creative-selection": { type: "string", description: "OPTIMIZED|ROUND_ROBIN", required: false },
5454
+ status: { type: "string", description: "ACTIVE|PAUSED|ARCHIVED", required: false },
5455
+ file: { type: "string", description: "JSON file with fields to change", required: false }
5456
+ }
5457
+ });
5458
+ var statusSugarArgs = {
5459
+ id: { type: "positional", description: "Entity id or URN", required: true },
5460
+ ...writeAccountArgs
5461
+ };
5462
+ registerSchema({
5463
+ command: "ads.linkedin.campaigns.pause",
5464
+ description: "Stage pausing a campaign (status \u2192 PAUSED on publish).",
5465
+ args: statusSugarArgs
5466
+ });
5467
+ registerSchema({
5468
+ command: "ads.linkedin.campaigns.resume",
5469
+ description: "Stage resuming a paused campaign (status \u2192 ACTIVE on publish).",
5470
+ args: statusSugarArgs
5471
+ });
5472
+ registerSchema({
5473
+ command: "ads.linkedin.campaigns.archive",
5474
+ description: "Stage archiving a campaign (status \u2192 ARCHIVED on publish).",
5475
+ args: statusSugarArgs
5476
+ });
5477
+ registerSchema({
5478
+ command: "ads.linkedin.campaign-groups.pause",
5479
+ description: "Stage pausing a campaign group.",
5480
+ args: statusSugarArgs
5481
+ });
5482
+ registerSchema({
5483
+ command: "ads.linkedin.campaign-groups.resume",
5484
+ description: "Stage resuming a campaign group.",
5485
+ args: statusSugarArgs
5486
+ });
5487
+ registerSchema({
5488
+ command: "ads.linkedin.creatives.pause",
5489
+ description: "Stage pausing a creative (intendedStatus \u2192 PAUSED on publish). Playbook early-kill rule: >30 impressions with 0 clicks.",
5490
+ args: statusSugarArgs
5491
+ });
5492
+ registerSchema({
5493
+ command: "ads.linkedin.creatives.resume",
5494
+ description: "Stage resuming a paused creative.",
5495
+ args: statusSugarArgs
5496
+ });
5497
+ var duplicateArgs = {
5498
+ id: { type: "positional", description: "Source id or URN", required: true },
5499
+ ...writeAccountArgs,
5500
+ name: { type: "string", description: "Name for the copy", required: false },
5501
+ file: { type: "string", description: "JSON file with field overrides for the copy", required: false }
5502
+ };
5503
+ registerSchema({
5504
+ command: "ads.linkedin.campaigns.duplicate",
5505
+ description: "Stage a copy of an existing campaign as a new DRAFT create (playbook: duplicate, never link-to-original). Reads the source at stage time; override fields via --name/--file.",
5506
+ args: duplicateArgs
5507
+ });
5508
+ registerSchema({
5509
+ command: "ads.linkedin.campaign-groups.duplicate",
5510
+ description: "Stage a copy of an existing campaign group as a new DRAFT create.",
5511
+ args: duplicateArgs
5512
+ });
5513
+ registerSchema({
5514
+ command: "ads.linkedin.creatives.duplicate",
5515
+ description: "Stage a copy of an existing creative by re-sponsoring its underlying post into a new DRAFT creative (--file can override the target campaign).",
5516
+ args: duplicateArgs
5517
+ });
5518
+ registerSchema({
5519
+ command: "ads.linkedin.creatives.create",
5520
+ description: "Stage a new creative (ad). Formats: image|video|text|spotlight|follower|document|carousel|conversation|tla|jobs. Media: --image-id/--video-id reference the Baker library (`baker images`/`baker videos`) and upload to LinkedIn at publish; --image-urn/--video-urn reference media already on LinkedIn. Limits: headline \u226470 (text ads \u226425), intro soft-truncates at 600 chars, landing URL must be https. Complex formats take --file with the full content object. Staged until publish.",
5521
+ args: {
5522
+ ...writeAccountArgs,
5523
+ campaign: { type: "string", description: "Campaign id/URN or li_temp_* ref", required: true },
5524
+ format: {
5525
+ type: "string",
5526
+ description: "image|video|text|spotlight|follower|document|carousel|conversation|tla|jobs",
5527
+ required: true
5528
+ },
5529
+ "image-id": { type: "string", description: "Baker image library id", required: false },
5530
+ "image-urn": { type: "string", description: "Existing urn:li:image:*", required: false },
5531
+ "video-id": { type: "string", description: "Baker video library id", required: false },
5532
+ "video-urn": { type: "string", description: "Existing urn:li:video:*", required: false },
5533
+ "logo-image-id": { type: "string", description: "Baker image id for the logo", required: false },
5534
+ intro: { type: "string", description: "Commentary / intro text", required: false },
5535
+ headline: { type: "string", description: "Headline", required: false },
5536
+ description: { type: "string", description: "Description (text/spotlight)", required: false },
5537
+ "landing-url": { type: "string", description: "https destination URL", required: false },
5538
+ cta: { type: "string", description: "LEARN_MORE|REQUEST_DEMO|SIGN_UP|REGISTER|DOWNLOAD|\u2026", required: false },
5539
+ "cta-label": { type: "string", description: "Spotlight CTA label (\u226418 chars)", required: false },
5540
+ "post-urn": { type: "string", description: "TLA: post to sponsor (urn:li:share|ugcPost:*)", required: false },
5541
+ "intended-status": { type: "string", description: "DRAFT|ACTIVE|PAUSED (default DRAFT)", required: false },
5542
+ title: { type: "string", description: "Media title", required: false },
5543
+ file: { type: "string", description: "JSON file with the full content object", required: false }
5544
+ }
5545
+ });
5546
+ registerSchema({
5547
+ command: "ads.linkedin.creatives.update",
5548
+ description: "Stage changes to an existing creative (intendedStatus, name). Applies on chat publish.",
5549
+ args: {
5550
+ id: { type: "positional", description: "Creative id or URN", required: true },
5551
+ ...writeAccountArgs,
5552
+ "intended-status": { type: "string", description: "ACTIVE|PAUSED|ARCHIVED|DRAFT", required: false },
5553
+ name: { type: "string", description: "New creative name", required: false },
5554
+ file: { type: "string", description: "JSON file with fields to change", required: false }
5555
+ }
5556
+ });
5557
+ registerSchema({
5558
+ command: "ads.linkedin.audiences.create",
5559
+ description: "Stage a new matched audience. company-list/user-list take --list-file (CSV with header; companyName,domain for companies; email column is SHA-256 hashed locally). LinkedIn needs 300+ MATCHED members to serve \u2014 upload well above that. retargeting/engagement configs go in --file. Staged until publish.",
5560
+ args: {
5561
+ ...writeAccountArgs,
5562
+ name: { type: "string", description: "Audience name (\u2264100 chars)", required: true },
5563
+ type: { type: "string", description: "company-list|user-list|retargeting|engagement", required: true },
5564
+ "list-file": { type: "string", description: "CSV file with the list rows", required: false },
5565
+ file: { type: "string", description: "JSON raw source config for retargeting/engagement", required: false }
5566
+ }
5567
+ });
5568
+ registerSchema({
5569
+ command: "ads.linkedin.audiences.upload",
5570
+ description: "Stage adding rows to an existing audience segment (or a li_temp_* segment staged in this chat). Same CSV rules as audiences.create.",
5571
+ args: {
5572
+ id: { type: "positional", description: "Segment URN/id or li_temp_* ref", required: true },
5573
+ ...writeAccountArgs,
5574
+ "list-file": { type: "string", description: "CSV file with the rows to add", required: true }
5575
+ }
5576
+ });
5577
+ registerSchema({
5578
+ command: "ads.linkedin.conversions.create",
5579
+ description: "Stage a new conversion rule. Playbook defaults: --post-click-window 30 --view-window 7, counting ONE_TIME_EACH_MEMBER for leads. Staged until publish.",
5580
+ args: {
5581
+ ...writeAccountArgs,
5582
+ name: { type: "string", description: "Rule name", required: true },
5583
+ type: {
5584
+ type: "string",
5585
+ description: "LEAD|SIGN_UP|DOWNLOAD|PURCHASE|KEY_PAGE_VIEW|ADD_TO_CART|INSTALL|OTHER",
5586
+ required: true
5587
+ },
5588
+ method: { type: "string", description: "INSIGHT_TAG|CONVERSIONS_API", required: true },
5589
+ "post-click-window": { type: "string", description: "1|7|30|90 days", required: false },
5590
+ "view-window": { type: "string", description: "1|7|30 days", required: false },
5591
+ "attribution-type": {
5592
+ type: "string",
5593
+ description: "LAST_TOUCH_BY_CAMPAIGN|LAST_TOUCH_BY_CONVERSION",
5594
+ required: false
5595
+ },
5596
+ "associate-all-campaigns": {
5597
+ type: "boolean",
5598
+ description: "Auto-associate with active campaigns",
5599
+ required: false
5600
+ },
5601
+ file: { type: "string", description: "JSON payload file (e.g. urlMatchRuleExpression)", required: false }
5602
+ }
5603
+ });
5604
+ registerSchema({
5605
+ command: "ads.linkedin.conversions.update",
5606
+ description: "Stage changes to a conversion rule (windows, attribution, enabled, name). Applies on chat publish.",
5607
+ args: {
5608
+ id: { type: "positional", description: "Conversion rule id or URN", required: true },
5609
+ ...writeAccountArgs,
5610
+ name: { type: "string", description: "New name", required: false },
5611
+ "post-click-window": { type: "string", description: "1|7|30|90 days", required: false },
5612
+ "view-window": { type: "string", description: "1|7|30 days", required: false },
5613
+ "attribution-type": { type: "string", description: "New attribution type", required: false },
5614
+ enabled: { type: "string", description: "on|off", required: false },
5615
+ file: { type: "string", description: "JSON file with fields to change", required: false }
5616
+ }
5617
+ });
5618
+ registerSchema({
5619
+ command: "ads.linkedin.lead-forms.create",
5620
+ description: "Stage a new Lead Gen Form from a JSON file: {name, headline \u226460, description? \u2264160, privacyPolicyUrl, questions[] \u226412 (playbook: \u22644 for completion), thankYou?, legalDisclaimer?}. Staged until publish.",
5621
+ args: {
5622
+ ...writeAccountArgs,
5623
+ file: { type: "string", description: "JSON form definition file", required: true },
5624
+ name: { type: "string", description: "Override the form name", required: false }
5625
+ }
5626
+ });
5627
+ registerSchema({
5628
+ command: "ads.linkedin.lead-forms.update",
5629
+ description: "Stage changes to a Lead Gen Form from a JSON file. Applies on chat publish.",
5630
+ args: {
5631
+ id: { type: "positional", description: "Lead form id or URN", required: true },
5632
+ ...writeAccountArgs,
5633
+ file: { type: "string", description: "JSON file with the fields to change", required: true },
5634
+ name: { type: "string", description: "New form name", required: false }
5635
+ }
5636
+ });
5637
+ registerSchema({
5638
+ command: "ads.linkedin.draft.list",
5639
+ description: "Show every LinkedIn write op staged in this chat: ref, summary, dependencies, warnings, mode (simulated = publish will NOT hit LinkedIn), and post-publish results (applied/simulated/failed/skipped). Ops are invisible to the read commands until publish \u2014 check here before finishing.",
5640
+ args: {}
5641
+ });
5642
+ registerSchema({
5643
+ command: "ads.linkedin.draft.remove",
5644
+ description: "Drop one staged LinkedIn op from this chat's draft. Removing a create cascades to every op that depends on it (a campaign removal drops its staged creatives).",
5645
+ args: {
5646
+ ref: {
5647
+ type: "positional",
5648
+ description: "Op ref (li_temp_* for creates, target id/URN for updates)",
5649
+ required: true
5650
+ }
5651
+ }
5652
+ });
5653
+ registerSchema({
5654
+ command: "ads.linkedin.draft.clear",
5655
+ description: "Discard ALL staged LinkedIn ops in this chat's draft. Nothing applies on publish.",
5656
+ args: {}
5657
+ });
4827
5658
 
4828
5659
  // src/commands/ads/linkedin/account.ts
4829
5660
  import { defineCommand as defineCommand30 } from "citty";
@@ -5678,55 +6509,779 @@ Examples:
5678
6509
  });
5679
6510
 
5680
6511
  // src/commands/ads/linkedin/campaign-groups.ts
5681
- import { defineCommand as defineCommand36 } from "citty";
5682
- var campaignGroupsCommand = defineCommand36({
5683
- meta: {
5684
- name: "campaign-groups",
5685
- description: `List LinkedIn campaign groups.
6512
+ import { defineCommand as defineCommand37 } from "citty";
5686
6513
 
5687
- Default: ACTIVE only. Pass --all-statuses to widen, or --statuses ACTIVE,PAUSED to override.
6514
+ // src/commands/ads/linkedin/write-commands.ts
6515
+ import { defineCommand as defineCommand36 } from "citty";
5688
6516
 
5689
- Examples:
5690
- baker ads linkedin campaign-groups --account-id 503001492
5691
- baker ads linkedin campaign-groups --account-id 503001492 --all-statuses
5692
- baker ads linkedin campaign-groups --account-id 503001492 --statuses ACTIVE,PAUSED --output csv`
5693
- },
5694
- args: {
5695
- "account-id": { type: "string", description: "Numeric account ID or urn:li:sponsoredAccount:N" },
5696
- "account-urn": { type: "string", description: "Alias for --account-id" },
5697
- "all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
5698
- statuses: { type: "string", description: "CSV of statuses (ACTIVE,PAUSED,ARCHIVED,COMPLETED,DRAFT)" },
5699
- limit: { type: "string", description: "Max rows (default: 500)" },
5700
- "skip-cache": { type: "boolean", description: "Bypass server-side cache" },
5701
- output: { type: "string", description: "json|csv|jsonl|md", default: "json" }
5702
- },
5703
- run: async ({ args }) => {
5704
- const accountId = resolveAccountIdArg(args);
5705
- try {
5706
- const params = { "account-id": accountId };
5707
- const statuses = resolveStatusFilter(args);
5708
- if (statuses) params.statuses = statuses.join(",");
5709
- if (args.limit) params.limit = String(args.limit);
5710
- if (args["skip-cache"]) params["skip-cache"] = "true";
5711
- const data = await apiGet("/api/ads/linkedin/campaign-groups", params);
5712
- const fmt = csvOrJson(args);
5713
- if (fmt !== "json") {
5714
- writeAdsOutput(data, fmt);
5715
- return;
5716
- }
5717
- writeAdsJson({ ok: true, data });
5718
- } catch (err) {
5719
- handleLinkedinError(err);
5720
- }
6517
+ // src/commands/ads/linkedin/write-shared.ts
6518
+ import { createHash as createHash2 } from "crypto";
6519
+ import { readFileSync as readFileSync6 } from "fs";
6520
+ function bareAccountId(args) {
6521
+ const raw = resolveAccountIdArg(args);
6522
+ return raw.replace(/^urn:li:sponsoredAccount:/, "").replace(/^sponsoredAccount:/, "");
6523
+ }
6524
+ function failWriteValidation(message) {
6525
+ writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
6526
+ process.exit(1);
6527
+ }
6528
+ function loadJsonFileArg(path11) {
6529
+ if (typeof path11 !== "string" || path11.length === 0) {
6530
+ return {};
6531
+ }
6532
+ try {
6533
+ const parsed = JSON.parse(readFileSync6(path11, "utf8"));
6534
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
6535
+ failWriteValidation(`${path11} must contain a JSON object`);
6536
+ }
6537
+ return parsed;
6538
+ } catch (err) {
6539
+ if (err instanceof SyntaxError) {
6540
+ failWriteValidation(`${path11} is not valid JSON: ${err.message}`);
6541
+ }
6542
+ throw err;
6543
+ }
6544
+ }
6545
+ function mergePayload(file, flags) {
6546
+ const merged = { ...file };
6547
+ for (const [key, value] of Object.entries(flags)) {
6548
+ if (value !== void 0) {
6549
+ merged[key] = value;
6550
+ }
6551
+ }
6552
+ return merged;
6553
+ }
6554
+ function parseMoneyFlag(amount, currency, flag) {
6555
+ if (amount === void 0 || amount === null || amount === "") {
6556
+ return void 0;
6557
+ }
6558
+ if (typeof currency !== "string" || currency.length !== 3) {
6559
+ failWriteValidation(`${flag} needs --currency (3-letter code matching the ad account, e.g. EUR)`);
6560
+ }
6561
+ return { amount: String(amount), currencyCode: currency.toUpperCase() };
6562
+ }
6563
+ function parseDateFlag(value, flag) {
6564
+ if (value === void 0 || value === null || value === "") {
6565
+ return void 0;
6566
+ }
6567
+ const raw = String(value);
6568
+ if (/^\d{10,}$/.test(raw)) {
6569
+ return Number(raw);
6570
+ }
6571
+ const parsed = Date.parse(raw);
6572
+ if (Number.isNaN(parsed)) {
6573
+ failWriteValidation(`${flag} must be an ISO date (2026-07-10) or epoch milliseconds`);
6574
+ }
6575
+ return parsed;
6576
+ }
6577
+ function parseOnOffFlag(value, flag) {
6578
+ if (value === void 0 || value === null || value === "") {
6579
+ return void 0;
6580
+ }
6581
+ const raw = String(value).toLowerCase();
6582
+ if (raw === "on" || raw === "true") {
6583
+ return true;
6584
+ }
6585
+ if (raw === "off" || raw === "false") {
6586
+ return false;
6587
+ }
6588
+ failWriteValidation(`${flag} must be on|off`);
6589
+ }
6590
+ function parseLocaleFlag(value) {
6591
+ if (value === void 0 || value === null || value === "") {
6592
+ return void 0;
6593
+ }
6594
+ const match = /^([a-z]{2})[_-]([A-Za-z]{2})$/.exec(String(value));
6595
+ if (!match) {
6596
+ failWriteValidation("--locale must look like en_US (language_COUNTRY)");
6597
+ }
6598
+ return { language: match[1], country: match[2].toUpperCase() };
6599
+ }
6600
+ function loadTargetingFileArg(path11) {
6601
+ if (typeof path11 !== "string" || path11.length === 0) {
6602
+ return void 0;
6603
+ }
6604
+ const parsed = loadJsonFileArg(path11);
6605
+ const criteria = parsed.targetingCriteria ?? parsed;
6606
+ if (!criteria.include) {
6607
+ failWriteValidation(
6608
+ `${path11} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
6609
+ );
6610
+ }
6611
+ return criteria;
6612
+ }
6613
+ function sha256Lower(value) {
6614
+ return createHash2("sha256").update(value.trim().toLowerCase()).digest("hex");
6615
+ }
6616
+ function parseCsvLine(line) {
6617
+ const cells = [];
6618
+ let current = "";
6619
+ let inQuotes = false;
6620
+ for (let i = 0; i < line.length; i++) {
6621
+ const char = line[i];
6622
+ if (inQuotes) {
6623
+ if (char === '"' && line[i + 1] === '"') {
6624
+ current += '"';
6625
+ i++;
6626
+ } else if (char === '"') {
6627
+ inQuotes = false;
6628
+ } else {
6629
+ current += char;
6630
+ }
6631
+ } else if (char === '"') {
6632
+ inQuotes = true;
6633
+ } else if (char === ",") {
6634
+ cells.push(current);
6635
+ current = "";
6636
+ } else {
6637
+ current += char;
6638
+ }
6639
+ }
6640
+ cells.push(current);
6641
+ return cells.map((cell) => cell.trim());
6642
+ }
6643
+ function parseListFileArg(path11, maxRows) {
6644
+ if (typeof path11 !== "string" || path11.length === 0) {
6645
+ return void 0;
6646
+ }
6647
+ const raw = readFileSync6(path11, "utf8");
6648
+ const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
6649
+ if (lines.length < 2) {
6650
+ failWriteValidation(`${path11} needs a header row and at least one data row`);
6651
+ }
6652
+ const columns = parseCsvLine(lines[0]).map((column) => column.trim());
6653
+ const rows = [];
6654
+ for (const line of lines.slice(1)) {
6655
+ const cells = parseCsvLine(line);
6656
+ const row = {};
6657
+ columns.forEach((column, index) => {
6658
+ const value = cells[index] ?? "";
6659
+ if (!value) {
6660
+ return;
6661
+ }
6662
+ row[column] = column.toLowerCase() === "email" ? sha256Lower(value) : value;
6663
+ });
6664
+ if (Object.keys(row).length > 0) {
6665
+ rows.push(row);
6666
+ }
6667
+ }
6668
+ if (rows.length > maxRows) {
6669
+ failWriteValidation(`${path11} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
6670
+ }
6671
+ return { columns, rows };
6672
+ }
6673
+ async function stageOp(raw) {
6674
+ const preflight = linkedinDraftOpInputSchema.safeParse(raw);
6675
+ if (!preflight.success) {
6676
+ const fields = preflight.error.issues.map((issue) => ({
6677
+ path: issue.path.join("."),
6678
+ message: issue.message
6679
+ }));
6680
+ writeJsonEnvelope({
6681
+ ok: false,
6682
+ error: {
6683
+ code: "VALIDATION_ERROR",
6684
+ message: fields.map((field) => field.path ? `${field.path}: ${field.message}` : field.message).join("; "),
6685
+ fields
6686
+ }
6687
+ });
6688
+ process.exit(1);
6689
+ }
6690
+ try {
6691
+ const chatId = requireChatId();
6692
+ const response = await apiPost("/api/ads/linkedin/draft/stage", {
6693
+ chatId,
6694
+ op: preflight.data
6695
+ });
6696
+ writeJsonEnvelope(response);
6697
+ } catch (err) {
6698
+ handleLinkedinError(err);
6699
+ }
6700
+ }
6701
+ async function stageStatusChange(input) {
6702
+ const payload = input.kind === "creative.update" ? { intendedStatus: input.status } : { status: input.status };
6703
+ await stageOp({ kind: input.kind, accountId: input.accountId, target: input.target, payload });
6704
+ }
6705
+ function requireTarget(args, entity) {
6706
+ const target = args.id ?? args.target;
6707
+ if (typeof target !== "string" || target.length === 0) {
6708
+ failWriteValidation(`pass the ${entity} id or URN as the positional argument`);
6709
+ }
6710
+ return target;
6711
+ }
6712
+
6713
+ // src/commands/ads/linkedin/write-commands.ts
6714
+ var STAGED_NOTE = "Staged until publish \u2014 review with `baker ads linkedin draft`.";
6715
+ var accountArgs = {
6716
+ "account-id": { type: "string", description: "Numeric account ID or urn:li:sponsoredAccount:N" },
6717
+ "account-urn": { type: "string", description: "Alias for --account-id" }
6718
+ };
6719
+ function runScheduleFromFlags(args) {
6720
+ const start = parseDateFlag(args.start, "--start");
6721
+ const end = parseDateFlag(args.end, "--end");
6722
+ if (start === void 0 && end === void 0) {
6723
+ return void 0;
6724
+ }
6725
+ return { ...start !== void 0 ? { start } : {}, ...end !== void 0 ? { end } : {} };
6726
+ }
6727
+ var campaignGroupsCreateCommand = defineCommand36({
6728
+ meta: {
6729
+ name: "create",
6730
+ description: `Stage a new campaign group. ${STAGED_NOTE}
6731
+ Example: baker ads linkedin campaign-groups create --name "Q3 ABM" --start 2026-07-10 --total-budget 5000 --currency EUR`
6732
+ },
6733
+ args: {
6734
+ ...accountArgs,
6735
+ name: { type: "string", description: "Campaign group name (\u2264100 chars)" },
6736
+ start: { type: "string", description: "Run schedule start (ISO date or epoch ms)" },
6737
+ end: { type: "string", description: "Run schedule end" },
6738
+ "total-budget": { type: "string", description: "Lifetime budget amount" },
6739
+ currency: { type: "string", description: "3-letter currency code (required with money flags)" },
6740
+ status: { type: "string", description: "DRAFT|ACTIVE|PAUSED (default DRAFT)" },
6741
+ file: { type: "string", description: "JSON file with the full payload; flags override file keys" }
6742
+ },
6743
+ run: async ({ args }) => {
6744
+ const accountId = bareAccountId(args);
6745
+ const payload = mergePayload(loadJsonFileArg(args.file), {
6746
+ name: args.name,
6747
+ runSchedule: runScheduleFromFlags(args),
6748
+ totalBudget: parseMoneyFlag(args["total-budget"], args.currency, "--total-budget"),
6749
+ status: args.status ? String(args.status).toUpperCase() : void 0
6750
+ });
6751
+ await stageOp({ kind: "campaignGroup.create", accountId, payload });
6752
+ }
6753
+ });
6754
+ var campaignGroupsUpdateCommand = defineCommand36({
6755
+ meta: {
6756
+ name: "update",
6757
+ description: `Stage changes to an existing campaign group. ${STAGED_NOTE}
6758
+ Example: baker ads linkedin campaign-groups update 635137195 --total-budget 8000 --currency EUR`
6759
+ },
6760
+ args: {
6761
+ id: { type: "positional", description: "Campaign group id or URN", required: true },
6762
+ ...accountArgs,
6763
+ name: { type: "string", description: "New name" },
6764
+ start: { type: "string", description: "New run schedule start" },
6765
+ end: { type: "string", description: "New run schedule end" },
6766
+ "total-budget": { type: "string", description: "New lifetime budget" },
6767
+ currency: { type: "string", description: "3-letter currency code" },
6768
+ status: { type: "string", description: "ACTIVE|PAUSED|ARCHIVED|\u2026" },
6769
+ file: { type: "string", description: "JSON file with fields to change" }
6770
+ },
6771
+ run: async ({ args }) => {
6772
+ const accountId = bareAccountId(args);
6773
+ const payload = mergePayload(loadJsonFileArg(args.file), {
6774
+ name: args.name,
6775
+ runSchedule: runScheduleFromFlags(args),
6776
+ totalBudget: parseMoneyFlag(args["total-budget"], args.currency, "--total-budget"),
6777
+ status: args.status ? String(args.status).toUpperCase() : void 0
6778
+ });
6779
+ await stageOp({
6780
+ kind: "campaignGroup.update",
6781
+ accountId,
6782
+ target: requireTarget(args, "campaign group"),
6783
+ payload
6784
+ });
6785
+ }
6786
+ });
6787
+ function campaignPayloadFromFlags(args) {
6788
+ return {
6789
+ name: args.name,
6790
+ campaignGroup: args.group,
6791
+ type: args.type ? String(args.type).toUpperCase() : void 0,
6792
+ objectiveType: args.objective ? String(args.objective).toUpperCase() : void 0,
6793
+ costType: args["cost-type"] ? String(args["cost-type"]).toUpperCase() : void 0,
6794
+ unitCost: parseMoneyFlag(args.bid, args.currency, "--bid"),
6795
+ dailyBudget: parseMoneyFlag(args["daily-budget"], args.currency, "--daily-budget"),
6796
+ totalBudget: parseMoneyFlag(args["total-budget"], args.currency, "--total-budget"),
6797
+ runSchedule: runScheduleFromFlags(args),
6798
+ locale: parseLocaleFlag(args.locale),
6799
+ targetingCriteria: loadTargetingFileArg(args["targeting-file"]),
6800
+ audienceExpansionEnabled: parseOnOffFlag(args["audience-expansion"], "--audience-expansion"),
6801
+ offsiteDeliveryEnabled: parseOnOffFlag(args.lan, "--lan"),
6802
+ connectedTelevisionOnly: parseOnOffFlag(args.ctv, "--ctv"),
6803
+ creativeSelection: args["creative-selection"] ? String(args["creative-selection"]).toUpperCase() : void 0,
6804
+ associatedEntity: args["associated-entity"],
6805
+ status: args.status ? String(args.status).toUpperCase() : void 0
6806
+ };
6807
+ }
6808
+ var campaignFlagArgs = {
6809
+ ...accountArgs,
6810
+ name: { type: "string", description: "Campaign name (\u2264255 chars)" },
6811
+ group: { type: "string", description: "Campaign group id/URN, or li_temp_* ref staged in this chat" },
6812
+ type: { type: "string", description: "SPONSORED_UPDATES|TEXT_AD|SPONSORED_INMAILS|DYNAMIC" },
6813
+ objective: { type: "string", description: "e.g. LEAD_GENERATION, WEBSITE_VISIT, BRAND_AWARENESS" },
6814
+ "cost-type": { type: "string", description: "CPC|CPM|CPV" },
6815
+ bid: { type: "string", description: "Manual bid (unitCost) \u2014 playbook mandates manual bidding" },
6816
+ "daily-budget": { type: "string", description: "Daily budget amount" },
6817
+ "total-budget": { type: "string", description: "Lifetime budget amount" },
6818
+ currency: { type: "string", description: "3-letter currency code (required with money flags)" },
6819
+ start: { type: "string", description: "Run schedule start (ISO date or epoch ms)" },
6820
+ end: { type: "string", description: "Run schedule end" },
6821
+ locale: { type: "string", description: "Profile locale like en_US" },
6822
+ "targeting-file": { type: "string", description: "JSON file with targetingCriteria (include.and[].or facets)" },
6823
+ "audience-expansion": { type: "string", description: "on|off (playbook: off)" },
6824
+ lan: { type: "string", description: "LinkedIn Audience Network on|off (playbook: off)" },
6825
+ ctv: { type: "string", description: "Connected TV on|off" },
6826
+ "creative-selection": { type: "string", description: "OPTIMIZED|ROUND_ROBIN" },
6827
+ "associated-entity": { type: "string", description: "Organization URN" },
6828
+ status: { type: "string", description: "DRAFT|ACTIVE|PAUSED" },
6829
+ file: { type: "string", description: "JSON file with the full payload; flags override file keys" }
6830
+ };
6831
+ var campaignsCreateCommand = defineCommand36({
6832
+ meta: {
6833
+ name: "create",
6834
+ description: `Stage a new campaign. ${STAGED_NOTE}
6835
+ Targeting goes in --targeting-file (facet URNs). --group accepts a li_temp_* ref from a campaign group staged in this chat.
6836
+ Example: baker ads linkedin campaigns create --name "ABM Tier-1" --group li_temp_x1 --objective WEBSITE_VISIT --type SPONSORED_UPDATES --cost-type CPC --bid 8.50 --daily-budget 75 --currency EUR --locale en_US --targeting-file targeting.json`
6837
+ },
6838
+ args: campaignFlagArgs,
6839
+ run: async ({ args }) => {
6840
+ const accountId = bareAccountId(args);
6841
+ const payload = mergePayload(loadJsonFileArg(args.file), campaignPayloadFromFlags(args));
6842
+ if (payload.locale === void 0) {
6843
+ payload.locale = { country: "US", language: "en" };
6844
+ }
6845
+ await stageOp({ kind: "campaign.create", accountId, payload });
6846
+ }
6847
+ });
6848
+ var campaignsUpdateCommand = defineCommand36({
6849
+ meta: {
6850
+ name: "update",
6851
+ description: `Stage changes to an existing campaign (budget, bid, targeting, flags, schedule, status). ${STAGED_NOTE}
6852
+ Example: baker ads linkedin campaigns update 123456 --daily-budget 100 --currency EUR --audience-expansion off`
6853
+ },
6854
+ args: {
6855
+ id: { type: "positional", description: "Campaign id or URN", required: true },
6856
+ ...campaignFlagArgs
6857
+ },
6858
+ run: async ({ args }) => {
6859
+ const accountId = bareAccountId(args);
6860
+ const flags = campaignPayloadFromFlags(args);
6861
+ flags.campaignGroup = void 0;
6862
+ flags.type = void 0;
6863
+ flags.locale = void 0;
6864
+ flags.associatedEntity = void 0;
6865
+ const payload = mergePayload(loadJsonFileArg(args.file), flags);
6866
+ await stageOp({
6867
+ kind: "campaign.update",
6868
+ accountId,
6869
+ target: requireTarget(args, "campaign"),
6870
+ payload
6871
+ });
6872
+ }
6873
+ });
6874
+ function statusSugarCommand(entity, kind, name) {
6875
+ const status = name === "pause" ? "PAUSED" : name === "resume" ? "ACTIVE" : "ARCHIVED";
6876
+ return defineCommand36({
6877
+ meta: {
6878
+ name,
6879
+ description: `Stage a status change to ${status}. ${STAGED_NOTE}
6880
+ Example: baker ads linkedin ${entity} ${name} 123456`
6881
+ },
6882
+ args: {
6883
+ id: { type: "positional", description: "Entity id or URN", required: true },
6884
+ ...accountArgs
6885
+ },
6886
+ run: async ({ args }) => {
6887
+ await stageStatusChange({
6888
+ kind,
6889
+ accountId: bareAccountId(args),
6890
+ target: requireTarget(args, entity.replace(/-/g, " ").replace(/s$/, "")),
6891
+ status
6892
+ });
6893
+ }
6894
+ });
6895
+ }
6896
+ var campaignsPauseCommand = statusSugarCommand("campaigns", "campaign.update", "pause");
6897
+ var campaignsResumeCommand = statusSugarCommand("campaigns", "campaign.update", "resume");
6898
+ var campaignsArchiveCommand = statusSugarCommand("campaigns", "campaign.update", "archive");
6899
+ var campaignGroupsPauseCommand = statusSugarCommand("campaign-groups", "campaignGroup.update", "pause");
6900
+ var campaignGroupsResumeCommand = statusSugarCommand("campaign-groups", "campaignGroup.update", "resume");
6901
+ var creativesPauseCommand = statusSugarCommand("creatives", "creative.update", "pause");
6902
+ var creativesResumeCommand = statusSugarCommand("creatives", "creative.update", "resume");
6903
+ function duplicateCommand(entity, cliGroup) {
6904
+ return defineCommand36({
6905
+ meta: {
6906
+ name: "duplicate",
6907
+ description: `Stage a copy of an existing ${entity} as a new DRAFT create (playbook: duplicate, never link-to-original). ${STAGED_NOTE}
6908
+ Example: baker ads linkedin ${cliGroup} duplicate 123456 --name "New variant"`
6909
+ },
6910
+ args: {
6911
+ id: { type: "positional", description: "Source id or URN", required: true },
6912
+ ...accountArgs,
6913
+ name: { type: "string", description: "Name for the copy" },
6914
+ file: { type: "string", description: "JSON file with field overrides for the copy" }
6915
+ },
6916
+ run: async ({ args }) => {
6917
+ try {
6918
+ const chatId = requireChatId();
6919
+ const overrides = mergePayload(loadJsonFileArg(args.file), { name: args.name });
6920
+ const response = await apiPost(
6921
+ "/api/ads/linkedin/draft/duplicate",
6922
+ {
6923
+ chatId,
6924
+ accountId: bareAccountId(args),
6925
+ entity,
6926
+ sourceId: requireTarget(args, entity),
6927
+ ...Object.keys(overrides).length > 0 ? { overrides } : {}
6928
+ }
6929
+ );
6930
+ writeJsonEnvelope(response);
6931
+ } catch (err) {
6932
+ handleLinkedinError(err);
6933
+ }
6934
+ }
6935
+ });
6936
+ }
6937
+ var campaignsDuplicateCommand = duplicateCommand("campaign", "campaigns");
6938
+ var campaignGroupsDuplicateCommand = duplicateCommand("campaignGroup", "campaign-groups");
6939
+ var creativesDuplicateCommand = duplicateCommand("creative", "creatives");
6940
+ var CREATIVE_FORMATS = [
6941
+ "image",
6942
+ "video",
6943
+ "text",
6944
+ "spotlight",
6945
+ "follower",
6946
+ "document",
6947
+ "carousel",
6948
+ "conversation",
6949
+ "tla",
6950
+ "jobs"
6951
+ ];
6952
+ var creativesCreateCommand = defineCommand36({
6953
+ meta: {
6954
+ name: "create",
6955
+ description: `Stage a new creative (ad). ${STAGED_NOTE}
6956
+ Formats: ${CREATIVE_FORMATS.join("|")}. Media comes from the Baker library (--image-id / --video-id from \`baker images\`/\`baker videos\`) or as LinkedIn URNs. Complex formats (carousel, conversation, jobs) take --file with the full content object.
6957
+ Examples:
6958
+ baker ads linkedin creatives create --campaign li_temp_x2 --format image --image-id <bakerImageId> --intro "Meet the platform\u2026" --headline "Book a demo" --landing-url https://example.com/demo --cta REQUEST_DEMO
6959
+ baker ads linkedin creatives create --campaign 123456 --format tla --post-urn urn:li:ugcPost:789`
6960
+ },
6961
+ args: {
6962
+ ...accountArgs,
6963
+ campaign: { type: "string", description: "Campaign id/URN, or li_temp_* ref staged in this chat" },
6964
+ format: { type: "string", description: CREATIVE_FORMATS.join("|") },
6965
+ "image-id": { type: "string", description: "Baker image library id (uploaded to LinkedIn at publish)" },
6966
+ "image-urn": { type: "string", description: "Existing urn:li:image:*" },
6967
+ "video-id": { type: "string", description: "Baker video library id" },
6968
+ "video-urn": { type: "string", description: "Existing urn:li:video:*" },
6969
+ "logo-image-id": { type: "string", description: "Baker image id for logo (text/spotlight/follower/jobs)" },
6970
+ intro: { type: "string", description: "Commentary / intro text (\u2264600 chars before feed truncation)" },
6971
+ headline: { type: "string", description: "Headline (\u226470; text ads \u226425)" },
6972
+ description: { type: "string", description: "Description (text ads \u226475, spotlight \u226470)" },
6973
+ "landing-url": { type: "string", description: "https destination URL" },
6974
+ cta: { type: "string", description: "LEARN_MORE|REQUEST_DEMO|SIGN_UP|REGISTER|DOWNLOAD|\u2026" },
6975
+ "cta-label": { type: "string", description: "Spotlight custom CTA label (\u226418 chars)" },
6976
+ "post-urn": { type: "string", description: "TLA: existing post to sponsor (urn:li:share|ugcPost:*)" },
6977
+ "intended-status": { type: "string", description: "DRAFT|ACTIVE|PAUSED (default DRAFT)" },
6978
+ title: { type: "string", description: "Media title" },
6979
+ file: { type: "string", description: "JSON file with the full content object; flags override" }
6980
+ },
6981
+ run: async ({ args }) => {
6982
+ const accountId = bareAccountId(args);
6983
+ if (!args.campaign) {
6984
+ failWriteValidation("--campaign is required (id, URN, or li_temp_* ref)");
6985
+ }
6986
+ const format = args.format ? String(args.format) : void 0;
6987
+ if (!format || !CREATIVE_FORMATS.includes(format)) {
6988
+ failWriteValidation(`--format must be one of ${CREATIVE_FORMATS.join("|")}`);
6989
+ }
6990
+ const content = mergePayload(loadJsonFileArg(args.file), {
6991
+ format,
6992
+ commentary: args.intro,
6993
+ imageId: args["image-id"],
6994
+ imageUrn: args["image-urn"],
6995
+ videoId: args["video-id"],
6996
+ videoUrn: args["video-urn"],
6997
+ logoImageId: args["logo-image-id"],
6998
+ headline: args.headline,
6999
+ description: args.description,
7000
+ landingUrl: args["landing-url"],
7001
+ cta: args.cta ? String(args.cta).toUpperCase() : void 0,
7002
+ ctaLabel: args["cta-label"],
7003
+ postUrn: args["post-urn"],
7004
+ mediaTitle: args.title
7005
+ });
7006
+ await stageOp({
7007
+ kind: "creative.create",
7008
+ accountId,
7009
+ payload: {
7010
+ campaign: args.campaign,
7011
+ intendedStatus: args["intended-status"] ? String(args["intended-status"]).toUpperCase() : void 0,
7012
+ content
7013
+ }
7014
+ });
7015
+ }
7016
+ });
7017
+ var creativesUpdateCommand = defineCommand36({
7018
+ meta: {
7019
+ name: "update",
7020
+ description: `Stage changes to an existing creative. ${STAGED_NOTE}
7021
+ Example: baker ads linkedin creatives update urn:li:sponsoredCreative:789 --intended-status PAUSED`
7022
+ },
7023
+ args: {
7024
+ id: { type: "positional", description: "Creative id or URN", required: true },
7025
+ ...accountArgs,
7026
+ "intended-status": { type: "string", description: "ACTIVE|PAUSED|ARCHIVED|DRAFT" },
7027
+ name: { type: "string", description: "New creative name" },
7028
+ file: { type: "string", description: "JSON file with fields to change" }
7029
+ },
7030
+ run: async ({ args }) => {
7031
+ const accountId = bareAccountId(args);
7032
+ const payload = mergePayload(loadJsonFileArg(args.file), {
7033
+ intendedStatus: args["intended-status"] ? String(args["intended-status"]).toUpperCase() : void 0,
7034
+ name: args.name
7035
+ });
7036
+ await stageOp({
7037
+ kind: "creative.update",
7038
+ accountId,
7039
+ target: requireTarget(args, "creative"),
7040
+ payload
7041
+ });
7042
+ }
7043
+ });
7044
+ var AUDIENCE_TYPES2 = ["company-list", "user-list", "retargeting", "engagement"];
7045
+ var INLINE_ROWS_MAX = 1e4;
7046
+ var audiencesCreateCommand = defineCommand36({
7047
+ meta: {
7048
+ name: "create",
7049
+ description: `Stage a new matched audience. ${STAGED_NOTE}
7050
+ List audiences take --list-file (CSV: companyName,domain for companies; email,\u2026 for contacts \u2014 emails are SHA-256 hashed locally). LinkedIn needs 300+ MATCHED members to serve.
7051
+ Example: baker ads linkedin audiences create --name "ABM Tier-1" --type company-list --list-file accounts.csv`
7052
+ },
7053
+ args: {
7054
+ ...accountArgs,
7055
+ name: { type: "string", description: "Audience name (\u2264100 chars)" },
7056
+ type: { type: "string", description: AUDIENCE_TYPES2.join("|") },
7057
+ "list-file": { type: "string", description: "CSV file with the list rows (header row required)" },
7058
+ file: { type: "string", description: "JSON file with a raw source config (retargeting/engagement)" }
7059
+ },
7060
+ run: async ({ args }) => {
7061
+ const accountId = bareAccountId(args);
7062
+ const list = parseListFileArg(args["list-file"], INLINE_ROWS_MAX);
7063
+ const raw = args.file ? loadJsonFileArg(args.file) : void 0;
7064
+ await stageOp({
7065
+ kind: "audience.create",
7066
+ accountId,
7067
+ payload: {
7068
+ name: args.name,
7069
+ audienceType: args.type,
7070
+ ...list ? { listColumns: list.columns, listRows: list.rows } : {},
7071
+ ...raw ? { raw } : {}
7072
+ }
7073
+ });
7074
+ }
7075
+ });
7076
+ var audiencesUploadCommand = defineCommand36({
7077
+ meta: {
7078
+ name: "upload",
7079
+ description: `Stage a list upload into an existing audience segment. ${STAGED_NOTE}
7080
+ Example: baker ads linkedin audiences upload urn:li:dmpSegment:42 --list-file more-accounts.csv`
7081
+ },
7082
+ args: {
7083
+ id: { type: "positional", description: "Segment URN/id, or li_temp_* ref staged in this chat", required: true },
7084
+ ...accountArgs,
7085
+ "list-file": { type: "string", description: "CSV file with the rows to add", required: true }
7086
+ },
7087
+ run: async ({ args }) => {
7088
+ const accountId = bareAccountId(args);
7089
+ const list = parseListFileArg(args["list-file"], INLINE_ROWS_MAX);
7090
+ if (!list) {
7091
+ failWriteValidation("--list-file is required");
7092
+ }
7093
+ await stageOp({
7094
+ kind: "audience.uploadList",
7095
+ accountId,
7096
+ payload: {
7097
+ segment: requireTarget(args, "audience segment"),
7098
+ listColumns: list.columns,
7099
+ listRows: list.rows
7100
+ }
7101
+ });
7102
+ }
7103
+ });
7104
+ var audiencesCommand = defineCommand36({
7105
+ meta: {
7106
+ name: "audiences",
7107
+ description: "Stage LinkedIn matched-audience changes (create lists, upload rows). Staged until publish \u2014 never hits the API directly."
7108
+ },
7109
+ subCommands: {
7110
+ create: audiencesCreateCommand,
7111
+ upload: audiencesUploadCommand
7112
+ }
7113
+ });
7114
+ var conversionsCreateCommand = defineCommand36({
7115
+ meta: {
7116
+ name: "create",
7117
+ description: `Stage a new conversion rule. ${STAGED_NOTE}
7118
+ Example: baker ads linkedin conversions create --name "Demo booked" --type LEAD --method INSIGHT_TAG --post-click-window 30 --view-window 7`
7119
+ },
7120
+ args: {
7121
+ ...accountArgs,
7122
+ name: { type: "string", description: "Conversion rule name" },
7123
+ type: { type: "string", description: "LEAD|SIGN_UP|DOWNLOAD|PURCHASE|KEY_PAGE_VIEW|ADD_TO_CART|INSTALL|OTHER" },
7124
+ method: { type: "string", description: "INSIGHT_TAG|CONVERSIONS_API" },
7125
+ "post-click-window": { type: "string", description: "1|7|30|90 days (playbook default 30)" },
7126
+ "view-window": { type: "string", description: "1|7|30 days (playbook default 7)" },
7127
+ "attribution-type": { type: "string", description: "LAST_TOUCH_BY_CAMPAIGN|LAST_TOUCH_BY_CONVERSION" },
7128
+ "associate-all-campaigns": { type: "boolean", description: "Auto-associate with active campaigns" },
7129
+ file: { type: "string", description: "JSON file with the full payload (e.g. urlMatchRuleExpression)" }
7130
+ },
7131
+ run: async ({ args }) => {
7132
+ const accountId = bareAccountId(args);
7133
+ const payload = mergePayload(loadJsonFileArg(args.file), {
7134
+ name: args.name,
7135
+ type: args.type ? String(args.type).toUpperCase() : void 0,
7136
+ conversionMethod: args.method ? String(args.method).toUpperCase() : void 0,
7137
+ postClickAttributionWindowSize: args["post-click-window"] ? Number(args["post-click-window"]) : void 0,
7138
+ viewThroughAttributionWindowSize: args["view-window"] ? Number(args["view-window"]) : void 0,
7139
+ attributionType: args["attribution-type"] ? String(args["attribution-type"]).toUpperCase() : void 0,
7140
+ associateAllCampaigns: args["associate-all-campaigns"] === true ? true : void 0
7141
+ });
7142
+ await stageOp({ kind: "conversion.create", accountId, payload });
7143
+ }
7144
+ });
7145
+ var conversionsUpdateCommand = defineCommand36({
7146
+ meta: {
7147
+ name: "update",
7148
+ description: `Stage changes to a conversion rule (windows, name, enabled). ${STAGED_NOTE}
7149
+ Example: baker ads linkedin conversions update 104988516 --post-click-window 30 --view-window 7`
7150
+ },
7151
+ args: {
7152
+ id: { type: "positional", description: "Conversion rule id or URN", required: true },
7153
+ ...accountArgs,
7154
+ name: { type: "string", description: "New name" },
7155
+ "post-click-window": { type: "string", description: "1|7|30|90 days" },
7156
+ "view-window": { type: "string", description: "1|7|30 days" },
7157
+ "attribution-type": { type: "string", description: "LAST_TOUCH_BY_CAMPAIGN|LAST_TOUCH_BY_CONVERSION" },
7158
+ enabled: { type: "string", description: "on|off" },
7159
+ file: { type: "string", description: "JSON file with fields to change" }
7160
+ },
7161
+ run: async ({ args }) => {
7162
+ const accountId = bareAccountId(args);
7163
+ const payload = mergePayload(loadJsonFileArg(args.file), {
7164
+ name: args.name,
7165
+ postClickAttributionWindowSize: args["post-click-window"] ? Number(args["post-click-window"]) : void 0,
7166
+ viewThroughAttributionWindowSize: args["view-window"] ? Number(args["view-window"]) : void 0,
7167
+ attributionType: args["attribution-type"] ? String(args["attribution-type"]).toUpperCase() : void 0,
7168
+ enabled: parseOnOffFlag(args.enabled, "--enabled")
7169
+ });
7170
+ await stageOp({
7171
+ kind: "conversion.update",
7172
+ accountId,
7173
+ target: requireTarget(args, "conversion rule"),
7174
+ payload
7175
+ });
7176
+ }
7177
+ });
7178
+ var leadFormsCreateCommand = defineCommand36({
7179
+ meta: {
7180
+ name: "create",
7181
+ description: `Stage a new Lead Gen Form from a JSON file. ${STAGED_NOTE}
7182
+ The file needs: name, headline (\u226460), privacyPolicyUrl, questions[] (\u226412; playbook: \u22644 for completion). Example: baker ads linkedin lead-forms create --file form.json`
7183
+ },
7184
+ args: {
7185
+ ...accountArgs,
7186
+ file: { type: "string", description: "JSON file with the form definition", required: true },
7187
+ name: { type: "string", description: "Override the form name" }
7188
+ },
7189
+ run: async ({ args }) => {
7190
+ const accountId = bareAccountId(args);
7191
+ const payload = mergePayload(loadJsonFileArg(args.file), { name: args.name });
7192
+ await stageOp({ kind: "leadForm.create", accountId, payload });
7193
+ }
7194
+ });
7195
+ var leadFormsUpdateCommand = defineCommand36({
7196
+ meta: {
7197
+ name: "update",
7198
+ description: `Stage changes to a Lead Gen Form from a JSON file. ${STAGED_NOTE}`
7199
+ },
7200
+ args: {
7201
+ id: { type: "positional", description: "Lead form id or URN", required: true },
7202
+ ...accountArgs,
7203
+ file: { type: "string", description: "JSON file with the fields to change", required: true },
7204
+ name: { type: "string", description: "New form name" }
7205
+ },
7206
+ run: async ({ args }) => {
7207
+ const accountId = bareAccountId(args);
7208
+ const payload = mergePayload({ raw: loadJsonFileArg(args.file) }, { name: args.name });
7209
+ await stageOp({
7210
+ kind: "leadForm.update",
7211
+ accountId,
7212
+ target: requireTarget(args, "lead form"),
7213
+ payload
7214
+ });
7215
+ }
7216
+ });
7217
+ var leadFormsCommand = defineCommand36({
7218
+ meta: {
7219
+ name: "lead-forms",
7220
+ description: "Stage LinkedIn Lead Gen Form changes (file-first). Staged until publish \u2014 never hits the API directly."
7221
+ },
7222
+ subCommands: {
7223
+ create: leadFormsCreateCommand,
7224
+ update: leadFormsUpdateCommand
7225
+ }
7226
+ });
7227
+
7228
+ // src/commands/ads/linkedin/campaign-groups.ts
7229
+ var campaignGroupsCommand = defineCommand37({
7230
+ meta: {
7231
+ name: "campaign-groups",
7232
+ description: `List LinkedIn campaign groups, or stage writes (create/update/pause/resume/duplicate).
7233
+
7234
+ Default: ACTIVE only. Pass --all-statuses to widen, or --statuses ACTIVE,PAUSED to override.
7235
+ Write subcommands stage ops on this chat's draft and apply only when the chat is published.
7236
+
7237
+ Examples:
7238
+ baker ads linkedin campaign-groups --account-id 503001492
7239
+ baker ads linkedin campaign-groups --account-id 503001492 --all-statuses
7240
+ baker ads linkedin campaign-groups create --name "Q3 ABM" --start 2026-07-10 --total-budget 5000 --currency EUR`
7241
+ },
7242
+ subCommands: {
7243
+ create: campaignGroupsCreateCommand,
7244
+ update: campaignGroupsUpdateCommand,
7245
+ pause: campaignGroupsPauseCommand,
7246
+ resume: campaignGroupsResumeCommand,
7247
+ duplicate: campaignGroupsDuplicateCommand
7248
+ },
7249
+ args: {
7250
+ "account-id": { type: "string", description: "Numeric account ID or urn:li:sponsoredAccount:N" },
7251
+ "account-urn": { type: "string", description: "Alias for --account-id" },
7252
+ "all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
7253
+ statuses: { type: "string", description: "CSV of statuses (ACTIVE,PAUSED,ARCHIVED,COMPLETED,DRAFT)" },
7254
+ limit: { type: "string", description: "Max rows (default: 500)" },
7255
+ "skip-cache": { type: "boolean", description: "Bypass server-side cache" },
7256
+ output: { type: "string", description: "json|csv|jsonl|md", default: "json" }
7257
+ },
7258
+ run: async ({ args }) => {
7259
+ const accountId = resolveAccountIdArg(args);
7260
+ try {
7261
+ const params = { "account-id": accountId };
7262
+ const statuses = resolveStatusFilter(args);
7263
+ if (statuses) params.statuses = statuses.join(",");
7264
+ if (args.limit) params.limit = String(args.limit);
7265
+ if (args["skip-cache"]) params["skip-cache"] = "true";
7266
+ const data = await apiGet("/api/ads/linkedin/campaign-groups", params);
7267
+ const fmt = csvOrJson(args);
7268
+ if (fmt !== "json") {
7269
+ writeAdsOutput(data, fmt);
7270
+ return;
7271
+ }
7272
+ writeAdsJson({ ok: true, data });
7273
+ } catch (err) {
7274
+ handleLinkedinError(err);
7275
+ }
5721
7276
  }
5722
7277
  });
5723
7278
 
5724
7279
  // src/commands/ads/linkedin/campaigns.ts
5725
- import { defineCommand as defineCommand37 } from "citty";
5726
- var campaignsCommand = defineCommand37({
7280
+ import { defineCommand as defineCommand38 } from "citty";
7281
+ var campaignsCommand = defineCommand38({
5727
7282
  meta: {
5728
7283
  name: "campaigns",
5729
- description: `List LinkedIn campaigns.
7284
+ description: `List LinkedIn campaigns, or stage writes (create/update/pause/resume/archive/duplicate).
5730
7285
 
5731
7286
  Default: ACTIVE only. The schema includes the audit-relevant settings:
5732
7287
  audienceExpansionEnabled \u2014 playbook \xA702 silent budget drain (should be false)
@@ -5734,10 +7289,22 @@ Default: ACTIVE only. The schema includes the audit-relevant settings:
5734
7289
  optimizationTargetType \u2014 driver of the bidding strategy
5735
7290
  costType \u2014 CPC | CPM | CPV | CPS
5736
7291
 
7292
+ Write subcommands stage ops on this chat's draft \u2014 they never hit the LinkedIn
7293
+ API directly and apply only when the chat is published.
7294
+
5737
7295
  Examples:
5738
7296
  baker ads linkedin campaigns --account-id 503001492
5739
- baker ads linkedin campaigns --account-id 503001492 --campaign-group-id 12345
5740
- baker ads linkedin campaigns --account-id 503001492 --all-statuses --output csv`
7297
+ baker ads linkedin campaigns --account-id 503001492 --all-statuses --output csv
7298
+ baker ads linkedin campaigns update 123456 --daily-budget 100 --currency EUR
7299
+ baker ads linkedin campaigns pause 123456`
7300
+ },
7301
+ subCommands: {
7302
+ create: campaignsCreateCommand,
7303
+ update: campaignsUpdateCommand,
7304
+ pause: campaignsPauseCommand,
7305
+ resume: campaignsResumeCommand,
7306
+ archive: campaignsArchiveCommand,
7307
+ duplicate: campaignsDuplicateCommand
5741
7308
  },
5742
7309
  args: {
5743
7310
  "account-id": { type: "string", description: "Numeric account ID or urn:li:sponsoredAccount:N" },
@@ -5772,8 +7339,8 @@ Examples:
5772
7339
  });
5773
7340
 
5774
7341
  // src/commands/ads/linkedin/conversation.ts
5775
- import { defineCommand as defineCommand38 } from "citty";
5776
- var conversationCommand = defineCommand38({
7342
+ import { defineCommand as defineCommand39 } from "citty";
7343
+ var conversationCommand = defineCommand39({
5777
7344
  meta: {
5778
7345
  name: "conversation",
5779
7346
  description: `Per-button click rates inside Sponsored Messaging / Conversation Ads.
@@ -5836,7 +7403,7 @@ Examples:
5836
7403
  });
5837
7404
 
5838
7405
  // src/commands/ads/linkedin/conversions.ts
5839
- import { defineCommand as defineCommand39 } from "citty";
7406
+ import { defineCommand as defineCommand40 } from "citty";
5840
7407
  var DAY_MS3 = 864e5;
5841
7408
  function healthOf(rules) {
5842
7409
  const enabled = rules.filter((r) => r.enabled !== false);
@@ -5862,7 +7429,7 @@ function healthOf(rules) {
5862
7429
  wrongLeadDedup: wrongDedup
5863
7430
  };
5864
7431
  }
5865
- var listCmd = defineCommand39({
7432
+ var listCmd = defineCommand40({
5866
7433
  meta: {
5867
7434
  name: "list",
5868
7435
  description: `List conversion rules on the account.`
@@ -5890,7 +7457,7 @@ var listCmd = defineCommand39({
5890
7457
  }
5891
7458
  }
5892
7459
  });
5893
- var healthCmd = defineCommand39({
7460
+ var healthCmd = defineCommand40({
5894
7461
  meta: {
5895
7462
  name: "health",
5896
7463
  description: `5-point Insight Tag / CAPI health check (playbook \xA707).
@@ -5920,27 +7487,30 @@ Surfaces:
5920
7487
  }
5921
7488
  }
5922
7489
  });
5923
- var conversionsCommand = defineCommand39({
7490
+ var conversionsCommand = defineCommand40({
5924
7491
  meta: {
5925
7492
  name: "conversions",
5926
7493
  description: `Conversion rules \u2014 Insight Tag and Conversions API.
5927
7494
 
5928
7495
  Subcommands:
5929
7496
  list \u2014 every rule on the account
5930
- health \u2014 playbook \xA707 5-point health check`
7497
+ health \u2014 playbook \xA707 5-point health check
7498
+ create / update \u2014 stage a conversion-rule write (applies on chat publish)`
5931
7499
  },
5932
7500
  subCommands: {
5933
7501
  list: listCmd,
5934
- health: healthCmd
7502
+ health: healthCmd,
7503
+ create: conversionsCreateCommand,
7504
+ update: conversionsUpdateCommand
5935
7505
  }
5936
7506
  });
5937
7507
 
5938
7508
  // src/commands/ads/linkedin/creatives.ts
5939
- import { defineCommand as defineCommand40 } from "citty";
5940
- var creativesCommand = defineCommand40({
7509
+ import { defineCommand as defineCommand41 } from "citty";
7510
+ var creativesCommand = defineCommand41({
5941
7511
  meta: {
5942
7512
  name: "creatives",
5943
- description: `List LinkedIn creatives (ads).
7513
+ description: `List LinkedIn creatives (ads), or stage writes (create/update/pause/resume/duplicate).
5944
7514
 
5945
7515
  Defaults to ACTIVE intended-status. Pass --all-statuses or --statuses ACTIVE,PAUSED to widen.
5946
7516
 
@@ -5948,10 +7518,20 @@ The 'content' block is opaque (varies by creative type \u2014 image, video, docu
5948
7518
  spotlight, conversation, dynamic). Use 'reviewStatus' to spot rejected/pending
5949
7519
  creatives during an audit.
5950
7520
 
7521
+ Write subcommands stage ops on this chat's draft \u2014 media comes from the Baker
7522
+ library and is uploaded to LinkedIn only at publish.
7523
+
5951
7524
  Examples:
5952
7525
  baker ads linkedin creatives --account-id 503001492
5953
- baker ads linkedin creatives --account-id 503001492 --campaign-id 1234
5954
- baker ads linkedin creatives --account-id 503001492 --all-statuses --output csv`
7526
+ baker ads linkedin creatives create --campaign 1234 --format image --image-id <bakerImageId> --intro "\u2026" --headline "Book a demo" --landing-url https://example.com --cta REQUEST_DEMO
7527
+ baker ads linkedin creatives pause urn:li:sponsoredCreative:789`
7528
+ },
7529
+ subCommands: {
7530
+ create: creativesCreateCommand,
7531
+ update: creativesUpdateCommand,
7532
+ pause: creativesPauseCommand,
7533
+ resume: creativesResumeCommand,
7534
+ duplicate: creativesDuplicateCommand
5955
7535
  },
5956
7536
  args: {
5957
7537
  "account-id": { type: "string", description: "Numeric account ID or urn:li:sponsoredAccount:N" },
@@ -5986,7 +7566,7 @@ Examples:
5986
7566
  });
5987
7567
 
5988
7568
  // src/commands/ads/linkedin/demographics.ts
5989
- import { defineCommand as defineCommand41 } from "citty";
7569
+ import { defineCommand as defineCommand42 } from "citty";
5990
7570
  var DEFAULT_PIVOTS = ["job-title", "company", "industry", "seniority", "job-function", "company-size"];
5991
7571
  function numberOf2(v) {
5992
7572
  if (typeof v === "number") return Number.isFinite(v) ? v : 0;
@@ -5999,7 +7579,7 @@ function numberOf2(v) {
5999
7579
  function topByImpressions(rows, limit) {
6000
7580
  return [...rows].sort((a, b) => numberOf2(b.impressions) - numberOf2(a.impressions)).slice(0, limit);
6001
7581
  }
6002
- var demographicsCommand = defineCommand41({
7582
+ var demographicsCommand = defineCommand42({
6003
7583
  meta: {
6004
7584
  name: "demographics",
6005
7585
  description: `Sweep all firmographic pivots in one command \u2014 LinkedIn's superpower.
@@ -6082,22 +7662,97 @@ Examples:
6082
7662
  }
6083
7663
  }
6084
7664
  });
6085
- function resolveRange(args) {
6086
- const start = args.start;
6087
- const end = args.end;
6088
- if (start) {
6089
- return { start, end };
6090
- }
6091
- const days = args["last-days"] ? Number(args["last-days"]) : 30;
6092
- if (!Number.isFinite(days) || days < 1) {
6093
- handleLinkedinError(new Error("Invalid --last-days; must be a positive integer."));
6094
- }
6095
- return { start: daysAgoIso(days), end: todayIso() };
6096
- }
7665
+ function resolveRange(args) {
7666
+ const start = args.start;
7667
+ const end = args.end;
7668
+ if (start) {
7669
+ return { start, end };
7670
+ }
7671
+ const days = args["last-days"] ? Number(args["last-days"]) : 30;
7672
+ if (!Number.isFinite(days) || days < 1) {
7673
+ handleLinkedinError(new Error("Invalid --last-days; must be a positive integer."));
7674
+ }
7675
+ return { start: daysAgoIso(days), end: todayIso() };
7676
+ }
7677
+
7678
+ // src/commands/ads/linkedin/draft.ts
7679
+ import { defineCommand as defineCommand43 } from "citty";
7680
+ async function listDraft() {
7681
+ try {
7682
+ const chatId = requireChatId();
7683
+ const response = await apiPost("/api/ads/linkedin/draft", {
7684
+ chatId
7685
+ });
7686
+ writeJsonEnvelope(response);
7687
+ } catch (err) {
7688
+ handleLinkedinError(err);
7689
+ }
7690
+ }
7691
+ var listCommand3 = defineCommand43({
7692
+ meta: {
7693
+ name: "list",
7694
+ description: "Show every LinkedIn write op staged in this chat, its mode (simulated = publish will NOT hit LinkedIn), dependencies, and post-publish results. Example: baker ads linkedin draft"
7695
+ },
7696
+ run: listDraft
7697
+ });
7698
+ var removeCommand2 = defineCommand43({
7699
+ meta: {
7700
+ name: "remove",
7701
+ description: "Drop one staged LinkedIn op. Removing a create cascades to everything that depends on it. Example: baker ads linkedin draft remove li_temp_abc123"
7702
+ },
7703
+ args: {
7704
+ ref: {
7705
+ type: "positional",
7706
+ description: "Op ref (li_temp_* for creates, target id/URN for updates)",
7707
+ required: true
7708
+ }
7709
+ },
7710
+ run: async ({ args }) => {
7711
+ try {
7712
+ const chatId = requireChatId();
7713
+ const response = await apiPost(
7714
+ "/api/ads/linkedin/draft/remove",
7715
+ { chatId, ref: args.ref }
7716
+ );
7717
+ writeJsonEnvelope(response);
7718
+ } catch (err) {
7719
+ handleLinkedinError(err);
7720
+ }
7721
+ }
7722
+ });
7723
+ var clearCommand2 = defineCommand43({
7724
+ meta: {
7725
+ name: "clear",
7726
+ description: "Discard ALL staged LinkedIn ops in this chat's draft \u2014 nothing will apply on publish. Example: baker ads linkedin draft clear"
7727
+ },
7728
+ run: async () => {
7729
+ try {
7730
+ const chatId = requireChatId();
7731
+ const response = await apiPost("/api/ads/linkedin/draft/clear", {
7732
+ chatId
7733
+ });
7734
+ writeJsonEnvelope(response);
7735
+ } catch (err) {
7736
+ handleLinkedinError(err);
7737
+ }
7738
+ }
7739
+ });
7740
+ var linkedinDraftCommand = defineCommand43({
7741
+ meta: {
7742
+ name: "draft",
7743
+ description: "Review and edit the LinkedIn write ops staged in this chat BEFORE publish. Subcommands: list (default), remove, clear. Ops never hit LinkedIn until the chat is published."
7744
+ },
7745
+ subCommands: {
7746
+ list: listCommand3,
7747
+ remove: removeCommand2,
7748
+ clear: clearCommand2
7749
+ },
7750
+ run: listDraft
7751
+ });
6097
7752
 
6098
7753
  // src/commands/ads/linkedin/facets.ts
6099
- import { defineCommand as defineCommand42 } from "citty";
6100
- var listCmd2 = defineCommand42({
7754
+ import { defineCommand as defineCommand44 } from "citty";
7755
+ var listCmd2 = defineCommand44({
6101
7756
  meta: {
6102
7757
  name: "list",
6103
7758
  description: `List every targeting facet LinkedIn supports.
@@ -6125,7 +7780,7 @@ seniorities, titles, employers, growthRate, companyCategory, skills, etc.).`
6125
7780
  }
6126
7781
  }
6127
7782
  });
6128
- var valuesCmd = defineCommand42({
7783
+ var valuesCmd = defineCommand44({
6129
7784
  meta: {
6130
7785
  name: "values",
6131
7786
  description: `Look up entity values for a single facet \u2014 full list or typeahead search.
@@ -6166,7 +7821,7 @@ or the full URN (urn:li:adTargetingFacet:industries).`
6166
7821
  }
6167
7822
  }
6168
7823
  });
6169
- var facetsCommand = defineCommand42({
7824
+ var facetsCommand = defineCommand44({
6170
7825
  meta: {
6171
7826
  name: "facets",
6172
7827
  description: `LinkedIn targeting facets and entity lookup.
@@ -6183,8 +7838,8 @@ Subcommands:
6183
7838
  });
6184
7839
 
6185
7840
  // src/commands/ads/linkedin/forecast.ts
6186
- import { readFileSync as readFileSync6 } from "fs";
6187
- import { defineCommand as defineCommand43 } from "citty";
7841
+ import { readFileSync as readFileSync7 } from "fs";
7842
+ import { defineCommand as defineCommand45 } from "citty";
6188
7843
  function loadTargeting3(args) {
6189
7844
  const inline = args.targeting;
6190
7845
  if (inline) {
@@ -6197,7 +7852,7 @@ function loadTargeting3(args) {
6197
7852
  const file = args["targeting-file"];
6198
7853
  if (file) {
6199
7854
  try {
6200
- return JSON.parse(readFileSync6(file, "utf-8"));
7855
+ return JSON.parse(readFileSync7(file, "utf-8"));
6201
7856
  } catch (e) {
6202
7857
  handleLinkedinError(
6203
7858
  new Error(`Failed to read --targeting-file: ${e instanceof Error ? e.message : "I/O error"}`)
@@ -6214,7 +7869,7 @@ function parseMoney(raw) {
6214
7869
  }
6215
7870
  return { amount: m[1] ?? "0", currencyCode: m[2] ?? "USD" };
6216
7871
  }
6217
- var forecastCommand = defineCommand43({
7872
+ var forecastCommand = defineCommand45({
6218
7873
  meta: {
6219
7874
  name: "forecast",
6220
7875
  description: `Forecast reach + impressions + clicks + spend for a hypothetical campaign.
@@ -6261,9 +7916,9 @@ Examples:
6261
7916
  });
6262
7917
 
6263
7918
  // src/commands/ads/linkedin/leads.ts
6264
- import { defineCommand as defineCommand44 } from "citty";
7919
+ import { defineCommand as defineCommand46 } from "citty";
6265
7920
  var DAY_MS4 = 864e5;
6266
- var leadsCommand = defineCommand44({
7921
+ var leadsCommand = defineCommand46({
6267
7922
  meta: {
6268
7923
  name: "leads",
6269
7924
  description: `List Lead Gen Form responses (playbook \xA707).
@@ -6323,7 +7978,7 @@ Examples:
6323
7978
  });
6324
7979
 
6325
7980
  // src/commands/ads/linkedin/resolve.ts
6326
- import { defineCommand as defineCommand45 } from "citty";
7981
+ import { defineCommand as defineCommand47 } from "citty";
6327
7982
  function toOrgUrn(raw) {
6328
7983
  const trimmed = raw.trim();
6329
7984
  if (trimmed.length === 0) {
@@ -6334,7 +7989,7 @@ function toOrgUrn(raw) {
6334
7989
  }
6335
7990
  return /^\d+$/.test(trimmed) ? `urn:li:organization:${trimmed}` : null;
6336
7991
  }
6337
- var resolveCommand = defineCommand45({
7992
+ var resolveCommand = defineCommand47({
6338
7993
  meta: {
6339
7994
  name: "resolve",
6340
7995
  description: `Resolve organization URNs to company names.
@@ -6376,8 +8031,8 @@ couldn't be resolved \u2014 typically an org outside LinkedIn's targetable set.`
6376
8031
  });
6377
8032
 
6378
8033
  // src/commands/ads/linkedin/top-companies.ts
6379
- import { defineCommand as defineCommand46 } from "citty";
6380
- var topCompaniesCommand = defineCommand46({
8034
+ import { defineCommand as defineCommand48 } from "citty";
8035
+ var topCompaniesCommand = defineCommand48({
6381
8036
  meta: {
6382
8037
  name: "top-companies",
6383
8038
  description: `Top companies whose employees saw / clicked / converted on a campaign.
@@ -6448,7 +8103,7 @@ Examples:
6448
8103
  });
6449
8104
 
6450
8105
  // src/commands/ads/linkedin/index.ts
6451
- var linkedinCommand = defineCommand47({
8106
+ var linkedinCommand = defineCommand49({
6452
8107
  meta: {
6453
8108
  name: "linkedin",
6454
8109
  description: `LinkedIn Marketing API \u2014 AI-first command surface for B2B ad insights.
@@ -6474,6 +8129,17 @@ Performance \u2014 the workhorse (3 axes):
6474
8129
  baker ads linkedin analytics --list-intents
6475
8130
  baker ads linkedin analytics --list-pivots
6476
8131
 
8132
+ Staged writes (NEVER hit LinkedIn directly \u2014 ops stage on this chat's draft,
8133
+ show in the dashboard as pending LinkedIn changes, and apply when the chat is
8134
+ published; if the company's LinkedIn-write flag is off the publish is simulated):
8135
+ baker ads linkedin campaign-groups create|update|pause|resume|duplicate
8136
+ baker ads linkedin campaigns create|update|pause|resume|archive|duplicate
8137
+ baker ads linkedin creatives create|update|pause|resume|duplicate
8138
+ baker ads linkedin audiences create|upload
8139
+ baker ads linkedin conversions create|update
8140
+ baker ads linkedin lead-forms create|update
8141
+ baker ads linkedin draft [list|remove <ref>|clear] \u2014 review/undo staged ops
8142
+
6477
8143
  Account ID format:
6478
8144
  --account-id accepts numeric (503001492) or URN (urn:li:sponsoredAccount:503001492).
6479
8145
  Set BAKER_LINKEDIN_AD_ACCOUNT_ID env to skip --account-id on every call.`
@@ -6484,6 +8150,9 @@ Account ID format:
6484
8150
  "campaign-groups": campaignGroupsCommand,
6485
8151
  campaigns: campaignsCommand,
6486
8152
  creatives: creativesCommand,
8153
+ audiences: audiencesCommand,
8154
+ "lead-forms": leadFormsCommand,
8155
+ draft: linkedinDraftCommand,
6487
8156
  analytics: analyticsCommand,
6488
8157
  demographics: demographicsCommand,
6489
8158
  "top-companies": topCompaniesCommand,
@@ -6500,10 +8169,10 @@ Account ID format:
6500
8169
  });
6501
8170
 
6502
8171
  // src/commands/ads/meta/index.ts
6503
- import { defineCommand as defineCommand60 } from "citty";
8172
+ import { defineCommand as defineCommand62 } from "citty";
6504
8173
 
6505
8174
  // src/commands/ads/meta/account.ts
6506
- import { defineCommand as defineCommand48 } from "citty";
8175
+ import { defineCommand as defineCommand50 } from "citty";
6507
8176
 
6508
8177
  // src/commands/ads/meta/shared.ts
6509
8178
  var DAY_MS5 = 864e5;
@@ -6582,7 +8251,7 @@ function resolveEffectiveStatus(args) {
6582
8251
  }
6583
8252
 
6584
8253
  // src/commands/ads/meta/account.ts
6585
- var accountCommand2 = defineCommand48({
8254
+ var accountCommand2 = defineCommand50({
6586
8255
  meta: {
6587
8256
  name: "account",
6588
8257
  description: `Show single Meta ad account detail (currency, timezone, balance, business).
@@ -6609,8 +8278,8 @@ Examples:
6609
8278
  });
6610
8279
 
6611
8280
  // src/commands/ads/meta/accounts.ts
6612
- import { defineCommand as defineCommand49 } from "citty";
6613
- var accountsCommand3 = defineCommand49({
8281
+ import { defineCommand as defineCommand51 } from "citty";
8282
+ var accountsCommand3 = defineCommand51({
6614
8283
  meta: {
6615
8284
  name: "accounts",
6616
8285
  description: `List Meta ad accounts in this company's connected scope.
@@ -6658,8 +8327,8 @@ Examples:
6658
8327
  });
6659
8328
 
6660
8329
  // src/commands/ads/meta/activities.ts
6661
- import { defineCommand as defineCommand50 } from "citty";
6662
- var activitiesCommand = defineCommand50({
8330
+ import { defineCommand as defineCommand52 } from "citty";
8331
+ var activitiesCommand = defineCommand52({
6663
8332
  meta: {
6664
8333
  name: "activities",
6665
8334
  description: `Audit log of recent ad-account changes (created, paused, edited). Default lookback 7 days,
@@ -6696,8 +8365,8 @@ Examples:
6696
8365
  });
6697
8366
 
6698
8367
  // src/commands/ads/meta/ads.ts
6699
- import { defineCommand as defineCommand51 } from "citty";
6700
- var adsListCommand = defineCommand51({
8368
+ import { defineCommand as defineCommand53 } from "citty";
8369
+ var adsListCommand = defineCommand53({
6701
8370
  meta: {
6702
8371
  name: "ads",
6703
8372
  description: `List ads in a Meta ad account. Defaults to ACTIVE only \u2014 pass --all-statuses to widen.
@@ -6745,8 +8414,8 @@ Examples:
6745
8414
  });
6746
8415
 
6747
8416
  // src/commands/ads/meta/adsets.ts
6748
- import { defineCommand as defineCommand52 } from "citty";
6749
- var adsetsCommand = defineCommand52({
8417
+ import { defineCommand as defineCommand54 } from "citty";
8418
+ var adsetsCommand = defineCommand54({
6750
8419
  meta: {
6751
8420
  name: "adsets",
6752
8421
  description: `List ad sets in a Meta ad account, optionally scoped to one campaign. Defaults to ACTIVE only.
@@ -6788,8 +8457,8 @@ Examples:
6788
8457
  });
6789
8458
 
6790
8459
  // src/commands/ads/meta/audiences.ts
6791
- import { defineCommand as defineCommand53 } from "citty";
6792
- var audiencesCommand = defineCommand53({
8460
+ import { defineCommand as defineCommand55 } from "citty";
8461
+ var audiencesCommand2 = defineCommand55({
6793
8462
  meta: {
6794
8463
  name: "audiences",
6795
8464
  description: `List custom audiences for a Meta ad account. Includes lookalikes, website-pixel audiences,
@@ -6824,8 +8493,8 @@ Examples:
6824
8493
  });
6825
8494
 
6826
8495
  // src/commands/ads/meta/businesses.ts
6827
- import { defineCommand as defineCommand54 } from "citty";
6828
- var businessesCommand = defineCommand54({
8496
+ import { defineCommand as defineCommand56 } from "citty";
8497
+ var businessesCommand = defineCommand56({
6829
8498
  meta: {
6830
8499
  name: "businesses",
6831
8500
  description: `List Meta Business Manager accounts the connected user has access to. Required for ad-studies and product-catalogs commands.
@@ -6855,8 +8524,8 @@ Examples:
6855
8524
  });
6856
8525
 
6857
8526
  // src/commands/ads/meta/campaigns.ts
6858
- import { defineCommand as defineCommand55 } from "citty";
6859
- var campaignsCommand2 = defineCommand55({
8527
+ import { defineCommand as defineCommand57 } from "citty";
8528
+ var campaignsCommand2 = defineCommand57({
6860
8529
  meta: {
6861
8530
  name: "campaigns",
6862
8531
  description: `List campaigns for a Meta ad account. Defaults to ACTIVE only \u2014 pass --all-statuses to widen.
@@ -6900,8 +8569,8 @@ Examples:
6900
8569
  });
6901
8570
 
6902
8571
  // src/commands/ads/meta/creatives.ts
6903
- import { defineCommand as defineCommand56 } from "citty";
6904
- var creativesCommand2 = defineCommand56({
8572
+ import { defineCommand as defineCommand58 } from "citty";
8573
+ var creativesCommand2 = defineCommand58({
6905
8574
  meta: {
6906
8575
  name: "creatives",
6907
8576
  description: `List ad creatives in an account, or fetch a single creative by ID.
@@ -6945,7 +8614,7 @@ Examples:
6945
8614
  });
6946
8615
 
6947
8616
  // src/commands/ads/meta/insights.ts
6948
- import { defineCommand as defineCommand57 } from "citty";
8617
+ import { defineCommand as defineCommand59 } from "citty";
6949
8618
 
6950
8619
  // src/commands/ads/meta/presets.ts
6951
8620
  var INSIGHTS_INTENTS = {
@@ -7150,7 +8819,7 @@ function sortRowsBySpendDesc(rows) {
7150
8819
  return sb - sa;
7151
8820
  });
7152
8821
  }
7153
- var insightsCommand = defineCommand57({
8822
+ var insightsCommand = defineCommand59({
7154
8823
  meta: {
7155
8824
  name: "insights",
7156
8825
  description: `Performance reporting \u2014 the main Meta tool for AI agents.
@@ -7251,8 +8920,8 @@ Async is automatic for heavy queries; pass --async to force it, or --no-async to
7251
8920
  });
7252
8921
 
7253
8922
  // src/commands/ads/meta/pixels.ts
7254
- import { defineCommand as defineCommand58 } from "citty";
7255
- var pixelsCommand = defineCommand58({
8923
+ import { defineCommand as defineCommand60 } from "citty";
8924
+ var pixelsCommand = defineCommand60({
7256
8925
  meta: {
7257
8926
  name: "pixels",
7258
8927
  description: `List Meta Pixels for an ad account, or fetch firing stats for one pixel.
@@ -7323,7 +8992,7 @@ function emit(data, args) {
7323
8992
 
7324
8993
  // src/commands/ads/meta/preview.ts
7325
8994
  import { writeFileSync as writeFileSync3 } from "fs";
7326
- import { defineCommand as defineCommand59 } from "citty";
8995
+ import { defineCommand as defineCommand61 } from "citty";
7327
8996
  var VALID_AD_FORMATS = [
7328
8997
  "DESKTOP_FEED_STANDARD",
7329
8998
  "MOBILE_FEED_STANDARD",
@@ -7357,7 +9026,7 @@ var VALID_AD_FORMATS = [
7357
9026
  "MARKETPLACE_MOBILE",
7358
9027
  "BIZ_DISCO_FEED_MOBILE"
7359
9028
  ];
7360
- var previewCommand = defineCommand59({
9029
+ var previewCommand = defineCommand61({
7361
9030
  meta: {
7362
9031
  name: "preview",
7363
9032
  description: `Generate a Meta-hosted preview iframe for a creative or ad. Returns iframe HTML which you
@@ -7404,7 +9073,7 @@ Examples:
7404
9073
  });
7405
9074
 
7406
9075
  // src/commands/ads/meta/index.ts
7407
- var metaCommand = defineCommand60({
9076
+ var metaCommand = defineCommand62({
7408
9077
  meta: {
7409
9078
  name: "meta",
7410
9079
  description: `Meta Marketing API \u2014 AI-first command surface (Facebook + Instagram ads).
@@ -7447,7 +9116,7 @@ Audit & review:
7447
9116
  adsets: adsetsCommand,
7448
9117
  ads: adsListCommand,
7449
9118
  creatives: creativesCommand2,
7450
- audiences: audiencesCommand,
9119
+ audiences: audiencesCommand2,
7451
9120
  pixels: pixelsCommand,
7452
9121
  activities: activitiesCommand,
7453
9122
  insights: insightsCommand,
@@ -7456,10 +9125,10 @@ Audit & review:
7456
9125
  });
7457
9126
 
7458
9127
  // src/commands/ads/x/index.ts
7459
- import { defineCommand as defineCommand77 } from "citty";
9128
+ import { defineCommand as defineCommand79 } from "citty";
7460
9129
 
7461
9130
  // src/commands/ads/x/accounts.ts
7462
- import { defineCommand as defineCommand61 } from "citty";
9131
+ import { defineCommand as defineCommand63 } from "citty";
7463
9132
  registerSchema({
7464
9133
  command: "ads.x.accounts",
7465
9134
  description: "List all accessible X Ads accounts. Returns accounts with id (base36), name, approval_status, timezone, currency. Run this first to find account IDs for other commands.",
@@ -7487,7 +9156,7 @@ function handleAccountsError2(err) {
7487
9156
  writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
7488
9157
  process.exit(1);
7489
9158
  }
7490
- var accountsCommand4 = defineCommand61({
9159
+ var accountsCommand4 = defineCommand63({
7491
9160
  meta: {
7492
9161
  name: "accounts",
7493
9162
  description: `List accessible X Ads accounts. Returns account IDs needed for all other commands.
@@ -7527,7 +9196,7 @@ Examples:
7527
9196
  });
7528
9197
 
7529
9198
  // src/commands/ads/x/active-entities.ts
7530
- import { defineCommand as defineCommand62 } from "citty";
9199
+ import { defineCommand as defineCommand64 } from "citty";
7531
9200
 
7532
9201
  // src/commands/ads/x/error-parser.ts
7533
9202
  function mapXErrorCode(message) {
@@ -7678,7 +9347,7 @@ function parseCsv(v) {
7678
9347
  const parts = v.split(",").map((s) => s.trim()).filter(Boolean);
7679
9348
  return parts.length > 0 ? parts : void 0;
7680
9349
  }
7681
- var activeEntitiesCommand = defineCommand62({
9350
+ var activeEntitiesCommand = defineCommand64({
7682
9351
  meta: {
7683
9352
  name: "active-entities",
7684
9353
  description: `List entities with metric activity in a time range.
@@ -7736,7 +9405,7 @@ Examples:
7736
9405
  });
7737
9406
 
7738
9407
  // src/commands/ads/x/audiences.ts
7739
- import { defineCommand as defineCommand63 } from "citty";
9408
+ import { defineCommand as defineCommand65 } from "citty";
7740
9409
  registerSchema({
7741
9410
  command: "ads.x.audiences",
7742
9411
  description: "List custom audiences for an X Ads account. Returns id, name, audience_size, audience_type, targetable status. Audiences need 100+ active users in the past 90 days to be targetable.",
@@ -7745,7 +9414,7 @@ registerSchema({
7745
9414
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
7746
9415
  }
7747
9416
  });
7748
- var audiencesCommand2 = defineCommand63({
9417
+ var audiencesCommand3 = defineCommand65({
7749
9418
  meta: {
7750
9419
  name: "audiences",
7751
9420
  description: `List X Ads custom audiences.
@@ -7794,7 +9463,7 @@ Examples:
7794
9463
  });
7795
9464
 
7796
9465
  // src/commands/ads/x/campaigns.ts
7797
- import { defineCommand as defineCommand64 } from "citty";
9466
+ import { defineCommand as defineCommand66 } from "citty";
7798
9467
 
7799
9468
  // src/commands/ads/x/run-list.ts
7800
9469
  function buildCleanParams(opts) {
@@ -7857,7 +9526,7 @@ registerSchema({
7857
9526
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
7858
9527
  }
7859
9528
  });
7860
- var campaignsCommand3 = defineCommand64({
9529
+ var campaignsCommand3 = defineCommand66({
7861
9530
  meta: {
7862
9531
  name: "campaigns",
7863
9532
  description: `List X Ads campaigns. Returns budget, schedule, funding instrument, status.
@@ -7899,7 +9568,7 @@ Examples:
7899
9568
  });
7900
9569
 
7901
9570
  // src/commands/ads/x/cards.ts
7902
- import { defineCommand as defineCommand65 } from "citty";
9571
+ import { defineCommand as defineCommand67 } from "citty";
7903
9572
  registerSchema({
7904
9573
  command: "ads.x.cards",
7905
9574
  description: "List website cards, video cards, and carousels for an X Ads account.",
@@ -7908,7 +9577,7 @@ registerSchema({
7908
9577
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
7909
9578
  }
7910
9579
  });
7911
- var cardsCommand = defineCommand65({
9580
+ var cardsCommand = defineCommand67({
7912
9581
  meta: {
7913
9582
  name: "cards",
7914
9583
  description: `List X Ads cards (rich creatives).
@@ -7957,7 +9626,7 @@ Examples:
7957
9626
  });
7958
9627
 
7959
9628
  // src/commands/ads/x/funding.ts
7960
- import { defineCommand as defineCommand66 } from "citty";
9629
+ import { defineCommand as defineCommand68 } from "citty";
7961
9630
  registerSchema({
7962
9631
  command: "ads.x.funding",
7963
9632
  description: "List funding instruments for an X Ads account. Returns id, type, currency, credit_limit_local_micro, funded_amount_local_micro, status. Falls back to BAKER_X_ADS_ACCOUNT_ID env var.",
@@ -7966,7 +9635,7 @@ registerSchema({
7966
9635
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
7967
9636
  }
7968
9637
  });
7969
- var fundingCommand = defineCommand66({
9638
+ var fundingCommand = defineCommand68({
7970
9639
  meta: {
7971
9640
  name: "funding",
7972
9641
  description: `List funding instruments for an X Ads account.
@@ -8015,7 +9684,7 @@ Examples:
8015
9684
  });
8016
9685
 
8017
9686
  // src/commands/ads/x/line-items.ts
8018
- import { defineCommand as defineCommand67 } from "citty";
9687
+ import { defineCommand as defineCommand69 } from "citty";
8019
9688
  registerSchema({
8020
9689
  command: "ads.x.lineItems",
8021
9690
  description: "List line items (ad groups) for an X Ads account. Returns bid, product_type, objective, placements, schedule. Filter by campaign-ids or line-item-ids (CSV).",
@@ -8027,7 +9696,7 @@ registerSchema({
8027
9696
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
8028
9697
  }
8029
9698
  });
8030
- var lineItemsCommand = defineCommand67({
9699
+ var lineItemsCommand = defineCommand69({
8031
9700
  meta: {
8032
9701
  name: "line-items",
8033
9702
  description: `List X Ads line items (ad groups).
@@ -8068,7 +9737,7 @@ Examples:
8068
9737
  });
8069
9738
 
8070
9739
  // src/commands/ads/x/media.ts
8071
- import { defineCommand as defineCommand68 } from "citty";
9740
+ import { defineCommand as defineCommand70 } from "citty";
8072
9741
  registerSchema({
8073
9742
  command: "ads.x.media",
8074
9743
  description: "List media assets in the X Ads media library (images, GIFs, videos). Filter by media-type (IMAGE, GIF, VIDEO).",
@@ -8078,7 +9747,7 @@ registerSchema({
8078
9747
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
8079
9748
  }
8080
9749
  });
8081
- var mediaCommand = defineCommand68({
9750
+ var mediaCommand = defineCommand70({
8082
9751
  meta: {
8083
9752
  name: "media",
8084
9753
  description: `List media assets in the X Ads media library.
@@ -8130,7 +9799,7 @@ Examples:
8130
9799
  });
8131
9800
 
8132
9801
  // src/commands/ads/x/promoted-tweets.ts
8133
- import { defineCommand as defineCommand69 } from "citty";
9802
+ import { defineCommand as defineCommand71 } from "citty";
8134
9803
  registerSchema({
8135
9804
  command: "ads.x.promotedTweets",
8136
9805
  description: "List promoted tweets for an X Ads account. Returns id, line_item_id, tweet_id, approval_status. Filter by line-item-ids (CSV).",
@@ -8141,7 +9810,7 @@ registerSchema({
8141
9810
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
8142
9811
  }
8143
9812
  });
8144
- var promotedTweetsCommand = defineCommand69({
9813
+ var promotedTweetsCommand = defineCommand71({
8145
9814
  meta: {
8146
9815
  name: "promoted-tweets",
8147
9816
  description: `List X Ads promoted tweets.
@@ -8195,11 +9864,11 @@ Examples:
8195
9864
  });
8196
9865
 
8197
9866
  // src/commands/ads/x/stats/index.ts
8198
- import { defineCommand as defineCommand74 } from "citty";
9867
+ import { defineCommand as defineCommand76 } from "citty";
8199
9868
 
8200
9869
  // src/commands/ads/x/stats/job.ts
8201
9870
  import { gunzipSync } from "zlib";
8202
- import { defineCommand as defineCommand70 } from "citty";
9871
+ import { defineCommand as defineCommand72 } from "citty";
8203
9872
  var POLL_INTERVAL_MS2 = 1e4;
8204
9873
  var DEADLINE_MS = 12 * 60 * 1e3;
8205
9874
  var RESULT_CACHE_TTL_MS = 6 * 60 * 60 * 1e3;
@@ -8269,7 +9938,7 @@ async function pollUntilDone(accountId, jobId) {
8269
9938
  function buildCacheKey(body) {
8270
9939
  return `stats-job:${JSON.stringify(body)}`;
8271
9940
  }
8272
- var statsJobCommand = defineCommand70({
9941
+ var statsJobCommand = defineCommand72({
8273
9942
  meta: {
8274
9943
  name: "job",
8275
9944
  description: `Async X Ads stats job, sync from the CLI's perspective. Creates \u2192 polls \u2192 downloads \u2192 returns.
@@ -8374,7 +10043,7 @@ For fine-grained control (don't wait, poll yourself), use:
8374
10043
  });
8375
10044
 
8376
10045
  // src/commands/ads/x/stats/job-create.ts
8377
- import { defineCommand as defineCommand71 } from "citty";
10046
+ import { defineCommand as defineCommand73 } from "citty";
8378
10047
  registerSchema({
8379
10048
  command: "ads.x.statsJobCreate",
8380
10049
  description: "Create an asynchronous X Ads stats job (range up to 90 days non-segmented, 45 days segmented). Returns a job id; poll with `stats job-status`. Times must be ISO 8601 hour-aligned.",
@@ -8397,7 +10066,7 @@ function parseCsv3(v) {
8397
10066
  const parts = v.split(",").map((s) => s.trim()).filter(Boolean);
8398
10067
  return parts.length > 0 ? parts : void 0;
8399
10068
  }
8400
- var statsJobCreateCommand = defineCommand71({
10069
+ var statsJobCreateCommand = defineCommand73({
8401
10070
  meta: {
8402
10071
  name: "job-create",
8403
10072
  description: `Create an async X Ads stats job (up to 90 days, supports segmentation).
@@ -8460,7 +10129,7 @@ Examples:
8460
10129
  });
8461
10130
 
8462
10131
  // src/commands/ads/x/stats/job-status.ts
8463
- import { defineCommand as defineCommand72 } from "citty";
10132
+ import { defineCommand as defineCommand74 } from "citty";
8464
10133
  registerSchema({
8465
10134
  command: "ads.x.statsJobStatus",
8466
10135
  description: "Check the status of one or more X Ads stats jobs. Returns status (PROCESSING|SUCCESS|FAILED) and a downloadable url when SUCCESS. Pass --job-id or --job-ids (CSV).",
@@ -8470,7 +10139,7 @@ registerSchema({
8470
10139
  "job-ids": { type: "string", description: "CSV of job IDs", required: false }
8471
10140
  }
8472
10141
  });
8473
- var statsJobStatusCommand = defineCommand72({
10142
+ var statsJobStatusCommand = defineCommand74({
8474
10143
  meta: {
8475
10144
  name: "job-status",
8476
10145
  description: `Poll the status of an async X Ads stats job.
@@ -8511,7 +10180,7 @@ Examples:
8511
10180
  });
8512
10181
 
8513
10182
  // src/commands/ads/x/stats/sync.ts
8514
- import { defineCommand as defineCommand73 } from "citty";
10183
+ import { defineCommand as defineCommand75 } from "citty";
8515
10184
 
8516
10185
  // src/commands/ads/x/presets.ts
8517
10186
  var X_STATS_PRESETS = [
@@ -8670,7 +10339,7 @@ async function runSync(args, q) {
8670
10339
  process.exit(1);
8671
10340
  }
8672
10341
  }
8673
- var statsSyncCommand = defineCommand73({
10342
+ var statsSyncCommand = defineCommand75({
8674
10343
  meta: {
8675
10344
  name: "sync",
8676
10345
  description: `Synchronous X Ads analytics (max 7-day window).
@@ -8713,7 +10382,7 @@ Examples:
8713
10382
  });
8714
10383
 
8715
10384
  // src/commands/ads/x/stats/index.ts
8716
- var statsCommand = defineCommand74({
10385
+ var statsCommand = defineCommand76({
8717
10386
  meta: {
8718
10387
  name: "stats",
8719
10388
  description: `X Ads analytics. Sync (\u22647 days, no segmentation) or async jobs (\u226490 days, segmentable).
@@ -8741,7 +10410,7 @@ Examples:
8741
10410
  });
8742
10411
 
8743
10412
  // src/commands/ads/x/targeting-constants.ts
8744
- import { defineCommand as defineCommand75 } from "citty";
10413
+ import { defineCommand as defineCommand77 } from "citty";
8745
10414
  var ALLOWED_CONSTANTS = [
8746
10415
  "locations",
8747
10416
  "interests",
@@ -8769,7 +10438,7 @@ registerSchema({
8769
10438
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
8770
10439
  }
8771
10440
  });
8772
- var targetingConstantsCommand = defineCommand75({
10441
+ var targetingConstantsCommand = defineCommand77({
8773
10442
  meta: {
8774
10443
  name: "targeting-constants",
8775
10444
  description: `Lookup X Ads targeting constants.
@@ -8819,7 +10488,7 @@ Examples:
8819
10488
  });
8820
10489
 
8821
10490
  // src/commands/ads/x/targeting-criteria.ts
8822
- import { defineCommand as defineCommand76 } from "citty";
10491
+ import { defineCommand as defineCommand78 } from "citty";
8823
10492
  registerSchema({
8824
10493
  command: "ads.x.targetingCriteria",
8825
10494
  description: "List targeting criteria attached to line items in an X Ads account. Returns targeting_type, targeting_value, name, operator_type per criterion. Filter by line-item-ids.",
@@ -8829,7 +10498,7 @@ registerSchema({
8829
10498
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
8830
10499
  }
8831
10500
  });
8832
- var targetingCriteriaCommand = defineCommand76({
10501
+ var targetingCriteriaCommand = defineCommand78({
8833
10502
  meta: {
8834
10503
  name: "targeting-criteria",
8835
10504
  description: `List targeting criteria attached to line items.
@@ -8880,7 +10549,7 @@ Examples:
8880
10549
  });
8881
10550
 
8882
10551
  // src/commands/ads/x/index.ts
8883
- var xCommand = defineCommand77({
10552
+ var xCommand = defineCommand79({
8884
10553
  meta: {
8885
10554
  name: "x",
8886
10555
  description: `X (Twitter) Ads commands. Read campaigns, line items, promoted tweets, creatives, audiences, and analytics.
@@ -8909,7 +10578,7 @@ The CLI auto-detects --account-id when exactly one X Ads account is connected, o
8909
10578
  "promoted-tweets": promotedTweetsCommand,
8910
10579
  cards: cardsCommand,
8911
10580
  media: mediaCommand,
8912
- audiences: audiencesCommand2,
10581
+ audiences: audiencesCommand3,
8913
10582
  "targeting-criteria": targetingCriteriaCommand,
8914
10583
  "targeting-constants": targetingConstantsCommand,
8915
10584
  "active-entities": activeEntitiesCommand,
@@ -8918,7 +10587,7 @@ The CLI auto-detects --account-id when exactly one X Ads account is connected, o
8918
10587
  });
8919
10588
 
8920
10589
  // src/commands/ads/index.ts
8921
- var adsCommand = defineCommand78({
10590
+ var adsCommand = defineCommand80({
8922
10591
  meta: {
8923
10592
  name: "ads",
8924
10593
  description: `Ad platform commands. Each platform exposes its own native command surface \u2014 no forced parity.
@@ -8948,11 +10617,11 @@ Examples:
8948
10617
  });
8949
10618
 
8950
10619
  // src/commands/canvas/index.ts
8951
- import { defineCommand as defineCommand86 } from "citty";
10620
+ import { defineCommand as defineCommand88 } from "citty";
8952
10621
 
8953
10622
  // src/commands/canvas/catalog.ts
8954
- import { defineCommand as defineCommand79 } from "citty";
8955
- var catalogCommand = defineCommand79({
10623
+ import { defineCommand as defineCommand81 } from "citty";
10624
+ var catalogCommand = defineCommand81({
8956
10625
  meta: {
8957
10626
  name: "catalog",
8958
10627
  description: "Print the agent-facing node catalog (JSON Schema). Includes every registered node grouped by category."
@@ -8969,9 +10638,9 @@ import { execFile } from "child_process";
8969
10638
  import { readdir, readFile, stat } from "fs/promises";
8970
10639
  import path from "path";
8971
10640
  import { promisify } from "util";
8972
- import { defineCommand as defineCommand80 } from "citty";
10641
+ import { defineCommand as defineCommand82 } from "citty";
8973
10642
  var execFileAsync = promisify(execFile);
8974
- var inspectCommand = defineCommand80({
10643
+ var inspectCommand = defineCommand82({
8975
10644
  meta: {
8976
10645
  name: "inspect",
8977
10646
  description: "Dump a one-page summary of a canvas run: per-node duration + cache status, list of output files in the run dir, and optionally three thumbnail frames per video output. Pass either a run_id (resolved against --outputs-dir) or an absolute run directory."
@@ -9080,7 +10749,7 @@ async function probeDuration(filePath) {
9080
10749
  // src/commands/canvas/run.ts
9081
10750
  import { readFile as readFile2 } from "fs/promises";
9082
10751
  import path4 from "path";
9083
- import { defineCommand as defineCommand81 } from "citty";
10752
+ import { defineCommand as defineCommand83 } from "citty";
9084
10753
 
9085
10754
  // src/commands/canvas/placeholders.ts
9086
10755
  function unsuppliedPlaceholderAssets(canvas) {
@@ -9150,7 +10819,7 @@ async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
9150
10819
  }
9151
10820
 
9152
10821
  // src/commands/canvas/run.ts
9153
- var runCommand = defineCommand81({
10822
+ var runCommand = defineCommand83({
9154
10823
  meta: { name: "run", description: "Validate and execute a canvas JSON file." },
9155
10824
  args: {
9156
10825
  file: { type: "positional", required: true, description: "Path to canvas JSON" },
@@ -9246,30 +10915,30 @@ var runCommand = defineCommand81({
9246
10915
  // src/commands/canvas/scaffold-static-ad.ts
9247
10916
  import { readFile as readFile3, writeFile } from "fs/promises";
9248
10917
  import path5 from "path";
9249
- import { defineCommand as defineCommand82 } from "citty";
10918
+ import { defineCommand as defineCommand84 } from "citty";
9250
10919
 
9251
10920
  // src/engine/scaffold/staticAd.ts
9252
- import { z as z6 } from "zod";
10921
+ import { z as z8 } from "zod";
9253
10922
  var GEN_ASPECT_RATIOS = /* @__PURE__ */ new Set(["1:1", "4:5", "9:16", "16:9", "4:3", "3:4", "2:3", "3:2", "21:9"]);
9254
10923
  var DEFAULT_ASPECT_RATIO = "9:16";
9255
- var Blueprint = z6.object({
9256
- meta: z6.object({ estimated_aspect_ratio: z6.string().optional() }).loose().optional(),
9257
- text_content: z6.array(z6.object({ text: z6.string().optional() }).loose()).optional()
10924
+ var Blueprint = z8.object({
10925
+ meta: z8.object({ estimated_aspect_ratio: z8.string().optional() }).loose().optional(),
10926
+ text_content: z8.array(z8.object({ text: z8.string().optional() }).loose()).optional()
9258
10927
  }).loose();
9259
- var ElementLocator = z6.object({
9260
- collection: z6.enum(["subjects", "people", "brands_logos"]),
9261
- index: z6.number().int().nonnegative()
10928
+ var ElementLocator = z8.object({
10929
+ collection: z8.enum(["subjects", "people", "brands_logos"]),
10930
+ index: z8.number().int().nonnegative()
9262
10931
  }).loose();
9263
- var MainElement = z6.object({
10932
+ var MainElement = z8.object({
9264
10933
  // logo | product | person | animal | badge | other
9265
- type: z6.string(),
9266
- label: z6.string().optional(),
9267
- description: z6.string().optional(),
9268
- expression: z6.string().nullable().optional(),
9269
- reason: z6.string().optional(),
10934
+ type: z8.string(),
10935
+ label: z8.string().optional(),
10936
+ description: z8.string().optional(),
10937
+ expression: z8.string().nullable().optional(),
10938
+ reason: z8.string().optional(),
9270
10939
  locator: ElementLocator.optional()
9271
10940
  }).loose();
9272
- var MainElements = z6.array(MainElement);
10941
+ var MainElements = z8.array(MainElement);
9273
10942
  function sanitizeId(raw, fallback) {
9274
10943
  const id = raw.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
9275
10944
  return /^[a-z]/.test(id) ? id : `${fallback}_${id}`.replace(/_+$/g, "") || fallback;
@@ -9565,7 +11234,7 @@ async function runVisionPasses(canvas) {
9565
11234
  return fail("read_outputs", e instanceof Error ? e.message : String(e));
9566
11235
  }
9567
11236
  }
9568
- var scaffoldStaticAdCommand = defineCommand82({
11237
+ var scaffoldStaticAdCommand = defineCommand84({
9569
11238
  meta: {
9570
11239
  name: "scaffold-static-ad",
9571
11240
  description: "Turn a source/inspiration image into a runnable static-ad canvas. Runs billed passes \u2014 image_describe (the blueprint, baked to prompt.json as the editable 'prompt'), an AI selection of the image's MAIN identity elements, and a structured global-layout pass (the column/row grid with per-region bounds and text sizes) \u2014 then scaffolds a canvas that wires one [TODO] ingest slot per element (logo/product/subject/badge + brand font) into image_generate. Edit prompt.json and drop the real assets, then `baker canvas run` it."
@@ -9659,7 +11328,7 @@ var scaffoldStaticAdCommand = defineCommand82({
9659
11328
  // src/commands/canvas/scaffold-video.ts
9660
11329
  import { cp, mkdir, readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
9661
11330
  import path8 from "path";
9662
- import { defineCommand as defineCommand83 } from "citty";
11331
+ import { defineCommand as defineCommand85 } from "citty";
9663
11332
 
9664
11333
  // src/engine/nodes/local/lib/sceneDetect.ts
9665
11334
  import { execFile as execFile2 } from "child_process";
@@ -9764,7 +11433,7 @@ import { toCardinal as nwKo } from "n2words/ko-KR";
9764
11433
  import { toCardinal as nwNl } from "n2words/nl-NL";
9765
11434
  import { toCardinal as nwPl } from "n2words/pl-PL";
9766
11435
  import { toCardinal as nwPt } from "n2words/pt-PT";
9767
- import { z as z7 } from "zod";
11436
+ import { z as z9 } from "zod";
9768
11437
 
9769
11438
  // src/engine/scaffold/lib/shoot-modes.ts
9770
11439
  var SHOOT_MODES = [
@@ -10021,49 +11690,49 @@ function trimArgs(durationS, offsetS = 0) {
10021
11690
  "{{out.video}}"
10022
11691
  ];
10023
11692
  }
10024
- var FrameAsset = z7.object({ url: z7.string().optional() }).loose().optional();
10025
- var DialogueLine = z7.object({
10026
- speaker: z7.string().optional(),
10027
- line: z7.string().optional(),
11693
+ var FrameAsset = z9.object({ url: z9.string().optional() }).loose().optional();
11694
+ var DialogueLine = z9.object({
11695
+ speaker: z9.string().optional(),
11696
+ line: z9.string().optional(),
10028
11697
  // Absolute seconds on the source timeline (the deconstruct emits both).
10029
- start_s: z7.number().optional(),
10030
- end_s: z7.number().optional(),
10031
- delivery: z7.string().optional(),
10032
- voice_description: z7.string().optional()
11698
+ start_s: z9.number().optional(),
11699
+ end_s: z9.number().optional(),
11700
+ delivery: z9.string().optional(),
11701
+ voice_description: z9.string().optional()
10033
11702
  }).loose();
10034
- var Sfx = z7.object({
10035
- at_s: z7.number().optional(),
10036
- duration_s: z7.number().optional(),
10037
- sound_effect_prompt: z7.string().optional(),
10038
- description: z7.string().optional()
11703
+ var Sfx = z9.object({
11704
+ at_s: z9.number().optional(),
11705
+ duration_s: z9.number().optional(),
11706
+ sound_effect_prompt: z9.string().optional(),
11707
+ description: z9.string().optional()
10039
11708
  }).loose();
10040
- var CompositionRegion = z7.object({
11709
+ var CompositionRegion = z9.object({
10041
11710
  // full | top | bottom | left | right | inset
10042
- panel: z7.string().optional(),
11711
+ panel: z9.string().optional(),
10043
11712
  // 9-grid anchor for an `inset` presenter box.
10044
- position: z7.string().optional(),
10045
- is_presenter: z7.boolean().optional(),
11713
+ position: z9.string().optional(),
11714
+ is_presenter: z9.boolean().optional(),
10046
11715
  // The cast id shown/speaking in this region (routes lip-sync + element refs).
10047
- cast_ref: z7.string().optional(),
10048
- summary: z7.string().optional(),
10049
- frame_prompt: z7.string().optional(),
10050
- motion_prompt: z7.string().optional()
11716
+ cast_ref: z9.string().optional(),
11717
+ summary: z9.string().optional(),
11718
+ frame_prompt: z9.string().optional(),
11719
+ motion_prompt: z9.string().optional()
10051
11720
  }).loose();
10052
- var SceneComposition = z7.object({
11721
+ var SceneComposition = z9.object({
10053
11722
  // full_frame (default) | split_screen | pip | keyed_overlay
10054
- layout: z7.string().optional(),
11723
+ layout: z9.string().optional(),
10055
11724
  // split_screen only: vertical (top/bottom) | horizontal (left/right).
10056
- split_axis: z7.string().optional(),
10057
- regions: z7.array(CompositionRegion).optional()
11725
+ split_axis: z9.string().optional(),
11726
+ regions: z9.array(CompositionRegion).optional()
10058
11727
  }).loose();
10059
- var CameraMotion = z7.object({ movement: z7.string().optional(), detail: z7.string().optional() }).loose();
10060
- var TranscriptWord = z7.object({ text: z7.string().optional() }).loose();
10061
- var Scene = z7.object({
10062
- start_s: z7.number().optional(),
10063
- end_s: z7.number().optional(),
10064
- duration_s: z7.number().optional(),
10065
- summary: z7.string().optional(),
10066
- action_detail: z7.string().optional(),
11728
+ var CameraMotion = z9.object({ movement: z9.string().optional(), detail: z9.string().optional() }).loose();
11729
+ var TranscriptWord = z9.object({ text: z9.string().optional() }).loose();
11730
+ var Scene = z9.object({
11731
+ start_s: z9.number().optional(),
11732
+ end_s: z9.number().optional(),
11733
+ duration_s: z9.number().optional(),
11734
+ summary: z9.string().optional(),
11735
+ action_detail: z9.string().optional(),
10067
11736
  // The scene's spatial layout. Absent/full_frame ⇒ one uncut shot (default path).
10068
11737
  // A layered layout (split_screen/pip/keyed_overlay) with regions ⇒ the scaffold
10069
11738
  // builds one clip per region and stacks/overlays them into the scene picture.
@@ -10071,77 +11740,77 @@ var Scene = z7.object({
10071
11740
  // The capture "look" for this scene — selected from the ad-native shoot-mode
10072
11741
  // grammar (see lib/shoot-modes.ts). When absent the scaffold auto-derives a
10073
11742
  // UGC/product mode; a human can override per scene by setting this.
10074
- shoot_mode: z7.string().optional(),
11743
+ shoot_mode: z9.string().optional(),
10075
11744
  // Diegetic ambient the clip's native audio should carry (no music). When
10076
11745
  // absent the scene falls back to its shoot mode's default ambience.
10077
- ambient: z7.string().optional(),
11746
+ ambient: z9.string().optional(),
10078
11747
  camera_motion: CameraMotion.optional(),
10079
- start_frame_prompt: z7.string().optional(),
10080
- end_frame_prompt: z7.string().optional(),
10081
- motion_prompt: z7.string().optional(),
11748
+ start_frame_prompt: z9.string().optional(),
11749
+ end_frame_prompt: z9.string().optional(),
11750
+ motion_prompt: z9.string().optional(),
10082
11751
  // The scene's role in the ad's persuasion arc (DECON-supplied); drives the
10083
11752
  // script re-craft checklist. Inferred from position when absent.
10084
- narrative_role: z7.string().optional(),
11753
+ narrative_role: z9.string().optional(),
10085
11754
  // DECON-supplied on the HOOK scene: the engineered physical/emotional state that
10086
11755
  // makes the first frame stop the scroll (sweaty/breathless/urgent …). Injected
10087
11756
  // into the hook's start-frame description so the generator renders that state,
10088
11757
  // not a calm influencer (CCA-11).
10089
- hook_mechanic: z7.object({ mechanic: z7.string().optional(), why_it_stops_scroll: z7.string().optional() }).loose().optional(),
11758
+ hook_mechanic: z9.object({ mechanic: z9.string().optional(), why_it_stops_scroll: z9.string().optional() }).loose().optional(),
10090
11759
  // DECON-supplied per-scene location (so a gym hook isn't flattened to "home").
10091
- scene_setting: z7.string().optional(),
11760
+ scene_setting: z9.string().optional(),
10092
11761
  // How this scene cuts to the next (DECON-supplied). A recognized non-cut type
10093
11762
  // (fade/whip/zoom/dissolve/swipe) is reproduced as an ffmpeg xfade at the
10094
11763
  // boundary; cut/match_cut/none/other stay hard cuts. The last scene's value is
10095
11764
  // ignored (nothing follows it).
10096
- transition_out: z7.object({ type: z7.string().optional(), description: z7.string().optional() }).loose().optional(),
10097
- dialogue: z7.array(DialogueLine).optional(),
10098
- sfx: z7.array(Sfx).optional(),
10099
- overlays: z7.array(z7.unknown()).optional(),
10100
- floating_elements: z7.array(z7.unknown()).optional(),
10101
- transcript_slice: z7.array(TranscriptWord).optional(),
11765
+ transition_out: z9.object({ type: z9.string().optional(), description: z9.string().optional() }).loose().optional(),
11766
+ dialogue: z9.array(DialogueLine).optional(),
11767
+ sfx: z9.array(Sfx).optional(),
11768
+ overlays: z9.array(z9.unknown()).optional(),
11769
+ floating_elements: z9.array(z9.unknown()).optional(),
11770
+ transcript_slice: z9.array(TranscriptWord).optional(),
10102
11771
  start_frame_asset: FrameAsset,
10103
11772
  end_frame_asset: FrameAsset,
10104
11773
  // DECON-supplied: true when this scene is a length-split CONTINUATION of the
10105
11774
  // previous one (the SAME physical shot, broken up only because it exceeded the
10106
11775
  // clip ceiling). The scaffold then shares the splice keyframe — this scene's
10107
11776
  // start frame IS the previous scene's end frame — so the join is seamless.
10108
- continues_previous: z7.boolean().optional()
11777
+ continues_previous: z9.boolean().optional()
10109
11778
  }).loose();
10110
- var VideoBlueprint = z7.object({
10111
- source: z7.object({ aspect_ratio: z7.string().optional(), duration_s: z7.number().optional() }).loose().optional(),
10112
- global: z7.object({
10113
- music: z7.object({
10114
- present: z7.boolean().optional(),
10115
- music_prompt: z7.string().optional(),
11779
+ var VideoBlueprint = z9.object({
11780
+ source: z9.object({ aspect_ratio: z9.string().optional(), duration_s: z9.number().optional() }).loose().optional(),
11781
+ global: z9.object({
11782
+ music: z9.object({
11783
+ present: z9.boolean().optional(),
11784
+ music_prompt: z9.string().optional(),
10116
11785
  // Absolute second the music enters in the reference (the bed often
10117
11786
  // kicks in mid-ad, after the hook). We start the regenerated track here
10118
11787
  // instead of at 0 so the timing matches.
10119
- starts_at_s: z7.number().optional(),
11788
+ starts_at_s: z9.number().optional(),
10120
11789
  // Populated by the deconstruct when AudD (Shazam-style) recognizes the
10121
11790
  // reference track. We never reuse it — only style the regenerated bed.
10122
- identified_track: z7.object({ title: z7.string().optional(), artist: z7.string().optional() }).loose().nullish()
11791
+ identified_track: z9.object({ title: z9.string().optional(), artist: z9.string().optional() }).loose().nullish()
10123
11792
  }).loose().optional(),
10124
- cast: z7.array(
10125
- z7.object({
10126
- id: z7.string().optional(),
10127
- description: z7.string().optional(),
11793
+ cast: z9.array(
11794
+ z9.object({
11795
+ id: z9.string().optional(),
11796
+ description: z9.string().optional(),
10128
11797
  // The deconstruct's note on the target-market localization (e.g. "native
10129
11798
  // French speaker") — read to derive the spoken-track language code.
10130
- market_localization_note: z7.string().optional()
11799
+ market_localization_note: z9.string().optional()
10131
11800
  }).loose()
10132
11801
  ).optional(),
10133
- voiceover: z7.object({
11802
+ voiceover: z9.object({
10134
11803
  // on_camera | mixed → mouths are on screen (lip-sync candidates);
10135
11804
  // voiceover | none → narration over the picture (no lip-sync).
10136
- mode: z7.string().optional(),
10137
- voice_description: z7.string().optional(),
10138
- persona: z7.string().optional()
11805
+ mode: z9.string().optional(),
11806
+ voice_description: z9.string().optional(),
11807
+ persona: z9.string().optional()
10139
11808
  }).loose().optional(),
10140
11809
  // Visual palette — read only to colour a clean brand-card/CTA plate (the
10141
11810
  // first hex is the dominant brand colour); never to drive frame generation.
10142
- style: z7.object({ palette: z7.array(z7.object({ hex: z7.string().optional() }).loose()).optional() }).loose().optional()
11811
+ style: z9.object({ palette: z9.array(z9.object({ hex: z9.string().optional() }).loose()).optional() }).loose().optional()
10143
11812
  }).loose().optional(),
10144
- scenes: z7.array(Scene).min(1)
11813
+ scenes: z9.array(Scene).min(1)
10145
11814
  }).loose();
10146
11815
  function injectHookPhysicality(blueprint) {
10147
11816
  for (const scene of blueprint.scenes) {
@@ -10151,26 +11820,26 @@ function injectHookPhysicality(blueprint) {
10151
11820
  scene.start_frame_prompt = `${prompt} The subject's physical state IS the scroll-stopper \u2014 render it explicitly, not a calm pose: ${why}.`;
10152
11821
  }
10153
11822
  }
10154
- var AppearsItem = z7.union([z7.number(), z7.object({ scene: z7.number(), edge: z7.string().optional() }).loose()]);
10155
- var RecurringElement = z7.object({
11823
+ var AppearsItem = z9.union([z9.number(), z9.object({ scene: z9.number(), edge: z9.string().optional() }).loose()]);
11824
+ var RecurringElement = z9.object({
10156
11825
  // person | animal | product | logo | badge | other
10157
- type: z7.string(),
10158
- label: z7.string().optional(),
10159
- description: z7.string().optional(),
10160
- expression: z7.string().nullable().optional(),
11826
+ type: z9.string(),
11827
+ label: z9.string().optional(),
11828
+ description: z9.string().optional(),
11829
+ expression: z9.string().nullable().optional(),
10161
11830
  // When the element maps to a global cast entry, its stable id (for annotation).
10162
- cast_id: z7.string().nullable().optional(),
11831
+ cast_id: z9.string().nullable().optional(),
10163
11832
  // The label of another element that is the SAME individual as this one, shown
10164
11833
  // in a DIFFERENT wardrobe/persona/state (e.g. one creator playing skeptic in a
10165
11834
  // pink shirt and believer in a white shirt). Each look gets its own reference
10166
11835
  // slot, but the face/identity must stay identical across them.
10167
- same_as: z7.string().nullable().optional(),
11836
+ same_as: z9.string().nullable().optional(),
10168
11837
  // Scenes the element appears in. Either a bare list of scene indices (both
10169
11838
  // edges) or per-{scene,edge} entries. Both forms are accepted and merged.
10170
- scenes: z7.array(z7.number()).optional(),
10171
- appears_in: z7.array(AppearsItem).optional()
11839
+ scenes: z9.array(z9.number()).optional(),
11840
+ appears_in: z9.array(AppearsItem).optional()
10172
11841
  }).loose();
10173
- var RecurringElements = z7.array(RecurringElement);
11842
+ var RecurringElements = z9.array(RecurringElement);
10174
11843
  function sanitizeId2(raw, fallback) {
10175
11844
  const id = raw.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
10176
11845
  return /^[a-z]/.test(id) ? id : `${fallback}_${id}`.replace(/_+$/g, "") || fallback;
@@ -11633,25 +13302,25 @@ function buildSfxMusic(blueprint, nodes) {
11633
13302
  }
11634
13303
  return tracks;
11635
13304
  }
11636
- var OverlayStyle = z7.object({ color_hex: z7.string().optional(), background: z7.string().optional(), size: z7.string().optional() }).loose();
11637
- var Overlay = z7.object({
11638
- text: z7.string().optional(),
11639
- appears_at_s: z7.number().optional(),
11640
- duration_s: z7.number().optional(),
11641
- position: z7.string().optional(),
11642
- role: z7.string().optional(),
11643
- animation: z7.string().optional(),
11644
- animation_detail: z7.string().optional(),
13305
+ var OverlayStyle = z9.object({ color_hex: z9.string().optional(), background: z9.string().optional(), size: z9.string().optional() }).loose();
13306
+ var Overlay = z9.object({
13307
+ text: z9.string().optional(),
13308
+ appears_at_s: z9.number().optional(),
13309
+ duration_s: z9.number().optional(),
13310
+ position: z9.string().optional(),
13311
+ role: z9.string().optional(),
13312
+ animation: z9.string().optional(),
13313
+ animation_detail: z9.string().optional(),
11645
13314
  style: OverlayStyle.optional()
11646
13315
  }).loose();
11647
- var FloatingElement = z7.object({
11648
- kind: z7.string().optional(),
11649
- description: z7.string().optional(),
11650
- brand_name: z7.string().nullish(),
11651
- what_it_represents: z7.string().optional(),
11652
- appears_at_s: z7.number().optional(),
11653
- duration_s: z7.number().optional(),
11654
- position: z7.string().optional()
13316
+ var FloatingElement = z9.object({
13317
+ kind: z9.string().optional(),
13318
+ description: z9.string().optional(),
13319
+ brand_name: z9.string().nullish(),
13320
+ what_it_represents: z9.string().optional(),
13321
+ appears_at_s: z9.number().optional(),
13322
+ duration_s: z9.number().optional(),
13323
+ position: z9.string().optional()
11655
13324
  }).loose();
11656
13325
  function escapeHtml(s) {
11657
13326
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
@@ -11683,7 +13352,7 @@ function positionClass(position) {
11683
13352
  function collectCaptions(blueprint) {
11684
13353
  return blueprint.scenes.flatMap((scene) => {
11685
13354
  const sceneStart = scene.start_s ?? 0;
11686
- const overlays = z7.array(Overlay).safeParse(scene.overlays ?? []);
13355
+ const overlays = z9.array(Overlay).safeParse(scene.overlays ?? []);
11687
13356
  return overlays.success ? overlays.data.filter((ov) => Boolean(ov.text?.trim())).map((ov) => {
11688
13357
  const at = ov.appears_at_s ?? sceneStart;
11689
13358
  return { text: ov.text.trim(), at, end: at + (ov.duration_s ?? 2.5), ov };
@@ -11792,7 +13461,7 @@ function buildOverlayHtml(input) {
11792
13461
  if (ovParts.length > 0) blocks.push(ovParts.join("\n"));
11793
13462
  for (const scene of blueprint.scenes) {
11794
13463
  const sceneStart = scene.start_s ?? 0;
11795
- const floats = z7.array(FloatingElement).safeParse(scene.floating_elements ?? []);
13464
+ const floats = z9.array(FloatingElement).safeParse(scene.floating_elements ?? []);
11796
13465
  const parts = (floats.success ? floats.data.map((fe) => floatingStub(fe, sceneStart)) : []).filter(Boolean);
11797
13466
  const pip = uiPipStub(scene);
11798
13467
  if (pip) parts.push(pip);
@@ -12049,8 +13718,8 @@ function buildMotionBoard(blueprint) {
12049
13718
  const end_s = scene.end_s ?? start_s + sceneDurationS(scene);
12050
13719
  cursor = end_s;
12051
13720
  const spoken = sceneSpokenText(scene);
12052
- const overlays = z7.array(Overlay).safeParse(scene.overlays ?? []);
12053
- const floats = z7.array(FloatingElement).safeParse(scene.floating_elements ?? []);
13721
+ const overlays = z9.array(Overlay).safeParse(scene.overlays ?? []);
13722
+ const floats = z9.array(FloatingElement).safeParse(scene.floating_elements ?? []);
12054
13723
  const graphics = [
12055
13724
  ...(overlays.success ? overlays.data : []).filter((ov) => ov.text?.trim()).map((ov) => ({
12056
13725
  kind: "text",
@@ -12491,7 +14160,7 @@ async function runAnalysisPasses(deconstructCanvas, selectModel) {
12491
14160
  return fail2("deconstruct", e instanceof Error ? e.message : String(e));
12492
14161
  }
12493
14162
  }
12494
- var scaffoldVideoCommand = defineCommand83({
14163
+ var scaffoldVideoCommand = defineCommand85({
12495
14164
  meta: {
12496
14165
  name: "scaffold-video",
12497
14166
  description: "Turn a reference video into a runnable reproduction canvas in one command. Runs billed passes \u2014 video_deconstruct (the full scene-by-scene blueprint + transcript, baked to prompt.json as the editable 'prompt') and an AI selection of the video's RECURRING identity elements (person/animal/product/logo) \u2014 then scaffolds a pipeline where every scene boundary is a static-ad-grade frame (the blueprint as target_blueprint, a reference legend, the real frame as anchor) and each recurring element gets ONE shared [TODO] ingest slot wired into every frame it appears in. The clips feed Seedance an ultra-detailed motion brief (action, camera, dialogue, transcript). Edit prompt.json, drop the real source images, then `baker canvas run`."
@@ -12636,7 +14305,7 @@ var scaffoldVideoCommand = defineCommand83({
12636
14305
  // src/commands/canvas/set-prompt.ts
12637
14306
  import { readFile as readFile7, writeFile as writeFile3 } from "fs/promises";
12638
14307
  import path9 from "path";
12639
- import { defineCommand as defineCommand84 } from "citty";
14308
+ import { defineCommand as defineCommand86 } from "citty";
12640
14309
  function setNodePrompt(canvas, nodeId, text) {
12641
14310
  const nodes = canvas?.nodes;
12642
14311
  if (!Array.isArray(nodes)) throw new Error("canvas has no nodes array");
@@ -12651,7 +14320,7 @@ function setNodePrompt(canvas, nodeId, text) {
12651
14320
  newNodes[idx] = newNode;
12652
14321
  return { ...canvas, nodes: newNodes };
12653
14322
  }
12654
- var setPromptCommand = defineCommand84({
14323
+ var setPromptCommand = defineCommand86({
12655
14324
  meta: {
12656
14325
  name: "set-prompt",
12657
14326
  description: "Safely set a node's params.prompt (a frame description, motion prompt, etc.) without hand-editing the JSON. Prefer --text-file for multi-line/accented copy \u2014 it preserves UTF-8 exactly, unlike shell-quoted jq."
@@ -12711,8 +14380,8 @@ var setPromptCommand = defineCommand84({
12711
14380
  // src/commands/canvas/validate.ts
12712
14381
  import { readFile as readFile8 } from "fs/promises";
12713
14382
  import path10 from "path";
12714
- import { defineCommand as defineCommand85 } from "citty";
12715
- var validateCommand = defineCommand85({
14383
+ import { defineCommand as defineCommand87 } from "citty";
14384
+ var validateCommand = defineCommand87({
12716
14385
  meta: {
12717
14386
  name: "validate",
12718
14387
  description: "Validate a canvas JSON file (no execution). Includes a per-node cost preview and runs each node's deep validators (composition meta checks for hyperframe_render/_snapshot)."
@@ -12755,7 +14424,7 @@ var validateCommand = defineCommand85({
12755
14424
  });
12756
14425
 
12757
14426
  // src/commands/canvas/index.ts
12758
- var canvasCommand = defineCommand86({
14427
+ var canvasCommand = defineCommand88({
12759
14428
  meta: {
12760
14429
  name: "canvas",
12761
14430
  description: `Run Baker creative canvas JSON files locally. Local nodes execute in-process; remote nodes POST to the Convex backend gateway.
@@ -12782,10 +14451,10 @@ Subcommands:
12782
14451
  });
12783
14452
 
12784
14453
  // src/commands/creatives/index.ts
12785
- import { defineCommand as defineCommand88 } from "citty";
14454
+ import { defineCommand as defineCommand90 } from "citty";
12786
14455
 
12787
14456
  // src/commands/creatives/publish.ts
12788
- import { defineCommand as defineCommand87 } from "citty";
14457
+ import { defineCommand as defineCommand89 } from "citty";
12789
14458
 
12790
14459
  // src/commands/images/api.ts
12791
14460
  import { readFile as readFile9 } from "fs/promises";
@@ -12908,7 +14577,7 @@ async function publishCreative(args, deps = defaultImageApiDeps) {
12908
14577
  sourceReferenceUrl
12909
14578
  });
12910
14579
  }
12911
- var publishCommand = defineCommand87({
14580
+ var publishCommand = defineCommand89({
12912
14581
  meta: {
12913
14582
  name: "publish",
12914
14583
  description: "Publish a final static creative image to Baker Creatives and print the creative reference JSON."
@@ -12954,7 +14623,7 @@ var publishCommand = defineCommand87({
12954
14623
  });
12955
14624
 
12956
14625
  // src/commands/creatives/index.ts
12957
- var creativesCommand3 = defineCommand88({
14626
+ var creativesCommand3 = defineCommand90({
12958
14627
  meta: {
12959
14628
  name: "creatives",
12960
14629
  description: `Publish static ad creatives as first-class Baker outputs.
@@ -12970,10 +14639,10 @@ Publishing uploads the image to the Company image library, applies the official
12970
14639
  });
12971
14640
 
12972
14641
  // src/commands/ga4/index.ts
12973
- import { defineCommand as defineCommand92 } from "citty";
14642
+ import { defineCommand as defineCommand94 } from "citty";
12974
14643
 
12975
14644
  // src/commands/ga4/audit.ts
12976
- import { defineCommand as defineCommand89 } from "citty";
14645
+ import { defineCommand as defineCommand91 } from "citty";
12977
14646
 
12978
14647
  // src/commands/ga4/resolve.ts
12979
14648
  async function fetchProperties(useCache = true) {
@@ -13036,7 +14705,7 @@ registerSchema({
13036
14705
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
13037
14706
  }
13038
14707
  });
13039
- var auditCommand2 = defineCommand89({
14708
+ var auditCommand2 = defineCommand91({
13040
14709
  meta: {
13041
14710
  name: "audit",
13042
14711
  description: `Run all GA4 admin health checks. Returns property config with playbook warnings.
@@ -13088,7 +14757,7 @@ Examples:
13088
14757
  });
13089
14758
 
13090
14759
  // src/commands/ga4/properties.ts
13091
- import { defineCommand as defineCommand90 } from "citty";
14760
+ import { defineCommand as defineCommand92 } from "citty";
13092
14761
  registerSchema({
13093
14762
  command: "ga4.properties",
13094
14763
  description: "List all accessible GA4 properties. Returns property IDs needed for query and audit commands. Run this first to find property IDs.",
@@ -13096,7 +14765,7 @@ registerSchema({
13096
14765
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
13097
14766
  }
13098
14767
  });
13099
- var propertiesCommand = defineCommand90({
14768
+ var propertiesCommand = defineCommand92({
13100
14769
  meta: {
13101
14770
  name: "properties",
13102
14771
  description: `List accessible GA4 properties.
@@ -13144,9 +14813,9 @@ Examples:
13144
14813
  });
13145
14814
 
13146
14815
  // src/commands/ga4/query.ts
13147
- import { appendFileSync as appendFileSync2, existsSync as existsSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
14816
+ import { appendFileSync as appendFileSync2, existsSync as existsSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "fs";
13148
14817
  import { resolve as resolve2 } from "path";
13149
- import { defineCommand as defineCommand91 } from "citty";
14818
+ import { defineCommand as defineCommand93 } from "citty";
13150
14819
 
13151
14820
  // src/commands/ga4/presets.ts
13152
14821
  var GA4_PRESETS = [
@@ -13235,7 +14904,7 @@ function writeRowsToFile2(filePath, rows, append) {
13235
14904
  writeFileSync4(filePath, content, "utf-8");
13236
14905
  }
13237
14906
  } else if (append && existsSync5(filePath)) {
13238
- const existing = JSON.parse(readFileSync7(filePath, "utf-8"));
14907
+ const existing = JSON.parse(readFileSync8(filePath, "utf-8"));
13239
14908
  writeFileSync4(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
13240
14909
  } else {
13241
14910
  writeFileSync4(filePath, JSON.stringify(rows, null, 2), "utf-8");
@@ -13278,7 +14947,7 @@ function handleError(err) {
13278
14947
  });
13279
14948
  process.exit(1);
13280
14949
  }
13281
- var queryCommand2 = defineCommand91({
14950
+ var queryCommand2 = defineCommand93({
13282
14951
  meta: {
13283
14952
  name: "query",
13284
14953
  description: `Run GA4 Data API reports. Preset-first with free-form escape hatch.
@@ -13349,7 +15018,7 @@ Free-form (escape hatch):
13349
15018
  });
13350
15019
 
13351
15020
  // src/commands/ga4/index.ts
13352
- var ga4Command = defineCommand92({
15021
+ var ga4Command = defineCommand94({
13353
15022
  meta: {
13354
15023
  name: "ga4",
13355
15024
  description: `Google Analytics 4 commands. Audit property config, run playbook-aligned reports.
@@ -13372,12 +15041,12 @@ Examples:
13372
15041
  });
13373
15042
 
13374
15043
  // src/commands/gsc/index.ts
13375
- import { defineCommand as defineCommand96 } from "citty";
15044
+ import { defineCommand as defineCommand98 } from "citty";
13376
15045
 
13377
15046
  // src/commands/gsc/query.ts
13378
- import { appendFileSync as appendFileSync3, existsSync as existsSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
15047
+ import { appendFileSync as appendFileSync3, existsSync as existsSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "fs";
13379
15048
  import { resolve as resolve3 } from "path";
13380
- import { defineCommand as defineCommand93 } from "citty";
15049
+ import { defineCommand as defineCommand95 } from "citty";
13381
15050
 
13382
15051
  // src/commands/gsc/presets.ts
13383
15052
  var GSC_PRESETS = [
@@ -13520,7 +15189,7 @@ function writeRowsToFile3(filePath, rows, append) {
13520
15189
  writeFileSync5(filePath, content, "utf-8");
13521
15190
  }
13522
15191
  } else if (append && existsSync6(filePath)) {
13523
- const existing = JSON.parse(readFileSync8(filePath, "utf-8"));
15192
+ const existing = JSON.parse(readFileSync9(filePath, "utf-8"));
13524
15193
  writeFileSync5(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
13525
15194
  } else {
13526
15195
  writeFileSync5(filePath, JSON.stringify(rows, null, 2), "utf-8");
@@ -13565,7 +15234,7 @@ function handleError2(err) {
13565
15234
  });
13566
15235
  process.exit(1);
13567
15236
  }
13568
- var queryCommand3 = defineCommand93({
15237
+ var queryCommand3 = defineCommand95({
13569
15238
  meta: {
13570
15239
  name: "query",
13571
15240
  description: `Run GSC Search Analytics queries. Preset-first with free-form escape hatch.
@@ -13643,7 +15312,7 @@ Free-form (escape hatch):
13643
15312
  });
13644
15313
 
13645
15314
  // src/commands/gsc/sitemaps.ts
13646
- import { defineCommand as defineCommand94 } from "citty";
15315
+ import { defineCommand as defineCommand96 } from "citty";
13647
15316
  registerSchema({
13648
15317
  command: "gsc.sitemaps",
13649
15318
  description: "List sitemaps for a Search Console site. Check sitemap health and errors.",
@@ -13652,7 +15321,7 @@ registerSchema({
13652
15321
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
13653
15322
  }
13654
15323
  });
13655
- var sitemapsCommand = defineCommand94({
15324
+ var sitemapsCommand = defineCommand96({
13656
15325
  meta: {
13657
15326
  name: "sitemaps",
13658
15327
  description: `List sitemaps for a site. Check health and errors.
@@ -13702,7 +15371,7 @@ Examples:
13702
15371
  });
13703
15372
 
13704
15373
  // src/commands/gsc/sites.ts
13705
- import { defineCommand as defineCommand95 } from "citty";
15374
+ import { defineCommand as defineCommand97 } from "citty";
13706
15375
  registerSchema({
13707
15376
  command: "gsc.sites",
13708
15377
  description: "List all verified Google Search Console sites. Returns site URLs needed for query and sitemaps commands.",
@@ -13710,7 +15379,7 @@ registerSchema({
13710
15379
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
13711
15380
  }
13712
15381
  });
13713
- var sitesCommand = defineCommand95({
15382
+ var sitesCommand = defineCommand97({
13714
15383
  meta: {
13715
15384
  name: "sites",
13716
15385
  description: `List verified Search Console sites.
@@ -13758,7 +15427,7 @@ Examples:
13758
15427
  });
13759
15428
 
13760
15429
  // src/commands/gsc/index.ts
13761
- var gscCommand = defineCommand96({
15430
+ var gscCommand = defineCommand98({
13762
15431
  meta: {
13763
15432
  name: "gsc",
13764
15433
  description: `Google Search Console commands. PPC-SEO arbitrage, brand halo analysis, negative keyword discovery.
@@ -13781,10 +15450,10 @@ Examples:
13781
15450
  });
13782
15451
 
13783
15452
  // src/commands/images/index.ts
13784
- import { defineCommand as defineCommand120 } from "citty";
15453
+ import { defineCommand as defineCommand122 } from "citty";
13785
15454
 
13786
15455
  // src/commands/images/crop.ts
13787
- import { defineCommand as defineCommand97 } from "citty";
15456
+ import { defineCommand as defineCommand99 } from "citty";
13788
15457
 
13789
15458
  // src/lib/image/crop-sprite.ts
13790
15459
  import sharp from "sharp";
@@ -13909,7 +15578,7 @@ function emitError2(err) {
13909
15578
  }
13910
15579
  process.exit(1);
13911
15580
  }
13912
- var cropCommand = defineCommand97({
15581
+ var cropCommand = defineCommand99({
13913
15582
  meta: {
13914
15583
  name: "crop",
13915
15584
  description: "Crop a rectangular region from an image.\n\nExample: baker images crop sprite.png --x 0 --y 0 --width 64 --height 64 --output icon.png"
@@ -13945,7 +15614,7 @@ var cropCommand = defineCommand97({
13945
15614
  });
13946
15615
 
13947
15616
  // src/commands/images/delete.ts
13948
- import { defineCommand as defineCommand98 } from "citty";
15617
+ import { defineCommand as defineCommand100 } from "citty";
13949
15618
  registerSchema({
13950
15619
  command: "images.delete",
13951
15620
  description: "Delete an image by ID",
@@ -13959,7 +15628,7 @@ registerSchema({
13959
15628
  }
13960
15629
  }
13961
15630
  });
13962
- var deleteCommand = defineCommand98({
15631
+ var deleteCommand = defineCommand100({
13963
15632
  meta: {
13964
15633
  name: "delete",
13965
15634
  description: "Delete an image by ID. Use --dry-run to preview. Example: baker images delete j571abc123 --dry-run"
@@ -14000,7 +15669,7 @@ var deleteCommand = defineCommand98({
14000
15669
  });
14001
15670
 
14002
15671
  // src/commands/images/dimensions.ts
14003
- import { defineCommand as defineCommand99 } from "citty";
15672
+ import { defineCommand as defineCommand101 } from "citty";
14004
15673
 
14005
15674
  // src/lib/image/dimensions.ts
14006
15675
  import { imageSize } from "image-size";
@@ -14023,7 +15692,7 @@ registerSchema({
14023
15692
  target: { type: "string", description: "Local file path or remote http(s) URL", required: true }
14024
15693
  }
14025
15694
  });
14026
- var dimensionsCommand = defineCommand99({
15695
+ var dimensionsCommand = defineCommand101({
14027
15696
  meta: {
14028
15697
  name: "dimensions",
14029
15698
  description: "Read image dimensions without decoding the full file.\n\nExample: baker images dimensions ./logo.png\nExample: baker images dimensions https://acme.com/hero.png"
@@ -14067,7 +15736,7 @@ var dimensionsCommand = defineCommand99({
14067
15736
  });
14068
15737
 
14069
15738
  // src/commands/images/extract.ts
14070
- import { defineCommand as defineCommand100 } from "citty";
15739
+ import { defineCommand as defineCommand102 } from "citty";
14071
15740
  registerSchema({
14072
15741
  command: "images.extract",
14073
15742
  description: "Extract images from a URL via Firecrawl (formats: images).",
@@ -14083,7 +15752,7 @@ registerSchema({
14083
15752
  }
14084
15753
  }
14085
15754
  });
14086
- var extractCommand = defineCommand100({
15755
+ var extractCommand = defineCommand102({
14087
15756
  meta: {
14088
15757
  name: "extract",
14089
15758
  description: "Pull every image from a single URL via Firecrawl. ~$0.001/scrape. Cap auto-ingest at 20.\n\nExample: baker images extract https://stripe.com --auto-ingest 5"
@@ -14121,7 +15790,7 @@ var extractCommand = defineCommand100({
14121
15790
  });
14122
15791
 
14123
15792
  // src/commands/images/find.ts
14124
- import { defineCommand as defineCommand101 } from "citty";
15793
+ import { defineCommand as defineCommand103 } from "citty";
14125
15794
  registerSchema({
14126
15795
  command: "images.find",
14127
15796
  description: "Fanout image search: library first, then opted-in external providers.",
@@ -14153,7 +15822,7 @@ registerSchema({
14153
15822
  }
14154
15823
  }
14155
15824
  });
14156
- var findCommand = defineCommand101({
15825
+ var findCommand = defineCommand103({
14157
15826
  meta: {
14158
15827
  name: "find",
14159
15828
  description: "Library-first fanout image search. Opt in to providers with --sources. `--fallback` short-circuits to externals only when library is thin. With --auto-ingest, ingested external hits return Baker-owned URLs.\n\nExample: baker images find 'office' --sources library,magnific --limit 20"
@@ -14202,7 +15871,7 @@ var findCommand = defineCommand101({
14202
15871
 
14203
15872
  // src/commands/images/generate.ts
14204
15873
  import { readFile as readFile11 } from "fs/promises";
14205
- import { defineCommand as defineCommand102 } from "citty";
15874
+ import { defineCommand as defineCommand104 } from "citty";
14206
15875
  import sharp2 from "sharp";
14207
15876
  var GENERATE_TIMEOUT_MS = 18e4;
14208
15877
  var REFERENCE_MAX_EDGE = 1536;
@@ -14305,7 +15974,7 @@ async function resolveReferences(spec) {
14305
15974
  }
14306
15975
  return out;
14307
15976
  }
14308
- var generateCommand = defineCommand102({
15977
+ var generateCommand = defineCommand104({
14309
15978
  meta: {
14310
15979
  name: "generate",
14311
15980
  description: "Generate an image with AI and store it in the library (cost-tracked per request via OpenRouter usage). Models mirror the canvas: openai/gpt-5.4-image-2 (default \u2014 photoreal, cleanest text, best for ad/landing reproduction), google/gemini-3-pro-image-preview (Nano Banana Pro), google/gemini-3.5-flash & google/gemini-3.1-flash-image-preview (fast, extreme aspect ratios), recraft/recraft-v4.1-pro-vector (vector/SVG-style with palette control). The result is auto-ingested (describe + embed), so the next `baker images library` query finds it. Pass --reference with image URLs and/or local file paths (Pinterest, stock, brand assets, sandbox files) to ground generation in reality.\n\nExamples:\n baker images generate 'a friendly golden retriever sitting in a bright modern living room' --aspect-ratio 16:9\n baker images generate 'hero shot of a matte black water bottle on marble' --model google/gemini-3-pro-image-preview --image-size 2K\n baker images generate 'lifestyle photo matching this mood' --reference 'https://\u2026/ref1.jpg,https://\u2026/ref2.jpg'\n baker images generate 'put this product on a marble countertop, soft daylight' --reference './src/brand/logos/product.png,./refs/kitchen-mood.jpg'\n baker images generate 'flat geometric mascot, brand palette' --model recraft/recraft-v4.1-pro-vector --rgb-colors '[[10,10,10],[255,80,0]]'"
@@ -14357,7 +16026,7 @@ var generateCommand = defineCommand102({
14357
16026
  });
14358
16027
 
14359
16028
  // src/commands/images/get.ts
14360
- import { defineCommand as defineCommand103 } from "citty";
16029
+ import { defineCommand as defineCommand105 } from "citty";
14361
16030
  registerSchema({
14362
16031
  command: "images.get",
14363
16032
  description: "Get a single image by ID",
@@ -14365,7 +16034,7 @@ registerSchema({
14365
16034
  id: { type: "string", description: "Image ID", required: true }
14366
16035
  }
14367
16036
  });
14368
- var getCommand2 = defineCommand103({
16037
+ var getCommand2 = defineCommand105({
14369
16038
  meta: { name: "get", description: "Get a single image by ID. Example: baker images get j571abc123" },
14370
16039
  args: {
14371
16040
  id: { type: "positional", description: "Image ID", required: false },
@@ -14401,7 +16070,7 @@ var getCommand2 = defineCommand103({
14401
16070
  });
14402
16071
 
14403
16072
  // src/commands/images/gif.ts
14404
- import { defineCommand as defineCommand104 } from "citty";
16073
+ import { defineCommand as defineCommand106 } from "citty";
14405
16074
  registerSchema({
14406
16075
  command: "images.gif",
14407
16076
  description: "Search Giphy for GIFs / reaction memes (paid social creative).",
@@ -14433,7 +16102,7 @@ registerSchema({
14433
16102
  }
14434
16103
  }
14435
16104
  });
14436
- var gifCommand = defineCommand104({
16105
+ var gifCommand = defineCommand106({
14437
16106
  meta: {
14438
16107
  name: "gif",
14439
16108
  description: "Search Giphy for GIFs / reaction memes \u2014 built for paid-social creative (Meta, TikTok, LinkedIn, X). Free API. Each hit carries WebP + GIF + MP4 URLs in providerMeta so you can pick the right format per platform.\n\nExample: baker images gif 'this is fine' --limit 10\nExample: baker images gif 'office reaction' --rating pg --auto-ingest 2\nExample: baker images gif --trending --limit 25"
@@ -14480,7 +16149,7 @@ var gifCommand = defineCommand104({
14480
16149
  });
14481
16150
 
14482
16151
  // src/commands/images/google.ts
14483
- import { defineCommand as defineCommand105 } from "citty";
16152
+ import { defineCommand as defineCommand107 } from "citty";
14484
16153
  registerSchema({
14485
16154
  command: "images.google",
14486
16155
  description: "Google Images search via the official Custom Search JSON API. Unverified source \u2014 inspect before placing.",
@@ -14516,7 +16185,7 @@ registerSchema({
14516
16185
  }
14517
16186
  }
14518
16187
  });
14519
- var googleCommand2 = defineCommand105({
16188
+ var googleCommand2 = defineCommand107({
14520
16189
  meta: {
14521
16190
  name: "google",
14522
16191
  description: "Google Images via the official Custom Search JSON API ($0.005/query, free 100/day). \u26A0 Source unverified \u2014 watermarks, low-res, mislabeled results are common. Use as last resort. With --auto-ingest, ingested hits return Baker-owned URLs.\n\nExample: baker images google 'industrial workshop' --type photo --size large --limit 20"
@@ -14564,7 +16233,7 @@ var googleCommand2 = defineCommand105({
14564
16233
  });
14565
16234
 
14566
16235
  // src/commands/images/icon.ts
14567
- import { defineCommand as defineCommand106 } from "citty";
16236
+ import { defineCommand as defineCommand108 } from "citty";
14568
16237
  registerSchema({
14569
16238
  command: "images.icon",
14570
16239
  description: "Icon lookup via Iconify (200+ icon sets, free CDN).",
@@ -14590,7 +16259,7 @@ registerSchema({
14590
16259
  }
14591
16260
  }
14592
16261
  });
14593
- var iconCommand = defineCommand106({
16262
+ var iconCommand = defineCommand108({
14594
16263
  meta: {
14595
16264
  name: "icon",
14596
16265
  description: "Icon via Iconify (simple-icons, logos, lucide, devicon, heroicons, tabler, phosphor, material-symbols, \u2026). Free CDN, no API key.\n\nExample: baker images icon react --set devicon\nExample: baker images icon lucide:check --color '#0a0a0a'"
@@ -14630,7 +16299,7 @@ var iconCommand = defineCommand106({
14630
16299
  });
14631
16300
 
14632
16301
  // src/commands/images/ingest.ts
14633
- import { defineCommand as defineCommand107 } from "citty";
16302
+ import { defineCommand as defineCommand109 } from "citty";
14634
16303
  registerSchema({
14635
16304
  command: "images.ingest",
14636
16305
  description: "Ingest a remote image URL into the library (full describe + embed).",
@@ -14642,7 +16311,7 @@ registerSchema({
14642
16311
  context: { type: "string", description: "Description context hint", required: false }
14643
16312
  }
14644
16313
  });
14645
- var ingestCommand = defineCommand107({
16314
+ var ingestCommand = defineCommand109({
14646
16315
  meta: {
14647
16316
  name: "ingest",
14648
16317
  description: "Download a remote URL and store it in the library. Hash-deduped on bytes + externalId.\n\nExample: baker images ingest https://img.freepik.com/free-photo/xyz.jpg --source magnific --external-id 12345"
@@ -14684,7 +16353,7 @@ var ingestCommand = defineCommand107({
14684
16353
  });
14685
16354
 
14686
16355
  // src/commands/images/library.ts
14687
- import { defineCommand as defineCommand108 } from "citty";
16356
+ import { defineCommand as defineCommand110 } from "citty";
14688
16357
  registerSchema({
14689
16358
  command: "images.library",
14690
16359
  description: "Search the company image library. Returns only ready images.",
@@ -14710,7 +16379,7 @@ registerSchema({
14710
16379
  }
14711
16380
  }
14712
16381
  });
14713
- var libraryCommand = defineCommand108({
16382
+ var libraryCommand = defineCommand110({
14714
16383
  meta: {
14715
16384
  name: "library",
14716
16385
  description: "Search the company image library (hybrid BM25 + vector + Cohere rerank). Use this BEFORE any external provider.\n\nExample: baker images library 'hero banner' --aspect-ratio 16:9 --source magnific"
@@ -14767,7 +16436,7 @@ var libraryCommand = defineCommand108({
14767
16436
  });
14768
16437
 
14769
16438
  // src/commands/images/logo.ts
14770
- import { defineCommand as defineCommand109 } from "citty";
16439
+ import { defineCommand as defineCommand111 } from "citty";
14771
16440
  registerSchema({
14772
16441
  command: "images.logo",
14773
16442
  description: "Brand logo lookup via Brandfetch CDN (fallback/404). Auto-ingests by default.",
@@ -14792,7 +16461,7 @@ registerSchema({
14792
16461
  }
14793
16462
  }
14794
16463
  });
14795
- var logoCommand = defineCommand109({
16464
+ var logoCommand = defineCommand111({
14796
16465
  meta: {
14797
16466
  name: "logo",
14798
16467
  description: "Brand logo via Brandfetch CDN. Returns up to 5 variants (icon, light/dark logo, light/dark symbol). Auto-ingests the first variant.\n\nExample: baker images logo stripe.com --variant logo"
@@ -14830,7 +16499,7 @@ var logoCommand = defineCommand109({
14830
16499
  });
14831
16500
 
14832
16501
  // src/commands/images/normalize.ts
14833
- import { defineCommand as defineCommand110 } from "citty";
16502
+ import { defineCommand as defineCommand112 } from "citty";
14834
16503
 
14835
16504
  // src/lib/image/color-changer.ts
14836
16505
  import quantize from "quantize";
@@ -15562,7 +17231,7 @@ function coerceRawArgs(args) {
15562
17231
  "dry-run": bool(args["dry-run"])
15563
17232
  };
15564
17233
  }
15565
- var normalizeCommand = defineCommand110({
17234
+ var normalizeCommand = defineCommand112({
15566
17235
  meta: {
15567
17236
  name: "normalize",
15568
17237
  description: `Normalize logos / images: declarative recolor + bg removal + trim + resize. Operates on local files; writes in-place by default.
@@ -15617,7 +17286,7 @@ Examples:
15617
17286
  });
15618
17287
 
15619
17288
  // src/commands/images/pinterest.ts
15620
- import { defineCommand as defineCommand111 } from "citty";
17289
+ import { defineCommand as defineCommand113 } from "citty";
15621
17290
  registerSchema({
15622
17291
  command: "images.pinterest",
15623
17292
  description: "Pinterest image search via ScrapeCreators. Reference-grade real-world photography, product styling, interiors, fashion, food, and aesthetic mood boards. Inspect before placing \u2014 Pinterest is unverified, trademark-bearing web content.",
@@ -15637,7 +17306,7 @@ registerSchema({
15637
17306
  }
15638
17307
  }
15639
17308
  });
15640
- var pinterestCommand = defineCommand111({
17309
+ var pinterestCommand = defineCommand113({
15641
17310
  meta: {
15642
17311
  name: "pinterest",
15643
17312
  description: "Pinterest image search via ScrapeCreators ($0.00188/request). Best for photo-realistic reference imagery \u2014 lifestyle, interiors, fashion, food, product styling, and mood boards to brief AI generation against. \u26A0 Unverified, trademark-bearing web content \u2014 inspect and respect rights before placing on a customer page. Browse first; auto-ingest only the pins you commit to.\n\nExamples:\n baker images pinterest 'scandinavian living room'\n baker images pinterest 'minimalist skincare product photography' --limit 20\n baker images pinterest 'cozy coffee shop interior' --auto-ingest 2 --context 'Mood reference for hero photography'"
@@ -15677,7 +17346,7 @@ var pinterestCommand = defineCommand111({
15677
17346
  });
15678
17347
 
15679
17348
  // src/commands/images/screenshot.ts
15680
- import { defineCommand as defineCommand112 } from "citty";
17349
+ import { defineCommand as defineCommand114 } from "citty";
15681
17350
  registerSchema({
15682
17351
  command: "images.screenshot",
15683
17352
  description: "Capture a website screenshot via ScreenshotOne. Auto-ingests on success.",
@@ -15693,7 +17362,7 @@ registerSchema({
15693
17362
  }
15694
17363
  }
15695
17364
  });
15696
- var screenshotCommand = defineCommand112({
17365
+ var screenshotCommand = defineCommand114({
15697
17366
  meta: {
15698
17367
  name: "screenshot",
15699
17368
  description: "Screenshot a URL via ScreenshotOne. $0.009/capture. Auto-ingests to library.\n\nExample: baker images screenshot https://stripe.com --full-page"
@@ -15743,7 +17412,7 @@ var screenshotCommand = defineCommand112({
15743
17412
  });
15744
17413
 
15745
17414
  // src/commands/images/search.ts
15746
- import { defineCommand as defineCommand113 } from "citty";
17415
+ import { defineCommand as defineCommand115 } from "citty";
15747
17416
  registerSchema({
15748
17417
  command: "images.search",
15749
17418
  description: "Search images by text query. Only returns ready images.",
@@ -15759,7 +17428,7 @@ registerSchema({
15759
17428
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
15760
17429
  }
15761
17430
  });
15762
- var searchCommand = defineCommand113({
17431
+ var searchCommand = defineCommand115({
15763
17432
  meta: {
15764
17433
  name: "search",
15765
17434
  description: "Semantic search images by text query. Uses hybrid BM25 + vector + reranking. Example: baker images search 'hero banner' --aspect-ratio 16:9 --tags logo"
@@ -15819,7 +17488,7 @@ var searchCommand = defineCommand113({
15819
17488
  });
15820
17489
 
15821
17490
  // src/commands/images/sticker.ts
15822
- import { defineCommand as defineCommand114 } from "citty";
17491
+ import { defineCommand as defineCommand116 } from "citty";
15823
17492
  registerSchema({
15824
17493
  command: "images.sticker",
15825
17494
  description: "Search Giphy stickers \u2014 transparent-background overlays for ad creative.",
@@ -15851,7 +17520,7 @@ registerSchema({
15851
17520
  }
15852
17521
  }
15853
17522
  });
15854
- var stickerCommand = defineCommand114({
17523
+ var stickerCommand = defineCommand116({
15855
17524
  meta: {
15856
17525
  name: "sticker",
15857
17526
  description: "Search Giphy's sticker corpus \u2014 transparent-background WebPs / GIFs ideal for overlaying on ad creative (Meta, TikTok, Stories). Same Giphy free API as `baker images gif`; results carry WebP + GIF + MP4 URLs in providerMeta.\n\nExample: baker images sticker 'thumbs up' --limit 10\nExample: baker images sticker celebration --rating g --auto-ingest 3\nExample: baker images sticker --trending --limit 25"
@@ -15898,7 +17567,7 @@ var stickerCommand = defineCommand114({
15898
17567
  });
15899
17568
 
15900
17569
  // src/commands/images/stock.ts
15901
- import { defineCommand as defineCommand115 } from "citty";
17570
+ import { defineCommand as defineCommand117 } from "citty";
15902
17571
  registerSchema({
15903
17572
  command: "images.stock",
15904
17573
  description: "Stock photo, vector illustration, icon-set, and PSD search via Magnific (Freepik's developer API).",
@@ -15956,7 +17625,7 @@ registerSchema({
15956
17625
  }
15957
17626
  }
15958
17627
  });
15959
- var stockCommand = defineCommand115({
17628
+ var stockCommand = defineCommand117({
15960
17629
  meta: {
15961
17630
  name: "stock",
15962
17631
  description: "Stock search via Magnific \u2014 Freepik's developer API (~250M assets: photos, vectors, illustrations, icons, PSDs). $0.002/req. With --auto-ingest, ingested hits return Baker-owned URLs.\n\nExamples:\n baker images stock 'minimalist office'\n baker images stock 'flat office workers' --type vector\n baker images stock 'hero photo of a kitchen' --type photo --orientation landscape --ai exclude\n baker images stock 'brand pattern' --color '#0a0a0a' --license freemium --auto-ingest 2"
@@ -16012,7 +17681,7 @@ var stockCommand = defineCommand115({
16012
17681
  });
16013
17682
 
16014
17683
  // src/lib/tags-command.ts
16015
- import { defineCommand as defineCommand116 } from "citty";
17684
+ import { defineCommand as defineCommand118 } from "citty";
16016
17685
  function makeTagsCommand(command, label, endpoint) {
16017
17686
  registerSchema({
16018
17687
  command: `${command}.tags`,
@@ -16021,7 +17690,7 @@ function makeTagsCommand(command, label, endpoint) {
16021
17690
  output: { type: "string", description: "Output format: md|json", required: false, default: "md" }
16022
17691
  }
16023
17692
  });
16024
- return defineCommand116({
17693
+ return defineCommand118({
16025
17694
  meta: {
16026
17695
  name: "tags",
16027
17696
  description: `List the available ${label} tag names (defaults + company custom tags). Use before filtering with --tags. Example: baker ${command} tags`
@@ -16057,7 +17726,7 @@ function makeTagsCommand(command, label, endpoint) {
16057
17726
  var tagsCommand2 = makeTagsCommand("images", "image", "/api/images/tags");
16058
17727
 
16059
17728
  // src/commands/images/upload.ts
16060
- import { defineCommand as defineCommand117 } from "citty";
17729
+ import { defineCommand as defineCommand119 } from "citty";
16061
17730
  registerSchema({
16062
17731
  command: "images.upload",
16063
17732
  description: "Upload an image to the library \u2014 local file path or remote http(s) URL.",
@@ -16095,7 +17764,7 @@ registerSchema({
16095
17764
  function isRemoteUrl2(value) {
16096
17765
  return /^https?:\/\//i.test(value);
16097
17766
  }
16098
- var uploadCommand = defineCommand117({
17767
+ var uploadCommand = defineCommand119({
16099
17768
  meta: {
16100
17769
  name: "upload",
16101
17770
  description: "Upload an image to the library \u2014 accepts a local file path OR a remote http(s) URL.\n\nLocal: reads bytes, sends to /api/images/upload, content-type auto-detected from extension.\nRemote: dispatches to /api/images/ingest with hash-dedup on bytes + externalId.\n\nExamples:\n baker images upload ./logo.png --source uploaded\n baker images upload ./cert.png --context 'ISO 27001 badge \u2014 enterprise tier'\n baker images upload https://acme.com/hero.png --source firecrawl --context 'Acme competitor pricing hero'"
@@ -16188,7 +17857,7 @@ async function uploadLocal(target, args) {
16188
17857
  }
16189
17858
 
16190
17859
  // src/commands/images/upscale.ts
16191
- import { defineCommand as defineCommand118 } from "citty";
17860
+ import { defineCommand as defineCommand120 } from "citty";
16192
17861
  registerSchema({
16193
17862
  command: "images.upscale",
16194
17863
  description: "Upscale a library image via the backend (Replicate, cost-tracked). Waits for completion by default. The image must be status 'ready' and raster (not SVG/AVIF).",
@@ -16203,7 +17872,7 @@ registerSchema({
16203
17872
  }
16204
17873
  });
16205
17874
  var POLL_INTERVAL_MS3 = 1500;
16206
- var upscaleCommand = defineCommand118({
17875
+ var upscaleCommand = defineCommand120({
16207
17876
  meta: {
16208
17877
  name: "upscale",
16209
17878
  description: "Upscale a library image via the Convex backend (Replicate, cost-tracked at $0.05/image). Waits for completion by default.\n\nExample: baker images upscale j571abc123def\nExample: baker images upscale j571abc123def --max-wait 0 # fire-and-forget"
@@ -16258,7 +17927,7 @@ var upscaleCommand = defineCommand118({
16258
17927
  });
16259
17928
 
16260
17929
  // src/commands/images/use.ts
16261
- import { defineCommand as defineCommand119 } from "citty";
17930
+ import { defineCommand as defineCommand121 } from "citty";
16262
17931
  registerSchema({
16263
17932
  command: "images.use",
16264
17933
  description: "Ingest a URL and wait for the library record to be ready.",
@@ -16274,7 +17943,7 @@ registerSchema({
16274
17943
  }
16275
17944
  });
16276
17945
  var POLL_INTERVAL_MS4 = 1500;
16277
- var useCommand = defineCommand119({
17946
+ var useCommand = defineCommand121({
16278
17947
  meta: {
16279
17948
  name: "use",
16280
17949
  description: "Sugar over `ingest`: download \u2192 store \u2192 wait until describe + embed complete \u2192 return ready library record.\n\nExample: baker images use https://cdn.example.com/hero.png --source uploaded"
@@ -16320,7 +17989,7 @@ var useCommand = defineCommand119({
16320
17989
  });
16321
17990
 
16322
17991
  // src/commands/images/index.ts
16323
- var imagesCommand = defineCommand120({
17992
+ var imagesCommand = defineCommand122({
16324
17993
  meta: {
16325
17994
  name: "images",
16326
17995
  description: `Find, source, and normalize images. Subcommands route by provider so cost + license are explicit.
@@ -16390,10 +18059,10 @@ Paid transforms (run on the Convex backend, cost-tracked):
16390
18059
  });
16391
18060
 
16392
18061
  // src/commands/research/index.ts
16393
- import { defineCommand as defineCommand131 } from "citty";
18062
+ import { defineCommand as defineCommand133 } from "citty";
16394
18063
 
16395
18064
  // src/commands/research/advertisers.ts
16396
- import { defineCommand as defineCommand121 } from "citty";
18065
+ import { defineCommand as defineCommand123 } from "citty";
16397
18066
 
16398
18067
  // src/commands/research/output.ts
16399
18068
  var RESEARCH_DATA_NOTE = "Estimates based on third-party SERP data \u2014 not exact figures. Use for directional insights, not precise measurement.";
@@ -16506,7 +18175,7 @@ var FIELDS3 = {
16506
18175
  etv: "Estimated traffic value (USD)",
16507
18176
  visibility: "SERP visibility score (0-1)"
16508
18177
  };
16509
- var advertisersCommand = defineCommand121({
18178
+ var advertisersCommand = defineCommand123({
16510
18179
  meta: {
16511
18180
  name: "advertisers",
16512
18181
  description: `Find domains competing for a keyword in Google SERPs.
@@ -16553,7 +18222,7 @@ Examples:
16553
18222
  });
16554
18223
 
16555
18224
  // src/commands/research/autocomplete.ts
16556
- import { defineCommand as defineCommand122 } from "citty";
18225
+ import { defineCommand as defineCommand124 } from "citty";
16557
18226
  registerSchema({
16558
18227
  command: "research.autocomplete",
16559
18228
  description: "Get Google Autocomplete suggestions for a seed keyword. Useful for keyword expansion and discovering what people actually search for. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en).",
@@ -16576,7 +18245,7 @@ registerSchema({
16576
18245
  var FIELDS4 = {
16577
18246
  suggestion: "Autocomplete suggestion from Google"
16578
18247
  };
16579
- var autocompleteCommand = defineCommand122({
18248
+ var autocompleteCommand = defineCommand124({
16580
18249
  meta: {
16581
18250
  name: "autocomplete",
16582
18251
  description: `Get Google Autocomplete suggestions for keyword expansion.
@@ -16622,7 +18291,7 @@ Examples:
16622
18291
  });
16623
18292
 
16624
18293
  // src/commands/research/countries.ts
16625
- import { defineCommand as defineCommand123 } from "citty";
18294
+ import { defineCommand as defineCommand125 } from "citty";
16626
18295
  registerSchema({
16627
18296
  command: "research.countries",
16628
18297
  description: "List all supported country codes for --location flag in research commands.",
@@ -16679,7 +18348,7 @@ var FIELDS5 = {
16679
18348
  code: "Country code to pass as --location",
16680
18349
  name: "Country name"
16681
18350
  };
16682
- var countriesCommand = defineCommand123({
18351
+ var countriesCommand = defineCommand125({
16683
18352
  meta: {
16684
18353
  name: "countries",
16685
18354
  description: "List all supported country codes for --location flag."
@@ -16690,7 +18359,7 @@ var countriesCommand = defineCommand123({
16690
18359
  });
16691
18360
 
16692
18361
  // src/commands/research/intent.ts
16693
- import { defineCommand as defineCommand124 } from "citty";
18362
+ import { defineCommand as defineCommand126 } from "citty";
16694
18363
  registerSchema({
16695
18364
  command: "research.intent",
16696
18365
  description: "Classify Google Search intent for keywords. Determines if someone searching is looking to buy, research, or navigate. IMPORTANT: If --language is omitted, defaults to English (en). The response includes a query_context object showing which language was used.",
@@ -16713,7 +18382,7 @@ var FIELDS6 = {
16713
18382
  intent: "Primary Google Search intent: informational, navigational, commercial, transactional",
16714
18383
  probability: "Confidence score 0.0-1.0"
16715
18384
  };
16716
- var intentCommand = defineCommand124({
18385
+ var intentCommand = defineCommand126({
16717
18386
  meta: {
16718
18387
  name: "intent",
16719
18388
  description: `Classify Google Search intent for keywords. Returns intent type and confidence.
@@ -16761,7 +18430,7 @@ Examples:
16761
18430
  });
16762
18431
 
16763
18432
  // src/commands/research/keyword-gap.ts
16764
- import { defineCommand as defineCommand125 } from "citty";
18433
+ import { defineCommand as defineCommand127 } from "citty";
16765
18434
  registerSchema({
16766
18435
  command: "research.keyword-gap",
16767
18436
  description: "Find keywords a competitor ranks for (organic or paid) that you don't. Discovers expansion opportunities. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en). The response includes a query_context object showing which location/language were used.",
@@ -16790,7 +18459,7 @@ var FIELDS7 = {
16790
18459
  cpc: "Cost per click USD",
16791
18460
  their_position: "Competitor's ranking position"
16792
18461
  };
16793
- var keywordGapCommand = defineCommand125({
18462
+ var keywordGapCommand = defineCommand127({
16794
18463
  meta: {
16795
18464
  name: "keyword-gap",
16796
18465
  description: `Find keywords a competitor has that you don't. Supports pagination via --offset.
@@ -16864,7 +18533,7 @@ Examples:
16864
18533
  });
16865
18534
 
16866
18535
  // src/commands/research/keywords-for-site.ts
16867
- import { defineCommand as defineCommand126 } from "citty";
18536
+ import { defineCommand as defineCommand128 } from "citty";
16868
18537
  registerSchema({
16869
18538
  command: "research.keywords-for-site",
16870
18539
  description: "Get keywords a competitor targets in Google. Use --type paid to see only paid keywords, --type organic for organic only. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en). The response includes a query_context object showing which location/language were used.",
@@ -16897,7 +18566,7 @@ var FIELDS8 = {
16897
18566
  competition: "LOW, MEDIUM, or HIGH",
16898
18567
  competition_index: "Competition score 0-100"
16899
18568
  };
16900
- var keywordsForSiteCommand = defineCommand126({
18569
+ var keywordsForSiteCommand = defineCommand128({
16901
18570
  meta: {
16902
18571
  name: "keywords-for-site",
16903
18572
  description: `Get keywords a competitor targets in Google. Use --type to filter paid/organic.
@@ -16950,7 +18619,7 @@ Examples:
16950
18619
  });
16951
18620
 
16952
18621
  // src/commands/research/languages.ts
16953
- import { defineCommand as defineCommand127 } from "citty";
18622
+ import { defineCommand as defineCommand129 } from "citty";
16954
18623
  registerSchema({
16955
18624
  command: "research.languages",
16956
18625
  description: "List all supported language codes for --language flag in research commands.",
@@ -16980,7 +18649,7 @@ var FIELDS9 = {
16980
18649
  code: "Language code to pass as --language",
16981
18650
  name: "Language name (also accepted by --language)"
16982
18651
  };
16983
- var languagesCommand2 = defineCommand127({
18652
+ var languagesCommand2 = defineCommand129({
16984
18653
  meta: {
16985
18654
  name: "languages",
16986
18655
  description: "List all supported language codes for --language flag."
@@ -16991,7 +18660,7 @@ var languagesCommand2 = defineCommand127({
16991
18660
  });
16992
18661
 
16993
18662
  // src/commands/research/lighthouse.ts
16994
- import { defineCommand as defineCommand128 } from "citty";
18663
+ import { defineCommand as defineCommand130 } from "citty";
16995
18664
  registerSchema({
16996
18665
  command: "research.lighthouse",
16997
18666
  description: "Landing page performance audit. Returns metrics that affect Google Ads Quality Score and CPC.",
@@ -17010,7 +18679,7 @@ var FIELDS10 = {
17010
18679
  speed_index_ms: "Speed Index in ms (good: < 3400)",
17011
18680
  interactive_ms: "Time to Interactive in ms (good: < 3800)"
17012
18681
  };
17013
- var lighthouseCommand = defineCommand128({
18682
+ var lighthouseCommand = defineCommand130({
17014
18683
  meta: {
17015
18684
  name: "lighthouse",
17016
18685
  description: `Landing page performance audit. Metrics affecting Google Ads Quality Score.
@@ -17048,7 +18717,7 @@ Examples:
17048
18717
  });
17049
18718
 
17050
18719
  // src/commands/research/relevant-pages.ts
17051
- import { defineCommand as defineCommand129 } from "citty";
18720
+ import { defineCommand as defineCommand131 } from "citty";
17052
18721
  registerSchema({
17053
18722
  command: "research.relevant-pages",
17054
18723
  description: "Get the top pages of a competitor domain with organic traffic and ranking data. Shows which pages drive the most traffic. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en).",
@@ -17074,7 +18743,7 @@ var FIELDS11 = {
17074
18743
  keywords: "Total organic keywords the page ranks for",
17075
18744
  top_10: "Keywords in positions 1-10"
17076
18745
  };
17077
- var relevantPagesCommand = defineCommand129({
18746
+ var relevantPagesCommand = defineCommand131({
17078
18747
  meta: {
17079
18748
  name: "relevant-pages",
17080
18749
  description: `Get the top pages of a competitor domain with traffic data.
@@ -17120,7 +18789,7 @@ Examples:
17120
18789
  });
17121
18790
 
17122
18791
  // src/commands/research/web.ts
17123
- import { defineCommand as defineCommand130 } from "citty";
18792
+ import { defineCommand as defineCommand132 } from "citty";
17124
18793
  registerSchema({
17125
18794
  command: "research.web",
17126
18795
  description: "Search the web with AI to answer marketing questions \u2014 competitors, ICP, pricing, pain points, market trends. Three depth levels: medium (quick, default), high (thorough), xhigh (exhaustive deep research).",
@@ -17171,7 +18840,7 @@ async function runDeepResearch(question) {
17171
18840
  }
17172
18841
  throw new Error("Deep research timed out");
17173
18842
  }
17174
- var webCommand = defineCommand130({
18843
+ var webCommand = defineCommand132({
17175
18844
  meta: {
17176
18845
  name: "web",
17177
18846
  description: `Search the web with AI to answer any open-ended marketing question. Uses live internet data via Google Search.
@@ -17231,7 +18900,7 @@ Examples:
17231
18900
  });
17232
18901
 
17233
18902
  // src/commands/research/index.ts
17234
- var researchCommand = defineCommand131({
18903
+ var researchCommand = defineCommand133({
17235
18904
  meta: {
17236
18905
  name: "research",
17237
18906
  description: `Competitive intelligence and AI-powered research commands.
@@ -17271,10 +18940,10 @@ Examples:
17271
18940
  });
17272
18941
 
17273
18942
  // src/commands/scheduled-actions/index.ts
17274
- import { defineCommand as defineCommand138 } from "citty";
18943
+ import { defineCommand as defineCommand140 } from "citty";
17275
18944
 
17276
18945
  // src/commands/scheduled-actions/create.ts
17277
- import { defineCommand as defineCommand132 } from "citty";
18946
+ import { defineCommand as defineCommand134 } from "citty";
17278
18947
 
17279
18948
  // src/commands/scheduled-actions/shared.ts
17280
18949
  var TEMP_SCHEDULED_ACTION_PREFIX = "temp_sched_";
@@ -17389,7 +19058,7 @@ registerSchema({
17389
19058
  prompt: { type: "string", description: "Additional prompt instructions for the spawned agent", required: false }
17390
19059
  }
17391
19060
  });
17392
- var createCommand2 = defineCommand132({
19061
+ var createCommand2 = defineCommand134({
17393
19062
  meta: {
17394
19063
  name: "create",
17395
19064
  description: 'Stage a scheduled action. Example: baker scheduled-actions create --name "Weekly report" --description "..." --cron "0 9 * * MON"'
@@ -17438,7 +19107,7 @@ var createCommand2 = defineCommand132({
17438
19107
  });
17439
19108
 
17440
19109
  // src/commands/scheduled-actions/delete.ts
17441
- import { defineCommand as defineCommand133 } from "citty";
19110
+ import { defineCommand as defineCommand135 } from "citty";
17442
19111
  registerSchema({
17443
19112
  command: "scheduled-actions.delete",
17444
19113
  description: "Stage deletion of a published scheduled action or cancellation of a temp_sched_* draft creation.",
@@ -17446,7 +19115,7 @@ registerSchema({
17446
19115
  id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
17447
19116
  }
17448
19117
  });
17449
- var deleteCommand2 = defineCommand133({
19118
+ var deleteCommand2 = defineCommand135({
17450
19119
  meta: {
17451
19120
  name: "delete",
17452
19121
  description: "Stage scheduled action deletion. Example: baker scheduled-actions delete <id-or-temp_sched_id>"
@@ -17475,7 +19144,7 @@ var deleteCommand2 = defineCommand133({
17475
19144
  });
17476
19145
 
17477
19146
  // src/commands/scheduled-actions/get.ts
17478
- import { defineCommand as defineCommand134 } from "citty";
19147
+ import { defineCommand as defineCommand136 } from "citty";
17479
19148
  registerSchema({
17480
19149
  command: "scheduled-actions.get",
17481
19150
  description: "Get a published scheduled action or a temp_sched_* draft-created scheduled action.",
@@ -17483,7 +19152,7 @@ registerSchema({
17483
19152
  id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
17484
19153
  }
17485
19154
  });
17486
- var getCommand3 = defineCommand134({
19155
+ var getCommand3 = defineCommand136({
17487
19156
  meta: {
17488
19157
  name: "get",
17489
19158
  description: "Get a scheduled action. Example: baker scheduled-actions get <id-or-temp_sched_id>"
@@ -17520,13 +19189,13 @@ var getCommand3 = defineCommand134({
17520
19189
  });
17521
19190
 
17522
19191
  // src/commands/scheduled-actions/list.ts
17523
- import { defineCommand as defineCommand135 } from "citty";
19192
+ import { defineCommand as defineCommand137 } from "citty";
17524
19193
  registerSchema({
17525
19194
  command: "scheduled-actions.list",
17526
19195
  description: "List published scheduled actions. Includes draft state when BAKER_CHAT_ID is set.",
17527
19196
  args: {}
17528
19197
  });
17529
- var listCommand3 = defineCommand135({
19198
+ var listCommand4 = defineCommand137({
17530
19199
  meta: {
17531
19200
  name: "list",
17532
19201
  description: "List scheduled actions. Includes staged draft ops when BAKER_CHAT_ID is set."
@@ -17547,7 +19216,7 @@ var listCommand3 = defineCommand135({
17547
19216
  });
17548
19217
 
17549
19218
  // src/commands/scheduled-actions/trigger.ts
17550
- import { defineCommand as defineCommand136 } from "citty";
19219
+ import { defineCommand as defineCommand138 } from "citty";
17551
19220
  registerSchema({
17552
19221
  command: "scheduled-actions.trigger",
17553
19222
  description: "Immediately trigger a published scheduled action. Does not require BAKER_CHAT_ID and rejects temp_sched_* IDs.",
@@ -17555,7 +19224,7 @@ registerSchema({
17555
19224
  id: { type: "string", description: "Published scheduled action ID", required: true }
17556
19225
  }
17557
19226
  });
17558
- var triggerCommand = defineCommand136({
19227
+ var triggerCommand = defineCommand138({
17559
19228
  meta: {
17560
19229
  name: "trigger",
17561
19230
  description: "Immediately trigger a published scheduled action. Example: baker scheduled-actions trigger <id>"
@@ -17592,7 +19261,7 @@ var triggerCommand = defineCommand136({
17592
19261
  });
17593
19262
 
17594
19263
  // src/commands/scheduled-actions/update.ts
17595
- import { defineCommand as defineCommand137 } from "citty";
19264
+ import { defineCommand as defineCommand139 } from "citty";
17596
19265
  registerSchema({
17597
19266
  command: "scheduled-actions.update",
17598
19267
  description: "Stage an update to a published scheduled action or temp_sched_* draft-created scheduled action.",
@@ -17617,7 +19286,7 @@ registerSchema({
17617
19286
  prompt: { type: "string", description: "Replacement additional spawned-agent instructions", required: false }
17618
19287
  }
17619
19288
  });
17620
- var updateCommand2 = defineCommand137({
19289
+ var updateCommand2 = defineCommand139({
17621
19290
  meta: {
17622
19291
  name: "update",
17623
19292
  description: "Stage a scheduled action update. Example: baker scheduled-actions update <id> --enabled false"
@@ -17688,7 +19357,7 @@ var updateCommand2 = defineCommand137({
17688
19357
  });
17689
19358
 
17690
19359
  // src/commands/scheduled-actions/index.ts
17691
- var scheduledActionsCommand = defineCommand138({
19360
+ var scheduledActionsCommand = defineCommand140({
17692
19361
  meta: {
17693
19362
  name: "scheduled-actions",
17694
19363
  description: `Manage Scheduled Actions. Subcommands: list, get, create, update, delete, trigger.
@@ -17704,7 +19373,7 @@ Examples:
17704
19373
  baker scheduled-actions trigger <id>`
17705
19374
  },
17706
19375
  subCommands: {
17707
- list: listCommand3,
19376
+ list: listCommand4,
17708
19377
  get: getCommand3,
17709
19378
  create: createCommand2,
17710
19379
  update: updateCommand2,
@@ -17714,8 +19383,8 @@ Examples:
17714
19383
  });
17715
19384
 
17716
19385
  // src/commands/schema.ts
17717
- import { defineCommand as defineCommand139 } from "citty";
17718
- var schemaCommand = defineCommand139({
19386
+ import { defineCommand as defineCommand141 } from "citty";
19387
+ var schemaCommand = defineCommand141({
17719
19388
  meta: {
17720
19389
  name: "schema",
17721
19390
  description: "Inspect command argument schemas (for AI agent introspection). Lists all commands if no argument given. Example: baker schema images.search"
@@ -17751,10 +19420,10 @@ var schemaCommand = defineCommand139({
17751
19420
  });
17752
19421
 
17753
19422
  // src/commands/testimonials/index.ts
17754
- import { defineCommand as defineCommand143 } from "citty";
19423
+ import { defineCommand as defineCommand145 } from "citty";
17755
19424
 
17756
19425
  // src/commands/testimonials/get.ts
17757
- import { defineCommand as defineCommand140 } from "citty";
19426
+ import { defineCommand as defineCommand142 } from "citty";
17758
19427
  registerSchema({
17759
19428
  command: "testimonials.get",
17760
19429
  description: "Get a single testimonial by ID",
@@ -17762,7 +19431,7 @@ registerSchema({
17762
19431
  id: { type: "string", description: "Testimonial ID", required: true }
17763
19432
  }
17764
19433
  });
17765
- var getCommand4 = defineCommand140({
19434
+ var getCommand4 = defineCommand142({
17766
19435
  meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
17767
19436
  args: {
17768
19437
  id: { type: "positional", description: "Testimonial ID", required: false },
@@ -17799,7 +19468,7 @@ var getCommand4 = defineCommand140({
17799
19468
  });
17800
19469
 
17801
19470
  // src/commands/testimonials/list.ts
17802
- import { defineCommand as defineCommand141 } from "citty";
19471
+ import { defineCommand as defineCommand143 } from "citty";
17803
19472
  registerSchema({
17804
19473
  command: "testimonials.list",
17805
19474
  description: "List testimonials with optional filters.",
@@ -17829,7 +19498,7 @@ registerSchema({
17829
19498
  limit: { type: "number", description: "Max results (default 50)", required: false, default: 50 }
17830
19499
  }
17831
19500
  });
17832
- var listCommand4 = defineCommand141({
19501
+ var listCommand5 = defineCommand143({
17833
19502
  meta: {
17834
19503
  name: "list",
17835
19504
  description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
@@ -17878,7 +19547,7 @@ var listCommand4 = defineCommand141({
17878
19547
  });
17879
19548
 
17880
19549
  // src/commands/testimonials/search.ts
17881
- import { defineCommand as defineCommand142 } from "citty";
19550
+ import { defineCommand as defineCommand144 } from "citty";
17882
19551
  registerSchema({
17883
19552
  command: "testimonials.search",
17884
19553
  description: "Search testimonials by text query. Uses hybrid BM25 + vector + reranking.",
@@ -17909,7 +19578,7 @@ registerSchema({
17909
19578
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
17910
19579
  }
17911
19580
  });
17912
- var searchCommand2 = defineCommand142({
19581
+ var searchCommand2 = defineCommand144({
17913
19582
  meta: {
17914
19583
  name: "search",
17915
19584
  description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
@@ -17983,7 +19652,7 @@ var searchCommand2 = defineCommand142({
17983
19652
  var tagsCommand3 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
17984
19653
 
17985
19654
  // src/commands/testimonials/index.ts
17986
- var testimonialsCommand = defineCommand143({
19655
+ var testimonialsCommand = defineCommand145({
17987
19656
  meta: {
17988
19657
  name: "testimonials",
17989
19658
  description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
@@ -17998,16 +19667,16 @@ Examples:
17998
19667
  subCommands: {
17999
19668
  get: getCommand4,
18000
19669
  search: searchCommand2,
18001
- list: listCommand4,
19670
+ list: listCommand5,
18002
19671
  tags: tagsCommand3
18003
19672
  }
18004
19673
  });
18005
19674
 
18006
19675
  // src/commands/videos/index.ts
18007
- import { defineCommand as defineCommand148 } from "citty";
19676
+ import { defineCommand as defineCommand150 } from "citty";
18008
19677
 
18009
19678
  // src/commands/videos/delete.ts
18010
- import { defineCommand as defineCommand144 } from "citty";
19679
+ import { defineCommand as defineCommand146 } from "citty";
18011
19680
  registerSchema({
18012
19681
  command: "videos.delete",
18013
19682
  description: "Delete a video by ID",
@@ -18021,7 +19690,7 @@ registerSchema({
18021
19690
  }
18022
19691
  }
18023
19692
  });
18024
- var deleteCommand3 = defineCommand144({
19693
+ var deleteCommand3 = defineCommand146({
18025
19694
  meta: {
18026
19695
  name: "delete",
18027
19696
  description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
@@ -18062,7 +19731,7 @@ var deleteCommand3 = defineCommand144({
18062
19731
  });
18063
19732
 
18064
19733
  // src/commands/videos/get.ts
18065
- import { defineCommand as defineCommand145 } from "citty";
19734
+ import { defineCommand as defineCommand147 } from "citty";
18066
19735
  registerSchema({
18067
19736
  command: "videos.get",
18068
19737
  description: "Get a single video by ID",
@@ -18070,7 +19739,7 @@ registerSchema({
18070
19739
  id: { type: "string", description: "Video ID", required: true }
18071
19740
  }
18072
19741
  });
18073
- var getCommand5 = defineCommand145({
19742
+ var getCommand5 = defineCommand147({
18074
19743
  meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
18075
19744
  args: {
18076
19745
  id: { type: "positional", description: "Video ID", required: false },
@@ -18107,7 +19776,7 @@ var getCommand5 = defineCommand145({
18107
19776
  });
18108
19777
 
18109
19778
  // src/commands/videos/search.ts
18110
- import { defineCommand as defineCommand146 } from "citty";
19779
+ import { defineCommand as defineCommand148 } from "citty";
18111
19780
  registerSchema({
18112
19781
  command: "videos.search",
18113
19782
  description: "Search videos by text query. Only returns ready videos.",
@@ -18117,7 +19786,7 @@ registerSchema({
18117
19786
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
18118
19787
  }
18119
19788
  });
18120
- var searchCommand3 = defineCommand146({
19789
+ var searchCommand3 = defineCommand148({
18121
19790
  meta: {
18122
19791
  name: "search",
18123
19792
  description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
@@ -18169,7 +19838,7 @@ var tagsCommand4 = makeTagsCommand("videos", "video", "/api/videos/tags");
18169
19838
  // src/commands/videos/upload.ts
18170
19839
  import { readFile as readFile12, stat as stat3 } from "fs/promises";
18171
19840
  import { extname as extname3 } from "path";
18172
- import { defineCommand as defineCommand147 } from "citty";
19841
+ import { defineCommand as defineCommand149 } from "citty";
18173
19842
  var MIME_MAP = {
18174
19843
  ".mp4": "video/mp4",
18175
19844
  ".mov": "video/quicktime",
@@ -18203,7 +19872,7 @@ function detectContentType(filePath) {
18203
19872
  }
18204
19873
  return mime;
18205
19874
  }
18206
- var uploadCommand2 = defineCommand147({
19875
+ var uploadCommand2 = defineCommand149({
18207
19876
  meta: {
18208
19877
  name: "upload",
18209
19878
  description: "Upload a video file to Baker via Mux direct upload. Auto-detects content type. Example: baker videos upload ./demo.mp4"
@@ -18257,7 +19926,7 @@ var uploadCommand2 = defineCommand147({
18257
19926
  });
18258
19927
 
18259
19928
  // src/commands/videos/index.ts
18260
- var videosCommand = defineCommand148({
19929
+ var videosCommand = defineCommand150({
18261
19930
  meta: {
18262
19931
  name: "videos",
18263
19932
  description: `Find and manage videos in Baker. Subcommands: search, get, upload, delete, tags.
@@ -18280,10 +19949,10 @@ Examples:
18280
19949
  });
18281
19950
 
18282
19951
  // src/commands/winning-ads/index.ts
18283
- import { defineCommand as defineCommand151 } from "citty";
19952
+ import { defineCommand as defineCommand153 } from "citty";
18284
19953
 
18285
19954
  // src/commands/winning-ads/advertisers.ts
18286
- import { defineCommand as defineCommand149 } from "citty";
19955
+ import { defineCommand as defineCommand151 } from "citty";
18287
19956
  registerSchema({
18288
19957
  command: "winning-ads.advertisers",
18289
19958
  description: "Resolve a brand name to advertiser_id(s) in the ad-dna corpus \u2014 to find your OWN advertiser (to --exclude-advertiser) or a competitor (to --advertiser-id).",
@@ -18296,7 +19965,7 @@ registerSchema({
18296
19965
  function identity(record) {
18297
19966
  return record;
18298
19967
  }
18299
- var advertisersCommand2 = defineCommand149({
19968
+ var advertisersCommand2 = defineCommand151({
18300
19969
  meta: {
18301
19970
  name: "advertisers",
18302
19971
  description: 'Resolve a brand name to advertiser_id(s). Use it to find your own advertiser for --exclude-advertiser, or a competitor for --advertiser-id. Example: baker winning-ads advertisers "Deel" --output md'
@@ -18347,7 +20016,7 @@ var advertisersCommand2 = defineCommand149({
18347
20016
  });
18348
20017
 
18349
20018
  // src/commands/winning-ads/search.ts
18350
- import { defineCommand as defineCommand150 } from "citty";
20019
+ import { defineCommand as defineCommand152 } from "citty";
18351
20020
  registerSchema({
18352
20021
  command: "winning-ads.search",
18353
20022
  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.",
@@ -18455,7 +20124,7 @@ function buildSearchBody(args) {
18455
20124
  }
18456
20125
  return body;
18457
20126
  }
18458
- var searchCommand4 = defineCommand150({
20127
+ var searchCommand4 = defineCommand152({
18459
20128
  meta: {
18460
20129
  name: "search",
18461
20130
  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"
@@ -18567,7 +20236,7 @@ var searchCommand4 = defineCommand150({
18567
20236
  });
18568
20237
 
18569
20238
  // src/commands/winning-ads/index.ts
18570
- var winningAdsCommand = defineCommand151({
20239
+ var winningAdsCommand = defineCommand153({
18571
20240
  meta: {
18572
20241
  name: "winning-ads",
18573
20242
  description: `Search the ad-dna corpus of scored "winning" ads for reference creatives to reproduce. Proxied through the Baker backend (BAKER_API_KEY) \u2014 no separate token needed.
@@ -18591,7 +20260,7 @@ Examples:
18591
20260
  });
18592
20261
 
18593
20262
  // src/version.ts
18594
- import { readFileSync as readFileSync9 } from "fs";
20263
+ import { readFileSync as readFileSync10 } from "fs";
18595
20264
  function packageJsonUrl() {
18596
20265
  return new URL("../package.json", import.meta.url);
18597
20266
  }
@@ -18603,11 +20272,11 @@ function parsePackageVersion(raw) {
18603
20272
  throw new Error("Invalid CLI package.json: missing version");
18604
20273
  }
18605
20274
  function getCliVersion() {
18606
- return parsePackageVersion(readFileSync9(packageJsonUrl(), "utf8"));
20275
+ return parsePackageVersion(readFileSync10(packageJsonUrl(), "utf8"));
18607
20276
  }
18608
20277
 
18609
20278
  // src/cli.ts
18610
- var main = defineCommand152({
20279
+ var main = defineCommand154({
18611
20280
  meta: {
18612
20281
  name: "baker",
18613
20282
  version: getCliVersion(),