@koda-sl/baker-cli 0.113.2 → 0.114.0-dev.249eaa8ed

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
@@ -12,10 +12,10 @@ import {
12
12
  generateCatalog,
13
13
  resolveConcurrency,
14
14
  validateCanvasDeep
15
- } from "./chunk-7K2YAWUT.js";
15
+ } from "./chunk-5AWO4BHJ.js";
16
16
 
17
17
  // src/cli.ts
18
- import { defineCommand as defineCommand155, runMain } from "citty";
18
+ import { defineCommand as defineCommand157, runMain } from "citty";
19
19
 
20
20
  // src/commands/actions/index.ts
21
21
  import { defineCommand as defineCommand18 } from "citty";
@@ -2847,10 +2847,10 @@ Examples:
2847
2847
  });
2848
2848
 
2849
2849
  // src/commands/ads/index.ts
2850
- import { defineCommand as defineCommand80 } from "citty";
2850
+ import { defineCommand as defineCommand82 } from "citty";
2851
2851
 
2852
2852
  // src/commands/ads/google/index.ts
2853
- import { defineCommand as defineCommand29 } from "citty";
2853
+ import { defineCommand as defineCommand31 } from "citty";
2854
2854
 
2855
2855
  // src/commands/ads/google/accounts.ts
2856
2856
  import { defineCommand as defineCommand19 } from "citty";
@@ -3268,6 +3268,28 @@ function buildCommand(query, ctx) {
3268
3268
  return `baker ads google query "${query}" --customer-id ${ctx.customerId}`;
3269
3269
  }
3270
3270
  var CORRECTION_RULES = [
3271
+ // 0. EXPECTED_REFERENCED_FIELD_IN_SELECT_CLAUSE — some resources (e.g. campaign_budget)
3272
+ // require fields filtered in WHERE to also be selected. The error names the exact field,
3273
+ // so add it to SELECT and retry. Kept first: field-specific rules below must not shadow
3274
+ // this with an unrelated rewrite when the named field happens to match their pattern.
3275
+ {
3276
+ matchApiError: /must be present in SELECT clause:\s*'([\w.]+)'/i,
3277
+ fix: (ctx) => {
3278
+ const field = ctx.apiErrorMessage?.match(/must be present in SELECT clause:\s*'([\w.]+)'/i)?.[1];
3279
+ if (!field) {
3280
+ return {
3281
+ action: "add_required_field",
3282
+ explanation: "Add the field named in the error to the SELECT clause and retry"
3283
+ };
3284
+ }
3285
+ const corrected = ctx.originalQuery.replace(/SELECT\s+/i, `SELECT ${field}, `);
3286
+ return {
3287
+ action: "add_required_field",
3288
+ correctedCommand: buildCommand(corrected, ctx),
3289
+ explanation: `${field} is used in WHERE but this resource requires it in SELECT too \u2014 added it`
3290
+ };
3291
+ }
3292
+ },
3271
3293
  // 1. bare keyword.text → ad_group_criterion.keyword.text (leaves <resource>.keyword.text untouched)
3272
3294
  {
3273
3295
  matchQuery: /(?<![\w.])keyword\.text\b/,
@@ -3503,6 +3525,20 @@ var CORRECTION_RULES = [
3503
3525
  };
3504
3526
  }
3505
3527
  },
3528
+ // 15b. asset.<type>_asset.final_urls → asset.final_urls (final URLs live on the asset
3529
+ // itself; the typed sub-message only carries type-specific fields like link_text)
3530
+ {
3531
+ matchQuery: /asset\.\w+_asset\.final_(mobile_)?urls\b/,
3532
+ matchApiError: /asset\.\w+_asset\.final_(mobile_)?urls/i,
3533
+ fix: (ctx) => {
3534
+ const corrected = ctx.originalQuery.replace(/asset\.\w+_asset\.final_(mobile_)?urls\b/g, "asset.final_$1urls");
3535
+ return {
3536
+ action: "retry_with_modified_query",
3537
+ correctedCommand: buildCommand(corrected, ctx),
3538
+ explanation: "Final URLs are on the asset itself \u2014 use asset.final_urls, not asset.<type>_asset.final_urls"
3539
+ };
3540
+ }
3541
+ },
3506
3542
  // 16. Rate limit / quota
3507
3543
  {
3508
3544
  matchApiError: /RESOURCE_EXHAUSTED|quota.*exceeded|rate.*limit/i,
@@ -3630,6 +3666,7 @@ var CORRECTION_RULES = [
3630
3666
 
3631
3667
  // src/commands/ads/google/error-parser.ts
3632
3668
  function mapErrorCode(message) {
3669
+ if (/must be present in SELECT clause/i.test(message)) return "MISSING_SELECT_FIELD";
3633
3670
  if (/field.*not.*found|unrecognized.*field|not.*valid.*field/i.test(message)) return "FIELD_NOT_FOUND";
3634
3671
  if (/not.*valid.*resource|cannot.*select.*from/i.test(message)) return "WRONG_RESOURCE";
3635
3672
  if (/operator|CONTAINS|LIKE/i.test(message)) return "INVALID_OPERATOR";
@@ -3835,11 +3872,1112 @@ Examples:
3835
3872
  }
3836
3873
  });
3837
3874
 
3875
+ // src/commands/ads/google/draft.ts
3876
+ import { defineCommand as defineCommand22 } from "citty";
3877
+
3878
+ // src/commands/ads/google/write-shared.ts
3879
+ import { readFileSync as readFileSync3 } from "fs";
3880
+
3881
+ // ../api/src/ads-google/limits.ts
3882
+ var GOOGLE_ADS_LIMITS = {
3883
+ budget: {
3884
+ nameMax: 255,
3885
+ amountMicrosMin: 1
3886
+ },
3887
+ campaign: {
3888
+ nameMax: 255
3889
+ },
3890
+ adGroup: {
3891
+ nameMax: 255
3892
+ },
3893
+ keyword: {
3894
+ textMax: 80,
3895
+ wordsMax: 10
3896
+ },
3897
+ responsiveSearchAd: {
3898
+ headlinesMin: 3,
3899
+ headlinesMax: 15,
3900
+ headlineTextMax: 30,
3901
+ descriptionsMin: 2,
3902
+ descriptionsMax: 4,
3903
+ descriptionTextMax: 90,
3904
+ pathMax: 15
3905
+ },
3906
+ responsiveDisplayAd: {
3907
+ headlinesMin: 1,
3908
+ headlinesMax: 5,
3909
+ headlineTextMax: 30,
3910
+ longHeadlineTextMax: 90,
3911
+ descriptionsMin: 1,
3912
+ descriptionsMax: 5,
3913
+ descriptionTextMax: 90,
3914
+ businessNameMax: 25
3915
+ },
3916
+ sharedSet: {
3917
+ nameMax: 255
3918
+ },
3919
+ asset: {
3920
+ sitelinkLinkTextMax: 25,
3921
+ sitelinkDescriptionMax: 35,
3922
+ calloutTextMax: 25,
3923
+ structuredSnippetHeaderMax: 25,
3924
+ structuredSnippetValuesMin: 3,
3925
+ structuredSnippetValuesMax: 10
3926
+ },
3927
+ conversionAction: {
3928
+ nameMax: 255
3929
+ },
3930
+ audience: {
3931
+ nameMax: 255
3932
+ },
3933
+ biddingStrategy: {
3934
+ nameMax: 255
3935
+ },
3936
+ label: {
3937
+ nameMax: 255
3938
+ }
3939
+ };
3940
+ var KEYWORD_MATCH_TYPES = ["EXACT", "PHRASE", "BROAD"];
3941
+ var ADVERTISING_CHANNEL_TYPES = [
3942
+ "SEARCH",
3943
+ "DISPLAY",
3944
+ "SHOPPING",
3945
+ "VIDEO",
3946
+ "PERFORMANCE_MAX",
3947
+ "DEMAND_GEN",
3948
+ "MULTI_CHANNEL",
3949
+ "LOCAL",
3950
+ "SMART",
3951
+ "TRAVEL",
3952
+ "HOTEL",
3953
+ "DISCOVERY"
3954
+ ];
3955
+ var ADVERTISING_CHANNEL_SUB_TYPES = [
3956
+ "SEARCH_MOBILE_APP",
3957
+ "DISPLAY_MOBILE_APP",
3958
+ "SEARCH_EXPRESS",
3959
+ "DISPLAY_EXPRESS",
3960
+ "SHOPPING_SMART_ADS",
3961
+ "DISPLAY_GMAIL_AD",
3962
+ "DISPLAY_SMART_CAMPAIGN",
3963
+ "VIDEO_OUTSTREAM",
3964
+ "VIDEO_ACTION",
3965
+ "VIDEO_NON_SKIPPABLE",
3966
+ "APP_CAMPAIGN",
3967
+ "APP_CAMPAIGN_FOR_ENGAGEMENT",
3968
+ "LOCAL_CAMPAIGN",
3969
+ "SHOPPING_COMPARISON_LISTING_ADS",
3970
+ "SEARCH_MOBILE_APP_ENGAGEMENT",
3971
+ "TRAVEL_ACTIVITIES"
3972
+ ];
3973
+ var BIDDING_STRATEGY_TYPES = [
3974
+ "MANUAL_CPC",
3975
+ "MAXIMIZE_CONVERSIONS",
3976
+ "MAXIMIZE_CONVERSION_VALUE",
3977
+ "TARGET_SPEND",
3978
+ "TARGET_CPA",
3979
+ "TARGET_ROAS",
3980
+ "TARGET_IMPRESSION_SHARE",
3981
+ "MANUAL_CPM",
3982
+ "MANUAL_CPV",
3983
+ "PERCENT_CPC"
3984
+ ];
3985
+ var BUDGET_DELIVERY_METHODS = ["STANDARD", "ACCELERATED"];
3986
+ var AD_GROUP_TYPES = [
3987
+ "SEARCH_STANDARD",
3988
+ "DISPLAY_STANDARD",
3989
+ "SHOPPING_PRODUCT_ADS",
3990
+ "VIDEO_BUMPER",
3991
+ "VIDEO_TRUE_VIEW_IN_STREAM",
3992
+ "VIDEO_TRUE_VIEW_IN_DISPLAY",
3993
+ "VIDEO_NON_SKIPPABLE_IN_STREAM",
3994
+ "VIDEO_OUTSTREAM",
3995
+ "DEMAND_GEN_AD"
3996
+ ];
3997
+ var SHARED_SET_TYPES = [
3998
+ "NEGATIVE_KEYWORDS",
3999
+ "NEGATIVE_PLACEMENTS",
4000
+ "ACCOUNT_LEVEL_NEGATIVE_KEYWORDS"
4001
+ ];
4002
+ var STAGEABLE_CREATE_STATUSES2 = ["ENABLED", "PAUSED"];
4003
+ var PINNED_FIELDS = ["HEADLINE_1", "HEADLINE_2", "HEADLINE_3", "DESCRIPTION_1", "DESCRIPTION_2"];
4004
+ var CONVERSION_ACTION_CATEGORIES = [
4005
+ "DEFAULT",
4006
+ "PAGE_VIEW",
4007
+ "PURCHASE",
4008
+ "SIGNUP",
4009
+ "LEAD",
4010
+ "DOWNLOAD",
4011
+ "ADD_TO_CART",
4012
+ "BEGIN_CHECKOUT",
4013
+ "SUBSCRIBE_PAID",
4014
+ "PHONE_CALL_LEAD",
4015
+ "SUBMIT_LEAD_FORM",
4016
+ "BOOK_APPOINTMENT",
4017
+ "REQUEST_QUOTE",
4018
+ "CONTACT"
4019
+ ];
4020
+ var CONVERSION_ACTION_TYPES = [
4021
+ "WEBPAGE",
4022
+ "UPLOAD_CLICKS",
4023
+ "UPLOAD_CALLS",
4024
+ "WEBSITE_CALL",
4025
+ "GOOGLE_ANALYTICS_4_CUSTOM"
4026
+ ];
4027
+ var CONVERSION_COUNTING_TYPES = ["ONE_PER_CLICK", "MANY_PER_CLICK"];
4028
+ var USER_LIST_TYPES = ["CRM_BASED", "RULE_BASED", "LOGICAL", "BASIC", "LOOKALIKE"];
4029
+ var ASSET_FIELD_TYPES = [
4030
+ "SITELINK",
4031
+ "CALLOUT",
4032
+ "STRUCTURED_SNIPPET",
4033
+ "CALL",
4034
+ "PRICE",
4035
+ "PROMOTION",
4036
+ "MOBILE_APP",
4037
+ "HEADLINE",
4038
+ "DESCRIPTION",
4039
+ "LOGO",
4040
+ "MARKETING_IMAGE",
4041
+ "BUSINESS_NAME"
4042
+ ];
4043
+ var DEVICE_TYPES = ["MOBILE", "TABLET", "DESKTOP", "CONNECTED_TV", "OTHER"];
4044
+ var DAYS_OF_WEEK = ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"];
4045
+ var CAMPAIGN_OBJECTIVES = [
4046
+ "SALES",
4047
+ "LEADS",
4048
+ "WEBSITE_TRAFFIC",
4049
+ "PRODUCT_BRAND_CONSIDERATION",
4050
+ "BRAND_AWARENESS_REACH",
4051
+ "APP_PROMOTION",
4052
+ "LOCAL_STORE_VISITS"
4053
+ ];
4054
+ var MICROS_PER_UNIT = 1e6;
4055
+ function toMicros(amount) {
4056
+ return Math.round(amount * MICROS_PER_UNIT);
4057
+ }
4058
+ var PLAYBOOK_DAILY_BUDGET_FLOOR_MICROS = 10 * MICROS_PER_UNIT;
4059
+ var TEMP_REF_REGEX2 = /^g_temp_[A-Za-z0-9_-]{2,}$/;
4060
+ var NUMERIC_ID_REGEX2 = /^\d+$/;
4061
+ var RESOURCE_NAME_REGEX = /^customers\/\d+\/[A-Za-z]+\/[-\w~]+$/;
4062
+ var GEO_TARGET_CONSTANT_REGEX = /^geoTargetConstants\/\d+$/;
4063
+ var LANGUAGE_CONSTANT_REGEX = /^languageConstants\/\d+$/;
4064
+
4065
+ // ../api/src/ads-google/ops.ts
4066
+ import { z as z8 } from "zod";
4067
+ var tempRefSchema2 = z8.string().regex(TEMP_REF_REGEX2, "expected a g_temp_* reference");
4068
+ var refSchema = z8.union([
4069
+ z8.string().regex(RESOURCE_NAME_REGEX, "expected a customers/\u2026/\u2026/\u2026 resource name"),
4070
+ z8.string().regex(NUMERIC_ID_REGEX2, "expected a numeric id"),
4071
+ tempRefSchema2
4072
+ ]);
4073
+ var targetRefSchema = refSchema;
4074
+ var microsSchema = z8.number().int().positive("expected a positive micros amount");
4075
+ var httpsUrlSchema2 = z8.string().url().refine((u) => u.startsWith("https://"), "final URLs must be https");
4076
+ var customerIdSchema = z8.string().regex(NUMERIC_ID_REGEX2, "customerId must be the bare numeric customer id");
4077
+ var stageableStatusSchema2 = z8.enum(STAGEABLE_CREATE_STATUSES2);
4078
+ var matchTypeSchema = z8.enum(KEYWORD_MATCH_TYPES);
4079
+ var keywordTextSchema = z8.string().min(1).max(GOOGLE_ADS_LIMITS.keyword.textMax).refine((t) => t.trim().split(/\s+/).length <= GOOGLE_ADS_LIMITS.keyword.wordsMax, "keyword exceeds 10 words");
4080
+ var budgetCreateSchema = z8.object({
4081
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.budget.nameMax),
4082
+ amountMicros: microsSchema,
4083
+ deliveryMethod: z8.enum(BUDGET_DELIVERY_METHODS).default("STANDARD"),
4084
+ explicitlyShared: z8.boolean().default(false)
4085
+ });
4086
+ var budgetUpdateSchema = z8.object({
4087
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.budget.nameMax).optional(),
4088
+ amountMicros: microsSchema.optional(),
4089
+ deliveryMethod: z8.enum(BUDGET_DELIVERY_METHODS).optional()
4090
+ }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4091
+ var biddingConfigSchema = z8.object({
4092
+ type: z8.enum(BIDDING_STRATEGY_TYPES),
4093
+ targetCpaMicros: microsSchema.optional(),
4094
+ targetRoas: z8.number().positive().optional(),
4095
+ cpcBidCeilingMicros: microsSchema.optional(),
4096
+ enhancedCpcEnabled: z8.boolean().optional()
4097
+ }).superRefine((p, ctx) => {
4098
+ if (p.type === "TARGET_CPA" && p.targetCpaMicros === void 0) {
4099
+ ctx.addIssue({ code: "custom", path: ["targetCpaMicros"], message: "TARGET_CPA needs targetCpaMicros" });
4100
+ }
4101
+ if (p.type === "TARGET_ROAS" && p.targetRoas === void 0) {
4102
+ ctx.addIssue({ code: "custom", path: ["targetRoas"], message: "TARGET_ROAS needs targetRoas" });
4103
+ }
4104
+ });
4105
+ var networkSettingsSchema = z8.object({
4106
+ targetGoogleSearch: z8.boolean().optional(),
4107
+ targetSearchNetwork: z8.boolean().optional(),
4108
+ targetContentNetwork: z8.boolean().optional(),
4109
+ targetPartnerSearchNetwork: z8.boolean().optional()
4110
+ });
4111
+ var dateSchema = z8.string().regex(/^\d{4}-\d{2}-\d{2}$/, "expected a YYYY-MM-DD date");
4112
+ var campaignCreateSchema2 = z8.object({
4113
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.campaign.nameMax),
4114
+ channelType: z8.enum(ADVERTISING_CHANNEL_TYPES),
4115
+ channelSubType: z8.enum(ADVERTISING_CHANNEL_SUB_TYPES).optional(),
4116
+ budget: refSchema,
4117
+ /** Inline standard bidding, or a portfolio strategy ref via biddingStrategy. */
4118
+ bidding: biddingConfigSchema.optional(),
4119
+ biddingStrategy: refSchema.optional(),
4120
+ networkSettings: networkSettingsSchema.optional(),
4121
+ startDate: dateSchema.optional(),
4122
+ endDate: dateSchema.optional(),
4123
+ /** Advisory Google Ads UI objective — drives warnings, not sent to the API. */
4124
+ objective: z8.enum(CAMPAIGN_OBJECTIVES).optional(),
4125
+ status: stageableStatusSchema2.default("PAUSED")
4126
+ }).superRefine((p, ctx) => {
4127
+ if (!p.bidding && !p.biddingStrategy) {
4128
+ ctx.addIssue({
4129
+ code: "custom",
4130
+ path: ["bidding"],
4131
+ message: "set an inline bidding strategy or reference a portfolio biddingStrategy"
4132
+ });
4133
+ }
4134
+ if (p.bidding && p.biddingStrategy) {
4135
+ ctx.addIssue({
4136
+ code: "custom",
4137
+ path: ["bidding"],
4138
+ message: "use inline bidding OR a portfolio biddingStrategy, not both"
4139
+ });
4140
+ }
4141
+ if (p.channelType === "PERFORMANCE_MAX" && p.bidding && p.bidding.type === "MANUAL_CPC") {
4142
+ ctx.addIssue({ code: "custom", path: ["bidding"], message: "Performance Max does not support Manual CPC" });
4143
+ }
4144
+ if (p.startDate && p.endDate && p.endDate <= p.startDate) {
4145
+ ctx.addIssue({ code: "custom", path: ["endDate"], message: "endDate must be after startDate" });
4146
+ }
4147
+ });
4148
+ var campaignUpdateSchema2 = z8.object({
4149
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.campaign.nameMax).optional(),
4150
+ budget: refSchema.optional(),
4151
+ bidding: biddingConfigSchema.optional(),
4152
+ networkSettings: networkSettingsSchema.optional(),
4153
+ startDate: dateSchema.optional(),
4154
+ endDate: dateSchema.optional(),
4155
+ status: z8.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
4156
+ }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4157
+ var adGroupCreateSchema = z8.object({
4158
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.adGroup.nameMax),
4159
+ campaign: refSchema,
4160
+ type: z8.enum(AD_GROUP_TYPES).default("SEARCH_STANDARD"),
4161
+ cpcBidMicros: microsSchema.optional(),
4162
+ status: stageableStatusSchema2.default("PAUSED")
4163
+ });
4164
+ var adGroupUpdateSchema = z8.object({
4165
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.adGroup.nameMax).optional(),
4166
+ cpcBidMicros: microsSchema.optional(),
4167
+ status: z8.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
4168
+ }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4169
+ var keywordAddSchema = z8.object({
4170
+ adGroup: refSchema,
4171
+ text: keywordTextSchema,
4172
+ matchType: matchTypeSchema,
4173
+ cpcBidMicros: microsSchema.optional(),
4174
+ finalUrls: z8.array(httpsUrlSchema2).optional(),
4175
+ status: stageableStatusSchema2.default("ENABLED")
4176
+ });
4177
+ var keywordUpdateSchema = z8.object({
4178
+ cpcBidMicros: microsSchema.optional(),
4179
+ finalUrls: z8.array(httpsUrlSchema2).optional(),
4180
+ status: z8.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
4181
+ }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4182
+ var negativeKeywordAddSchema = z8.object({
4183
+ level: z8.enum(["adGroup", "campaign"]),
4184
+ parent: refSchema,
4185
+ text: keywordTextSchema,
4186
+ matchType: matchTypeSchema
4187
+ });
4188
+ var sharedSetCreateSchema = z8.object({
4189
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.sharedSet.nameMax),
4190
+ type: z8.enum(SHARED_SET_TYPES).default("NEGATIVE_KEYWORDS")
4191
+ });
4192
+ var sharedSetMemberAddSchema = z8.object({
4193
+ sharedSet: refSchema,
4194
+ text: keywordTextSchema,
4195
+ matchType: matchTypeSchema
4196
+ });
4197
+ var campaignSharedSetAttachSchema = z8.object({
4198
+ campaign: refSchema,
4199
+ sharedSet: refSchema
4200
+ });
4201
+ var adTextAssetSchema = z8.object({
4202
+ text: z8.string().min(1),
4203
+ pinnedField: z8.enum(PINNED_FIELDS).optional()
4204
+ });
4205
+ var responsiveSearchAdSchema = z8.object({
4206
+ format: z8.literal("responsiveSearch"),
4207
+ headlines: z8.array(
4208
+ adTextAssetSchema.refine(
4209
+ (a) => a.text.length <= GOOGLE_ADS_LIMITS.responsiveSearchAd.headlineTextMax,
4210
+ "headline exceeds 30 chars"
4211
+ )
4212
+ ).min(GOOGLE_ADS_LIMITS.responsiveSearchAd.headlinesMin).max(GOOGLE_ADS_LIMITS.responsiveSearchAd.headlinesMax),
4213
+ descriptions: z8.array(
4214
+ adTextAssetSchema.refine(
4215
+ (a) => a.text.length <= GOOGLE_ADS_LIMITS.responsiveSearchAd.descriptionTextMax,
4216
+ "description exceeds 90 chars"
4217
+ )
4218
+ ).min(GOOGLE_ADS_LIMITS.responsiveSearchAd.descriptionsMin).max(GOOGLE_ADS_LIMITS.responsiveSearchAd.descriptionsMax),
4219
+ path1: z8.string().max(GOOGLE_ADS_LIMITS.responsiveSearchAd.pathMax).optional(),
4220
+ path2: z8.string().max(GOOGLE_ADS_LIMITS.responsiveSearchAd.pathMax).optional(),
4221
+ finalUrls: z8.array(httpsUrlSchema2).min(1)
4222
+ });
4223
+ var responsiveDisplayAdSchema = z8.object({
4224
+ format: z8.literal("responsiveDisplay"),
4225
+ headlines: z8.array(z8.object({ text: z8.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.headlineTextMax) })).min(1).max(5),
4226
+ longHeadline: z8.object({ text: z8.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.longHeadlineTextMax) }),
4227
+ descriptions: z8.array(z8.object({ text: z8.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.descriptionTextMax) })).min(1).max(5),
4228
+ businessName: z8.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.businessNameMax),
4229
+ marketingImageAssets: z8.array(refSchema).optional(),
4230
+ logoImageAssets: z8.array(refSchema).optional(),
4231
+ finalUrls: z8.array(httpsUrlSchema2).min(1)
4232
+ });
4233
+ var performanceMaxAssetGroupSchema = z8.object({
4234
+ format: z8.literal("performanceMaxAssetGroup"),
4235
+ name: z8.string().min(1).max(255),
4236
+ headlines: z8.array(z8.object({ text: z8.string().min(1).max(30) })).min(3).max(15),
4237
+ descriptions: z8.array(z8.object({ text: z8.string().min(1).max(90) })).min(2).max(5),
4238
+ finalUrls: z8.array(httpsUrlSchema2).min(1),
4239
+ imageAssets: z8.array(refSchema).optional(),
4240
+ logoAssets: z8.array(refSchema).optional()
4241
+ });
4242
+ var callAdSchema = z8.object({
4243
+ format: z8.literal("call"),
4244
+ countryCode: z8.string().length(2),
4245
+ phoneNumber: z8.string().min(3),
4246
+ headline1: z8.string().min(1).max(30),
4247
+ headline2: z8.string().min(1).max(30),
4248
+ description1: z8.string().min(1).max(90),
4249
+ description2: z8.string().min(1).max(90),
4250
+ businessName: z8.string().min(1).max(25),
4251
+ finalUrls: z8.array(httpsUrlSchema2).min(1)
4252
+ });
4253
+ var appAdSchema = z8.object({
4254
+ format: z8.literal("app"),
4255
+ headlines: z8.array(z8.object({ text: z8.string().min(1).max(30) })).min(1),
4256
+ descriptions: z8.array(z8.object({ text: z8.string().min(1).max(90) })).min(1)
4257
+ });
4258
+ var videoAdSchema = z8.object({
4259
+ format: z8.literal("video"),
4260
+ youtubeVideoId: z8.string().min(1),
4261
+ finalUrls: z8.array(httpsUrlSchema2).min(1)
4262
+ });
4263
+ var demandGenAdSchema = z8.object({
4264
+ format: z8.literal("demandGen"),
4265
+ headlines: z8.array(z8.object({ text: z8.string().min(1).max(40) })).min(1).max(5),
4266
+ descriptions: z8.array(z8.object({ text: z8.string().min(1).max(90) })).min(1).max(5),
4267
+ businessName: z8.string().min(1).max(25),
4268
+ finalUrls: z8.array(httpsUrlSchema2).min(1),
4269
+ imageAssets: z8.array(refSchema).optional()
4270
+ });
4271
+ var adContentSchema = z8.discriminatedUnion("format", [
4272
+ responsiveSearchAdSchema,
4273
+ responsiveDisplayAdSchema,
4274
+ performanceMaxAssetGroupSchema,
4275
+ callAdSchema,
4276
+ appAdSchema,
4277
+ videoAdSchema,
4278
+ demandGenAdSchema
4279
+ ]);
4280
+ var adCreateSchema = z8.object({
4281
+ adGroup: refSchema,
4282
+ status: stageableStatusSchema2.default("PAUSED"),
4283
+ content: adContentSchema
4284
+ });
4285
+ var adUpdateSchema = z8.object({
4286
+ status: z8.enum(["ENABLED", "PAUSED", "REMOVED"]).optional(),
4287
+ /** Whole-content replacement for RSA-like formats; re-validated against adContentSchema. */
4288
+ content: z8.record(z8.string(), z8.unknown()).optional()
4289
+ }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4290
+ var textAssetSchema = z8.object({ type: z8.literal("text"), text: z8.string().min(1) });
4291
+ var imageAssetSchema = z8.object({
4292
+ type: z8.literal("image"),
4293
+ imageId: z8.string().min(1),
4294
+ name: z8.string().optional()
4295
+ });
4296
+ var youtubeVideoAssetSchema = z8.object({
4297
+ type: z8.literal("youtubeVideo"),
4298
+ youtubeVideoId: z8.string().min(1),
4299
+ name: z8.string().optional()
4300
+ });
4301
+ var sitelinkAssetSchema = z8.object({
4302
+ type: z8.literal("sitelink"),
4303
+ linkText: z8.string().min(1).max(GOOGLE_ADS_LIMITS.asset.sitelinkLinkTextMax),
4304
+ description1: z8.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
4305
+ description2: z8.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
4306
+ finalUrls: z8.array(httpsUrlSchema2).min(1)
4307
+ });
4308
+ var calloutAssetSchema = z8.object({
4309
+ type: z8.literal("callout"),
4310
+ calloutText: z8.string().min(1).max(GOOGLE_ADS_LIMITS.asset.calloutTextMax)
4311
+ });
4312
+ var structuredSnippetAssetSchema = z8.object({
4313
+ type: z8.literal("structuredSnippet"),
4314
+ header: z8.string().min(1).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetHeaderMax),
4315
+ values: z8.array(z8.string().min(1)).min(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMin).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMax)
4316
+ });
4317
+ var callToActionAssetSchema = z8.object({ type: z8.literal("callToAction"), callToAction: z8.string().min(1) });
4318
+ var assetCreateSchema = z8.discriminatedUnion("type", [
4319
+ textAssetSchema,
4320
+ imageAssetSchema,
4321
+ youtubeVideoAssetSchema,
4322
+ sitelinkAssetSchema,
4323
+ calloutAssetSchema,
4324
+ structuredSnippetAssetSchema,
4325
+ callToActionAssetSchema
4326
+ ]);
4327
+ var assetLinkAttachSchema = z8.object({
4328
+ level: z8.enum(["campaign", "adGroup", "customer"]),
4329
+ parent: refSchema.optional(),
4330
+ asset: refSchema,
4331
+ fieldType: z8.enum(ASSET_FIELD_TYPES)
4332
+ }).superRefine((value, ctx) => {
4333
+ if (value.level !== "customer" && !value.parent) {
4334
+ ctx.addIssue({
4335
+ code: z8.ZodIssueCode.custom,
4336
+ path: ["parent"],
4337
+ message: `parent is required for a ${value.level}-level asset link (--parent-ref)`
4338
+ });
4339
+ }
4340
+ });
4341
+ var audienceCreateSchema2 = z8.object({
4342
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.audience.nameMax),
4343
+ type: z8.enum(USER_LIST_TYPES).default("BASIC"),
4344
+ description: z8.string().optional(),
4345
+ /** Customer-match members (crm-based) — file-first for large lists. */
4346
+ members: z8.array(z8.record(z8.string(), z8.string())).optional(),
4347
+ sourceFileRef: z8.string().optional()
4348
+ });
4349
+ var audienceCriterionAttachSchema = z8.object({
4350
+ level: z8.enum(["campaign", "adGroup"]),
4351
+ parent: refSchema,
4352
+ userList: refSchema,
4353
+ negative: z8.boolean().default(false)
4354
+ });
4355
+ var conversionActionCreateSchema = z8.object({
4356
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.conversionAction.nameMax),
4357
+ type: z8.enum(CONVERSION_ACTION_TYPES).default("WEBPAGE"),
4358
+ category: z8.enum(CONVERSION_ACTION_CATEGORIES).default("DEFAULT"),
4359
+ countingType: z8.enum(CONVERSION_COUNTING_TYPES).default("ONE_PER_CLICK"),
4360
+ defaultValueMicros: microsSchema.optional(),
4361
+ defaultCurrencyCode: z8.string().length(3).optional(),
4362
+ clickThroughLookbackWindowDays: z8.number().int().positive().optional(),
4363
+ viewThroughLookbackWindowDays: z8.number().int().positive().optional(),
4364
+ status: z8.enum(["ENABLED", "PAUSED"]).default("ENABLED")
4365
+ });
4366
+ var conversionActionUpdateSchema = z8.object({
4367
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.conversionAction.nameMax).optional(),
4368
+ category: z8.enum(CONVERSION_ACTION_CATEGORIES).optional(),
4369
+ countingType: z8.enum(CONVERSION_COUNTING_TYPES).optional(),
4370
+ defaultValueMicros: microsSchema.optional(),
4371
+ status: z8.enum(["ENABLED", "REMOVED", "HIDDEN"]).optional()
4372
+ }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4373
+ var biddingStrategyCreateSchema = z8.object({
4374
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.biddingStrategy.nameMax),
4375
+ config: biddingConfigSchema
4376
+ }).superRefine((p, ctx) => {
4377
+ if (p.config.type === "MANUAL_CPC") {
4378
+ ctx.addIssue({ code: "custom", path: ["config", "type"], message: "portfolio strategies cannot be Manual CPC" });
4379
+ }
4380
+ });
4381
+ var biddingStrategyUpdateSchema = z8.object({
4382
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.biddingStrategy.nameMax).optional(),
4383
+ config: biddingConfigSchema.optional()
4384
+ }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4385
+ var labelCreateSchema = z8.object({
4386
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.label.nameMax),
4387
+ backgroundColor: z8.string().regex(/^#[0-9A-Fa-f]{6}$/).optional(),
4388
+ description: z8.string().optional()
4389
+ });
4390
+ var labelAttachSchema = z8.object({
4391
+ level: z8.enum(["campaign", "adGroup", "ad"]),
4392
+ parent: refSchema,
4393
+ label: refSchema
4394
+ });
4395
+ var locationCriterionSchema = z8.object({
4396
+ criterionType: z8.literal("location"),
4397
+ geoTargetConstant: z8.union([z8.string().regex(GEO_TARGET_CONSTANT_REGEX), z8.string().regex(NUMERIC_ID_REGEX2)])
4398
+ });
4399
+ var languageCriterionSchema = z8.object({
4400
+ criterionType: z8.literal("language"),
4401
+ languageConstant: z8.union([z8.string().regex(LANGUAGE_CONSTANT_REGEX), z8.string().regex(NUMERIC_ID_REGEX2)])
4402
+ });
4403
+ var adScheduleCriterionSchema = z8.object({
4404
+ criterionType: z8.literal("adSchedule"),
4405
+ dayOfWeek: z8.enum(DAYS_OF_WEEK),
4406
+ startHour: z8.number().int().min(0).max(23),
4407
+ startMinute: z8.enum(["ZERO", "FIFTEEN", "THIRTY", "FORTY_FIVE"]).default("ZERO"),
4408
+ endHour: z8.number().int().min(0).max(24),
4409
+ endMinute: z8.enum(["ZERO", "FIFTEEN", "THIRTY", "FORTY_FIVE"]).default("ZERO")
4410
+ });
4411
+ var deviceCriterionSchema = z8.object({
4412
+ criterionType: z8.literal("device"),
4413
+ device: z8.enum(DEVICE_TYPES),
4414
+ bidModifier: z8.number().min(0.1).max(10).optional()
4415
+ });
4416
+ var campaignCriterionAddSchema = z8.object({
4417
+ campaign: refSchema,
4418
+ negative: z8.boolean().default(false),
4419
+ criterion: z8.discriminatedUnion("criterionType", [
4420
+ locationCriterionSchema,
4421
+ languageCriterionSchema,
4422
+ adScheduleCriterionSchema,
4423
+ deviceCriterionSchema
4424
+ ])
4425
+ });
4426
+ var GOOGLE_DRAFT_OP_KINDS = [
4427
+ "google.budget.create",
4428
+ "google.budget.update",
4429
+ "google.campaign.create",
4430
+ "google.campaign.update",
4431
+ "google.campaign.pause",
4432
+ "google.campaign.resume",
4433
+ "google.campaign.remove",
4434
+ "google.adGroup.create",
4435
+ "google.adGroup.update",
4436
+ "google.adGroup.pause",
4437
+ "google.adGroup.resume",
4438
+ "google.adGroup.remove",
4439
+ "google.keyword.add",
4440
+ "google.keyword.update",
4441
+ "google.keyword.remove",
4442
+ "google.negativeKeyword.add",
4443
+ "google.negativeKeyword.remove",
4444
+ "google.sharedSet.create",
4445
+ "google.sharedSetMember.add",
4446
+ "google.sharedSetMember.remove",
4447
+ "google.campaignSharedSet.attach",
4448
+ "google.campaignSharedSet.detach",
4449
+ "google.ad.create",
4450
+ "google.ad.update",
4451
+ "google.ad.pause",
4452
+ "google.ad.resume",
4453
+ "google.ad.remove",
4454
+ "google.asset.create",
4455
+ "google.assetLink.attach",
4456
+ "google.assetLink.detach",
4457
+ "google.audience.create",
4458
+ "google.audienceCriterion.attach",
4459
+ "google.audienceCriterion.detach",
4460
+ "google.conversionAction.create",
4461
+ "google.conversionAction.update",
4462
+ "google.biddingStrategy.create",
4463
+ "google.biddingStrategy.update",
4464
+ "google.label.create",
4465
+ "google.label.attach",
4466
+ "google.campaignCriterion.add",
4467
+ "google.campaignCriterion.remove"
4468
+ ];
4469
+ var googleDraftOpKindSchema = z8.enum(GOOGLE_DRAFT_OP_KINDS);
4470
+ function createOp2(kind, payload) {
4471
+ return z8.object({ kind: z8.literal(kind), customerId: customerIdSchema, payload });
4472
+ }
4473
+ function updateOp2(kind, payload) {
4474
+ return z8.object({ kind: z8.literal(kind), customerId: customerIdSchema, target: targetRefSchema, payload });
4475
+ }
4476
+ function targetOp(kind) {
4477
+ return z8.object({ kind: z8.literal(kind), customerId: customerIdSchema, target: targetRefSchema });
4478
+ }
4479
+ var googleDraftOpInputSchema = z8.discriminatedUnion("kind", [
4480
+ createOp2("google.budget.create", budgetCreateSchema),
4481
+ updateOp2("google.budget.update", budgetUpdateSchema),
4482
+ createOp2("google.campaign.create", campaignCreateSchema2),
4483
+ updateOp2("google.campaign.update", campaignUpdateSchema2),
4484
+ targetOp("google.campaign.pause"),
4485
+ targetOp("google.campaign.resume"),
4486
+ targetOp("google.campaign.remove"),
4487
+ createOp2("google.adGroup.create", adGroupCreateSchema),
4488
+ updateOp2("google.adGroup.update", adGroupUpdateSchema),
4489
+ targetOp("google.adGroup.pause"),
4490
+ targetOp("google.adGroup.resume"),
4491
+ targetOp("google.adGroup.remove"),
4492
+ createOp2("google.keyword.add", keywordAddSchema),
4493
+ updateOp2("google.keyword.update", keywordUpdateSchema),
4494
+ targetOp("google.keyword.remove"),
4495
+ createOp2("google.negativeKeyword.add", negativeKeywordAddSchema),
4496
+ targetOp("google.negativeKeyword.remove"),
4497
+ createOp2("google.sharedSet.create", sharedSetCreateSchema),
4498
+ createOp2("google.sharedSetMember.add", sharedSetMemberAddSchema),
4499
+ targetOp("google.sharedSetMember.remove"),
4500
+ createOp2("google.campaignSharedSet.attach", campaignSharedSetAttachSchema),
4501
+ targetOp("google.campaignSharedSet.detach"),
4502
+ createOp2("google.ad.create", adCreateSchema),
4503
+ updateOp2("google.ad.update", adUpdateSchema),
4504
+ targetOp("google.ad.pause"),
4505
+ targetOp("google.ad.resume"),
4506
+ targetOp("google.ad.remove"),
4507
+ createOp2("google.asset.create", assetCreateSchema),
4508
+ createOp2("google.assetLink.attach", assetLinkAttachSchema),
4509
+ targetOp("google.assetLink.detach"),
4510
+ createOp2("google.audience.create", audienceCreateSchema2),
4511
+ createOp2("google.audienceCriterion.attach", audienceCriterionAttachSchema),
4512
+ targetOp("google.audienceCriterion.detach"),
4513
+ createOp2("google.conversionAction.create", conversionActionCreateSchema),
4514
+ updateOp2("google.conversionAction.update", conversionActionUpdateSchema),
4515
+ createOp2("google.biddingStrategy.create", biddingStrategyCreateSchema),
4516
+ updateOp2("google.biddingStrategy.update", biddingStrategyUpdateSchema),
4517
+ createOp2("google.label.create", labelCreateSchema),
4518
+ createOp2("google.label.attach", labelAttachSchema),
4519
+ createOp2("google.campaignCriterion.add", campaignCriterionAddSchema),
4520
+ targetOp("google.campaignCriterion.remove")
4521
+ ]);
4522
+
4523
+ // ../api/src/ads-google/wire.ts
4524
+ import { z as z9 } from "zod";
4525
+ var googleWriteModeSchema = z9.enum(["live", "simulated"]);
4526
+ var googleDraftOpResultSchema = z9.object({
4527
+ status: z9.enum(["applied", "simulated", "failed", "skipped"]),
4528
+ resourceName: z9.string().optional(),
4529
+ error: z9.string().optional(),
4530
+ skippedBecause: z9.string().optional(),
4531
+ executedAt: z9.number().optional()
4532
+ });
4533
+ var googleDraftStageRequestSchema = z9.object({
4534
+ chatId: z9.string(),
4535
+ op: googleDraftOpInputSchema
4536
+ });
4537
+ var googleDraftStageResponseSchema = z9.object({
4538
+ staged: z9.literal(true),
4539
+ ref: z9.string(),
4540
+ kind: googleDraftOpKindSchema,
4541
+ mode: googleWriteModeSchema,
4542
+ dependsOn: z9.array(z9.string()),
4543
+ summary: z9.string(),
4544
+ warnings: z9.array(z9.string()),
4545
+ /** True when the op amended an already-staged op in place instead of appending a new one. */
4546
+ amended: z9.boolean().optional()
4547
+ });
4548
+ var GOOGLE_DRAFT_BATCH_MAX = 500;
4549
+ var googleDraftStageBatchRequestSchema = z9.object({
4550
+ chatId: z9.string(),
4551
+ ops: z9.array(googleDraftOpInputSchema).min(1).max(GOOGLE_DRAFT_BATCH_MAX)
4552
+ });
4553
+ var googleDraftStageBatchResponseSchema = z9.object({
4554
+ staged: z9.literal(true),
4555
+ mode: googleWriteModeSchema,
4556
+ count: z9.number(),
4557
+ ops: z9.array(
4558
+ z9.object({
4559
+ ref: z9.string(),
4560
+ kind: googleDraftOpKindSchema,
4561
+ dependsOn: z9.array(z9.string()),
4562
+ summary: z9.string(),
4563
+ warnings: z9.array(z9.string())
4564
+ })
4565
+ )
4566
+ });
4567
+ var googleDraftOpViewSchema = z9.object({
4568
+ ref: z9.string(),
4569
+ kind: googleDraftOpKindSchema,
4570
+ customerId: z9.string(),
4571
+ target: z9.string().optional(),
4572
+ dependsOn: z9.array(z9.string()),
4573
+ summary: z9.string(),
4574
+ stagedAt: z9.number(),
4575
+ result: googleDraftOpResultSchema.optional()
4576
+ });
4577
+ var googleDraftListRequestSchema = z9.object({
4578
+ chatId: z9.string()
4579
+ });
4580
+ var googleDraftAdvisorySchema = z9.object({
4581
+ scope: z9.enum(["campaign", "adGroup"]),
4582
+ message: z9.string()
4583
+ });
4584
+ var googleDraftStatusCollectionSchema = z9.object({
4585
+ label: z9.string(),
4586
+ added: z9.number(),
4587
+ removed: z9.number(),
4588
+ existing: z9.number()
4589
+ });
4590
+ var googleDraftChangeOperationSchema = z9.enum(["create", "update", "pause", "resume", "remove"]);
4591
+ var googleDraftStatusNodeSchema = z9.lazy(
4592
+ () => z9.object({
4593
+ entity: z9.string(),
4594
+ name: z9.string(),
4595
+ operation: googleDraftChangeOperationSchema.optional(),
4596
+ existing: z9.boolean(),
4597
+ collections: z9.array(googleDraftStatusCollectionSchema),
4598
+ children: z9.array(googleDraftStatusNodeSchema)
4599
+ })
4600
+ );
4601
+ var googleDraftListResponseSchema = z9.object({
4602
+ status: z9.enum(["active", "publishing", "applied", "discarded", "none"]),
4603
+ mode: googleWriteModeSchema,
4604
+ count: z9.number(),
4605
+ ops: z9.array(googleDraftOpViewSchema),
4606
+ /** Grouped campaign ▸ ad group ▸ ad tree for the readable CLI status view. */
4607
+ tree: z9.array(googleDraftStatusNodeSchema).optional(),
4608
+ /** Non-blocking completeness advisories for the whole draft. */
4609
+ advisories: z9.array(googleDraftAdvisorySchema).optional()
4610
+ });
4611
+ var googleDraftRemoveRequestSchema = z9.object({
4612
+ chatId: z9.string(),
4613
+ ref: z9.string()
4614
+ });
4615
+ var googleDraftRemoveResponseSchema = z9.object({
4616
+ /** The requested ref plus any dependents removed by cascade. */
4617
+ removed: z9.array(z9.string())
4618
+ });
4619
+ var googleDraftClearRequestSchema = z9.object({
4620
+ chatId: z9.string()
4621
+ });
4622
+ var googleDraftClearResponseSchema = z9.object({
4623
+ cleared: z9.number()
4624
+ });
4625
+ var googleFieldErrorSchema = z9.object({
4626
+ path: z9.string(),
4627
+ message: z9.string()
4628
+ });
4629
+ var googleDraftErrorResponseSchema = z9.object({
4630
+ code: z9.string(),
4631
+ error: z9.string(),
4632
+ fields: z9.array(googleFieldErrorSchema).optional()
4633
+ });
4634
+
4635
+ // src/commands/ads/google/draft-status.ts
4636
+ var OPERATION_LABELS = {
4637
+ create: "Creating",
4638
+ update: "Updating",
4639
+ pause: "Pausing",
4640
+ resume: "Resuming",
4641
+ remove: "Removing"
4642
+ };
4643
+ function badge(node) {
4644
+ const label = node.operation ? OPERATION_LABELS[node.operation] : void 0;
4645
+ if (label) {
4646
+ return label;
4647
+ }
4648
+ return node.existing ? "on Google Ads" : "staged";
4649
+ }
4650
+ function collectionLine(collection) {
4651
+ const parts = [];
4652
+ if (collection.added > 0) {
4653
+ parts.push(`+${collection.added}`);
4654
+ }
4655
+ if (collection.existing > 0) {
4656
+ parts.push(`${collection.existing} existing`);
4657
+ }
4658
+ if (collection.removed > 0) {
4659
+ parts.push(`-${collection.removed}`);
4660
+ }
4661
+ return parts.length > 0 ? `${collection.label}: ${parts.join(", ")}` : void 0;
4662
+ }
4663
+ function renderNode(node, depth, lines) {
4664
+ const indent = " ".repeat(depth);
4665
+ lines.push(`${indent}\u2022 ${node.name} \xB7 ${badge(node)}`);
4666
+ for (const collection of node.collections) {
4667
+ const line = collectionLine(collection);
4668
+ if (line) {
4669
+ lines.push(`${indent} ${line}`);
4670
+ }
4671
+ }
4672
+ for (const child of node.children) {
4673
+ renderNode(child, depth + 1, lines);
4674
+ }
4675
+ }
4676
+ var RESOURCE_ENTITIES = /* @__PURE__ */ new Set([
4677
+ "sharedSet",
4678
+ "biddingStrategy",
4679
+ "audience",
4680
+ "conversionAction",
4681
+ "label",
4682
+ "budget",
4683
+ "asset"
4684
+ ]);
4685
+ function renderSection(title, nodes, lines) {
4686
+ if (nodes.length === 0) {
4687
+ return;
4688
+ }
4689
+ lines.push("");
4690
+ lines.push(title);
4691
+ for (const node of nodes) {
4692
+ renderNode(node, 1, lines);
4693
+ }
4694
+ }
4695
+ function renderAdvisories(data, lines) {
4696
+ const advisories = data.advisories ?? [];
4697
+ if (advisories.length === 0) {
4698
+ return;
4699
+ }
4700
+ lines.push("");
4701
+ lines.push("Advisories (non-blocking \u2014 build these out for a higher-performance campaign)");
4702
+ for (const advisory of advisories) {
4703
+ lines.push(` \u2022 ${advisory.message}`);
4704
+ }
4705
+ }
4706
+ function renderDraftStatus(data) {
4707
+ if (data.status === "none" || data.count === 0) {
4708
+ return "No staged Google Ads changes on this chat.";
4709
+ }
4710
+ const modeNote = data.mode === "live" ? "Live \u2014 publishing writes directly to Google Ads." : "Simulated \u2014 publishing completes the whole draft without calling Google Ads.";
4711
+ const lines = [
4712
+ `Google Ads \u2014 ${data.count} staged change${data.count === 1 ? "" : "s"} \xB7 ${data.mode}`,
4713
+ modeNote
4714
+ ];
4715
+ const tree = data.tree ?? [];
4716
+ renderSection(
4717
+ "Shared resources",
4718
+ tree.filter((node) => RESOURCE_ENTITIES.has(node.entity)),
4719
+ lines
4720
+ );
4721
+ renderSection(
4722
+ "Campaigns",
4723
+ tree.filter((node) => node.entity === "campaign"),
4724
+ lines
4725
+ );
4726
+ const rest = tree.filter((node) => !RESOURCE_ENTITIES.has(node.entity) && node.entity !== "campaign");
4727
+ renderSection("Other", rest, lines);
4728
+ renderAdvisories(data, lines);
4729
+ return lines.join("\n");
4730
+ }
4731
+
4732
+ // src/commands/ads/google/write-shared.ts
4733
+ function failWriteValidation(message) {
4734
+ writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
4735
+ process.exit(1);
4736
+ }
4737
+ function requireCustomerId(args) {
4738
+ const raw = args["customer-id"] ?? args.customerId;
4739
+ if (!raw || !/^\d{10}$/.test(raw)) {
4740
+ failWriteValidation("pass --customer-id as the 10-digit Google Ads customer id (no dashes)");
4741
+ }
4742
+ return raw;
4743
+ }
4744
+ function requireTarget(args, entity) {
4745
+ const positional = Array.isArray(args._) ? args._[0] : void 0;
4746
+ const target = args.id ?? args.target ?? positional;
4747
+ if (typeof target !== "string" || target.length === 0) {
4748
+ failWriteValidation(`pass the ${entity} resource name or id as the positional argument`);
4749
+ }
4750
+ return target;
4751
+ }
4752
+ function requireStringFlag(value, flag) {
4753
+ if (typeof value !== "string" || value.length === 0) {
4754
+ failWriteValidation(`${flag} is required`);
4755
+ }
4756
+ return value;
4757
+ }
4758
+ function microsFlag(value, flag) {
4759
+ if (value === void 0 || value === null || value === "") {
4760
+ return void 0;
4761
+ }
4762
+ const num = Number(value);
4763
+ if (Number.isNaN(num) || num <= 0) {
4764
+ failWriteValidation(`${flag} must be a positive amount (major currency units, e.g. 50 or 50.00)`);
4765
+ }
4766
+ return toMicros(num);
4767
+ }
4768
+ function listFlag(value) {
4769
+ if (typeof value !== "string" || value.length === 0) {
4770
+ return void 0;
4771
+ }
4772
+ const items = value.split(",").map((v) => v.trim()).filter(Boolean);
4773
+ return items.length > 0 ? items : void 0;
4774
+ }
4775
+ var MATCH_TYPES = /* @__PURE__ */ new Set(["EXACT", "PHRASE", "BROAD"]);
4776
+ function parseKeywordEntry(raw, defaultMatch) {
4777
+ const colon = raw.lastIndexOf(":");
4778
+ if (colon > 0) {
4779
+ const suffix = raw.slice(colon + 1).trim().toUpperCase();
4780
+ if (MATCH_TYPES.has(suffix)) {
4781
+ return { text: raw.slice(0, colon).trim(), matchType: suffix };
4782
+ }
4783
+ failWriteValidation(`"${raw}": ":${raw.slice(colon + 1)}" is not a match type (EXACT | PHRASE | BROAD)`);
4784
+ }
4785
+ if (!defaultMatch) {
4786
+ failWriteValidation(`"${raw}" has no match type \u2014 add a :EXACT/:PHRASE/:BROAD suffix or pass --match-type`);
4787
+ }
4788
+ return { text: raw, matchType: defaultMatch };
4789
+ }
4790
+ function rawTextEntries(value) {
4791
+ const values = Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
4792
+ return values.filter((v) => typeof v === "string").flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
4793
+ }
4794
+ function rawFileEntries(path12) {
4795
+ if (typeof path12 !== "string" || path12.length === 0) {
4796
+ return [];
4797
+ }
4798
+ return readFileSync3(path12, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
4799
+ }
4800
+ function keywordEntries(args) {
4801
+ const defaultMatch = typeof args["match-type"] === "string" ? args["match-type"].toUpperCase() : void 0;
4802
+ const raw = [...rawTextEntries(args.text), ...rawFileEntries(args.file)];
4803
+ if (raw.length === 0) {
4804
+ failWriteValidation("pass keywords via --text (comma-separated) and/or --file (one per line)");
4805
+ }
4806
+ if (raw.length > GOOGLE_DRAFT_BATCH_MAX) {
4807
+ failWriteValidation(`${raw.length} keywords exceeds the batch limit of ${GOOGLE_DRAFT_BATCH_MAX}`);
4808
+ }
4809
+ const entries = [];
4810
+ const seen = /* @__PURE__ */ new Set();
4811
+ for (const item of raw) {
4812
+ const entry = parseKeywordEntry(item, defaultMatch);
4813
+ const key = `${entry.text}\0${entry.matchType}`;
4814
+ if (!seen.has(key)) {
4815
+ seen.add(key);
4816
+ entries.push(entry);
4817
+ }
4818
+ }
4819
+ return entries;
4820
+ }
4821
+ function loadJsonFileArg(path12) {
4822
+ if (typeof path12 !== "string" || path12.length === 0) {
4823
+ return {};
4824
+ }
4825
+ try {
4826
+ const parsed = JSON.parse(readFileSync3(path12, "utf8"));
4827
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
4828
+ failWriteValidation(`${path12} must contain a JSON object`);
4829
+ }
4830
+ return parsed;
4831
+ } catch (err) {
4832
+ if (err instanceof SyntaxError) {
4833
+ failWriteValidation(`${path12} is not valid JSON: ${err.message}`);
4834
+ }
4835
+ throw err;
4836
+ }
4837
+ }
4838
+ function mergePayload(file, flags) {
4839
+ const merged = { ...file };
4840
+ for (const [key, value] of Object.entries(flags)) {
4841
+ if (value !== void 0) {
4842
+ merged[key] = value;
4843
+ }
4844
+ }
4845
+ return merged;
4846
+ }
4847
+ function handleGoogleError(err) {
4848
+ if (err instanceof ApiError) {
4849
+ writeJsonEnvelope({ ok: false, error: { code: err.code ?? "API_ERROR", message: err.message } });
4850
+ process.exit(1);
4851
+ }
4852
+ writeJsonEnvelope({
4853
+ ok: false,
4854
+ error: { code: "UNKNOWN", message: err instanceof Error ? err.message : String(err) }
4855
+ });
4856
+ process.exit(1);
4857
+ }
4858
+ async function stageGoogleOp(raw) {
4859
+ const preflight = googleDraftOpInputSchema.safeParse(raw);
4860
+ if (!preflight.success) {
4861
+ const fields = preflight.error.issues.map((issue) => ({ path: issue.path.join("."), message: issue.message }));
4862
+ writeJsonEnvelope({
4863
+ ok: false,
4864
+ error: {
4865
+ code: "VALIDATION_ERROR",
4866
+ message: fields.map((f) => f.path ? `${f.path}: ${f.message}` : f.message).join("; "),
4867
+ fields
4868
+ }
4869
+ });
4870
+ process.exit(1);
4871
+ }
4872
+ try {
4873
+ const chatId = requireChatId();
4874
+ const response = await apiPost("/api/ads/google/draft/stage", { chatId, op: preflight.data });
4875
+ writeJsonEnvelope(response);
4876
+ } catch (err) {
4877
+ handleGoogleError(err);
4878
+ }
4879
+ }
4880
+ async function stageCreate(kind, customerId, payload) {
4881
+ await stageGoogleOp({ kind, customerId, payload });
4882
+ }
4883
+ async function stageGoogleOps(rawOps) {
4884
+ if (rawOps.length === 1 && rawOps[0]) {
4885
+ await stageGoogleOp(rawOps[0]);
4886
+ return;
4887
+ }
4888
+ const ops = [];
4889
+ for (const [index, raw] of rawOps.entries()) {
4890
+ const preflight = googleDraftOpInputSchema.safeParse(raw);
4891
+ if (!preflight.success) {
4892
+ const fields = preflight.error.issues.map((issue) => ({
4893
+ path: `ops[${index}].${issue.path.join(".")}`,
4894
+ message: issue.message
4895
+ }));
4896
+ writeJsonEnvelope({
4897
+ ok: false,
4898
+ error: {
4899
+ code: "VALIDATION_ERROR",
4900
+ message: fields.map((f) => `${f.path}: ${f.message}`).join("; "),
4901
+ fields
4902
+ }
4903
+ });
4904
+ process.exit(1);
4905
+ }
4906
+ ops.push(preflight.data);
4907
+ }
4908
+ try {
4909
+ const chatId = requireChatId();
4910
+ const response = await apiPost("/api/ads/google/draft/stage-batch", { chatId, ops });
4911
+ writeJsonEnvelope(response);
4912
+ } catch (err) {
4913
+ handleGoogleError(err);
4914
+ }
4915
+ }
4916
+ async function stageUpdate(kind, customerId, target, payload) {
4917
+ await stageGoogleOp({ kind, customerId, target, payload });
4918
+ }
4919
+ async function stageTarget(kind, customerId, target) {
4920
+ await stageGoogleOp({ kind, customerId, target });
4921
+ }
4922
+ async function draftAction(path12, body) {
4923
+ try {
4924
+ const chatId = requireChatId();
4925
+ const response = await apiPost(path12, { chatId, ...body });
4926
+ writeJsonEnvelope(response);
4927
+ } catch (err) {
4928
+ handleGoogleError(err);
4929
+ }
4930
+ }
4931
+ async function draftListAction(json) {
4932
+ try {
4933
+ const chatId = requireChatId();
4934
+ const response = await apiPost("/api/ads/google/draft", { chatId });
4935
+ if (json || !response.ok || !response.data) {
4936
+ writeJsonEnvelope(response);
4937
+ return;
4938
+ }
4939
+ process.stdout.write(`${renderDraftStatus(response.data)}
4940
+ `);
4941
+ } catch (err) {
4942
+ handleGoogleError(err);
4943
+ }
4944
+ }
4945
+
4946
+ // src/commands/ads/google/draft.ts
4947
+ var draftCommand2 = defineCommand22({
4948
+ meta: { name: "draft", description: "List, remove, or clear staged Google Ads write ops for this chat" },
4949
+ subCommands: {
4950
+ list: defineCommand22({
4951
+ meta: {
4952
+ name: "list",
4953
+ description: "Review everything staged as a campaign \u25B8 ad group \u25B8 ad tree (--json for the raw envelope)"
4954
+ },
4955
+ args: { json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable tree" } },
4956
+ run: async ({ args }) => {
4957
+ await draftListAction(args.json === true);
4958
+ }
4959
+ }),
4960
+ remove: defineCommand22({
4961
+ meta: { name: "remove", description: "Remove one staged op (cascades to dependents)" },
4962
+ args: { ref: { type: "positional", description: "Staged op ref (g_temp_* or target)", required: false } },
4963
+ run: async ({ args }) => {
4964
+ await draftAction("/api/ads/google/draft/remove", { ref: requireTarget(args, "op") });
4965
+ }
4966
+ }),
4967
+ clear: defineCommand22({
4968
+ meta: { name: "clear", description: "Discard all staged ops on this chat" },
4969
+ run: async () => {
4970
+ await draftAction("/api/ads/google/draft/clear", {});
4971
+ }
4972
+ })
4973
+ }
4974
+ });
4975
+
3838
4976
  // src/commands/ads/google/keywords/index.ts
3839
- import { defineCommand as defineCommand26 } from "citty";
4977
+ import { defineCommand as defineCommand27 } from "citty";
3840
4978
 
3841
4979
  // src/commands/ads/google/keywords/discover.ts
3842
- import { defineCommand as defineCommand22 } from "citty";
4980
+ import { defineCommand as defineCommand23 } from "citty";
3843
4981
 
3844
4982
  // src/geo-context.ts
3845
4983
  var GOOGLE_ADS_LOCATIONS = [
@@ -4114,7 +5252,7 @@ function handleKeywordError(err) {
4114
5252
  writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
4115
5253
  process.exit(1);
4116
5254
  }
4117
- var discoverCommand = defineCommand22({
5255
+ var discoverCommand = defineCommand23({
4118
5256
  meta: {
4119
5257
  name: "discover",
4120
5258
  description: `Discover new keyword ideas from seed keywords or competitor URLs.
@@ -4176,7 +5314,7 @@ Examples:
4176
5314
  });
4177
5315
 
4178
5316
  // src/commands/ads/google/keywords/languages.ts
4179
- import { defineCommand as defineCommand23 } from "citty";
5317
+ import { defineCommand as defineCommand24 } from "citty";
4180
5318
  registerSchema({
4181
5319
  command: "ads.google.keywords.languages",
4182
5320
  description: "List all supported language IDs for --language flag in Google Ads keyword commands.",
@@ -4186,7 +5324,7 @@ var FIELDS = {
4186
5324
  id: "Language ID to pass as --language",
4187
5325
  name: "Language name"
4188
5326
  };
4189
- var languagesCommand = defineCommand23({
5327
+ var languagesCommand = defineCommand24({
4190
5328
  meta: {
4191
5329
  name: "languages",
4192
5330
  description: "List all supported language IDs for --language flag."
@@ -4197,7 +5335,7 @@ var languagesCommand = defineCommand23({
4197
5335
  });
4198
5336
 
4199
5337
  // src/commands/ads/google/keywords/locations.ts
4200
- import { defineCommand as defineCommand24 } from "citty";
5338
+ import { defineCommand as defineCommand25 } from "citty";
4201
5339
  registerSchema({
4202
5340
  command: "ads.google.keywords.locations",
4203
5341
  description: "List all supported geo target IDs for --location flag in Google Ads keyword commands.",
@@ -4207,7 +5345,7 @@ var FIELDS2 = {
4207
5345
  id: "Geo target ID to pass as --location",
4208
5346
  name: "Country/region name"
4209
5347
  };
4210
- var locationsCommand = defineCommand24({
5348
+ var locationsCommand = defineCommand25({
4211
5349
  meta: {
4212
5350
  name: "locations",
4213
5351
  description: "List all supported geo target IDs for --location flag."
@@ -4218,7 +5356,7 @@ var locationsCommand = defineCommand24({
4218
5356
  });
4219
5357
 
4220
5358
  // src/commands/ads/google/keywords/metrics.ts
4221
- import { defineCommand as defineCommand25 } from "citty";
5359
+ import { defineCommand as defineCommand26 } from "citty";
4222
5360
  registerSchema({
4223
5361
  command: "ads.google.keywords.metrics",
4224
5362
  description: "Get historical metrics for specific keywords. Returns { historical_metrics: [...] } with snake_case fields matching the Google Ads API. IMPORTANT: If --location and --language are omitted, defaults to United States (2840) and English (1000). The response includes a query_context object showing which location/language were used.",
@@ -4242,7 +5380,7 @@ registerSchema({
4242
5380
  output: { type: "string", description: "Format: json|csv|jsonl|md", required: false, default: "json" }
4243
5381
  }
4244
5382
  });
4245
- var metricsCommand = defineCommand25({
5383
+ var metricsCommand = defineCommand26({
4246
5384
  meta: {
4247
5385
  name: "metrics",
4248
5386
  description: `Get historical search metrics for specific keywords.
@@ -4329,7 +5467,7 @@ Examples:
4329
5467
  });
4330
5468
 
4331
5469
  // src/commands/ads/google/keywords/index.ts
4332
- var keywordsCommand = defineCommand26({
5470
+ var keywordsCommand = defineCommand27({
4333
5471
  meta: {
4334
5472
  name: "keywords",
4335
5473
  description: `Keyword research tools. Subcommands: discover, metrics, locations, languages.
@@ -4349,8 +5487,8 @@ Examples:
4349
5487
  });
4350
5488
 
4351
5489
  // src/commands/ads/google/library/index.ts
4352
- import { defineCommand as defineCommand27 } from "citty";
4353
- var listAdvertisers = defineCommand27({
5490
+ import { defineCommand as defineCommand28 } from "citty";
5491
+ var listAdvertisers = defineCommand28({
4354
5492
  meta: {
4355
5493
  name: "list-advertisers",
4356
5494
  description: "List tracked Google advertisers and their accounts"
@@ -4367,7 +5505,7 @@ var listAdvertisers = defineCommand27({
4367
5505
  }
4368
5506
  }
4369
5507
  });
4370
- var syncStatus = defineCommand27({
5508
+ var syncStatus = defineCommand28({
4371
5509
  meta: {
4372
5510
  name: "sync-status",
4373
5511
  description: "Check the sync status and ad counts of a Google account"
@@ -4387,7 +5525,7 @@ var syncStatus = defineCommand27({
4387
5525
  writeAdsJson({ ok: true, data });
4388
5526
  }
4389
5527
  });
4390
- var searchAds = defineCommand27({
5528
+ var searchAds = defineCommand28({
4391
5529
  meta: {
4392
5530
  name: "search-ads",
4393
5531
  description: "Search and filter Google ads for an account"
@@ -4444,7 +5582,7 @@ var searchAds = defineCommand27({
4444
5582
  }
4445
5583
  }
4446
5584
  });
4447
- var searchAdvertiser = defineCommand27({
5585
+ var searchAdvertiser = defineCommand28({
4448
5586
  meta: {
4449
5587
  name: "search-advertiser",
4450
5588
  description: "Search for an advertiser on the Google Ads Transparency Center"
@@ -4479,7 +5617,7 @@ var searchAdvertiser = defineCommand27({
4479
5617
  function sleep(ms) {
4480
5618
  return new Promise((resolve5) => setTimeout(resolve5, ms));
4481
5619
  }
4482
- var track = defineCommand27({
5620
+ var track = defineCommand28({
4483
5621
  meta: {
4484
5622
  name: "track",
4485
5623
  description: "Track a new Google advertiser (from search results). Waits for initial sync to complete before returning."
@@ -4537,7 +5675,7 @@ var track = defineCommand27({
4537
5675
  process.exit(1);
4538
5676
  }
4539
5677
  });
4540
- var sync = defineCommand27({
5678
+ var sync = defineCommand28({
4541
5679
  meta: {
4542
5680
  name: "sync",
4543
5681
  description: "Trigger an immediate sync for a Google account. Waits for completion before returning."
@@ -4581,7 +5719,7 @@ var sync = defineCommand27({
4581
5719
  process.exit(1);
4582
5720
  }
4583
5721
  });
4584
- var searchCompetitors = defineCommand27({
5722
+ var searchCompetitors = defineCommand28({
4585
5723
  meta: {
4586
5724
  name: "search-competitors",
4587
5725
  description: "Search for competitors running Google ads for a keyword (DataForSEO)"
@@ -4613,7 +5751,7 @@ var searchCompetitors = defineCommand27({
4613
5751
  }
4614
5752
  }
4615
5753
  });
4616
- var library = defineCommand27({
5754
+ var library = defineCommand28({
4617
5755
  meta: {
4618
5756
  name: "library",
4619
5757
  description: "Manage and search the Google Ads Library"
@@ -4630,9 +5768,9 @@ var library = defineCommand27({
4630
5768
  });
4631
5769
 
4632
5770
  // src/commands/ads/google/query.ts
4633
- import { appendFileSync, existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
5771
+ import { appendFileSync, existsSync as existsSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
4634
5772
  import { resolve } from "path";
4635
- import { defineCommand as defineCommand28 } from "citty";
5773
+ import { defineCommand as defineCommand29 } from "citty";
4636
5774
 
4637
5775
  // src/commands/ads/google/preflight.ts
4638
5776
  function buildCommand2(query, customerId) {
@@ -4653,6 +5791,24 @@ function applyAutoFixes(query, limit) {
4653
5791
  corrected = corrected.replace(/shopping_performance_view\.product_(\w+)/g, "segments.product_$1");
4654
5792
  warnings.push({ code: "FIELD_RENAMED", message: "shopping_performance_view.product_* \u2192 segments.product_*" });
4655
5793
  }
5794
+ if (/asset\.\w+_asset\.final_(mobile_)?urls\b/.test(corrected)) {
5795
+ corrected = corrected.replace(/asset\.\w+_asset\.final_(mobile_)?urls\b/g, "asset.final_$1urls");
5796
+ warnings.push({ code: "FIELD_RENAMED", message: "asset.<type>_asset.final_urls \u2192 asset.final_urls" });
5797
+ }
5798
+ if (/FROM\s+campaign_budget\b/i.test(corrected)) {
5799
+ const whereClause = corrected.split(/\bWHERE\b/i)[1] ?? "";
5800
+ const selectClause = corrected.split(/\bFROM\b/i)[0] ?? "";
5801
+ const missing = [...new Set(whereClause.match(/campaign\.[\w.]+/g) ?? [])].filter(
5802
+ (field) => !selectClause.includes(field)
5803
+ );
5804
+ if (missing.length > 0) {
5805
+ corrected = corrected.replace(/SELECT\s+/i, `SELECT ${missing.join(", ")}, `);
5806
+ warnings.push({
5807
+ code: "REQUIRED_FIELD_ADDED",
5808
+ message: `Added ${missing.join(", ")} to SELECT \u2014 campaign_budget queries must select campaign fields used in WHERE`
5809
+ });
5810
+ }
5811
+ }
4656
5812
  if (/campaign\.status\s*=\s*'ACTIVE'/i.test(corrected)) {
4657
5813
  corrected = corrected.replace(/campaign\.status\s*=\s*'ACTIVE'/gi, "campaign.status = 'ENABLED'");
4658
5814
  warnings.push({ code: "ENUM_CORRECTED", message: "campaign.status ACTIVE \u2192 ENABLED" });
@@ -4924,7 +6080,7 @@ function writeRowsToFile(filePath, rows, fields, append) {
4924
6080
  `, "utf-8");
4925
6081
  }
4926
6082
  } else if (append && existsSync3(filePath)) {
4927
- const existing = JSON.parse(readFileSync3(filePath, "utf-8"));
6083
+ const existing = JSON.parse(readFileSync4(filePath, "utf-8"));
4928
6084
  writeFileSync2(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
4929
6085
  } else {
4930
6086
  writeFileSync2(filePath, JSON.stringify(rows, null, 2), "utf-8");
@@ -5088,7 +6244,7 @@ function handleQueryError(err, finalQuery, customerId) {
5088
6244
  });
5089
6245
  process.exit(1);
5090
6246
  }
5091
- var queryCommand = defineCommand28({
6247
+ var queryCommand = defineCommand29({
5092
6248
  meta: {
5093
6249
  name: "query",
5094
6250
  description: `Run GAQL queries against Google Ads. Supports raw GAQL, presets, pagination, file export, and caching.
@@ -5145,8 +6301,546 @@ Examples:
5145
6301
  }
5146
6302
  });
5147
6303
 
6304
+ // src/commands/ads/google/write-commands.ts
6305
+ import { defineCommand as defineCommand30 } from "citty";
6306
+ var customerIdArg = { "customer-id": { type: "string", description: "10-digit Google Ads customer id" } };
6307
+ var fileArg = {
6308
+ file: { type: "string", description: "JSON file with the full op payload (flags override)" }
6309
+ };
6310
+ var budgetsCommand = defineCommand30({
6311
+ meta: { name: "budgets", description: "Stage campaign budget create/update" },
6312
+ subCommands: {
6313
+ create: defineCommand30({
6314
+ meta: { name: "create", description: "Stage a campaign budget" },
6315
+ args: {
6316
+ ...customerIdArg,
6317
+ ...fileArg,
6318
+ name: { type: "string", description: "Budget name" },
6319
+ amount: { type: "string", description: "Daily amount in major currency units (e.g. 50)" },
6320
+ delivery: { type: "string", description: "STANDARD | ACCELERATED" },
6321
+ shared: { type: "boolean", description: "Explicitly shared budget" }
6322
+ },
6323
+ run: async ({ args }) => {
6324
+ const customerId = requireCustomerId(args);
6325
+ const payload = mergePayload(loadJsonFileArg(args.file), {
6326
+ name: args.name,
6327
+ amountMicros: microsFlag(args.amount, "--amount"),
6328
+ deliveryMethod: args.delivery,
6329
+ explicitlyShared: args.shared || void 0
6330
+ });
6331
+ await stageCreate("google.budget.create", customerId, payload);
6332
+ }
6333
+ }),
6334
+ update: defineCommand30({
6335
+ meta: { name: "update", description: "Stage a budget update" },
6336
+ args: {
6337
+ ...customerIdArg,
6338
+ ...fileArg,
6339
+ name: { type: "string" },
6340
+ amount: { type: "string", description: "New daily amount in major currency units" },
6341
+ delivery: { type: "string" }
6342
+ },
6343
+ run: async ({ args }) => {
6344
+ const customerId = requireCustomerId(args);
6345
+ const target = requireTarget(args, "budget");
6346
+ const payload = mergePayload(loadJsonFileArg(args.file), {
6347
+ name: args.name,
6348
+ amountMicros: microsFlag(args.amount, "--amount"),
6349
+ deliveryMethod: args.delivery
6350
+ });
6351
+ await stageUpdate("google.budget.update", customerId, target, payload);
6352
+ }
6353
+ })
6354
+ }
6355
+ });
6356
+ function biddingFromFlags(args) {
6357
+ const type = args["bidding-strategy"];
6358
+ if (!type) {
6359
+ return void 0;
6360
+ }
6361
+ return {
6362
+ type,
6363
+ targetCpaMicros: microsFlag(args["target-cpa"], "--target-cpa"),
6364
+ targetRoas: args["target-roas"] !== void 0 ? Number(args["target-roas"]) : void 0
6365
+ };
6366
+ }
6367
+ var campaignsCommand = defineCommand30({
6368
+ meta: { name: "campaigns", description: "Stage campaign create/update/pause/resume/remove" },
6369
+ subCommands: {
6370
+ create: defineCommand30({
6371
+ meta: { name: "create", description: "Stage a campaign" },
6372
+ args: {
6373
+ ...customerIdArg,
6374
+ ...fileArg,
6375
+ name: { type: "string" },
6376
+ "channel-type": {
6377
+ type: "string",
6378
+ description: "SEARCH | DISPLAY | SHOPPING | VIDEO | PERFORMANCE_MAX | DEMAND_GEN | \u2026"
6379
+ },
6380
+ "sub-type": { type: "string", description: "Advertising channel sub-type" },
6381
+ "budget-ref": { type: "string", description: "Budget ref (g_temp_*, id, or resource name)" },
6382
+ "bidding-strategy": {
6383
+ type: "string",
6384
+ description: "MANUAL_CPC | MAXIMIZE_CONVERSIONS | TARGET_CPA | TARGET_ROAS | \u2026"
6385
+ },
6386
+ "target-cpa": { type: "string", description: "Target CPA (major units) for TARGET_CPA" },
6387
+ "target-roas": { type: "string", description: "Target ROAS (e.g. 4.0) for TARGET_ROAS" },
6388
+ objective: { type: "string", description: "Advisory UI objective (SALES, LEADS, \u2026)" },
6389
+ "start-date": { type: "string", description: "YYYY-MM-DD" },
6390
+ "end-date": { type: "string", description: "YYYY-MM-DD" },
6391
+ status: { type: "string", description: "ENABLED | PAUSED (default PAUSED)" }
6392
+ },
6393
+ run: async ({ args }) => {
6394
+ const customerId = requireCustomerId(args);
6395
+ const payload = mergePayload(loadJsonFileArg(args.file), {
6396
+ name: args.name,
6397
+ channelType: args["channel-type"],
6398
+ channelSubType: args["sub-type"],
6399
+ budget: args["budget-ref"],
6400
+ bidding: biddingFromFlags(args),
6401
+ objective: args.objective,
6402
+ startDate: args["start-date"],
6403
+ endDate: args["end-date"],
6404
+ status: args.status
6405
+ });
6406
+ await stageCreate("google.campaign.create", customerId, payload);
6407
+ }
6408
+ }),
6409
+ update: defineCommand30({
6410
+ meta: { name: "update", description: "Stage a campaign update" },
6411
+ args: {
6412
+ ...customerIdArg,
6413
+ ...fileArg,
6414
+ name: { type: "string" },
6415
+ "budget-ref": { type: "string" },
6416
+ "bidding-strategy": { type: "string" },
6417
+ "target-cpa": { type: "string" },
6418
+ "target-roas": { type: "string" },
6419
+ status: { type: "string" }
6420
+ },
6421
+ run: async ({ args }) => {
6422
+ const customerId = requireCustomerId(args);
6423
+ const target = requireTarget(args, "campaign");
6424
+ const payload = mergePayload(loadJsonFileArg(args.file), {
6425
+ name: args.name,
6426
+ budget: args["budget-ref"],
6427
+ bidding: biddingFromFlags(args),
6428
+ status: args.status
6429
+ });
6430
+ await stageUpdate("google.campaign.update", customerId, target, payload);
6431
+ }
6432
+ }),
6433
+ pause: statusCommand2("google.campaign.pause", "campaign"),
6434
+ resume: statusCommand2("google.campaign.resume", "campaign"),
6435
+ remove: statusCommand2("google.campaign.remove", "campaign")
6436
+ }
6437
+ });
6438
+ function statusCommand2(kind, entity) {
6439
+ return defineCommand30({
6440
+ meta: { name: kind.split(".")[2], description: `Stage a ${entity} ${kind.split(".")[2]}` },
6441
+ args: {
6442
+ ...customerIdArg,
6443
+ id: { type: "positional", description: `${entity} resource name or id`, required: false }
6444
+ },
6445
+ run: async ({ args }) => {
6446
+ const customerId = requireCustomerId(args);
6447
+ await stageTarget(kind, customerId, requireTarget(args, entity));
6448
+ }
6449
+ });
6450
+ }
6451
+ var adGroupsCommand = defineCommand30({
6452
+ meta: { name: "ad-groups", description: "Stage ad group create/update/pause/resume/remove" },
6453
+ subCommands: {
6454
+ create: defineCommand30({
6455
+ meta: { name: "create", description: "Stage an ad group" },
6456
+ args: {
6457
+ ...customerIdArg,
6458
+ ...fileArg,
6459
+ name: { type: "string" },
6460
+ "campaign-ref": { type: "string", description: "Campaign ref (g_temp_*, id, or resource name)" },
6461
+ type: { type: "string", description: "Ad group type (default SEARCH_STANDARD)" },
6462
+ "cpc-bid": { type: "string", description: "Default CPC bid in major units" },
6463
+ status: { type: "string" }
6464
+ },
6465
+ run: async ({ args }) => {
6466
+ const customerId = requireCustomerId(args);
6467
+ const payload = mergePayload(loadJsonFileArg(args.file), {
6468
+ name: args.name,
6469
+ campaign: args["campaign-ref"],
6470
+ type: args.type,
6471
+ cpcBidMicros: microsFlag(args["cpc-bid"], "--cpc-bid"),
6472
+ status: args.status
6473
+ });
6474
+ await stageCreate("google.adGroup.create", customerId, payload);
6475
+ }
6476
+ }),
6477
+ update: defineCommand30({
6478
+ meta: { name: "update", description: "Stage an ad group update" },
6479
+ args: {
6480
+ ...customerIdArg,
6481
+ ...fileArg,
6482
+ name: { type: "string" },
6483
+ "cpc-bid": { type: "string" },
6484
+ status: { type: "string" }
6485
+ },
6486
+ run: async ({ args }) => {
6487
+ const customerId = requireCustomerId(args);
6488
+ const target = requireTarget(args, "ad group");
6489
+ const payload = mergePayload(loadJsonFileArg(args.file), {
6490
+ name: args.name,
6491
+ cpcBidMicros: microsFlag(args["cpc-bid"], "--cpc-bid"),
6492
+ status: args.status
6493
+ });
6494
+ await stageUpdate("google.adGroup.update", customerId, target, payload);
6495
+ }
6496
+ }),
6497
+ pause: statusCommand2("google.adGroup.pause", "ad group"),
6498
+ resume: statusCommand2("google.adGroup.resume", "ad group"),
6499
+ remove: statusCommand2("google.adGroup.remove", "ad group")
6500
+ }
6501
+ });
6502
+ var keywordWriteSubcommands = {
6503
+ add: defineCommand30({
6504
+ meta: { name: "add", description: "Add keyword(s) to an ad group \u2014 one --text or a whole batch" },
6505
+ args: {
6506
+ ...customerIdArg,
6507
+ "ad-group-ref": { type: "string", description: "Ad group ref (g_temp_*, id, or resource name)" },
6508
+ text: {
6509
+ type: "string",
6510
+ description: 'Keyword text \u2014 comma-separate for a batch, optional ":EXACT|:PHRASE|:BROAD" suffix per entry'
6511
+ },
6512
+ file: { type: "string", description: "Text file with one keyword[:MATCH_TYPE] per line" },
6513
+ "match-type": { type: "string", description: "Default match type: EXACT | PHRASE | BROAD" },
6514
+ "cpc-bid": { type: "string", description: "Keyword CPC bid in major units (applies to all)" },
6515
+ "final-url": { type: "string", description: "Keyword-level final URL (applies to all)" }
6516
+ },
6517
+ run: async ({ args }) => {
6518
+ const customerId = requireCustomerId(args);
6519
+ const adGroup = requireStringFlag(args["ad-group-ref"], "--ad-group-ref");
6520
+ const cpcBidMicros = microsFlag(args["cpc-bid"], "--cpc-bid");
6521
+ const finalUrls = args["final-url"] ? [args["final-url"]] : void 0;
6522
+ await stageGoogleOps(
6523
+ keywordEntries(args).map((entry) => ({
6524
+ kind: "google.keyword.add",
6525
+ customerId,
6526
+ payload: { adGroup, text: entry.text, matchType: entry.matchType, cpcBidMicros, finalUrls }
6527
+ }))
6528
+ );
6529
+ }
6530
+ }),
6531
+ update: defineCommand30({
6532
+ meta: { name: "update", description: "Update a keyword" },
6533
+ args: { ...customerIdArg, "cpc-bid": { type: "string" }, status: { type: "string" } },
6534
+ run: async ({ args }) => {
6535
+ const customerId = requireCustomerId(args);
6536
+ await stageUpdate("google.keyword.update", customerId, requireTarget(args, "keyword"), {
6537
+ cpcBidMicros: microsFlag(args["cpc-bid"], "--cpc-bid"),
6538
+ status: args.status
6539
+ });
6540
+ }
6541
+ }),
6542
+ remove: statusCommand2("google.keyword.remove", "keyword")
6543
+ };
6544
+ var negativeKeywordsCommand = defineCommand30({
6545
+ meta: { name: "negative-keywords", description: "Stage negative keyword add/remove (ad-group or campaign level)" },
6546
+ subCommands: {
6547
+ add: defineCommand30({
6548
+ meta: { name: "add", description: "Add negative keyword(s) \u2014 one --text or a whole batch" },
6549
+ args: {
6550
+ ...customerIdArg,
6551
+ level: { type: "string", description: "adGroup | campaign" },
6552
+ "parent-ref": { type: "string", description: "Ad group or campaign ref" },
6553
+ text: {
6554
+ type: "string",
6555
+ description: 'Keyword text \u2014 comma-separate for a batch, optional ":MATCH_TYPE" suffix per entry'
6556
+ },
6557
+ file: { type: "string", description: "Text file with one keyword[:MATCH_TYPE] per line" },
6558
+ "match-type": { type: "string", description: "Default match type: EXACT | PHRASE | BROAD" }
6559
+ },
6560
+ run: async ({ args }) => {
6561
+ const customerId = requireCustomerId(args);
6562
+ const level = requireStringFlag(args.level, "--level");
6563
+ const parent = requireStringFlag(args["parent-ref"], "--parent-ref");
6564
+ await stageGoogleOps(
6565
+ keywordEntries(args).map((entry) => ({
6566
+ kind: "google.negativeKeyword.add",
6567
+ customerId,
6568
+ payload: { level, parent, text: entry.text, matchType: entry.matchType }
6569
+ }))
6570
+ );
6571
+ }
6572
+ }),
6573
+ remove: statusCommand2("google.negativeKeyword.remove", "negative keyword")
6574
+ }
6575
+ });
6576
+ var keywordListsCommand = defineCommand30({
6577
+ meta: {
6578
+ name: "keyword-lists",
6579
+ description: "Stage shared negative keyword lists (create/add/attach/detach). Build at least one shared negative list (brand, competitor, junk-intent terms) and attach it to every campaign to protect spend."
6580
+ },
6581
+ subCommands: {
6582
+ create: defineCommand30({
6583
+ meta: { name: "create", description: "Create a shared negative keyword list" },
6584
+ args: {
6585
+ ...customerIdArg,
6586
+ name: { type: "string" },
6587
+ type: {
6588
+ type: "string",
6589
+ description: "NEGATIVE_KEYWORDS (default) | NEGATIVE_PLACEMENTS | ACCOUNT_LEVEL_NEGATIVE_KEYWORDS"
6590
+ }
6591
+ },
6592
+ run: async ({ args }) => {
6593
+ const customerId = requireCustomerId(args);
6594
+ await stageCreate("google.sharedSet.create", customerId, {
6595
+ name: requireStringFlag(args.name, "--name"),
6596
+ type: args.type
6597
+ });
6598
+ }
6599
+ }),
6600
+ add: defineCommand30({
6601
+ meta: { name: "add", description: "Add keyword(s) to a shared list \u2014 one --text or a whole batch" },
6602
+ args: {
6603
+ ...customerIdArg,
6604
+ "list-ref": { type: "string", description: "Shared set ref" },
6605
+ text: {
6606
+ type: "string",
6607
+ description: 'Keyword text \u2014 comma-separate for a batch, optional ":MATCH_TYPE" suffix per entry'
6608
+ },
6609
+ file: { type: "string", description: "Text file with one keyword[:MATCH_TYPE] per line" },
6610
+ "match-type": { type: "string", description: "Default match type: EXACT | PHRASE | BROAD" }
6611
+ },
6612
+ run: async ({ args }) => {
6613
+ const customerId = requireCustomerId(args);
6614
+ const sharedSet = requireStringFlag(args["list-ref"], "--list-ref");
6615
+ await stageGoogleOps(
6616
+ keywordEntries(args).map((entry) => ({
6617
+ kind: "google.sharedSetMember.add",
6618
+ customerId,
6619
+ payload: { sharedSet, text: entry.text, matchType: entry.matchType }
6620
+ }))
6621
+ );
6622
+ }
6623
+ }),
6624
+ attach: defineCommand30({
6625
+ meta: { name: "attach", description: "Attach a keyword list to a campaign" },
6626
+ args: { ...customerIdArg, "campaign-ref": { type: "string" }, "list-ref": { type: "string" } },
6627
+ run: async ({ args }) => {
6628
+ const customerId = requireCustomerId(args);
6629
+ await stageCreate("google.campaignSharedSet.attach", customerId, {
6630
+ campaign: requireStringFlag(args["campaign-ref"], "--campaign-ref"),
6631
+ sharedSet: requireStringFlag(args["list-ref"], "--list-ref")
6632
+ });
6633
+ }
6634
+ }),
6635
+ detach: statusCommand2("google.campaignSharedSet.detach", "campaign shared set")
6636
+ }
6637
+ });
6638
+ function rsaContentFromFlags(args) {
6639
+ const headlines = listFlag(args.headlines);
6640
+ const descriptions = listFlag(args.descriptions);
6641
+ if (!headlines || !descriptions) {
6642
+ failWriteValidation("responsive search ads need --headlines and --descriptions (comma-separated), or use --file");
6643
+ }
6644
+ const finalUrls = listFlag(args["final-url"]);
6645
+ if (!finalUrls) {
6646
+ failWriteValidation("--final-url is required for a responsive search ad");
6647
+ }
6648
+ return {
6649
+ format: "responsiveSearch",
6650
+ headlines: headlines.map((text) => ({ text })),
6651
+ descriptions: descriptions.map((text) => ({ text })),
6652
+ path1: args.path1,
6653
+ path2: args.path2,
6654
+ finalUrls
6655
+ };
6656
+ }
6657
+ var adsCommand = defineCommand30({
6658
+ meta: { name: "ads", description: "Stage ad create/update/pause/resume/remove" },
6659
+ subCommands: {
6660
+ create: defineCommand30({
6661
+ meta: {
6662
+ name: "create",
6663
+ description: "Stage an ad (responsive search via flags; other formats via --file). RSA needs 3\u201315 headlines and 2\u20134 descriptions \u2014 give Google 8\u201312 varied headlines to test, and stage 2\u20134 ads per ad group."
6664
+ },
6665
+ args: {
6666
+ ...customerIdArg,
6667
+ ...fileArg,
6668
+ "ad-group-ref": { type: "string", description: "Ad group ref" },
6669
+ format: {
6670
+ type: "string",
6671
+ description: "responsiveSearch (default) | responsiveDisplay | performanceMaxAssetGroup | call | app | video | demandGen"
6672
+ },
6673
+ headlines: { type: "string", description: "Comma-separated headlines (RSA)" },
6674
+ descriptions: { type: "string", description: "Comma-separated descriptions (RSA)" },
6675
+ path1: { type: "string" },
6676
+ path2: { type: "string" },
6677
+ "final-url": { type: "string", description: "Comma-separated final URLs" },
6678
+ status: { type: "string" }
6679
+ },
6680
+ run: async ({ args }) => {
6681
+ const customerId = requireCustomerId(args);
6682
+ const file = loadJsonFileArg(args.file);
6683
+ const format = args.format ?? "responsiveSearch";
6684
+ const content = file.content ?? (format === "responsiveSearch" ? rsaContentFromFlags(args) : failWriteValidation(`--format ${format} needs --file with the ad content`));
6685
+ await stageCreate("google.ad.create", customerId, {
6686
+ adGroup: requireStringFlag(args["ad-group-ref"] ?? file.adGroup, "--ad-group-ref"),
6687
+ status: args.status ?? file.status,
6688
+ content
6689
+ });
6690
+ }
6691
+ }),
6692
+ update: defineCommand30({
6693
+ meta: { name: "update", description: "Stage an ad update" },
6694
+ args: { ...customerIdArg, ...fileArg, status: { type: "string" } },
6695
+ run: async ({ args }) => {
6696
+ const customerId = requireCustomerId(args);
6697
+ const file = loadJsonFileArg(args.file);
6698
+ await stageUpdate(
6699
+ "google.ad.update",
6700
+ customerId,
6701
+ requireTarget(args, "ad"),
6702
+ mergePayload(file, { status: args.status })
6703
+ );
6704
+ }
6705
+ }),
6706
+ pause: statusCommand2("google.ad.pause", "ad"),
6707
+ resume: statusCommand2("google.ad.resume", "ad"),
6708
+ remove: statusCommand2("google.ad.remove", "ad")
6709
+ }
6710
+ });
6711
+ function fileCreateCommand(name, kind, description) {
6712
+ return defineCommand30({
6713
+ meta: { name, description },
6714
+ args: { ...customerIdArg, ...fileArg },
6715
+ run: async ({ args }) => {
6716
+ const customerId = requireCustomerId(args);
6717
+ const payload = loadJsonFileArg(args.file);
6718
+ if (Object.keys(payload).length === 0) {
6719
+ failWriteValidation(`${kind} needs --file with the op payload`);
6720
+ }
6721
+ await stageGoogleOp({ kind, customerId, payload });
6722
+ }
6723
+ });
6724
+ }
6725
+ var assetsCommand = defineCommand30({
6726
+ meta: {
6727
+ name: "assets",
6728
+ description: "Stage asset create + asset-link attach/detach (via --file). For a high-performance Search campaign add \u22654 sitelinks, \u22653 callouts, and \u22651 structured snippet per campaign."
6729
+ },
6730
+ subCommands: {
6731
+ create: fileCreateCommand(
6732
+ "create",
6733
+ "google.asset.create",
6734
+ "Stage an asset (text/image/sitelink/callout/structuredSnippet/\u2026)"
6735
+ ),
6736
+ attach: fileCreateCommand("attach", "google.assetLink.attach", "Attach an asset to a campaign/adGroup/customer"),
6737
+ detach: statusCommand2("google.assetLink.detach", "asset link")
6738
+ }
6739
+ });
6740
+ var audiencesCommand = defineCommand30({
6741
+ meta: { name: "audiences", description: "Stage audience (user list) create + criterion attach/detach (via --file)" },
6742
+ subCommands: {
6743
+ create: fileCreateCommand("create", "google.audience.create", "Stage a user-list audience"),
6744
+ attach: fileCreateCommand(
6745
+ "attach",
6746
+ "google.audienceCriterion.attach",
6747
+ "Target/exclude an audience on a campaign/adGroup"
6748
+ ),
6749
+ detach: statusCommand2("google.audienceCriterion.detach", "audience criterion")
6750
+ }
6751
+ });
6752
+ var conversionsCommand = defineCommand30({
6753
+ meta: { name: "conversions", description: "Stage conversion action create/update (via --file)" },
6754
+ subCommands: {
6755
+ create: fileCreateCommand("create", "google.conversionAction.create", "Stage a conversion action"),
6756
+ update: defineCommand30({
6757
+ meta: { name: "update", description: "Stage a conversion action update" },
6758
+ args: { ...customerIdArg, ...fileArg },
6759
+ run: async ({ args }) => {
6760
+ const customerId = requireCustomerId(args);
6761
+ await stageUpdate(
6762
+ "google.conversionAction.update",
6763
+ customerId,
6764
+ requireTarget(args, "conversion action"),
6765
+ loadJsonFileArg(args.file)
6766
+ );
6767
+ }
6768
+ })
6769
+ }
6770
+ });
6771
+ var biddingStrategiesCommand = defineCommand30({
6772
+ meta: { name: "bidding-strategies", description: "Stage portfolio bidding strategy create/update (via --file)" },
6773
+ subCommands: {
6774
+ create: fileCreateCommand("create", "google.biddingStrategy.create", "Stage a portfolio bidding strategy"),
6775
+ update: defineCommand30({
6776
+ meta: { name: "update", description: "Stage a portfolio bidding strategy update" },
6777
+ args: { ...customerIdArg, ...fileArg },
6778
+ run: async ({ args }) => {
6779
+ const customerId = requireCustomerId(args);
6780
+ await stageUpdate(
6781
+ "google.biddingStrategy.update",
6782
+ customerId,
6783
+ requireTarget(args, "bidding strategy"),
6784
+ loadJsonFileArg(args.file)
6785
+ );
6786
+ }
6787
+ })
6788
+ }
6789
+ });
6790
+ var labelsCommand = defineCommand30({
6791
+ meta: { name: "labels", description: "Stage label create + attach (via --file)" },
6792
+ subCommands: {
6793
+ create: defineCommand30({
6794
+ meta: { name: "create", description: "Create a label" },
6795
+ args: {
6796
+ ...customerIdArg,
6797
+ name: { type: "string" },
6798
+ "background-color": { type: "string" },
6799
+ description: { type: "string" }
6800
+ },
6801
+ run: async ({ args }) => {
6802
+ const customerId = requireCustomerId(args);
6803
+ await stageCreate("google.label.create", customerId, {
6804
+ name: requireStringFlag(args.name, "--name"),
6805
+ backgroundColor: args["background-color"],
6806
+ description: args.description
6807
+ });
6808
+ }
6809
+ }),
6810
+ attach: fileCreateCommand("attach", "google.label.attach", "Attach a label to a campaign/adGroup/ad")
6811
+ }
6812
+ });
6813
+ var campaignCriteriaCommand = defineCommand30({
6814
+ meta: {
6815
+ name: "campaign-criteria",
6816
+ description: "Stage campaign criteria (location/language/adSchedule/device) add/remove (via --file)"
6817
+ },
6818
+ subCommands: {
6819
+ add: fileCreateCommand("add", "google.campaignCriterion.add", "Add a campaign criterion"),
6820
+ remove: statusCommand2("google.campaignCriterion.remove", "campaign criterion")
6821
+ }
6822
+ });
6823
+ var googleWriteCommands = {
6824
+ budgets: budgetsCommand,
6825
+ campaigns: campaignsCommand,
6826
+ "ad-groups": adGroupsCommand,
6827
+ "negative-keywords": negativeKeywordsCommand,
6828
+ "keyword-lists": keywordListsCommand,
6829
+ ads: adsCommand,
6830
+ assets: assetsCommand,
6831
+ audiences: audiencesCommand,
6832
+ conversions: conversionsCommand,
6833
+ "bidding-strategies": biddingStrategiesCommand,
6834
+ labels: labelsCommand,
6835
+ "campaign-criteria": campaignCriteriaCommand
6836
+ };
6837
+
5148
6838
  // src/commands/ads/google/index.ts
5149
- var googleCommand = defineCommand29({
6839
+ var keywordsWithWrites = defineCommand31({
6840
+ meta: keywordsCommand.meta,
6841
+ subCommands: { ...keywordsCommand.subCommands, ...keywordWriteSubcommands }
6842
+ });
6843
+ var googleCommand = defineCommand31({
5150
6844
  meta: {
5151
6845
  name: "google",
5152
6846
  description: `Google Ads commands. Query campaigns, keywords, search terms, and more via GAQL.
@@ -5161,20 +6855,28 @@ Examples:
5161
6855
  baker ads google query --preset campaign-performance --customer-id 1234567890
5162
6856
  baker ads google currency --customer-id 1234567890
5163
6857
  baker ads google keywords discover --customer-id 1234567890 --seeds "running shoes"
5164
- baker ads google library list-advertisers \u2014 list tracked Google advertisers`
6858
+ baker ads google library list-advertisers \u2014 list tracked Google advertisers
6859
+
6860
+ Staged writes (never touch Google until the chat is published):
6861
+ baker ads google budgets create --customer-id 1234567890 --name "Search" --amount 50
6862
+ baker ads google campaigns create --customer-id 1234567890 --name "Brand" --channel-type SEARCH --budget-ref g_temp_\u2026 --bidding-strategy MANUAL_CPC
6863
+ baker ads google keyword-lists create --customer-id 1234567890 --name "Brand exclusions"
6864
+ baker ads google draft list \u2014 review staged Google Ads changes`
5165
6865
  },
5166
6866
  subCommands: {
5167
6867
  accounts: accountsCommand,
5168
6868
  currency: currencyCommand,
5169
6869
  changes: changesCommand,
5170
6870
  query: queryCommand,
5171
- keywords: keywordsCommand,
5172
- library
6871
+ keywords: keywordsWithWrites,
6872
+ library,
6873
+ ...googleWriteCommands,
6874
+ draft: draftCommand2
5173
6875
  }
5174
6876
  });
5175
6877
 
5176
6878
  // src/commands/ads/linkedin/index.ts
5177
- import { defineCommand as defineCommand49 } from "citty";
6879
+ import { defineCommand as defineCommand51 } from "citty";
5178
6880
 
5179
6881
  // src/commands/ads/linkedin/schemas.ts
5180
6882
  registerSchema({
@@ -5835,7 +7537,7 @@ registerSchema({
5835
7537
  });
5836
7538
 
5837
7539
  // src/commands/ads/linkedin/account.ts
5838
- import { defineCommand as defineCommand30 } from "citty";
7540
+ import { defineCommand as defineCommand32 } from "citty";
5839
7541
 
5840
7542
  // src/commands/ads/linkedin/shared.ts
5841
7543
  var DAY_MS2 = 864e5;
@@ -5938,7 +7640,7 @@ function resolveStatusFilter(args) {
5938
7640
  }
5939
7641
 
5940
7642
  // src/commands/ads/linkedin/account.ts
5941
- var accountCommand = defineCommand30({
7643
+ var accountCommand = defineCommand32({
5942
7644
  meta: {
5943
7645
  name: "account",
5944
7646
  description: `Single LinkedIn ad account detail (currency, status, type).
@@ -5972,9 +7674,9 @@ Examples:
5972
7674
  });
5973
7675
 
5974
7676
  // src/commands/ads/linkedin/accounts.ts
5975
- import { defineCommand as defineCommand31 } from "citty";
7677
+ import { defineCommand as defineCommand33 } from "citty";
5976
7678
  var ACCOUNTS_TTL_MS = 60 * 60 * 1e3;
5977
- var accountsCommand2 = defineCommand31({
7679
+ var accountsCommand2 = defineCommand33({
5978
7680
  meta: {
5979
7681
  name: "accounts",
5980
7682
  description: `List LinkedIn ad accounts in this company's connected scope.
@@ -6022,7 +7724,7 @@ Examples:
6022
7724
  });
6023
7725
 
6024
7726
  // src/commands/ads/linkedin/analytics.ts
6025
- import { defineCommand as defineCommand32 } from "citty";
7727
+ import { defineCommand as defineCommand34 } from "citty";
6026
7728
 
6027
7729
  // src/commands/ads/linkedin/presets.ts
6028
7730
  var INTENTS = {
@@ -6294,7 +7996,7 @@ function numberOf(v) {
6294
7996
  }
6295
7997
  return 0;
6296
7998
  }
6297
- var analyticsCommand = defineCommand32({
7999
+ var analyticsCommand = defineCommand34({
6298
8000
  meta: {
6299
8001
  name: "analytics",
6300
8002
  description: `Performance reporting \u2014 the workhorse for AI agents.
@@ -6421,8 +8123,8 @@ Examples \u2014 common AI questions:
6421
8123
  });
6422
8124
 
6423
8125
  // src/commands/ads/linkedin/audience-size.ts
6424
- import { readFileSync as readFileSync4 } from "fs";
6425
- import { defineCommand as defineCommand33 } from "citty";
8126
+ import { readFileSync as readFileSync5 } from "fs";
8127
+ import { defineCommand as defineCommand35 } from "citty";
6426
8128
  function loadTargeting(args) {
6427
8129
  const inline = args.targeting;
6428
8130
  if (inline) {
@@ -6435,7 +8137,7 @@ function loadTargeting(args) {
6435
8137
  const file = args["targeting-file"];
6436
8138
  if (file) {
6437
8139
  try {
6438
- return JSON.parse(readFileSync4(file, "utf-8"));
8140
+ return JSON.parse(readFileSync5(file, "utf-8"));
6439
8141
  } catch (e) {
6440
8142
  handleLinkedinError(
6441
8143
  new Error(`Failed to read --targeting-file: ${e instanceof Error ? e.message : "I/O error"}`)
@@ -6444,7 +8146,7 @@ function loadTargeting(args) {
6444
8146
  }
6445
8147
  handleLinkedinError(new Error("Pass --targeting-file <path> or --targeting '{...JSON...}'"));
6446
8148
  }
6447
- var audienceSizeCommand = defineCommand33({
8149
+ var audienceSizeCommand = defineCommand35({
6448
8150
  meta: {
6449
8151
  name: "audience-size",
6450
8152
  description: `Estimate audience size for a targeting payload \u2014 pre-launch sanity check.
@@ -6489,7 +8191,7 @@ Examples:
6489
8191
  });
6490
8192
 
6491
8193
  // src/commands/ads/linkedin/audit.ts
6492
- import { defineCommand as defineCommand34 } from "citty";
8194
+ import { defineCommand as defineCommand36 } from "citty";
6493
8195
  var SEVERITY_RANK = {
6494
8196
  critical: 0,
6495
8197
  high: 1,
@@ -6548,7 +8250,7 @@ function noteOf(f) {
6548
8250
  const fix = f.fix?.explanation ?? "";
6549
8251
  return [fix, ev].filter(Boolean).join(" \u2014 ");
6550
8252
  }
6551
- var auditCommand = defineCommand34({
8253
+ var auditCommand = defineCommand36({
6552
8254
  meta: {
6553
8255
  name: "audit",
6554
8256
  description: `Run a LinkedIn Ads playbook audit \u2014 30+ checks across Settings, Tracking,
@@ -6614,8 +8316,8 @@ Examples:
6614
8316
  });
6615
8317
 
6616
8318
  // src/commands/ads/linkedin/bid-pricing.ts
6617
- import { readFileSync as readFileSync5 } from "fs";
6618
- import { defineCommand as defineCommand35 } from "citty";
8319
+ import { readFileSync as readFileSync6 } from "fs";
8320
+ import { defineCommand as defineCommand37 } from "citty";
6619
8321
  function loadTargeting2(args) {
6620
8322
  const inline = args.targeting;
6621
8323
  if (inline) {
@@ -6628,7 +8330,7 @@ function loadTargeting2(args) {
6628
8330
  const file = args["targeting-file"];
6629
8331
  if (file) {
6630
8332
  try {
6631
- return JSON.parse(readFileSync5(file, "utf-8"));
8333
+ return JSON.parse(readFileSync6(file, "utf-8"));
6632
8334
  } catch (e) {
6633
8335
  handleLinkedinError(
6634
8336
  new Error(`Failed to read --targeting-file: ${e instanceof Error ? e.message : "I/O error"}`)
@@ -6637,7 +8339,7 @@ function loadTargeting2(args) {
6637
8339
  }
6638
8340
  handleLinkedinError(new Error("Pass --targeting-file <path> or --targeting '{...JSON...}'"));
6639
8341
  }
6640
- var bidPricingCommand = defineCommand35({
8342
+ var bidPricingCommand = defineCommand37({
6641
8343
  meta: {
6642
8344
  name: "bid-pricing",
6643
8345
  description: `Get LinkedIn's suggested bid range for a targeting + objective + cost type.
@@ -6687,40 +8389,40 @@ Examples:
6687
8389
  });
6688
8390
 
6689
8391
  // src/commands/ads/linkedin/campaign-groups.ts
6690
- import { defineCommand as defineCommand37 } from "citty";
8392
+ import { defineCommand as defineCommand39 } from "citty";
6691
8393
 
6692
8394
  // src/commands/ads/linkedin/write-commands.ts
6693
- import { defineCommand as defineCommand36 } from "citty";
8395
+ import { defineCommand as defineCommand38 } from "citty";
6694
8396
 
6695
8397
  // src/commands/ads/linkedin/write-shared.ts
6696
8398
  import { createHash as createHash2 } from "crypto";
6697
- import { readFileSync as readFileSync6 } from "fs";
8399
+ import { readFileSync as readFileSync7 } from "fs";
6698
8400
  function bareAccountId(args) {
6699
8401
  const raw = resolveAccountIdArg(args);
6700
8402
  return raw.replace(/^urn:li:sponsoredAccount:/, "").replace(/^sponsoredAccount:/, "");
6701
8403
  }
6702
- function failWriteValidation(message) {
8404
+ function failWriteValidation2(message) {
6703
8405
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
6704
8406
  process.exit(1);
6705
8407
  }
6706
- function loadJsonFileArg(path12) {
8408
+ function loadJsonFileArg2(path12) {
6707
8409
  if (typeof path12 !== "string" || path12.length === 0) {
6708
8410
  return {};
6709
8411
  }
6710
8412
  try {
6711
- const parsed = JSON.parse(readFileSync6(path12, "utf8"));
8413
+ const parsed = JSON.parse(readFileSync7(path12, "utf8"));
6712
8414
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
6713
- failWriteValidation(`${path12} must contain a JSON object`);
8415
+ failWriteValidation2(`${path12} must contain a JSON object`);
6714
8416
  }
6715
8417
  return parsed;
6716
8418
  } catch (err) {
6717
8419
  if (err instanceof SyntaxError) {
6718
- failWriteValidation(`${path12} is not valid JSON: ${err.message}`);
8420
+ failWriteValidation2(`${path12} is not valid JSON: ${err.message}`);
6719
8421
  }
6720
8422
  throw err;
6721
8423
  }
6722
8424
  }
6723
- function mergePayload(file, flags) {
8425
+ function mergePayload2(file, flags) {
6724
8426
  const merged = { ...file };
6725
8427
  for (const [key, value] of Object.entries(flags)) {
6726
8428
  if (value !== void 0) {
@@ -6737,7 +8439,7 @@ function parseMoneyFlag(amount, currency, flag) {
6737
8439
  return { amount: String(amount) };
6738
8440
  }
6739
8441
  if (typeof currency !== "string" || currency.length !== 3) {
6740
- failWriteValidation(`${flag} got an invalid --currency (expected a 3-letter code like EUR)`);
8442
+ failWriteValidation2(`${flag} got an invalid --currency (expected a 3-letter code like EUR)`);
6741
8443
  }
6742
8444
  return { amount: String(amount), currencyCode: currency.toUpperCase() };
6743
8445
  }
@@ -6751,7 +8453,7 @@ function parseDateFlag(value, flag) {
6751
8453
  }
6752
8454
  const parsed = Date.parse(raw);
6753
8455
  if (Number.isNaN(parsed)) {
6754
- failWriteValidation(`${flag} must be an ISO date (2026-07-10) or epoch milliseconds`);
8456
+ failWriteValidation2(`${flag} must be an ISO date (2026-07-10) or epoch milliseconds`);
6755
8457
  }
6756
8458
  return parsed;
6757
8459
  }
@@ -6766,7 +8468,7 @@ function parseOnOffFlag(value, flag) {
6766
8468
  if (raw === "off" || raw === "false") {
6767
8469
  return false;
6768
8470
  }
6769
- failWriteValidation(`${flag} must be on|off`);
8471
+ failWriteValidation2(`${flag} must be on|off`);
6770
8472
  }
6771
8473
  function parseLocaleFlag(value) {
6772
8474
  if (value === void 0 || value === null || value === "") {
@@ -6774,7 +8476,7 @@ function parseLocaleFlag(value) {
6774
8476
  }
6775
8477
  const match = /^([a-z]{2})[_-]([A-Za-z]{2})$/.exec(String(value));
6776
8478
  if (!match) {
6777
- failWriteValidation("--locale must look like en_US (language_COUNTRY)");
8479
+ failWriteValidation2("--locale must look like en_US (language_COUNTRY)");
6778
8480
  }
6779
8481
  return { language: match[1], country: match[2].toUpperCase() };
6780
8482
  }
@@ -6782,10 +8484,10 @@ function loadTargetingFileArg(path12) {
6782
8484
  if (typeof path12 !== "string" || path12.length === 0) {
6783
8485
  return void 0;
6784
8486
  }
6785
- const parsed = loadJsonFileArg(path12);
8487
+ const parsed = loadJsonFileArg2(path12);
6786
8488
  const criteria = parsed.targetingCriteria ?? parsed;
6787
8489
  if (!criteria.include) {
6788
- failWriteValidation(
8490
+ failWriteValidation2(
6789
8491
  `${path12} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
6790
8492
  );
6791
8493
  }
@@ -6825,10 +8527,10 @@ function parseListFileArg(path12, maxRows) {
6825
8527
  if (typeof path12 !== "string" || path12.length === 0) {
6826
8528
  return void 0;
6827
8529
  }
6828
- const raw = readFileSync6(path12, "utf8");
8530
+ const raw = readFileSync7(path12, "utf8");
6829
8531
  const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
6830
8532
  if (lines.length < 2) {
6831
- failWriteValidation(`${path12} needs a header row and at least one data row`);
8533
+ failWriteValidation2(`${path12} needs a header row and at least one data row`);
6832
8534
  }
6833
8535
  const columns = parseCsvLine(lines[0]).map((column) => column.trim());
6834
8536
  const rows = [];
@@ -6847,7 +8549,7 @@ function parseListFileArg(path12, maxRows) {
6847
8549
  }
6848
8550
  }
6849
8551
  if (rows.length > maxRows) {
6850
- failWriteValidation(`${path12} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
8552
+ failWriteValidation2(`${path12} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
6851
8553
  }
6852
8554
  return { columns, rows };
6853
8555
  }
@@ -6883,10 +8585,10 @@ async function stageStatusChange(input) {
6883
8585
  const payload = input.kind === "creative.update" ? { intendedStatus: input.status } : { status: input.status };
6884
8586
  await stageOp({ kind: input.kind, accountId: input.accountId, target: input.target, payload });
6885
8587
  }
6886
- function requireTarget(args, entity) {
8588
+ function requireTarget2(args, entity) {
6887
8589
  const target = args.id ?? args.target;
6888
8590
  if (typeof target !== "string" || target.length === 0) {
6889
- failWriteValidation(`pass the ${entity} id or URN as the positional argument`);
8591
+ failWriteValidation2(`pass the ${entity} id or URN as the positional argument`);
6890
8592
  }
6891
8593
  return target;
6892
8594
  }
@@ -6905,7 +8607,7 @@ function runScheduleFromFlags(args) {
6905
8607
  }
6906
8608
  return { ...start !== void 0 ? { start } : {}, ...end !== void 0 ? { end } : {} };
6907
8609
  }
6908
- var campaignGroupsCreateCommand = defineCommand36({
8610
+ var campaignGroupsCreateCommand = defineCommand38({
6909
8611
  meta: {
6910
8612
  name: "create",
6911
8613
  description: `Stage a new campaign group. ${STAGED_NOTE}
@@ -6923,7 +8625,7 @@ Example: baker ads linkedin campaign-groups create --name "Q3 ABM" --start 2026-
6923
8625
  },
6924
8626
  run: async ({ args }) => {
6925
8627
  const accountId = bareAccountId(args);
6926
- const payload = mergePayload(loadJsonFileArg(args.file), {
8628
+ const payload = mergePayload2(loadJsonFileArg2(args.file), {
6927
8629
  name: args.name,
6928
8630
  runSchedule: runScheduleFromFlags(args),
6929
8631
  totalBudget: parseMoneyFlag(args["total-budget"], args.currency, "--total-budget"),
@@ -6932,7 +8634,7 @@ Example: baker ads linkedin campaign-groups create --name "Q3 ABM" --start 2026-
6932
8634
  await stageOp({ kind: "campaignGroup.create", accountId, payload });
6933
8635
  }
6934
8636
  });
6935
- var campaignGroupsUpdateCommand = defineCommand36({
8637
+ var campaignGroupsUpdateCommand = defineCommand38({
6936
8638
  meta: {
6937
8639
  name: "update",
6938
8640
  description: `Stage changes to an existing campaign group. ${STAGED_NOTE}
@@ -6952,7 +8654,7 @@ Example: baker ads linkedin campaign-groups update 635137195 --total-budget 8000
6952
8654
  },
6953
8655
  run: async ({ args }) => {
6954
8656
  const accountId = bareAccountId(args);
6955
- const payload = mergePayload(loadJsonFileArg(args.file), {
8657
+ const payload = mergePayload2(loadJsonFileArg2(args.file), {
6956
8658
  name: args.name,
6957
8659
  runSchedule: runScheduleFromFlags(args),
6958
8660
  totalBudget: parseMoneyFlag(args["total-budget"], args.currency, "--total-budget"),
@@ -6961,7 +8663,7 @@ Example: baker ads linkedin campaign-groups update 635137195 --total-budget 8000
6961
8663
  await stageOp({
6962
8664
  kind: "campaignGroup.update",
6963
8665
  accountId,
6964
- target: requireTarget(args, "campaign group"),
8666
+ target: requireTarget2(args, "campaign group"),
6965
8667
  payload
6966
8668
  });
6967
8669
  }
@@ -7010,7 +8712,7 @@ var campaignFlagArgs = {
7010
8712
  status: { type: "string", description: "DRAFT|ACTIVE|PAUSED" },
7011
8713
  file: { type: "string", description: "JSON file with the full payload; flags override file keys" }
7012
8714
  };
7013
- var campaignsCreateCommand = defineCommand36({
8715
+ var campaignsCreateCommand = defineCommand38({
7014
8716
  meta: {
7015
8717
  name: "create",
7016
8718
  description: `Stage a new campaign. ${STAGED_NOTE}
@@ -7020,14 +8722,14 @@ Example: baker ads linkedin campaigns create --name "ABM Tier-1" --group li_temp
7020
8722
  args: campaignFlagArgs,
7021
8723
  run: async ({ args }) => {
7022
8724
  const accountId = bareAccountId(args);
7023
- const payload = mergePayload(loadJsonFileArg(args.file), campaignPayloadFromFlags(args));
8725
+ const payload = mergePayload2(loadJsonFileArg2(args.file), campaignPayloadFromFlags(args));
7024
8726
  if (payload.locale === void 0) {
7025
8727
  payload.locale = { country: "US", language: "en" };
7026
8728
  }
7027
8729
  await stageOp({ kind: "campaign.create", accountId, payload });
7028
8730
  }
7029
8731
  });
7030
- var campaignsUpdateCommand = defineCommand36({
8732
+ var campaignsUpdateCommand = defineCommand38({
7031
8733
  meta: {
7032
8734
  name: "update",
7033
8735
  description: `Stage changes to an existing campaign (budget, bid, targeting, flags, schedule, status). ${STAGED_NOTE}
@@ -7045,18 +8747,18 @@ Example: baker ads linkedin campaigns update 123456 --daily-budget 100 --currenc
7045
8747
  flags.type = void 0;
7046
8748
  flags.locale = void 0;
7047
8749
  flags.associatedEntity = void 0;
7048
- const payload = mergePayload(loadJsonFileArg(args.file), flags);
8750
+ const payload = mergePayload2(loadJsonFileArg2(args.file), flags);
7049
8751
  await stageOp({
7050
8752
  kind: "campaign.update",
7051
8753
  accountId,
7052
- target: requireTarget(args, "campaign"),
8754
+ target: requireTarget2(args, "campaign"),
7053
8755
  payload
7054
8756
  });
7055
8757
  }
7056
8758
  });
7057
8759
  function statusSugarCommand(entity, kind, name) {
7058
8760
  const status = name === "pause" ? "PAUSED" : name === "resume" ? "ACTIVE" : "ARCHIVED";
7059
- return defineCommand36({
8761
+ return defineCommand38({
7060
8762
  meta: {
7061
8763
  name,
7062
8764
  description: `Stage a status change to ${status}. ${STAGED_NOTE}
@@ -7070,7 +8772,7 @@ Example: baker ads linkedin ${entity} ${name} 123456`
7070
8772
  await stageStatusChange({
7071
8773
  kind,
7072
8774
  accountId: bareAccountId(args),
7073
- target: requireTarget(args, entity.replace(/-/g, " ").replace(/s$/, "")),
8775
+ target: requireTarget2(args, entity.replace(/-/g, " ").replace(/s$/, "")),
7074
8776
  status
7075
8777
  });
7076
8778
  }
@@ -7084,7 +8786,7 @@ var campaignGroupsResumeCommand = statusSugarCommand("campaign-groups", "campaig
7084
8786
  var creativesPauseCommand = statusSugarCommand("creatives", "creative.update", "pause");
7085
8787
  var creativesResumeCommand = statusSugarCommand("creatives", "creative.update", "resume");
7086
8788
  function duplicateCommand(entity, cliGroup) {
7087
- return defineCommand36({
8789
+ return defineCommand38({
7088
8790
  meta: {
7089
8791
  name: "duplicate",
7090
8792
  description: `Stage a copy of an existing ${entity} as a new DRAFT create (playbook: duplicate, never link-to-original). ${STAGED_NOTE}
@@ -7099,14 +8801,14 @@ Example: baker ads linkedin ${cliGroup} duplicate 123456 --name "New variant"`
7099
8801
  run: async ({ args }) => {
7100
8802
  try {
7101
8803
  const chatId = requireChatId();
7102
- const overrides = mergePayload(loadJsonFileArg(args.file), { name: args.name });
8804
+ const overrides = mergePayload2(loadJsonFileArg2(args.file), { name: args.name });
7103
8805
  const response = await apiPost(
7104
8806
  "/api/ads/linkedin/draft/duplicate",
7105
8807
  {
7106
8808
  chatId,
7107
8809
  accountId: bareAccountId(args),
7108
8810
  entity,
7109
- sourceId: requireTarget(args, entity),
8811
+ sourceId: requireTarget2(args, entity),
7110
8812
  ...Object.keys(overrides).length > 0 ? { overrides } : {}
7111
8813
  }
7112
8814
  );
@@ -7119,7 +8821,7 @@ Example: baker ads linkedin ${cliGroup} duplicate 123456 --name "New variant"`
7119
8821
  }
7120
8822
  var campaignsDuplicateCommand = duplicateCommand("campaign", "campaigns");
7121
8823
  var campaignGroupsDuplicateCommand = duplicateCommand("campaignGroup", "campaign-groups");
7122
- var creativesDuplicateCommand = defineCommand36({
8824
+ var creativesDuplicateCommand = defineCommand38({
7123
8825
  meta: {
7124
8826
  name: "duplicate",
7125
8827
  description: `Stage a copy of an existing ad, optionally with new content \u2014 the ONLY way to change copy/media/URL on a live ad (LinkedIn makes ad content immutable). ${STAGED_NOTE}
@@ -7157,10 +8859,10 @@ Examples:
7157
8859
  run: async ({ args }) => {
7158
8860
  try {
7159
8861
  const chatId = requireChatId();
7160
- const file = loadJsonFileArg(args.file);
8862
+ const file = loadJsonFileArg2(args.file);
7161
8863
  const fileContent = file.content !== null && typeof file.content === "object" && !Array.isArray(file.content) ? file.content : {};
7162
8864
  const content = { ...fileContent, ...creativeContentPatch(args) };
7163
- const overrides = mergePayload(file, {
8865
+ const overrides = mergePayload2(file, {
7164
8866
  campaign: args.campaign,
7165
8867
  intendedStatus: args["intended-status"] ? String(args["intended-status"]).toUpperCase() : void 0,
7166
8868
  content: Object.keys(content).length > 0 ? content : void 0
@@ -7171,7 +8873,7 @@ Examples:
7171
8873
  chatId,
7172
8874
  accountId: bareAccountId(args),
7173
8875
  entity: "creative",
7174
- sourceId: requireTarget(args, "creative"),
8876
+ sourceId: requireTarget2(args, "creative"),
7175
8877
  ...Object.keys(overrides).length > 0 ? { overrides } : {},
7176
8878
  ...args.replace ? { replace: true } : {}
7177
8879
  }
@@ -7196,7 +8898,7 @@ var CREATIVE_FORMATS = [
7196
8898
  "event",
7197
8899
  "article"
7198
8900
  ];
7199
- var creativesCreateCommand = defineCommand36({
8901
+ var creativesCreateCommand = defineCommand38({
7200
8902
  meta: {
7201
8903
  name: "create",
7202
8904
  description: `Stage a new creative (ad). ${STAGED_NOTE}
@@ -7232,13 +8934,13 @@ Examples:
7232
8934
  run: async ({ args }) => {
7233
8935
  const accountId = bareAccountId(args);
7234
8936
  if (!args.campaign) {
7235
- failWriteValidation("--campaign is required (id, URN, or li_temp_* ref)");
8937
+ failWriteValidation2("--campaign is required (id, URN, or li_temp_* ref)");
7236
8938
  }
7237
8939
  const format = args.format ? String(args.format) : void 0;
7238
8940
  if (!format || !CREATIVE_FORMATS.includes(format)) {
7239
- failWriteValidation(`--format must be one of ${CREATIVE_FORMATS.join("|")}`);
8941
+ failWriteValidation2(`--format must be one of ${CREATIVE_FORMATS.join("|")}`);
7240
8942
  }
7241
- const content = mergePayload(loadJsonFileArg(args.file), {
8943
+ const content = mergePayload2(loadJsonFileArg2(args.file), {
7242
8944
  format,
7243
8945
  commentary: args.intro,
7244
8946
  imageId: args["image-id"],
@@ -7297,7 +8999,7 @@ function creativeContentPatch(args) {
7297
8999
  }
7298
9000
  return patch;
7299
9001
  }
7300
- var creativesUpdateCommand = defineCommand36({
9002
+ var creativesUpdateCommand = defineCommand38({
7301
9003
  meta: {
7302
9004
  name: "update",
7303
9005
  description: `Stage changes to an existing creative, or amend a creative staged in this chat by passing its li_temp_* ref. ${STAGED_NOTE}
@@ -7329,13 +9031,13 @@ Examples:
7329
9031
  },
7330
9032
  run: async ({ args }) => {
7331
9033
  const accountId = bareAccountId(args);
7332
- const target = requireTarget(args, "creative");
7333
- const file = loadJsonFileArg(args.file);
9034
+ const target = requireTarget2(args, "creative");
9035
+ const file = loadJsonFileArg2(args.file);
7334
9036
  const contentPatch = creativeContentPatch(args);
7335
9037
  const intendedStatus = args["intended-status"] ? String(args["intended-status"]).toUpperCase() : void 0;
7336
9038
  const fileContent = file.content !== null && typeof file.content === "object" && !Array.isArray(file.content) ? file.content : {};
7337
9039
  const content = { ...fileContent, ...contentPatch };
7338
- const payload = mergePayload(file, {
9040
+ const payload = mergePayload2(file, {
7339
9041
  intendedStatus,
7340
9042
  name: args.name,
7341
9043
  content: Object.keys(content).length > 0 ? content : void 0
@@ -7345,7 +9047,7 @@ Examples:
7345
9047
  });
7346
9048
  var AUDIENCE_TYPES2 = ["company-list", "user-list", "retargeting", "engagement"];
7347
9049
  var INLINE_ROWS_MAX = 1e4;
7348
- var audiencesCreateCommand = defineCommand36({
9050
+ var audiencesCreateCommand = defineCommand38({
7349
9051
  meta: {
7350
9052
  name: "create",
7351
9053
  description: `Stage a new matched audience. ${STAGED_NOTE}
@@ -7362,7 +9064,7 @@ Example: baker ads linkedin audiences create --name "ABM Tier-1" --type company-
7362
9064
  run: async ({ args }) => {
7363
9065
  const accountId = bareAccountId(args);
7364
9066
  const list = parseListFileArg(args["list-file"], INLINE_ROWS_MAX);
7365
- const raw = args.file ? loadJsonFileArg(args.file) : void 0;
9067
+ const raw = args.file ? loadJsonFileArg2(args.file) : void 0;
7366
9068
  await stageOp({
7367
9069
  kind: "audience.create",
7368
9070
  accountId,
@@ -7375,7 +9077,7 @@ Example: baker ads linkedin audiences create --name "ABM Tier-1" --type company-
7375
9077
  });
7376
9078
  }
7377
9079
  });
7378
- var audiencesUploadCommand = defineCommand36({
9080
+ var audiencesUploadCommand = defineCommand38({
7379
9081
  meta: {
7380
9082
  name: "upload",
7381
9083
  description: `Stage a list upload into an existing audience segment. ${STAGED_NOTE}
@@ -7390,20 +9092,20 @@ Example: baker ads linkedin audiences upload urn:li:dmpSegment:42 --list-file mo
7390
9092
  const accountId = bareAccountId(args);
7391
9093
  const list = parseListFileArg(args["list-file"], INLINE_ROWS_MAX);
7392
9094
  if (!list) {
7393
- failWriteValidation("--list-file is required");
9095
+ failWriteValidation2("--list-file is required");
7394
9096
  }
7395
9097
  await stageOp({
7396
9098
  kind: "audience.uploadList",
7397
9099
  accountId,
7398
9100
  payload: {
7399
- segment: requireTarget(args, "audience segment"),
9101
+ segment: requireTarget2(args, "audience segment"),
7400
9102
  listColumns: list.columns,
7401
9103
  listRows: list.rows
7402
9104
  }
7403
9105
  });
7404
9106
  }
7405
9107
  });
7406
- var audiencesCommand = defineCommand36({
9108
+ var audiencesCommand2 = defineCommand38({
7407
9109
  meta: {
7408
9110
  name: "audiences",
7409
9111
  description: "Stage LinkedIn matched-audience changes (create lists, upload rows). Staged until publish \u2014 never hits the API directly."
@@ -7413,7 +9115,7 @@ var audiencesCommand = defineCommand36({
7413
9115
  upload: audiencesUploadCommand
7414
9116
  }
7415
9117
  });
7416
- var conversionsCreateCommand = defineCommand36({
9118
+ var conversionsCreateCommand = defineCommand38({
7417
9119
  meta: {
7418
9120
  name: "create",
7419
9121
  description: `Stage a new conversion rule. ${STAGED_NOTE}
@@ -7432,7 +9134,7 @@ Example: baker ads linkedin conversions create --name "Demo booked" --type LEAD
7432
9134
  },
7433
9135
  run: async ({ args }) => {
7434
9136
  const accountId = bareAccountId(args);
7435
- const payload = mergePayload(loadJsonFileArg(args.file), {
9137
+ const payload = mergePayload2(loadJsonFileArg2(args.file), {
7436
9138
  name: args.name,
7437
9139
  type: args.type ? String(args.type).toUpperCase() : void 0,
7438
9140
  conversionMethod: args.method ? String(args.method).toUpperCase() : void 0,
@@ -7444,7 +9146,7 @@ Example: baker ads linkedin conversions create --name "Demo booked" --type LEAD
7444
9146
  await stageOp({ kind: "conversion.create", accountId, payload });
7445
9147
  }
7446
9148
  });
7447
- var conversionsUpdateCommand = defineCommand36({
9149
+ var conversionsUpdateCommand = defineCommand38({
7448
9150
  meta: {
7449
9151
  name: "update",
7450
9152
  description: `Stage changes to a conversion rule (windows, name, enabled). ${STAGED_NOTE}
@@ -7462,7 +9164,7 @@ Example: baker ads linkedin conversions update 104988516 --post-click-window 30
7462
9164
  },
7463
9165
  run: async ({ args }) => {
7464
9166
  const accountId = bareAccountId(args);
7465
- const payload = mergePayload(loadJsonFileArg(args.file), {
9167
+ const payload = mergePayload2(loadJsonFileArg2(args.file), {
7466
9168
  name: args.name,
7467
9169
  postClickAttributionWindowSize: args["post-click-window"] ? Number(args["post-click-window"]) : void 0,
7468
9170
  viewThroughAttributionWindowSize: args["view-window"] ? Number(args["view-window"]) : void 0,
@@ -7472,12 +9174,12 @@ Example: baker ads linkedin conversions update 104988516 --post-click-window 30
7472
9174
  await stageOp({
7473
9175
  kind: "conversion.update",
7474
9176
  accountId,
7475
- target: requireTarget(args, "conversion rule"),
9177
+ target: requireTarget2(args, "conversion rule"),
7476
9178
  payload
7477
9179
  });
7478
9180
  }
7479
9181
  });
7480
- var leadFormsCreateCommand = defineCommand36({
9182
+ var leadFormsCreateCommand = defineCommand38({
7481
9183
  meta: {
7482
9184
  name: "create",
7483
9185
  description: `Stage a new Lead Gen Form from a JSON file. ${STAGED_NOTE}
@@ -7490,11 +9192,11 @@ The file needs: name, headline (\u226460), privacyPolicyUrl, questions[] (\u2264
7490
9192
  },
7491
9193
  run: async ({ args }) => {
7492
9194
  const accountId = bareAccountId(args);
7493
- const payload = mergePayload(loadJsonFileArg(args.file), { name: args.name });
9195
+ const payload = mergePayload2(loadJsonFileArg2(args.file), { name: args.name });
7494
9196
  await stageOp({ kind: "leadForm.create", accountId, payload });
7495
9197
  }
7496
9198
  });
7497
- var leadFormsUpdateCommand = defineCommand36({
9199
+ var leadFormsUpdateCommand = defineCommand38({
7498
9200
  meta: {
7499
9201
  name: "update",
7500
9202
  description: `Stage changes to a Lead Gen Form from a JSON file. ${STAGED_NOTE}`
@@ -7507,16 +9209,16 @@ var leadFormsUpdateCommand = defineCommand36({
7507
9209
  },
7508
9210
  run: async ({ args }) => {
7509
9211
  const accountId = bareAccountId(args);
7510
- const payload = mergePayload({ raw: loadJsonFileArg(args.file) }, { name: args.name });
9212
+ const payload = mergePayload2({ raw: loadJsonFileArg2(args.file) }, { name: args.name });
7511
9213
  await stageOp({
7512
9214
  kind: "leadForm.update",
7513
9215
  accountId,
7514
- target: requireTarget(args, "lead form"),
9216
+ target: requireTarget2(args, "lead form"),
7515
9217
  payload
7516
9218
  });
7517
9219
  }
7518
9220
  });
7519
- var leadFormsCommand = defineCommand36({
9221
+ var leadFormsCommand = defineCommand38({
7520
9222
  meta: {
7521
9223
  name: "lead-forms",
7522
9224
  description: "Stage LinkedIn Lead Gen Form changes (file-first). Staged until publish \u2014 never hits the API directly."
@@ -7528,7 +9230,7 @@ var leadFormsCommand = defineCommand36({
7528
9230
  });
7529
9231
 
7530
9232
  // src/commands/ads/linkedin/campaign-groups.ts
7531
- var campaignGroupsCommand = defineCommand37({
9233
+ var campaignGroupsCommand = defineCommand39({
7532
9234
  meta: {
7533
9235
  name: "campaign-groups",
7534
9236
  description: `List LinkedIn campaign groups, or stage writes (create/update/pause/resume/duplicate).
@@ -7579,8 +9281,8 @@ Examples:
7579
9281
  });
7580
9282
 
7581
9283
  // src/commands/ads/linkedin/campaigns.ts
7582
- import { defineCommand as defineCommand38 } from "citty";
7583
- var campaignsCommand = defineCommand38({
9284
+ import { defineCommand as defineCommand40 } from "citty";
9285
+ var campaignsCommand2 = defineCommand40({
7584
9286
  meta: {
7585
9287
  name: "campaigns",
7586
9288
  description: `List LinkedIn campaigns, or stage writes (create/update/pause/resume/archive/duplicate).
@@ -7641,8 +9343,8 @@ Examples:
7641
9343
  });
7642
9344
 
7643
9345
  // src/commands/ads/linkedin/conversation.ts
7644
- import { defineCommand as defineCommand39 } from "citty";
7645
- var conversationCommand = defineCommand39({
9346
+ import { defineCommand as defineCommand41 } from "citty";
9347
+ var conversationCommand = defineCommand41({
7646
9348
  meta: {
7647
9349
  name: "conversation",
7648
9350
  description: `Per-button click rates inside Sponsored Messaging / Conversation Ads.
@@ -7705,7 +9407,7 @@ Examples:
7705
9407
  });
7706
9408
 
7707
9409
  // src/commands/ads/linkedin/conversions.ts
7708
- import { defineCommand as defineCommand40 } from "citty";
9410
+ import { defineCommand as defineCommand42 } from "citty";
7709
9411
  var DAY_MS3 = 864e5;
7710
9412
  function healthOf(rules) {
7711
9413
  const enabled = rules.filter((r) => r.enabled !== false);
@@ -7731,7 +9433,7 @@ function healthOf(rules) {
7731
9433
  wrongLeadDedup: wrongDedup
7732
9434
  };
7733
9435
  }
7734
- var listCmd = defineCommand40({
9436
+ var listCmd = defineCommand42({
7735
9437
  meta: {
7736
9438
  name: "list",
7737
9439
  description: `List conversion rules on the account.`
@@ -7759,7 +9461,7 @@ var listCmd = defineCommand40({
7759
9461
  }
7760
9462
  }
7761
9463
  });
7762
- var healthCmd = defineCommand40({
9464
+ var healthCmd = defineCommand42({
7763
9465
  meta: {
7764
9466
  name: "health",
7765
9467
  description: `5-point Insight Tag / CAPI health check (playbook \xA707).
@@ -7789,7 +9491,7 @@ Surfaces:
7789
9491
  }
7790
9492
  }
7791
9493
  });
7792
- var conversionsCommand = defineCommand40({
9494
+ var conversionsCommand2 = defineCommand42({
7793
9495
  meta: {
7794
9496
  name: "conversions",
7795
9497
  description: `Conversion rules \u2014 Insight Tag and Conversions API.
@@ -7808,8 +9510,8 @@ Subcommands:
7808
9510
  });
7809
9511
 
7810
9512
  // src/commands/ads/linkedin/creatives.ts
7811
- import { defineCommand as defineCommand41 } from "citty";
7812
- var creativesCommand = defineCommand41({
9513
+ import { defineCommand as defineCommand43 } from "citty";
9514
+ var creativesCommand = defineCommand43({
7813
9515
  meta: {
7814
9516
  name: "creatives",
7815
9517
  description: `List LinkedIn creatives (ads), or stage writes (create/update/pause/resume/duplicate).
@@ -7868,7 +9570,7 @@ Examples:
7868
9570
  });
7869
9571
 
7870
9572
  // src/commands/ads/linkedin/demographics.ts
7871
- import { defineCommand as defineCommand42 } from "citty";
9573
+ import { defineCommand as defineCommand44 } from "citty";
7872
9574
  var DEFAULT_PIVOTS = ["job-title", "company", "industry", "seniority", "job-function", "company-size"];
7873
9575
  function numberOf2(v) {
7874
9576
  if (typeof v === "number") return Number.isFinite(v) ? v : 0;
@@ -7881,7 +9583,7 @@ function numberOf2(v) {
7881
9583
  function topByImpressions(rows, limit) {
7882
9584
  return [...rows].sort((a, b) => numberOf2(b.impressions) - numberOf2(a.impressions)).slice(0, limit);
7883
9585
  }
7884
- var demographicsCommand = defineCommand42({
9586
+ var demographicsCommand = defineCommand44({
7885
9587
  meta: {
7886
9588
  name: "demographics",
7887
9589
  description: `Sweep all firmographic pivots in one command \u2014 LinkedIn's superpower.
@@ -7978,7 +9680,7 @@ function resolveRange(args) {
7978
9680
  }
7979
9681
 
7980
9682
  // src/commands/ads/linkedin/draft.ts
7981
- import { defineCommand as defineCommand43 } from "citty";
9683
+ import { defineCommand as defineCommand45 } from "citty";
7982
9684
  async function listDraft() {
7983
9685
  try {
7984
9686
  const chatId = requireChatId();
@@ -7990,14 +9692,14 @@ async function listDraft() {
7990
9692
  handleLinkedinError(err);
7991
9693
  }
7992
9694
  }
7993
- var listCommand3 = defineCommand43({
9695
+ var listCommand3 = defineCommand45({
7994
9696
  meta: {
7995
9697
  name: "list",
7996
9698
  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"
7997
9699
  },
7998
9700
  run: listDraft
7999
9701
  });
8000
- var removeCommand2 = defineCommand43({
9702
+ var removeCommand2 = defineCommand45({
8001
9703
  meta: {
8002
9704
  name: "remove",
8003
9705
  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"
@@ -8022,7 +9724,7 @@ var removeCommand2 = defineCommand43({
8022
9724
  }
8023
9725
  }
8024
9726
  });
8025
- var clearCommand2 = defineCommand43({
9727
+ var clearCommand2 = defineCommand45({
8026
9728
  meta: {
8027
9729
  name: "clear",
8028
9730
  description: "Discard ALL staged LinkedIn ops in this chat's draft \u2014 nothing will apply on publish. Example: baker ads linkedin draft clear"
@@ -8039,7 +9741,7 @@ var clearCommand2 = defineCommand43({
8039
9741
  }
8040
9742
  }
8041
9743
  });
8042
- var linkedinDraftCommand = defineCommand43({
9744
+ var linkedinDraftCommand = defineCommand45({
8043
9745
  meta: {
8044
9746
  name: "draft",
8045
9747
  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."
@@ -8053,8 +9755,8 @@ var linkedinDraftCommand = defineCommand43({
8053
9755
  });
8054
9756
 
8055
9757
  // src/commands/ads/linkedin/facets.ts
8056
- import { defineCommand as defineCommand44 } from "citty";
8057
- var listCmd2 = defineCommand44({
9758
+ import { defineCommand as defineCommand46 } from "citty";
9759
+ var listCmd2 = defineCommand46({
8058
9760
  meta: {
8059
9761
  name: "list",
8060
9762
  description: `List every targeting facet LinkedIn supports.
@@ -8082,7 +9784,7 @@ seniorities, titles, employers, growthRate, companyCategory, skills, etc.).`
8082
9784
  }
8083
9785
  }
8084
9786
  });
8085
- var valuesCmd = defineCommand44({
9787
+ var valuesCmd = defineCommand46({
8086
9788
  meta: {
8087
9789
  name: "values",
8088
9790
  description: `Look up entity values for a single facet \u2014 full list or typeahead search.
@@ -8123,7 +9825,7 @@ or the full URN (urn:li:adTargetingFacet:industries).`
8123
9825
  }
8124
9826
  }
8125
9827
  });
8126
- var facetsCommand = defineCommand44({
9828
+ var facetsCommand = defineCommand46({
8127
9829
  meta: {
8128
9830
  name: "facets",
8129
9831
  description: `LinkedIn targeting facets and entity lookup.
@@ -8140,8 +9842,8 @@ Subcommands:
8140
9842
  });
8141
9843
 
8142
9844
  // src/commands/ads/linkedin/forecast.ts
8143
- import { readFileSync as readFileSync7 } from "fs";
8144
- import { defineCommand as defineCommand45 } from "citty";
9845
+ import { readFileSync as readFileSync8 } from "fs";
9846
+ import { defineCommand as defineCommand47 } from "citty";
8145
9847
  function loadTargeting3(args) {
8146
9848
  const inline = args.targeting;
8147
9849
  if (inline) {
@@ -8154,7 +9856,7 @@ function loadTargeting3(args) {
8154
9856
  const file = args["targeting-file"];
8155
9857
  if (file) {
8156
9858
  try {
8157
- return JSON.parse(readFileSync7(file, "utf-8"));
9859
+ return JSON.parse(readFileSync8(file, "utf-8"));
8158
9860
  } catch (e) {
8159
9861
  handleLinkedinError(
8160
9862
  new Error(`Failed to read --targeting-file: ${e instanceof Error ? e.message : "I/O error"}`)
@@ -8171,7 +9873,7 @@ function parseMoney(raw) {
8171
9873
  }
8172
9874
  return { amount: m[1] ?? "0", currencyCode: m[2] ?? "USD" };
8173
9875
  }
8174
- var forecastCommand = defineCommand45({
9876
+ var forecastCommand = defineCommand47({
8175
9877
  meta: {
8176
9878
  name: "forecast",
8177
9879
  description: `Forecast reach + impressions + clicks + spend for a hypothetical campaign.
@@ -8218,9 +9920,9 @@ Examples:
8218
9920
  });
8219
9921
 
8220
9922
  // src/commands/ads/linkedin/leads.ts
8221
- import { defineCommand as defineCommand46 } from "citty";
9923
+ import { defineCommand as defineCommand48 } from "citty";
8222
9924
  var DAY_MS4 = 864e5;
8223
- var leadsCommand = defineCommand46({
9925
+ var leadsCommand = defineCommand48({
8224
9926
  meta: {
8225
9927
  name: "leads",
8226
9928
  description: `List Lead Gen Form responses (playbook \xA707).
@@ -8280,7 +9982,7 @@ Examples:
8280
9982
  });
8281
9983
 
8282
9984
  // src/commands/ads/linkedin/resolve.ts
8283
- import { defineCommand as defineCommand47 } from "citty";
9985
+ import { defineCommand as defineCommand49 } from "citty";
8284
9986
  function toOrgUrn(raw) {
8285
9987
  const trimmed = raw.trim();
8286
9988
  if (trimmed.length === 0) {
@@ -8291,7 +9993,7 @@ function toOrgUrn(raw) {
8291
9993
  }
8292
9994
  return /^\d+$/.test(trimmed) ? `urn:li:organization:${trimmed}` : null;
8293
9995
  }
8294
- var resolveCommand = defineCommand47({
9996
+ var resolveCommand = defineCommand49({
8295
9997
  meta: {
8296
9998
  name: "resolve",
8297
9999
  description: `Resolve organization URNs to company names.
@@ -8333,8 +10035,8 @@ couldn't be resolved \u2014 typically an org outside LinkedIn's targetable set.`
8333
10035
  });
8334
10036
 
8335
10037
  // src/commands/ads/linkedin/top-companies.ts
8336
- import { defineCommand as defineCommand48 } from "citty";
8337
- var topCompaniesCommand = defineCommand48({
10038
+ import { defineCommand as defineCommand50 } from "citty";
10039
+ var topCompaniesCommand = defineCommand50({
8338
10040
  meta: {
8339
10041
  name: "top-companies",
8340
10042
  description: `Top companies whose employees saw / clicked / converted on a campaign.
@@ -8405,7 +10107,7 @@ Examples:
8405
10107
  });
8406
10108
 
8407
10109
  // src/commands/ads/linkedin/index.ts
8408
- var linkedinCommand = defineCommand49({
10110
+ var linkedinCommand = defineCommand51({
8409
10111
  meta: {
8410
10112
  name: "linkedin",
8411
10113
  description: `LinkedIn Marketing API \u2014 AI-first command surface for B2B ad insights.
@@ -8450,9 +10152,9 @@ Account ID format:
8450
10152
  accounts: accountsCommand2,
8451
10153
  account: accountCommand,
8452
10154
  "campaign-groups": campaignGroupsCommand,
8453
- campaigns: campaignsCommand,
10155
+ campaigns: campaignsCommand2,
8454
10156
  creatives: creativesCommand,
8455
- audiences: audiencesCommand,
10157
+ audiences: audiencesCommand2,
8456
10158
  "lead-forms": leadFormsCommand,
8457
10159
  draft: linkedinDraftCommand,
8458
10160
  analytics: analyticsCommand,
@@ -8464,17 +10166,17 @@ Account ID format:
8464
10166
  "bid-pricing": bidPricingCommand,
8465
10167
  forecast: forecastCommand,
8466
10168
  leads: leadsCommand,
8467
- conversions: conversionsCommand,
10169
+ conversions: conversionsCommand2,
8468
10170
  conversation: conversationCommand,
8469
10171
  audit: auditCommand
8470
10172
  }
8471
10173
  });
8472
10174
 
8473
10175
  // src/commands/ads/meta/index.ts
8474
- import { defineCommand as defineCommand62 } from "citty";
10176
+ import { defineCommand as defineCommand64 } from "citty";
8475
10177
 
8476
10178
  // src/commands/ads/meta/account.ts
8477
- import { defineCommand as defineCommand50 } from "citty";
10179
+ import { defineCommand as defineCommand52 } from "citty";
8478
10180
 
8479
10181
  // src/commands/ads/meta/shared.ts
8480
10182
  var DAY_MS5 = 864e5;
@@ -8553,7 +10255,7 @@ function resolveEffectiveStatus(args) {
8553
10255
  }
8554
10256
 
8555
10257
  // src/commands/ads/meta/account.ts
8556
- var accountCommand2 = defineCommand50({
10258
+ var accountCommand2 = defineCommand52({
8557
10259
  meta: {
8558
10260
  name: "account",
8559
10261
  description: `Show single Meta ad account detail (currency, timezone, balance, business).
@@ -8580,8 +10282,8 @@ Examples:
8580
10282
  });
8581
10283
 
8582
10284
  // src/commands/ads/meta/accounts.ts
8583
- import { defineCommand as defineCommand51 } from "citty";
8584
- var accountsCommand3 = defineCommand51({
10285
+ import { defineCommand as defineCommand53 } from "citty";
10286
+ var accountsCommand3 = defineCommand53({
8585
10287
  meta: {
8586
10288
  name: "accounts",
8587
10289
  description: `List Meta ad accounts in this company's connected scope.
@@ -8629,8 +10331,8 @@ Examples:
8629
10331
  });
8630
10332
 
8631
10333
  // src/commands/ads/meta/activities.ts
8632
- import { defineCommand as defineCommand52 } from "citty";
8633
- var activitiesCommand = defineCommand52({
10334
+ import { defineCommand as defineCommand54 } from "citty";
10335
+ var activitiesCommand = defineCommand54({
8634
10336
  meta: {
8635
10337
  name: "activities",
8636
10338
  description: `Audit log of recent ad-account changes (created, paused, edited). Default lookback 7 days,
@@ -8667,8 +10369,8 @@ Examples:
8667
10369
  });
8668
10370
 
8669
10371
  // src/commands/ads/meta/ads.ts
8670
- import { defineCommand as defineCommand53 } from "citty";
8671
- var adsListCommand = defineCommand53({
10372
+ import { defineCommand as defineCommand55 } from "citty";
10373
+ var adsListCommand = defineCommand55({
8672
10374
  meta: {
8673
10375
  name: "ads",
8674
10376
  description: `List ads in a Meta ad account. Defaults to ACTIVE only \u2014 pass --all-statuses to widen.
@@ -8716,8 +10418,8 @@ Examples:
8716
10418
  });
8717
10419
 
8718
10420
  // src/commands/ads/meta/adsets.ts
8719
- import { defineCommand as defineCommand54 } from "citty";
8720
- var adsetsCommand = defineCommand54({
10421
+ import { defineCommand as defineCommand56 } from "citty";
10422
+ var adsetsCommand = defineCommand56({
8721
10423
  meta: {
8722
10424
  name: "adsets",
8723
10425
  description: `List ad sets in a Meta ad account, optionally scoped to one campaign. Defaults to ACTIVE only.
@@ -8759,8 +10461,8 @@ Examples:
8759
10461
  });
8760
10462
 
8761
10463
  // src/commands/ads/meta/audiences.ts
8762
- import { defineCommand as defineCommand55 } from "citty";
8763
- var audiencesCommand2 = defineCommand55({
10464
+ import { defineCommand as defineCommand57 } from "citty";
10465
+ var audiencesCommand3 = defineCommand57({
8764
10466
  meta: {
8765
10467
  name: "audiences",
8766
10468
  description: `List custom audiences for a Meta ad account. Includes lookalikes, website-pixel audiences,
@@ -8795,8 +10497,8 @@ Examples:
8795
10497
  });
8796
10498
 
8797
10499
  // src/commands/ads/meta/businesses.ts
8798
- import { defineCommand as defineCommand56 } from "citty";
8799
- var businessesCommand = defineCommand56({
10500
+ import { defineCommand as defineCommand58 } from "citty";
10501
+ var businessesCommand = defineCommand58({
8800
10502
  meta: {
8801
10503
  name: "businesses",
8802
10504
  description: `List Meta Business Manager accounts the connected user has access to. Required for ad-studies and product-catalogs commands.
@@ -8826,8 +10528,8 @@ Examples:
8826
10528
  });
8827
10529
 
8828
10530
  // src/commands/ads/meta/campaigns.ts
8829
- import { defineCommand as defineCommand57 } from "citty";
8830
- var campaignsCommand2 = defineCommand57({
10531
+ import { defineCommand as defineCommand59 } from "citty";
10532
+ var campaignsCommand3 = defineCommand59({
8831
10533
  meta: {
8832
10534
  name: "campaigns",
8833
10535
  description: `List campaigns for a Meta ad account. Defaults to ACTIVE only \u2014 pass --all-statuses to widen.
@@ -8871,8 +10573,8 @@ Examples:
8871
10573
  });
8872
10574
 
8873
10575
  // src/commands/ads/meta/creatives.ts
8874
- import { defineCommand as defineCommand58 } from "citty";
8875
- var creativesCommand2 = defineCommand58({
10576
+ import { defineCommand as defineCommand60 } from "citty";
10577
+ var creativesCommand2 = defineCommand60({
8876
10578
  meta: {
8877
10579
  name: "creatives",
8878
10580
  description: `List ad creatives in an account, or fetch a single creative by ID.
@@ -8916,7 +10618,7 @@ Examples:
8916
10618
  });
8917
10619
 
8918
10620
  // src/commands/ads/meta/insights.ts
8919
- import { defineCommand as defineCommand59 } from "citty";
10621
+ import { defineCommand as defineCommand61 } from "citty";
8920
10622
 
8921
10623
  // src/commands/ads/meta/presets.ts
8922
10624
  var INSIGHTS_INTENTS = {
@@ -9121,7 +10823,7 @@ function sortRowsBySpendDesc(rows) {
9121
10823
  return sb - sa;
9122
10824
  });
9123
10825
  }
9124
- var insightsCommand = defineCommand59({
10826
+ var insightsCommand = defineCommand61({
9125
10827
  meta: {
9126
10828
  name: "insights",
9127
10829
  description: `Performance reporting \u2014 the main Meta tool for AI agents.
@@ -9222,8 +10924,8 @@ Async is automatic for heavy queries; pass --async to force it, or --no-async to
9222
10924
  });
9223
10925
 
9224
10926
  // src/commands/ads/meta/pixels.ts
9225
- import { defineCommand as defineCommand60 } from "citty";
9226
- var pixelsCommand = defineCommand60({
10927
+ import { defineCommand as defineCommand62 } from "citty";
10928
+ var pixelsCommand = defineCommand62({
9227
10929
  meta: {
9228
10930
  name: "pixels",
9229
10931
  description: `List Meta Pixels for an ad account, or fetch firing stats for one pixel.
@@ -9294,7 +10996,7 @@ function emit(data, args) {
9294
10996
 
9295
10997
  // src/commands/ads/meta/preview.ts
9296
10998
  import { writeFileSync as writeFileSync3 } from "fs";
9297
- import { defineCommand as defineCommand61 } from "citty";
10999
+ import { defineCommand as defineCommand63 } from "citty";
9298
11000
  var VALID_AD_FORMATS = [
9299
11001
  "DESKTOP_FEED_STANDARD",
9300
11002
  "MOBILE_FEED_STANDARD",
@@ -9328,7 +11030,7 @@ var VALID_AD_FORMATS = [
9328
11030
  "MARKETPLACE_MOBILE",
9329
11031
  "BIZ_DISCO_FEED_MOBILE"
9330
11032
  ];
9331
- var previewCommand = defineCommand61({
11033
+ var previewCommand = defineCommand63({
9332
11034
  meta: {
9333
11035
  name: "preview",
9334
11036
  description: `Generate a Meta-hosted preview iframe for a creative or ad. Returns iframe HTML which you
@@ -9375,7 +11077,7 @@ Examples:
9375
11077
  });
9376
11078
 
9377
11079
  // src/commands/ads/meta/index.ts
9378
- var metaCommand = defineCommand62({
11080
+ var metaCommand = defineCommand64({
9379
11081
  meta: {
9380
11082
  name: "meta",
9381
11083
  description: `Meta Marketing API \u2014 AI-first command surface (Facebook + Instagram ads).
@@ -9414,11 +11116,11 @@ Audit & review:
9414
11116
  accounts: accountsCommand3,
9415
11117
  account: accountCommand2,
9416
11118
  businesses: businessesCommand,
9417
- campaigns: campaignsCommand2,
11119
+ campaigns: campaignsCommand3,
9418
11120
  adsets: adsetsCommand,
9419
11121
  ads: adsListCommand,
9420
11122
  creatives: creativesCommand2,
9421
- audiences: audiencesCommand2,
11123
+ audiences: audiencesCommand3,
9422
11124
  pixels: pixelsCommand,
9423
11125
  activities: activitiesCommand,
9424
11126
  insights: insightsCommand,
@@ -9427,10 +11129,10 @@ Audit & review:
9427
11129
  });
9428
11130
 
9429
11131
  // src/commands/ads/x/index.ts
9430
- import { defineCommand as defineCommand79 } from "citty";
11132
+ import { defineCommand as defineCommand81 } from "citty";
9431
11133
 
9432
11134
  // src/commands/ads/x/accounts.ts
9433
- import { defineCommand as defineCommand63 } from "citty";
11135
+ import { defineCommand as defineCommand65 } from "citty";
9434
11136
  registerSchema({
9435
11137
  command: "ads.x.accounts",
9436
11138
  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.",
@@ -9458,7 +11160,7 @@ function handleAccountsError2(err) {
9458
11160
  writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
9459
11161
  process.exit(1);
9460
11162
  }
9461
- var accountsCommand4 = defineCommand63({
11163
+ var accountsCommand4 = defineCommand65({
9462
11164
  meta: {
9463
11165
  name: "accounts",
9464
11166
  description: `List accessible X Ads accounts. Returns account IDs needed for all other commands.
@@ -9498,7 +11200,7 @@ Examples:
9498
11200
  });
9499
11201
 
9500
11202
  // src/commands/ads/x/active-entities.ts
9501
- import { defineCommand as defineCommand64 } from "citty";
11203
+ import { defineCommand as defineCommand66 } from "citty";
9502
11204
 
9503
11205
  // src/commands/ads/x/error-parser.ts
9504
11206
  function mapXErrorCode(message) {
@@ -9649,7 +11351,7 @@ function parseCsv(v) {
9649
11351
  const parts = v.split(",").map((s) => s.trim()).filter(Boolean);
9650
11352
  return parts.length > 0 ? parts : void 0;
9651
11353
  }
9652
- var activeEntitiesCommand = defineCommand64({
11354
+ var activeEntitiesCommand = defineCommand66({
9653
11355
  meta: {
9654
11356
  name: "active-entities",
9655
11357
  description: `List entities with metric activity in a time range.
@@ -9707,7 +11409,7 @@ Examples:
9707
11409
  });
9708
11410
 
9709
11411
  // src/commands/ads/x/audiences.ts
9710
- import { defineCommand as defineCommand65 } from "citty";
11412
+ import { defineCommand as defineCommand67 } from "citty";
9711
11413
  registerSchema({
9712
11414
  command: "ads.x.audiences",
9713
11415
  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.",
@@ -9716,7 +11418,7 @@ registerSchema({
9716
11418
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
9717
11419
  }
9718
11420
  });
9719
- var audiencesCommand3 = defineCommand65({
11421
+ var audiencesCommand4 = defineCommand67({
9720
11422
  meta: {
9721
11423
  name: "audiences",
9722
11424
  description: `List X Ads custom audiences.
@@ -9765,7 +11467,7 @@ Examples:
9765
11467
  });
9766
11468
 
9767
11469
  // src/commands/ads/x/campaigns.ts
9768
- import { defineCommand as defineCommand66 } from "citty";
11470
+ import { defineCommand as defineCommand68 } from "citty";
9769
11471
 
9770
11472
  // src/commands/ads/x/run-list.ts
9771
11473
  function buildCleanParams(opts) {
@@ -9828,7 +11530,7 @@ registerSchema({
9828
11530
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
9829
11531
  }
9830
11532
  });
9831
- var campaignsCommand3 = defineCommand66({
11533
+ var campaignsCommand4 = defineCommand68({
9832
11534
  meta: {
9833
11535
  name: "campaigns",
9834
11536
  description: `List X Ads campaigns. Returns budget, schedule, funding instrument, status.
@@ -9870,7 +11572,7 @@ Examples:
9870
11572
  });
9871
11573
 
9872
11574
  // src/commands/ads/x/cards.ts
9873
- import { defineCommand as defineCommand67 } from "citty";
11575
+ import { defineCommand as defineCommand69 } from "citty";
9874
11576
  registerSchema({
9875
11577
  command: "ads.x.cards",
9876
11578
  description: "List website cards, video cards, and carousels for an X Ads account.",
@@ -9879,7 +11581,7 @@ registerSchema({
9879
11581
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
9880
11582
  }
9881
11583
  });
9882
- var cardsCommand = defineCommand67({
11584
+ var cardsCommand = defineCommand69({
9883
11585
  meta: {
9884
11586
  name: "cards",
9885
11587
  description: `List X Ads cards (rich creatives).
@@ -9928,7 +11630,7 @@ Examples:
9928
11630
  });
9929
11631
 
9930
11632
  // src/commands/ads/x/funding.ts
9931
- import { defineCommand as defineCommand68 } from "citty";
11633
+ import { defineCommand as defineCommand70 } from "citty";
9932
11634
  registerSchema({
9933
11635
  command: "ads.x.funding",
9934
11636
  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.",
@@ -9937,7 +11639,7 @@ registerSchema({
9937
11639
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
9938
11640
  }
9939
11641
  });
9940
- var fundingCommand = defineCommand68({
11642
+ var fundingCommand = defineCommand70({
9941
11643
  meta: {
9942
11644
  name: "funding",
9943
11645
  description: `List funding instruments for an X Ads account.
@@ -9986,7 +11688,7 @@ Examples:
9986
11688
  });
9987
11689
 
9988
11690
  // src/commands/ads/x/line-items.ts
9989
- import { defineCommand as defineCommand69 } from "citty";
11691
+ import { defineCommand as defineCommand71 } from "citty";
9990
11692
  registerSchema({
9991
11693
  command: "ads.x.lineItems",
9992
11694
  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).",
@@ -9998,7 +11700,7 @@ registerSchema({
9998
11700
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
9999
11701
  }
10000
11702
  });
10001
- var lineItemsCommand = defineCommand69({
11703
+ var lineItemsCommand = defineCommand71({
10002
11704
  meta: {
10003
11705
  name: "line-items",
10004
11706
  description: `List X Ads line items (ad groups).
@@ -10039,7 +11741,7 @@ Examples:
10039
11741
  });
10040
11742
 
10041
11743
  // src/commands/ads/x/media.ts
10042
- import { defineCommand as defineCommand70 } from "citty";
11744
+ import { defineCommand as defineCommand72 } from "citty";
10043
11745
  registerSchema({
10044
11746
  command: "ads.x.media",
10045
11747
  description: "List media assets in the X Ads media library (images, GIFs, videos). Filter by media-type (IMAGE, GIF, VIDEO).",
@@ -10049,7 +11751,7 @@ registerSchema({
10049
11751
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
10050
11752
  }
10051
11753
  });
10052
- var mediaCommand = defineCommand70({
11754
+ var mediaCommand = defineCommand72({
10053
11755
  meta: {
10054
11756
  name: "media",
10055
11757
  description: `List media assets in the X Ads media library.
@@ -10101,7 +11803,7 @@ Examples:
10101
11803
  });
10102
11804
 
10103
11805
  // src/commands/ads/x/promoted-tweets.ts
10104
- import { defineCommand as defineCommand71 } from "citty";
11806
+ import { defineCommand as defineCommand73 } from "citty";
10105
11807
  registerSchema({
10106
11808
  command: "ads.x.promotedTweets",
10107
11809
  description: "List promoted tweets for an X Ads account. Returns id, line_item_id, tweet_id, approval_status. Filter by line-item-ids (CSV).",
@@ -10112,7 +11814,7 @@ registerSchema({
10112
11814
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
10113
11815
  }
10114
11816
  });
10115
- var promotedTweetsCommand = defineCommand71({
11817
+ var promotedTweetsCommand = defineCommand73({
10116
11818
  meta: {
10117
11819
  name: "promoted-tweets",
10118
11820
  description: `List X Ads promoted tweets.
@@ -10166,11 +11868,11 @@ Examples:
10166
11868
  });
10167
11869
 
10168
11870
  // src/commands/ads/x/stats/index.ts
10169
- import { defineCommand as defineCommand76 } from "citty";
11871
+ import { defineCommand as defineCommand78 } from "citty";
10170
11872
 
10171
11873
  // src/commands/ads/x/stats/job.ts
10172
11874
  import { gunzipSync } from "zlib";
10173
- import { defineCommand as defineCommand72 } from "citty";
11875
+ import { defineCommand as defineCommand74 } from "citty";
10174
11876
  var POLL_INTERVAL_MS2 = 1e4;
10175
11877
  var DEADLINE_MS = 12 * 60 * 1e3;
10176
11878
  var RESULT_CACHE_TTL_MS = 6 * 60 * 60 * 1e3;
@@ -10240,7 +11942,7 @@ async function pollUntilDone(accountId, jobId) {
10240
11942
  function buildCacheKey(body) {
10241
11943
  return `stats-job:${JSON.stringify(body)}`;
10242
11944
  }
10243
- var statsJobCommand = defineCommand72({
11945
+ var statsJobCommand = defineCommand74({
10244
11946
  meta: {
10245
11947
  name: "job",
10246
11948
  description: `Async X Ads stats job, sync from the CLI's perspective. Creates \u2192 polls \u2192 downloads \u2192 returns.
@@ -10345,7 +12047,7 @@ For fine-grained control (don't wait, poll yourself), use:
10345
12047
  });
10346
12048
 
10347
12049
  // src/commands/ads/x/stats/job-create.ts
10348
- import { defineCommand as defineCommand73 } from "citty";
12050
+ import { defineCommand as defineCommand75 } from "citty";
10349
12051
  registerSchema({
10350
12052
  command: "ads.x.statsJobCreate",
10351
12053
  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.",
@@ -10368,7 +12070,7 @@ function parseCsv3(v) {
10368
12070
  const parts = v.split(",").map((s) => s.trim()).filter(Boolean);
10369
12071
  return parts.length > 0 ? parts : void 0;
10370
12072
  }
10371
- var statsJobCreateCommand = defineCommand73({
12073
+ var statsJobCreateCommand = defineCommand75({
10372
12074
  meta: {
10373
12075
  name: "job-create",
10374
12076
  description: `Create an async X Ads stats job (up to 90 days, supports segmentation).
@@ -10431,7 +12133,7 @@ Examples:
10431
12133
  });
10432
12134
 
10433
12135
  // src/commands/ads/x/stats/job-status.ts
10434
- import { defineCommand as defineCommand74 } from "citty";
12136
+ import { defineCommand as defineCommand76 } from "citty";
10435
12137
  registerSchema({
10436
12138
  command: "ads.x.statsJobStatus",
10437
12139
  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).",
@@ -10441,7 +12143,7 @@ registerSchema({
10441
12143
  "job-ids": { type: "string", description: "CSV of job IDs", required: false }
10442
12144
  }
10443
12145
  });
10444
- var statsJobStatusCommand = defineCommand74({
12146
+ var statsJobStatusCommand = defineCommand76({
10445
12147
  meta: {
10446
12148
  name: "job-status",
10447
12149
  description: `Poll the status of an async X Ads stats job.
@@ -10482,7 +12184,7 @@ Examples:
10482
12184
  });
10483
12185
 
10484
12186
  // src/commands/ads/x/stats/sync.ts
10485
- import { defineCommand as defineCommand75 } from "citty";
12187
+ import { defineCommand as defineCommand77 } from "citty";
10486
12188
 
10487
12189
  // src/commands/ads/x/presets.ts
10488
12190
  var X_STATS_PRESETS = [
@@ -10641,7 +12343,7 @@ async function runSync(args, q) {
10641
12343
  process.exit(1);
10642
12344
  }
10643
12345
  }
10644
- var statsSyncCommand = defineCommand75({
12346
+ var statsSyncCommand = defineCommand77({
10645
12347
  meta: {
10646
12348
  name: "sync",
10647
12349
  description: `Synchronous X Ads analytics (max 7-day window).
@@ -10684,7 +12386,7 @@ Examples:
10684
12386
  });
10685
12387
 
10686
12388
  // src/commands/ads/x/stats/index.ts
10687
- var statsCommand = defineCommand76({
12389
+ var statsCommand = defineCommand78({
10688
12390
  meta: {
10689
12391
  name: "stats",
10690
12392
  description: `X Ads analytics. Sync (\u22647 days, no segmentation) or async jobs (\u226490 days, segmentable).
@@ -10712,7 +12414,7 @@ Examples:
10712
12414
  });
10713
12415
 
10714
12416
  // src/commands/ads/x/targeting-constants.ts
10715
- import { defineCommand as defineCommand77 } from "citty";
12417
+ import { defineCommand as defineCommand79 } from "citty";
10716
12418
  var ALLOWED_CONSTANTS = [
10717
12419
  "locations",
10718
12420
  "interests",
@@ -10740,7 +12442,7 @@ registerSchema({
10740
12442
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
10741
12443
  }
10742
12444
  });
10743
- var targetingConstantsCommand = defineCommand77({
12445
+ var targetingConstantsCommand = defineCommand79({
10744
12446
  meta: {
10745
12447
  name: "targeting-constants",
10746
12448
  description: `Lookup X Ads targeting constants.
@@ -10790,7 +12492,7 @@ Examples:
10790
12492
  });
10791
12493
 
10792
12494
  // src/commands/ads/x/targeting-criteria.ts
10793
- import { defineCommand as defineCommand78 } from "citty";
12495
+ import { defineCommand as defineCommand80 } from "citty";
10794
12496
  registerSchema({
10795
12497
  command: "ads.x.targetingCriteria",
10796
12498
  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.",
@@ -10800,7 +12502,7 @@ registerSchema({
10800
12502
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
10801
12503
  }
10802
12504
  });
10803
- var targetingCriteriaCommand = defineCommand78({
12505
+ var targetingCriteriaCommand = defineCommand80({
10804
12506
  meta: {
10805
12507
  name: "targeting-criteria",
10806
12508
  description: `List targeting criteria attached to line items.
@@ -10851,7 +12553,7 @@ Examples:
10851
12553
  });
10852
12554
 
10853
12555
  // src/commands/ads/x/index.ts
10854
- var xCommand = defineCommand79({
12556
+ var xCommand = defineCommand81({
10855
12557
  meta: {
10856
12558
  name: "x",
10857
12559
  description: `X (Twitter) Ads commands. Read campaigns, line items, promoted tweets, creatives, audiences, and analytics.
@@ -10875,12 +12577,12 @@ The CLI auto-detects --account-id when exactly one X Ads account is connected, o
10875
12577
  subCommands: {
10876
12578
  accounts: accountsCommand4,
10877
12579
  funding: fundingCommand,
10878
- campaigns: campaignsCommand3,
12580
+ campaigns: campaignsCommand4,
10879
12581
  "line-items": lineItemsCommand,
10880
12582
  "promoted-tweets": promotedTweetsCommand,
10881
12583
  cards: cardsCommand,
10882
12584
  media: mediaCommand,
10883
- audiences: audiencesCommand3,
12585
+ audiences: audiencesCommand4,
10884
12586
  "targeting-criteria": targetingCriteriaCommand,
10885
12587
  "targeting-constants": targetingConstantsCommand,
10886
12588
  "active-entities": activeEntitiesCommand,
@@ -10889,7 +12591,7 @@ The CLI auto-detects --account-id when exactly one X Ads account is connected, o
10889
12591
  });
10890
12592
 
10891
12593
  // src/commands/ads/index.ts
10892
- var adsCommand = defineCommand80({
12594
+ var adsCommand2 = defineCommand82({
10893
12595
  meta: {
10894
12596
  name: "ads",
10895
12597
  description: `Ad platform commands. Each platform exposes its own native command surface \u2014 no forced parity.
@@ -10919,11 +12621,11 @@ Examples:
10919
12621
  });
10920
12622
 
10921
12623
  // src/commands/canvas/index.ts
10922
- import { defineCommand as defineCommand88 } from "citty";
12624
+ import { defineCommand as defineCommand90 } from "citty";
10923
12625
 
10924
12626
  // src/commands/canvas/catalog.ts
10925
- import { defineCommand as defineCommand81 } from "citty";
10926
- var catalogCommand = defineCommand81({
12627
+ import { defineCommand as defineCommand83 } from "citty";
12628
+ var catalogCommand = defineCommand83({
10927
12629
  meta: {
10928
12630
  name: "catalog",
10929
12631
  description: "Print the agent-facing node catalog (JSON Schema). Includes every registered node grouped by category."
@@ -10940,9 +12642,9 @@ import { execFile } from "child_process";
10940
12642
  import { readdir, readFile, stat } from "fs/promises";
10941
12643
  import path from "path";
10942
12644
  import { promisify } from "util";
10943
- import { defineCommand as defineCommand82 } from "citty";
12645
+ import { defineCommand as defineCommand84 } from "citty";
10944
12646
  var execFileAsync = promisify(execFile);
10945
- var inspectCommand = defineCommand82({
12647
+ var inspectCommand = defineCommand84({
10946
12648
  meta: {
10947
12649
  name: "inspect",
10948
12650
  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."
@@ -11051,7 +12753,7 @@ async function probeDuration(filePath) {
11051
12753
  // src/commands/canvas/run.ts
11052
12754
  import { readFile as readFile2 } from "fs/promises";
11053
12755
  import path4 from "path";
11054
- import { defineCommand as defineCommand83 } from "citty";
12756
+ import { defineCommand as defineCommand85 } from "citty";
11055
12757
 
11056
12758
  // src/commands/canvas/placeholders.ts
11057
12759
  function unsuppliedPlaceholderAssets(canvas) {
@@ -11121,7 +12823,7 @@ async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
11121
12823
  }
11122
12824
 
11123
12825
  // src/commands/canvas/run.ts
11124
- var runCommand = defineCommand83({
12826
+ var runCommand = defineCommand85({
11125
12827
  meta: { name: "run", description: "Validate and execute a canvas JSON file." },
11126
12828
  args: {
11127
12829
  file: { type: "positional", required: true, description: "Path to canvas JSON" },
@@ -11233,30 +12935,30 @@ var runCommand = defineCommand83({
11233
12935
  // src/commands/canvas/scaffold-static-ad.ts
11234
12936
  import { readFile as readFile3, writeFile } from "fs/promises";
11235
12937
  import path6 from "path";
11236
- import { defineCommand as defineCommand84 } from "citty";
12938
+ import { defineCommand as defineCommand86 } from "citty";
11237
12939
 
11238
12940
  // src/engine/scaffold/staticAd.ts
11239
- import { z as z8 } from "zod";
12941
+ import { z as z10 } from "zod";
11240
12942
  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"]);
11241
12943
  var DEFAULT_ASPECT_RATIO = "9:16";
11242
- var Blueprint = z8.object({
11243
- meta: z8.object({ estimated_aspect_ratio: z8.string().optional() }).loose().optional(),
11244
- text_content: z8.array(z8.object({ text: z8.string().optional() }).loose()).optional()
12944
+ var Blueprint = z10.object({
12945
+ meta: z10.object({ estimated_aspect_ratio: z10.string().optional() }).loose().optional(),
12946
+ text_content: z10.array(z10.object({ text: z10.string().optional() }).loose()).optional()
11245
12947
  }).loose();
11246
- var ElementLocator = z8.object({
11247
- collection: z8.enum(["subjects", "people", "brands_logos"]),
11248
- index: z8.number().int().nonnegative()
12948
+ var ElementLocator = z10.object({
12949
+ collection: z10.enum(["subjects", "people", "brands_logos"]),
12950
+ index: z10.number().int().nonnegative()
11249
12951
  }).loose();
11250
- var MainElement = z8.object({
12952
+ var MainElement = z10.object({
11251
12953
  // logo | product | person | animal | badge | other
11252
- type: z8.string(),
11253
- label: z8.string().optional(),
11254
- description: z8.string().optional(),
11255
- expression: z8.string().nullable().optional(),
11256
- reason: z8.string().optional(),
12954
+ type: z10.string(),
12955
+ label: z10.string().optional(),
12956
+ description: z10.string().optional(),
12957
+ expression: z10.string().nullable().optional(),
12958
+ reason: z10.string().optional(),
11257
12959
  locator: ElementLocator.optional()
11258
12960
  }).loose();
11259
- var MainElements = z8.array(MainElement);
12961
+ var MainElements = z10.array(MainElement);
11260
12962
  function sanitizeId(raw, fallback) {
11261
12963
  const id = raw.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
11262
12964
  return /^[a-z]/.test(id) ? id : `${fallback}_${id}`.replace(/_+$/g, "") || fallback;
@@ -11580,7 +13282,7 @@ async function runVisionPasses(canvas) {
11580
13282
  return fail("read_outputs", e instanceof Error ? e.message : String(e));
11581
13283
  }
11582
13284
  }
11583
- var scaffoldStaticAdCommand = defineCommand84({
13285
+ var scaffoldStaticAdCommand = defineCommand86({
11584
13286
  meta: {
11585
13287
  name: "scaffold-static-ad",
11586
13288
  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."
@@ -11676,7 +13378,7 @@ var scaffoldStaticAdCommand = defineCommand84({
11676
13378
  // src/commands/canvas/scaffold-video.ts
11677
13379
  import { cp, mkdir, readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
11678
13380
  import path9 from "path";
11679
- import { defineCommand as defineCommand85 } from "citty";
13381
+ import { defineCommand as defineCommand87 } from "citty";
11680
13382
 
11681
13383
  // src/engine/nodes/local/lib/sceneDetect.ts
11682
13384
  import { execFile as execFile2 } from "child_process";
@@ -11781,7 +13483,7 @@ import { toCardinal as nwKo } from "n2words/ko-KR";
11781
13483
  import { toCardinal as nwNl } from "n2words/nl-NL";
11782
13484
  import { toCardinal as nwPl } from "n2words/pl-PL";
11783
13485
  import { toCardinal as nwPt } from "n2words/pt-PT";
11784
- import { z as z9 } from "zod";
13486
+ import { z as z11 } from "zod";
11785
13487
 
11786
13488
  // src/engine/scaffold/lib/shoot-modes.ts
11787
13489
  var SHOOT_MODES = [
@@ -12081,49 +13783,49 @@ function trimArgs(durationS, offsetS = 0, dims) {
12081
13783
  "{{out.video}}"
12082
13784
  ];
12083
13785
  }
12084
- var FrameAsset = z9.object({ url: z9.string().optional() }).loose().optional();
12085
- var DialogueLine = z9.object({
12086
- speaker: z9.string().optional(),
12087
- line: z9.string().optional(),
13786
+ var FrameAsset = z11.object({ url: z11.string().optional() }).loose().optional();
13787
+ var DialogueLine = z11.object({
13788
+ speaker: z11.string().optional(),
13789
+ line: z11.string().optional(),
12088
13790
  // Absolute seconds on the source timeline (the deconstruct emits both).
12089
- start_s: z9.number().optional(),
12090
- end_s: z9.number().optional(),
12091
- delivery: z9.string().optional(),
12092
- voice_description: z9.string().optional()
13791
+ start_s: z11.number().optional(),
13792
+ end_s: z11.number().optional(),
13793
+ delivery: z11.string().optional(),
13794
+ voice_description: z11.string().optional()
12093
13795
  }).loose();
12094
- var Sfx = z9.object({
12095
- at_s: z9.number().optional(),
12096
- duration_s: z9.number().optional(),
12097
- sound_effect_prompt: z9.string().optional(),
12098
- description: z9.string().optional()
13796
+ var Sfx = z11.object({
13797
+ at_s: z11.number().optional(),
13798
+ duration_s: z11.number().optional(),
13799
+ sound_effect_prompt: z11.string().optional(),
13800
+ description: z11.string().optional()
12099
13801
  }).loose();
12100
- var CompositionRegion = z9.object({
13802
+ var CompositionRegion = z11.object({
12101
13803
  // full | top | bottom | left | right | inset
12102
- panel: z9.string().optional(),
13804
+ panel: z11.string().optional(),
12103
13805
  // 9-grid anchor for an `inset` presenter box.
12104
- position: z9.string().optional(),
12105
- is_presenter: z9.boolean().optional(),
13806
+ position: z11.string().optional(),
13807
+ is_presenter: z11.boolean().optional(),
12106
13808
  // The cast id shown/speaking in this region (routes lip-sync + element refs).
12107
- cast_ref: z9.string().optional(),
12108
- summary: z9.string().optional(),
12109
- frame_prompt: z9.string().optional(),
12110
- motion_prompt: z9.string().optional()
13809
+ cast_ref: z11.string().optional(),
13810
+ summary: z11.string().optional(),
13811
+ frame_prompt: z11.string().optional(),
13812
+ motion_prompt: z11.string().optional()
12111
13813
  }).loose();
12112
- var SceneComposition = z9.object({
13814
+ var SceneComposition = z11.object({
12113
13815
  // full_frame (default) | split_screen | pip | keyed_overlay
12114
- layout: z9.string().optional(),
13816
+ layout: z11.string().optional(),
12115
13817
  // split_screen only: vertical (top/bottom) | horizontal (left/right).
12116
- split_axis: z9.string().optional(),
12117
- regions: z9.array(CompositionRegion).optional()
13818
+ split_axis: z11.string().optional(),
13819
+ regions: z11.array(CompositionRegion).optional()
12118
13820
  }).loose();
12119
- var CameraMotion = z9.object({ movement: z9.string().optional(), detail: z9.string().optional() }).loose();
12120
- var TranscriptWord = z9.object({ text: z9.string().optional() }).loose();
12121
- var Scene = z9.object({
12122
- start_s: z9.number().optional(),
12123
- end_s: z9.number().optional(),
12124
- duration_s: z9.number().optional(),
12125
- summary: z9.string().optional(),
12126
- action_detail: z9.string().optional(),
13821
+ var CameraMotion = z11.object({ movement: z11.string().optional(), detail: z11.string().optional() }).loose();
13822
+ var TranscriptWord = z11.object({ text: z11.string().optional() }).loose();
13823
+ var Scene = z11.object({
13824
+ start_s: z11.number().optional(),
13825
+ end_s: z11.number().optional(),
13826
+ duration_s: z11.number().optional(),
13827
+ summary: z11.string().optional(),
13828
+ action_detail: z11.string().optional(),
12127
13829
  // The scene's spatial layout. Absent/full_frame ⇒ one uncut shot (default path).
12128
13830
  // A layered layout (split_screen/pip/keyed_overlay) with regions ⇒ the scaffold
12129
13831
  // builds one clip per region and stacks/overlays them into the scene picture.
@@ -12131,77 +13833,77 @@ var Scene = z9.object({
12131
13833
  // The capture "look" for this scene — selected from the ad-native shoot-mode
12132
13834
  // grammar (see lib/shoot-modes.ts). When absent the scaffold auto-derives a
12133
13835
  // UGC/product mode; a human can override per scene by setting this.
12134
- shoot_mode: z9.string().optional(),
13836
+ shoot_mode: z11.string().optional(),
12135
13837
  // Diegetic ambient the clip's native audio should carry (no music). When
12136
13838
  // absent the scene falls back to its shoot mode's default ambience.
12137
- ambient: z9.string().optional(),
13839
+ ambient: z11.string().optional(),
12138
13840
  camera_motion: CameraMotion.optional(),
12139
- start_frame_prompt: z9.string().optional(),
12140
- end_frame_prompt: z9.string().optional(),
12141
- motion_prompt: z9.string().optional(),
13841
+ start_frame_prompt: z11.string().optional(),
13842
+ end_frame_prompt: z11.string().optional(),
13843
+ motion_prompt: z11.string().optional(),
12142
13844
  // The scene's role in the ad's persuasion arc (DECON-supplied); drives the
12143
13845
  // script re-craft checklist. Inferred from position when absent.
12144
- narrative_role: z9.string().optional(),
13846
+ narrative_role: z11.string().optional(),
12145
13847
  // DECON-supplied on the HOOK scene: the engineered physical/emotional state that
12146
13848
  // makes the first frame stop the scroll (sweaty/breathless/urgent …). Injected
12147
13849
  // into the hook's start-frame description so the generator renders that state,
12148
13850
  // not a calm influencer (CCA-11).
12149
- hook_mechanic: z9.object({ mechanic: z9.string().optional(), why_it_stops_scroll: z9.string().optional() }).loose().optional(),
13851
+ hook_mechanic: z11.object({ mechanic: z11.string().optional(), why_it_stops_scroll: z11.string().optional() }).loose().optional(),
12150
13852
  // DECON-supplied per-scene location (so a gym hook isn't flattened to "home").
12151
- scene_setting: z9.string().optional(),
13853
+ scene_setting: z11.string().optional(),
12152
13854
  // How this scene cuts to the next (DECON-supplied). A recognized non-cut type
12153
13855
  // (fade/whip/zoom/dissolve/swipe) is reproduced as an ffmpeg xfade at the
12154
13856
  // boundary; cut/match_cut/none/other stay hard cuts. The last scene's value is
12155
13857
  // ignored (nothing follows it).
12156
- transition_out: z9.object({ type: z9.string().optional(), description: z9.string().optional() }).loose().optional(),
12157
- dialogue: z9.array(DialogueLine).optional(),
12158
- sfx: z9.array(Sfx).optional(),
12159
- overlays: z9.array(z9.unknown()).optional(),
12160
- floating_elements: z9.array(z9.unknown()).optional(),
12161
- transcript_slice: z9.array(TranscriptWord).optional(),
13858
+ transition_out: z11.object({ type: z11.string().optional(), description: z11.string().optional() }).loose().optional(),
13859
+ dialogue: z11.array(DialogueLine).optional(),
13860
+ sfx: z11.array(Sfx).optional(),
13861
+ overlays: z11.array(z11.unknown()).optional(),
13862
+ floating_elements: z11.array(z11.unknown()).optional(),
13863
+ transcript_slice: z11.array(TranscriptWord).optional(),
12162
13864
  start_frame_asset: FrameAsset,
12163
13865
  end_frame_asset: FrameAsset,
12164
13866
  // DECON-supplied: true when this scene is a length-split CONTINUATION of the
12165
13867
  // previous one (the SAME physical shot, broken up only because it exceeded the
12166
13868
  // clip ceiling). The scaffold then shares the splice keyframe — this scene's
12167
13869
  // start frame IS the previous scene's end frame — so the join is seamless.
12168
- continues_previous: z9.boolean().optional()
13870
+ continues_previous: z11.boolean().optional()
12169
13871
  }).loose();
12170
- var VideoBlueprint = z9.object({
12171
- source: z9.object({ aspect_ratio: z9.string().optional(), duration_s: z9.number().optional() }).loose().optional(),
12172
- global: z9.object({
12173
- music: z9.object({
12174
- present: z9.boolean().optional(),
12175
- music_prompt: z9.string().optional(),
13872
+ var VideoBlueprint = z11.object({
13873
+ source: z11.object({ aspect_ratio: z11.string().optional(), duration_s: z11.number().optional() }).loose().optional(),
13874
+ global: z11.object({
13875
+ music: z11.object({
13876
+ present: z11.boolean().optional(),
13877
+ music_prompt: z11.string().optional(),
12176
13878
  // Absolute second the music enters in the reference (the bed often
12177
13879
  // kicks in mid-ad, after the hook). We start the regenerated track here
12178
13880
  // instead of at 0 so the timing matches.
12179
- starts_at_s: z9.number().optional(),
13881
+ starts_at_s: z11.number().optional(),
12180
13882
  // Populated by the deconstruct when AudD (Shazam-style) recognizes the
12181
13883
  // reference track. We never reuse it — only style the regenerated bed.
12182
- identified_track: z9.object({ title: z9.string().optional(), artist: z9.string().optional() }).loose().nullish()
13884
+ identified_track: z11.object({ title: z11.string().optional(), artist: z11.string().optional() }).loose().nullish()
12183
13885
  }).loose().optional(),
12184
- cast: z9.array(
12185
- z9.object({
12186
- id: z9.string().optional(),
12187
- description: z9.string().optional(),
13886
+ cast: z11.array(
13887
+ z11.object({
13888
+ id: z11.string().optional(),
13889
+ description: z11.string().optional(),
12188
13890
  // The deconstruct's note on the target-market localization (e.g. "native
12189
13891
  // French speaker") — read to derive the spoken-track language code.
12190
- market_localization_note: z9.string().optional()
13892
+ market_localization_note: z11.string().optional()
12191
13893
  }).loose()
12192
13894
  ).optional(),
12193
- voiceover: z9.object({
13895
+ voiceover: z11.object({
12194
13896
  // on_camera | mixed → mouths are on screen (lip-sync candidates);
12195
13897
  // voiceover | none → narration over the picture (no lip-sync).
12196
- mode: z9.string().optional(),
12197
- voice_description: z9.string().optional(),
12198
- persona: z9.string().optional()
13898
+ mode: z11.string().optional(),
13899
+ voice_description: z11.string().optional(),
13900
+ persona: z11.string().optional()
12199
13901
  }).loose().optional(),
12200
13902
  // Visual palette — read only to colour a clean brand-card/CTA plate (the
12201
13903
  // first hex is the dominant brand colour); never to drive frame generation.
12202
- style: z9.object({ palette: z9.array(z9.object({ hex: z9.string().optional() }).loose()).optional() }).loose().optional()
13904
+ style: z11.object({ palette: z11.array(z11.object({ hex: z11.string().optional() }).loose()).optional() }).loose().optional()
12203
13905
  }).loose().optional(),
12204
- scenes: z9.array(Scene).min(1)
13906
+ scenes: z11.array(Scene).min(1)
12205
13907
  }).loose();
12206
13908
  function injectHookPhysicality(blueprint) {
12207
13909
  for (const scene of blueprint.scenes) {
@@ -12211,26 +13913,26 @@ function injectHookPhysicality(blueprint) {
12211
13913
  scene.start_frame_prompt = `${prompt} The subject's physical state IS the scroll-stopper \u2014 render it explicitly, not a calm pose: ${why}.`;
12212
13914
  }
12213
13915
  }
12214
- var AppearsItem = z9.union([z9.number(), z9.object({ scene: z9.number(), edge: z9.string().optional() }).loose()]);
12215
- var RecurringElement = z9.object({
13916
+ var AppearsItem = z11.union([z11.number(), z11.object({ scene: z11.number(), edge: z11.string().optional() }).loose()]);
13917
+ var RecurringElement = z11.object({
12216
13918
  // person | animal | product | logo | badge | other
12217
- type: z9.string(),
12218
- label: z9.string().optional(),
12219
- description: z9.string().optional(),
12220
- expression: z9.string().nullable().optional(),
13919
+ type: z11.string(),
13920
+ label: z11.string().optional(),
13921
+ description: z11.string().optional(),
13922
+ expression: z11.string().nullable().optional(),
12221
13923
  // When the element maps to a global cast entry, its stable id (for annotation).
12222
- cast_id: z9.string().nullable().optional(),
13924
+ cast_id: z11.string().nullable().optional(),
12223
13925
  // The label of another element that is the SAME individual as this one, shown
12224
13926
  // in a DIFFERENT wardrobe/persona/state (e.g. one creator playing skeptic in a
12225
13927
  // pink shirt and believer in a white shirt). Each look gets its own reference
12226
13928
  // slot, but the face/identity must stay identical across them.
12227
- same_as: z9.string().nullable().optional(),
13929
+ same_as: z11.string().nullable().optional(),
12228
13930
  // Scenes the element appears in. Either a bare list of scene indices (both
12229
13931
  // edges) or per-{scene,edge} entries. Both forms are accepted and merged.
12230
- scenes: z9.array(z9.number()).optional(),
12231
- appears_in: z9.array(AppearsItem).optional()
13932
+ scenes: z11.array(z11.number()).optional(),
13933
+ appears_in: z11.array(AppearsItem).optional()
12232
13934
  }).loose();
12233
- var RecurringElements = z9.array(RecurringElement);
13935
+ var RecurringElements = z11.array(RecurringElement);
12234
13936
  function sanitizeId2(raw, fallback) {
12235
13937
  const id = raw.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
12236
13938
  return /^[a-z]/.test(id) ? id : `${fallback}_${id}`.replace(/_+$/g, "") || fallback;
@@ -13756,25 +15458,25 @@ function buildSfxMusic(blueprint, nodes) {
13756
15458
  }
13757
15459
  return tracks;
13758
15460
  }
13759
- var OverlayStyle = z9.object({ color_hex: z9.string().optional(), background: z9.string().optional(), size: z9.string().optional() }).loose();
13760
- var Overlay = z9.object({
13761
- text: z9.string().optional(),
13762
- appears_at_s: z9.number().optional(),
13763
- duration_s: z9.number().optional(),
13764
- position: z9.string().optional(),
13765
- role: z9.string().optional(),
13766
- animation: z9.string().optional(),
13767
- animation_detail: z9.string().optional(),
15461
+ var OverlayStyle = z11.object({ color_hex: z11.string().optional(), background: z11.string().optional(), size: z11.string().optional() }).loose();
15462
+ var Overlay = z11.object({
15463
+ text: z11.string().optional(),
15464
+ appears_at_s: z11.number().optional(),
15465
+ duration_s: z11.number().optional(),
15466
+ position: z11.string().optional(),
15467
+ role: z11.string().optional(),
15468
+ animation: z11.string().optional(),
15469
+ animation_detail: z11.string().optional(),
13768
15470
  style: OverlayStyle.optional()
13769
15471
  }).loose();
13770
- var FloatingElement = z9.object({
13771
- kind: z9.string().optional(),
13772
- description: z9.string().optional(),
13773
- brand_name: z9.string().nullish(),
13774
- what_it_represents: z9.string().optional(),
13775
- appears_at_s: z9.number().optional(),
13776
- duration_s: z9.number().optional(),
13777
- position: z9.string().optional()
15472
+ var FloatingElement = z11.object({
15473
+ kind: z11.string().optional(),
15474
+ description: z11.string().optional(),
15475
+ brand_name: z11.string().nullish(),
15476
+ what_it_represents: z11.string().optional(),
15477
+ appears_at_s: z11.number().optional(),
15478
+ duration_s: z11.number().optional(),
15479
+ position: z11.string().optional()
13778
15480
  }).loose();
13779
15481
  function escapeHtml(s) {
13780
15482
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
@@ -13806,7 +15508,7 @@ function positionClass(position) {
13806
15508
  function collectCaptions(blueprint) {
13807
15509
  return blueprint.scenes.flatMap((scene) => {
13808
15510
  const sceneStart = scene.start_s ?? 0;
13809
- const overlays = z9.array(Overlay).safeParse(scene.overlays ?? []);
15511
+ const overlays = z11.array(Overlay).safeParse(scene.overlays ?? []);
13810
15512
  return overlays.success ? overlays.data.filter((ov) => Boolean(ov.text?.trim())).map((ov) => {
13811
15513
  const at = ov.appears_at_s ?? sceneStart;
13812
15514
  return { text: ov.text.trim(), at, end: at + (ov.duration_s ?? 2.5), ov };
@@ -13935,7 +15637,7 @@ function buildOverlayHtml(input) {
13935
15637
  };
13936
15638
  for (const scene of blueprint.scenes) {
13937
15639
  const sceneStart = scene.start_s ?? 0;
13938
- const floats = z9.array(FloatingElement).safeParse(scene.floating_elements ?? []);
15640
+ const floats = z11.array(FloatingElement).safeParse(scene.floating_elements ?? []);
13939
15641
  const parts = (floats.success ? floats.data.filter((fe) => keepFloat(fe, sceneStart)).map((fe) => floatingStub(fe, sceneStart)) : []).filter(Boolean);
13940
15642
  const pip = uiPipStub(scene);
13941
15643
  if (pip) parts.push(pip);
@@ -14196,8 +15898,8 @@ function buildMotionBoard(blueprint) {
14196
15898
  const end_s = scene.end_s ?? start_s + sceneDurationS(scene);
14197
15899
  cursor = end_s;
14198
15900
  const spoken = sceneSpokenText(scene);
14199
- const overlays = z9.array(Overlay).safeParse(scene.overlays ?? []);
14200
- const floats = z9.array(FloatingElement).safeParse(scene.floating_elements ?? []);
15901
+ const overlays = z11.array(Overlay).safeParse(scene.overlays ?? []);
15902
+ const floats = z11.array(FloatingElement).safeParse(scene.floating_elements ?? []);
14201
15903
  const graphics = [
14202
15904
  ...(overlays.success ? overlays.data : []).filter((ov) => ov.text?.trim()).map((ov) => ({
14203
15905
  kind: "text",
@@ -14659,7 +16361,7 @@ async function runAnalysisPasses(deconstructCanvas, selectModel) {
14659
16361
  return fail2("deconstruct", e instanceof Error ? e.message : String(e));
14660
16362
  }
14661
16363
  }
14662
- var scaffoldVideoCommand = defineCommand85({
16364
+ var scaffoldVideoCommand = defineCommand87({
14663
16365
  meta: {
14664
16366
  name: "scaffold-video",
14665
16367
  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`."
@@ -14828,7 +16530,7 @@ var scaffoldVideoCommand = defineCommand85({
14828
16530
  // src/commands/canvas/set-prompt.ts
14829
16531
  import { readFile as readFile7, writeFile as writeFile3 } from "fs/promises";
14830
16532
  import path10 from "path";
14831
- import { defineCommand as defineCommand86 } from "citty";
16533
+ import { defineCommand as defineCommand88 } from "citty";
14832
16534
  function setNodePrompt(canvas, nodeId, text) {
14833
16535
  const nodes = canvas?.nodes;
14834
16536
  if (!Array.isArray(nodes)) throw new Error("canvas has no nodes array");
@@ -14843,7 +16545,7 @@ function setNodePrompt(canvas, nodeId, text) {
14843
16545
  newNodes[idx] = newNode;
14844
16546
  return { ...canvas, nodes: newNodes };
14845
16547
  }
14846
- var setPromptCommand = defineCommand86({
16548
+ var setPromptCommand = defineCommand88({
14847
16549
  meta: {
14848
16550
  name: "set-prompt",
14849
16551
  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."
@@ -14903,8 +16605,8 @@ var setPromptCommand = defineCommand86({
14903
16605
  // src/commands/canvas/validate.ts
14904
16606
  import { readFile as readFile8 } from "fs/promises";
14905
16607
  import path11 from "path";
14906
- import { defineCommand as defineCommand87 } from "citty";
14907
- var validateCommand = defineCommand87({
16608
+ import { defineCommand as defineCommand89 } from "citty";
16609
+ var validateCommand = defineCommand89({
14908
16610
  meta: {
14909
16611
  name: "validate",
14910
16612
  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)."
@@ -14947,7 +16649,7 @@ var validateCommand = defineCommand87({
14947
16649
  });
14948
16650
 
14949
16651
  // src/commands/canvas/index.ts
14950
- var canvasCommand = defineCommand88({
16652
+ var canvasCommand = defineCommand90({
14951
16653
  meta: {
14952
16654
  name: "canvas",
14953
16655
  description: `Run Baker creative canvas JSON files locally. Local nodes execute in-process; remote nodes POST to the Convex backend gateway.
@@ -14974,10 +16676,10 @@ Subcommands:
14974
16676
  });
14975
16677
 
14976
16678
  // src/commands/creatives/index.ts
14977
- import { defineCommand as defineCommand90 } from "citty";
16679
+ import { defineCommand as defineCommand92 } from "citty";
14978
16680
 
14979
16681
  // src/commands/creatives/publish.ts
14980
- import { defineCommand as defineCommand89 } from "citty";
16682
+ import { defineCommand as defineCommand91 } from "citty";
14981
16683
 
14982
16684
  // src/commands/images/api.ts
14983
16685
  import { readFile as readFile9 } from "fs/promises";
@@ -15100,7 +16802,7 @@ async function publishCreative(args, deps = defaultImageApiDeps) {
15100
16802
  sourceReferenceUrl
15101
16803
  });
15102
16804
  }
15103
- var publishCommand = defineCommand89({
16805
+ var publishCommand = defineCommand91({
15104
16806
  meta: {
15105
16807
  name: "publish",
15106
16808
  description: "Publish a final static creative image to Baker Creatives and print the creative reference JSON."
@@ -15146,7 +16848,7 @@ var publishCommand = defineCommand89({
15146
16848
  });
15147
16849
 
15148
16850
  // src/commands/creatives/index.ts
15149
- var creativesCommand3 = defineCommand90({
16851
+ var creativesCommand3 = defineCommand92({
15150
16852
  meta: {
15151
16853
  name: "creatives",
15152
16854
  description: `Publish static ad creatives as first-class Baker outputs.
@@ -15162,10 +16864,10 @@ Publishing uploads the image to the Company image library, applies the official
15162
16864
  });
15163
16865
 
15164
16866
  // src/commands/ga4/index.ts
15165
- import { defineCommand as defineCommand94 } from "citty";
16867
+ import { defineCommand as defineCommand96 } from "citty";
15166
16868
 
15167
16869
  // src/commands/ga4/audit.ts
15168
- import { defineCommand as defineCommand91 } from "citty";
16870
+ import { defineCommand as defineCommand93 } from "citty";
15169
16871
 
15170
16872
  // src/commands/ga4/resolve.ts
15171
16873
  async function fetchProperties(useCache = true) {
@@ -15228,7 +16930,7 @@ registerSchema({
15228
16930
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
15229
16931
  }
15230
16932
  });
15231
- var auditCommand2 = defineCommand91({
16933
+ var auditCommand2 = defineCommand93({
15232
16934
  meta: {
15233
16935
  name: "audit",
15234
16936
  description: `Run all GA4 admin health checks. Returns property config with playbook warnings.
@@ -15280,7 +16982,7 @@ Examples:
15280
16982
  });
15281
16983
 
15282
16984
  // src/commands/ga4/properties.ts
15283
- import { defineCommand as defineCommand92 } from "citty";
16985
+ import { defineCommand as defineCommand94 } from "citty";
15284
16986
  registerSchema({
15285
16987
  command: "ga4.properties",
15286
16988
  description: "List all accessible GA4 properties. Returns property IDs needed for query and audit commands. Run this first to find property IDs.",
@@ -15288,7 +16990,7 @@ registerSchema({
15288
16990
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
15289
16991
  }
15290
16992
  });
15291
- var propertiesCommand = defineCommand92({
16993
+ var propertiesCommand = defineCommand94({
15292
16994
  meta: {
15293
16995
  name: "properties",
15294
16996
  description: `List accessible GA4 properties.
@@ -15336,9 +17038,9 @@ Examples:
15336
17038
  });
15337
17039
 
15338
17040
  // src/commands/ga4/query.ts
15339
- import { appendFileSync as appendFileSync2, existsSync as existsSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "fs";
17041
+ import { appendFileSync as appendFileSync2, existsSync as existsSync5, readFileSync as readFileSync9, writeFileSync as writeFileSync4 } from "fs";
15340
17042
  import { resolve as resolve2 } from "path";
15341
- import { defineCommand as defineCommand93 } from "citty";
17043
+ import { defineCommand as defineCommand95 } from "citty";
15342
17044
 
15343
17045
  // src/commands/ga4/presets.ts
15344
17046
  var GA4_PRESETS = [
@@ -15427,7 +17129,7 @@ function writeRowsToFile2(filePath, rows, append) {
15427
17129
  writeFileSync4(filePath, content, "utf-8");
15428
17130
  }
15429
17131
  } else if (append && existsSync5(filePath)) {
15430
- const existing = JSON.parse(readFileSync8(filePath, "utf-8"));
17132
+ const existing = JSON.parse(readFileSync9(filePath, "utf-8"));
15431
17133
  writeFileSync4(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
15432
17134
  } else {
15433
17135
  writeFileSync4(filePath, JSON.stringify(rows, null, 2), "utf-8");
@@ -15470,7 +17172,7 @@ function handleError(err) {
15470
17172
  });
15471
17173
  process.exit(1);
15472
17174
  }
15473
- var queryCommand2 = defineCommand93({
17175
+ var queryCommand2 = defineCommand95({
15474
17176
  meta: {
15475
17177
  name: "query",
15476
17178
  description: `Run GA4 Data API reports. Preset-first with free-form escape hatch.
@@ -15541,7 +17243,7 @@ Free-form (escape hatch):
15541
17243
  });
15542
17244
 
15543
17245
  // src/commands/ga4/index.ts
15544
- var ga4Command = defineCommand94({
17246
+ var ga4Command = defineCommand96({
15545
17247
  meta: {
15546
17248
  name: "ga4",
15547
17249
  description: `Google Analytics 4 commands. Audit property config, run playbook-aligned reports.
@@ -15564,12 +17266,12 @@ Examples:
15564
17266
  });
15565
17267
 
15566
17268
  // src/commands/gsc/index.ts
15567
- import { defineCommand as defineCommand98 } from "citty";
17269
+ import { defineCommand as defineCommand100 } from "citty";
15568
17270
 
15569
17271
  // src/commands/gsc/query.ts
15570
- import { appendFileSync as appendFileSync3, existsSync as existsSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "fs";
17272
+ import { appendFileSync as appendFileSync3, existsSync as existsSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync5 } from "fs";
15571
17273
  import { resolve as resolve3 } from "path";
15572
- import { defineCommand as defineCommand95 } from "citty";
17274
+ import { defineCommand as defineCommand97 } from "citty";
15573
17275
 
15574
17276
  // src/commands/gsc/presets.ts
15575
17277
  var GSC_PRESETS = [
@@ -15712,7 +17414,7 @@ function writeRowsToFile3(filePath, rows, append) {
15712
17414
  writeFileSync5(filePath, content, "utf-8");
15713
17415
  }
15714
17416
  } else if (append && existsSync6(filePath)) {
15715
- const existing = JSON.parse(readFileSync9(filePath, "utf-8"));
17417
+ const existing = JSON.parse(readFileSync10(filePath, "utf-8"));
15716
17418
  writeFileSync5(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
15717
17419
  } else {
15718
17420
  writeFileSync5(filePath, JSON.stringify(rows, null, 2), "utf-8");
@@ -15757,7 +17459,7 @@ function handleError2(err) {
15757
17459
  });
15758
17460
  process.exit(1);
15759
17461
  }
15760
- var queryCommand3 = defineCommand95({
17462
+ var queryCommand3 = defineCommand97({
15761
17463
  meta: {
15762
17464
  name: "query",
15763
17465
  description: `Run GSC Search Analytics queries. Preset-first with free-form escape hatch.
@@ -15835,7 +17537,7 @@ Free-form (escape hatch):
15835
17537
  });
15836
17538
 
15837
17539
  // src/commands/gsc/sitemaps.ts
15838
- import { defineCommand as defineCommand96 } from "citty";
17540
+ import { defineCommand as defineCommand98 } from "citty";
15839
17541
  registerSchema({
15840
17542
  command: "gsc.sitemaps",
15841
17543
  description: "List sitemaps for a Search Console site. Check sitemap health and errors.",
@@ -15844,7 +17546,7 @@ registerSchema({
15844
17546
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
15845
17547
  }
15846
17548
  });
15847
- var sitemapsCommand = defineCommand96({
17549
+ var sitemapsCommand = defineCommand98({
15848
17550
  meta: {
15849
17551
  name: "sitemaps",
15850
17552
  description: `List sitemaps for a site. Check health and errors.
@@ -15894,7 +17596,7 @@ Examples:
15894
17596
  });
15895
17597
 
15896
17598
  // src/commands/gsc/sites.ts
15897
- import { defineCommand as defineCommand97 } from "citty";
17599
+ import { defineCommand as defineCommand99 } from "citty";
15898
17600
  registerSchema({
15899
17601
  command: "gsc.sites",
15900
17602
  description: "List all verified Google Search Console sites. Returns site URLs needed for query and sitemaps commands.",
@@ -15902,7 +17604,7 @@ registerSchema({
15902
17604
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
15903
17605
  }
15904
17606
  });
15905
- var sitesCommand = defineCommand97({
17607
+ var sitesCommand = defineCommand99({
15906
17608
  meta: {
15907
17609
  name: "sites",
15908
17610
  description: `List verified Search Console sites.
@@ -15950,7 +17652,7 @@ Examples:
15950
17652
  });
15951
17653
 
15952
17654
  // src/commands/gsc/index.ts
15953
- var gscCommand = defineCommand98({
17655
+ var gscCommand = defineCommand100({
15954
17656
  meta: {
15955
17657
  name: "gsc",
15956
17658
  description: `Google Search Console commands. PPC-SEO arbitrage, brand halo analysis, negative keyword discovery.
@@ -15973,10 +17675,10 @@ Examples:
15973
17675
  });
15974
17676
 
15975
17677
  // src/commands/images/index.ts
15976
- import { defineCommand as defineCommand122 } from "citty";
17678
+ import { defineCommand as defineCommand124 } from "citty";
15977
17679
 
15978
17680
  // src/commands/images/crop.ts
15979
- import { defineCommand as defineCommand99 } from "citty";
17681
+ import { defineCommand as defineCommand101 } from "citty";
15980
17682
 
15981
17683
  // src/lib/image/crop-sprite.ts
15982
17684
  import sharp from "sharp";
@@ -16101,7 +17803,7 @@ function emitError2(err) {
16101
17803
  }
16102
17804
  process.exit(1);
16103
17805
  }
16104
- var cropCommand = defineCommand99({
17806
+ var cropCommand = defineCommand101({
16105
17807
  meta: {
16106
17808
  name: "crop",
16107
17809
  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"
@@ -16137,7 +17839,7 @@ var cropCommand = defineCommand99({
16137
17839
  });
16138
17840
 
16139
17841
  // src/commands/images/delete.ts
16140
- import { defineCommand as defineCommand100 } from "citty";
17842
+ import { defineCommand as defineCommand102 } from "citty";
16141
17843
  registerSchema({
16142
17844
  command: "images.delete",
16143
17845
  description: "Delete an image by ID",
@@ -16151,7 +17853,7 @@ registerSchema({
16151
17853
  }
16152
17854
  }
16153
17855
  });
16154
- var deleteCommand = defineCommand100({
17856
+ var deleteCommand = defineCommand102({
16155
17857
  meta: {
16156
17858
  name: "delete",
16157
17859
  description: "Delete an image by ID. Use --dry-run to preview. Example: baker images delete j571abc123 --dry-run"
@@ -16192,7 +17894,7 @@ var deleteCommand = defineCommand100({
16192
17894
  });
16193
17895
 
16194
17896
  // src/commands/images/dimensions.ts
16195
- import { defineCommand as defineCommand101 } from "citty";
17897
+ import { defineCommand as defineCommand103 } from "citty";
16196
17898
 
16197
17899
  // src/lib/image/dimensions.ts
16198
17900
  import { imageSize } from "image-size";
@@ -16215,7 +17917,7 @@ registerSchema({
16215
17917
  target: { type: "string", description: "Local file path or remote http(s) URL", required: true }
16216
17918
  }
16217
17919
  });
16218
- var dimensionsCommand = defineCommand101({
17920
+ var dimensionsCommand = defineCommand103({
16219
17921
  meta: {
16220
17922
  name: "dimensions",
16221
17923
  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"
@@ -16259,7 +17961,7 @@ var dimensionsCommand = defineCommand101({
16259
17961
  });
16260
17962
 
16261
17963
  // src/commands/images/extract.ts
16262
- import { defineCommand as defineCommand102 } from "citty";
17964
+ import { defineCommand as defineCommand104 } from "citty";
16263
17965
  registerSchema({
16264
17966
  command: "images.extract",
16265
17967
  description: "Extract images from a URL via Firecrawl (formats: images).",
@@ -16275,7 +17977,7 @@ registerSchema({
16275
17977
  }
16276
17978
  }
16277
17979
  });
16278
- var extractCommand = defineCommand102({
17980
+ var extractCommand = defineCommand104({
16279
17981
  meta: {
16280
17982
  name: "extract",
16281
17983
  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"
@@ -16313,7 +18015,7 @@ var extractCommand = defineCommand102({
16313
18015
  });
16314
18016
 
16315
18017
  // src/commands/images/find.ts
16316
- import { defineCommand as defineCommand103 } from "citty";
18018
+ import { defineCommand as defineCommand105 } from "citty";
16317
18019
  registerSchema({
16318
18020
  command: "images.find",
16319
18021
  description: "Fanout image search: library first, then opted-in external providers.",
@@ -16345,7 +18047,7 @@ registerSchema({
16345
18047
  }
16346
18048
  }
16347
18049
  });
16348
- var findCommand = defineCommand103({
18050
+ var findCommand = defineCommand105({
16349
18051
  meta: {
16350
18052
  name: "find",
16351
18053
  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"
@@ -16394,7 +18096,7 @@ var findCommand = defineCommand103({
16394
18096
 
16395
18097
  // src/commands/images/generate.ts
16396
18098
  import { readFile as readFile11 } from "fs/promises";
16397
- import { defineCommand as defineCommand104 } from "citty";
18099
+ import { defineCommand as defineCommand106 } from "citty";
16398
18100
  import sharp2 from "sharp";
16399
18101
  var GENERATE_TIMEOUT_MS = 18e4;
16400
18102
  var REFERENCE_MAX_EDGE = 1536;
@@ -16497,7 +18199,7 @@ async function resolveReferences(spec) {
16497
18199
  }
16498
18200
  return out;
16499
18201
  }
16500
- var generateCommand = defineCommand104({
18202
+ var generateCommand = defineCommand106({
16501
18203
  meta: {
16502
18204
  name: "generate",
16503
18205
  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]]'"
@@ -16549,7 +18251,7 @@ var generateCommand = defineCommand104({
16549
18251
  });
16550
18252
 
16551
18253
  // src/commands/images/get.ts
16552
- import { defineCommand as defineCommand105 } from "citty";
18254
+ import { defineCommand as defineCommand107 } from "citty";
16553
18255
  registerSchema({
16554
18256
  command: "images.get",
16555
18257
  description: "Get a single image by ID",
@@ -16557,7 +18259,7 @@ registerSchema({
16557
18259
  id: { type: "string", description: "Image ID", required: true }
16558
18260
  }
16559
18261
  });
16560
- var getCommand2 = defineCommand105({
18262
+ var getCommand2 = defineCommand107({
16561
18263
  meta: { name: "get", description: "Get a single image by ID. Example: baker images get j571abc123" },
16562
18264
  args: {
16563
18265
  id: { type: "positional", description: "Image ID", required: false },
@@ -16593,7 +18295,7 @@ var getCommand2 = defineCommand105({
16593
18295
  });
16594
18296
 
16595
18297
  // src/commands/images/gif.ts
16596
- import { defineCommand as defineCommand106 } from "citty";
18298
+ import { defineCommand as defineCommand108 } from "citty";
16597
18299
  registerSchema({
16598
18300
  command: "images.gif",
16599
18301
  description: "Search Giphy for GIFs / reaction memes (paid social creative).",
@@ -16625,7 +18327,7 @@ registerSchema({
16625
18327
  }
16626
18328
  }
16627
18329
  });
16628
- var gifCommand = defineCommand106({
18330
+ var gifCommand = defineCommand108({
16629
18331
  meta: {
16630
18332
  name: "gif",
16631
18333
  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"
@@ -16672,7 +18374,7 @@ var gifCommand = defineCommand106({
16672
18374
  });
16673
18375
 
16674
18376
  // src/commands/images/google.ts
16675
- import { defineCommand as defineCommand107 } from "citty";
18377
+ import { defineCommand as defineCommand109 } from "citty";
16676
18378
  registerSchema({
16677
18379
  command: "images.google",
16678
18380
  description: "Google Images search via the official Custom Search JSON API. Unverified source \u2014 inspect before placing.",
@@ -16708,7 +18410,7 @@ registerSchema({
16708
18410
  }
16709
18411
  }
16710
18412
  });
16711
- var googleCommand2 = defineCommand107({
18413
+ var googleCommand2 = defineCommand109({
16712
18414
  meta: {
16713
18415
  name: "google",
16714
18416
  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"
@@ -16756,7 +18458,7 @@ var googleCommand2 = defineCommand107({
16756
18458
  });
16757
18459
 
16758
18460
  // src/commands/images/icon.ts
16759
- import { defineCommand as defineCommand108 } from "citty";
18461
+ import { defineCommand as defineCommand110 } from "citty";
16760
18462
  registerSchema({
16761
18463
  command: "images.icon",
16762
18464
  description: "Icon lookup via Iconify (200+ icon sets, free CDN).",
@@ -16782,7 +18484,7 @@ registerSchema({
16782
18484
  }
16783
18485
  }
16784
18486
  });
16785
- var iconCommand = defineCommand108({
18487
+ var iconCommand = defineCommand110({
16786
18488
  meta: {
16787
18489
  name: "icon",
16788
18490
  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'"
@@ -16822,7 +18524,7 @@ var iconCommand = defineCommand108({
16822
18524
  });
16823
18525
 
16824
18526
  // src/commands/images/ingest.ts
16825
- import { defineCommand as defineCommand109 } from "citty";
18527
+ import { defineCommand as defineCommand111 } from "citty";
16826
18528
  registerSchema({
16827
18529
  command: "images.ingest",
16828
18530
  description: "Ingest a remote image URL into the library (full describe + embed).",
@@ -16834,7 +18536,7 @@ registerSchema({
16834
18536
  context: { type: "string", description: "Description context hint", required: false }
16835
18537
  }
16836
18538
  });
16837
- var ingestCommand = defineCommand109({
18539
+ var ingestCommand = defineCommand111({
16838
18540
  meta: {
16839
18541
  name: "ingest",
16840
18542
  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"
@@ -16876,7 +18578,7 @@ var ingestCommand = defineCommand109({
16876
18578
  });
16877
18579
 
16878
18580
  // src/commands/images/library.ts
16879
- import { defineCommand as defineCommand110 } from "citty";
18581
+ import { defineCommand as defineCommand112 } from "citty";
16880
18582
  registerSchema({
16881
18583
  command: "images.library",
16882
18584
  description: "Search the company image library. Returns only ready images.",
@@ -16902,7 +18604,7 @@ registerSchema({
16902
18604
  }
16903
18605
  }
16904
18606
  });
16905
- var libraryCommand = defineCommand110({
18607
+ var libraryCommand = defineCommand112({
16906
18608
  meta: {
16907
18609
  name: "library",
16908
18610
  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"
@@ -16959,7 +18661,7 @@ var libraryCommand = defineCommand110({
16959
18661
  });
16960
18662
 
16961
18663
  // src/commands/images/logo.ts
16962
- import { defineCommand as defineCommand111 } from "citty";
18664
+ import { defineCommand as defineCommand113 } from "citty";
16963
18665
  registerSchema({
16964
18666
  command: "images.logo",
16965
18667
  description: "Brand logo lookup via Brandfetch CDN (fallback/404). Auto-ingests by default.",
@@ -16984,7 +18686,7 @@ registerSchema({
16984
18686
  }
16985
18687
  }
16986
18688
  });
16987
- var logoCommand = defineCommand111({
18689
+ var logoCommand = defineCommand113({
16988
18690
  meta: {
16989
18691
  name: "logo",
16990
18692
  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"
@@ -17022,7 +18724,7 @@ var logoCommand = defineCommand111({
17022
18724
  });
17023
18725
 
17024
18726
  // src/commands/images/normalize.ts
17025
- import { defineCommand as defineCommand112 } from "citty";
18727
+ import { defineCommand as defineCommand114 } from "citty";
17026
18728
 
17027
18729
  // src/lib/image/color-changer.ts
17028
18730
  import quantize from "quantize";
@@ -17754,7 +19456,7 @@ function coerceRawArgs(args) {
17754
19456
  "dry-run": bool(args["dry-run"])
17755
19457
  };
17756
19458
  }
17757
- var normalizeCommand = defineCommand112({
19459
+ var normalizeCommand = defineCommand114({
17758
19460
  meta: {
17759
19461
  name: "normalize",
17760
19462
  description: `Normalize logos / images: declarative recolor + bg removal + trim + resize. Operates on local files; writes in-place by default.
@@ -17809,7 +19511,7 @@ Examples:
17809
19511
  });
17810
19512
 
17811
19513
  // src/commands/images/pinterest.ts
17812
- import { defineCommand as defineCommand113 } from "citty";
19514
+ import { defineCommand as defineCommand115 } from "citty";
17813
19515
  registerSchema({
17814
19516
  command: "images.pinterest",
17815
19517
  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.",
@@ -17829,7 +19531,7 @@ registerSchema({
17829
19531
  }
17830
19532
  }
17831
19533
  });
17832
- var pinterestCommand = defineCommand113({
19534
+ var pinterestCommand = defineCommand115({
17833
19535
  meta: {
17834
19536
  name: "pinterest",
17835
19537
  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'"
@@ -17869,7 +19571,7 @@ var pinterestCommand = defineCommand113({
17869
19571
  });
17870
19572
 
17871
19573
  // src/commands/images/screenshot.ts
17872
- import { defineCommand as defineCommand114 } from "citty";
19574
+ import { defineCommand as defineCommand116 } from "citty";
17873
19575
  registerSchema({
17874
19576
  command: "images.screenshot",
17875
19577
  description: "Capture a website screenshot via ScreenshotOne. Auto-ingests on success.",
@@ -17885,7 +19587,7 @@ registerSchema({
17885
19587
  }
17886
19588
  }
17887
19589
  });
17888
- var screenshotCommand = defineCommand114({
19590
+ var screenshotCommand = defineCommand116({
17889
19591
  meta: {
17890
19592
  name: "screenshot",
17891
19593
  description: "Screenshot a URL via ScreenshotOne. $0.009/capture. Auto-ingests to library.\n\nExample: baker images screenshot https://stripe.com --full-page"
@@ -17935,7 +19637,7 @@ var screenshotCommand = defineCommand114({
17935
19637
  });
17936
19638
 
17937
19639
  // src/commands/images/search.ts
17938
- import { defineCommand as defineCommand115 } from "citty";
19640
+ import { defineCommand as defineCommand117 } from "citty";
17939
19641
  registerSchema({
17940
19642
  command: "images.search",
17941
19643
  description: "Search images by text query. Only returns ready images.",
@@ -17951,7 +19653,7 @@ registerSchema({
17951
19653
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
17952
19654
  }
17953
19655
  });
17954
- var searchCommand = defineCommand115({
19656
+ var searchCommand = defineCommand117({
17955
19657
  meta: {
17956
19658
  name: "search",
17957
19659
  description: "Semantic search images by text query. Uses hybrid BM25 + vector + reranking. Example: baker images search 'hero banner' --aspect-ratio 16:9 --tags logo"
@@ -18011,7 +19713,7 @@ var searchCommand = defineCommand115({
18011
19713
  });
18012
19714
 
18013
19715
  // src/commands/images/sticker.ts
18014
- import { defineCommand as defineCommand116 } from "citty";
19716
+ import { defineCommand as defineCommand118 } from "citty";
18015
19717
  registerSchema({
18016
19718
  command: "images.sticker",
18017
19719
  description: "Search Giphy stickers \u2014 transparent-background overlays for ad creative.",
@@ -18043,7 +19745,7 @@ registerSchema({
18043
19745
  }
18044
19746
  }
18045
19747
  });
18046
- var stickerCommand = defineCommand116({
19748
+ var stickerCommand = defineCommand118({
18047
19749
  meta: {
18048
19750
  name: "sticker",
18049
19751
  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"
@@ -18090,7 +19792,7 @@ var stickerCommand = defineCommand116({
18090
19792
  });
18091
19793
 
18092
19794
  // src/commands/images/stock.ts
18093
- import { defineCommand as defineCommand117 } from "citty";
19795
+ import { defineCommand as defineCommand119 } from "citty";
18094
19796
  registerSchema({
18095
19797
  command: "images.stock",
18096
19798
  description: "Stock photo, vector illustration, icon-set, and PSD search via Magnific (Freepik's developer API).",
@@ -18148,7 +19850,7 @@ registerSchema({
18148
19850
  }
18149
19851
  }
18150
19852
  });
18151
- var stockCommand = defineCommand117({
19853
+ var stockCommand = defineCommand119({
18152
19854
  meta: {
18153
19855
  name: "stock",
18154
19856
  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"
@@ -18204,7 +19906,7 @@ var stockCommand = defineCommand117({
18204
19906
  });
18205
19907
 
18206
19908
  // src/lib/tags-command.ts
18207
- import { defineCommand as defineCommand118 } from "citty";
19909
+ import { defineCommand as defineCommand120 } from "citty";
18208
19910
  function makeTagsCommand(command, label, endpoint) {
18209
19911
  registerSchema({
18210
19912
  command: `${command}.tags`,
@@ -18213,7 +19915,7 @@ function makeTagsCommand(command, label, endpoint) {
18213
19915
  output: { type: "string", description: "Output format: md|json", required: false, default: "md" }
18214
19916
  }
18215
19917
  });
18216
- return defineCommand118({
19918
+ return defineCommand120({
18217
19919
  meta: {
18218
19920
  name: "tags",
18219
19921
  description: `List the available ${label} tag names (defaults + company custom tags). Use before filtering with --tags. Example: baker ${command} tags`
@@ -18249,7 +19951,7 @@ function makeTagsCommand(command, label, endpoint) {
18249
19951
  var tagsCommand2 = makeTagsCommand("images", "image", "/api/images/tags");
18250
19952
 
18251
19953
  // src/commands/images/upload.ts
18252
- import { defineCommand as defineCommand119 } from "citty";
19954
+ import { defineCommand as defineCommand121 } from "citty";
18253
19955
  registerSchema({
18254
19956
  command: "images.upload",
18255
19957
  description: "Upload an image to the library \u2014 local file path or remote http(s) URL.",
@@ -18287,7 +19989,7 @@ registerSchema({
18287
19989
  function isRemoteUrl2(value) {
18288
19990
  return /^https?:\/\//i.test(value);
18289
19991
  }
18290
- var uploadCommand = defineCommand119({
19992
+ var uploadCommand = defineCommand121({
18291
19993
  meta: {
18292
19994
  name: "upload",
18293
19995
  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'"
@@ -18380,7 +20082,7 @@ async function uploadLocal(target, args) {
18380
20082
  }
18381
20083
 
18382
20084
  // src/commands/images/upscale.ts
18383
- import { defineCommand as defineCommand120 } from "citty";
20085
+ import { defineCommand as defineCommand122 } from "citty";
18384
20086
  registerSchema({
18385
20087
  command: "images.upscale",
18386
20088
  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).",
@@ -18395,7 +20097,7 @@ registerSchema({
18395
20097
  }
18396
20098
  });
18397
20099
  var POLL_INTERVAL_MS3 = 1500;
18398
- var upscaleCommand = defineCommand120({
20100
+ var upscaleCommand = defineCommand122({
18399
20101
  meta: {
18400
20102
  name: "upscale",
18401
20103
  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"
@@ -18450,7 +20152,7 @@ var upscaleCommand = defineCommand120({
18450
20152
  });
18451
20153
 
18452
20154
  // src/commands/images/use.ts
18453
- import { defineCommand as defineCommand121 } from "citty";
20155
+ import { defineCommand as defineCommand123 } from "citty";
18454
20156
  registerSchema({
18455
20157
  command: "images.use",
18456
20158
  description: "Ingest a URL and wait for the library record to be ready.",
@@ -18466,7 +20168,7 @@ registerSchema({
18466
20168
  }
18467
20169
  });
18468
20170
  var POLL_INTERVAL_MS4 = 1500;
18469
- var useCommand = defineCommand121({
20171
+ var useCommand = defineCommand123({
18470
20172
  meta: {
18471
20173
  name: "use",
18472
20174
  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"
@@ -18512,7 +20214,7 @@ var useCommand = defineCommand121({
18512
20214
  });
18513
20215
 
18514
20216
  // src/commands/images/index.ts
18515
- var imagesCommand = defineCommand122({
20217
+ var imagesCommand = defineCommand124({
18516
20218
  meta: {
18517
20219
  name: "images",
18518
20220
  description: `Find, source, and normalize images. Subcommands route by provider so cost + license are explicit.
@@ -18582,7 +20284,7 @@ Paid transforms (run on the Convex backend, cost-tracked):
18582
20284
  });
18583
20285
 
18584
20286
  // src/commands/mcp/index.ts
18585
- import { defineCommand as defineCommand123 } from "citty";
20287
+ import { defineCommand as defineCommand125 } from "citty";
18586
20288
  var SCOPES = ["user", "user_org", "company", "org"];
18587
20289
  function parseScope(raw) {
18588
20290
  const scope = raw === void 0 ? "company" : String(raw);
@@ -18621,7 +20323,7 @@ registerSchema({
18621
20323
  description: "List the custom MCP servers this company's chats see (org + company + your own user scope).",
18622
20324
  args: {}
18623
20325
  });
18624
- var listCommand4 = defineCommand123({
20326
+ var listCommand4 = defineCommand125({
18625
20327
  meta: { name: "list", description: "List custom MCP servers visible to this company's chats." },
18626
20328
  run: async () => {
18627
20329
  try {
@@ -18646,7 +20348,7 @@ registerSchema({
18646
20348
  header: { type: "string", description: 'Auth header "Key: Value" (repeatable)', required: false }
18647
20349
  }
18648
20350
  });
18649
- var addCommand = defineCommand123({
20351
+ var addCommand = defineCommand125({
18650
20352
  meta: {
18651
20353
  name: "add",
18652
20354
  description: `Register a custom MCP server. Tools appear as mcp__<name>__* on the NEXT message.
@@ -18687,7 +20389,7 @@ registerSchema({
18687
20389
  description: "Remove a company custom MCP server by name.",
18688
20390
  args: { name: { type: "string", description: "Server name to remove", required: true } }
18689
20391
  });
18690
- var removeCommand3 = defineCommand123({
20392
+ var removeCommand3 = defineCommand125({
18691
20393
  meta: {
18692
20394
  name: "remove",
18693
20395
  description: `Remove a company custom MCP server by name.
@@ -18709,7 +20411,7 @@ Example:
18709
20411
  }
18710
20412
  }
18711
20413
  });
18712
- var mcpCommand = defineCommand123({
20414
+ var mcpCommand = defineCommand125({
18713
20415
  meta: {
18714
20416
  name: "mcp",
18715
20417
  description: `Custom MCP servers for this company \u2014 point the agent at any HTTPS MCP endpoint.
@@ -18733,10 +20435,10 @@ Examples:
18733
20435
  });
18734
20436
 
18735
20437
  // src/commands/research/index.ts
18736
- import { defineCommand as defineCommand134 } from "citty";
20438
+ import { defineCommand as defineCommand136 } from "citty";
18737
20439
 
18738
20440
  // src/commands/research/advertisers.ts
18739
- import { defineCommand as defineCommand124 } from "citty";
20441
+ import { defineCommand as defineCommand126 } from "citty";
18740
20442
 
18741
20443
  // src/commands/research/output.ts
18742
20444
  var RESEARCH_DATA_NOTE = "Estimates based on third-party SERP data \u2014 not exact figures. Use for directional insights, not precise measurement.";
@@ -18849,7 +20551,7 @@ var FIELDS3 = {
18849
20551
  etv: "Estimated traffic value (USD)",
18850
20552
  visibility: "SERP visibility score (0-1)"
18851
20553
  };
18852
- var advertisersCommand = defineCommand124({
20554
+ var advertisersCommand = defineCommand126({
18853
20555
  meta: {
18854
20556
  name: "advertisers",
18855
20557
  description: `Find domains competing for a keyword in Google SERPs.
@@ -18896,7 +20598,7 @@ Examples:
18896
20598
  });
18897
20599
 
18898
20600
  // src/commands/research/autocomplete.ts
18899
- import { defineCommand as defineCommand125 } from "citty";
20601
+ import { defineCommand as defineCommand127 } from "citty";
18900
20602
  registerSchema({
18901
20603
  command: "research.autocomplete",
18902
20604
  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).",
@@ -18919,7 +20621,7 @@ registerSchema({
18919
20621
  var FIELDS4 = {
18920
20622
  suggestion: "Autocomplete suggestion from Google"
18921
20623
  };
18922
- var autocompleteCommand = defineCommand125({
20624
+ var autocompleteCommand = defineCommand127({
18923
20625
  meta: {
18924
20626
  name: "autocomplete",
18925
20627
  description: `Get Google Autocomplete suggestions for keyword expansion.
@@ -18965,7 +20667,7 @@ Examples:
18965
20667
  });
18966
20668
 
18967
20669
  // src/commands/research/countries.ts
18968
- import { defineCommand as defineCommand126 } from "citty";
20670
+ import { defineCommand as defineCommand128 } from "citty";
18969
20671
  registerSchema({
18970
20672
  command: "research.countries",
18971
20673
  description: "List all supported country codes for --location flag in research commands.",
@@ -19022,7 +20724,7 @@ var FIELDS5 = {
19022
20724
  code: "Country code to pass as --location",
19023
20725
  name: "Country name"
19024
20726
  };
19025
- var countriesCommand = defineCommand126({
20727
+ var countriesCommand = defineCommand128({
19026
20728
  meta: {
19027
20729
  name: "countries",
19028
20730
  description: "List all supported country codes for --location flag."
@@ -19033,7 +20735,7 @@ var countriesCommand = defineCommand126({
19033
20735
  });
19034
20736
 
19035
20737
  // src/commands/research/intent.ts
19036
- import { defineCommand as defineCommand127 } from "citty";
20738
+ import { defineCommand as defineCommand129 } from "citty";
19037
20739
  registerSchema({
19038
20740
  command: "research.intent",
19039
20741
  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.",
@@ -19056,7 +20758,7 @@ var FIELDS6 = {
19056
20758
  intent: "Primary Google Search intent: informational, navigational, commercial, transactional",
19057
20759
  probability: "Confidence score 0.0-1.0"
19058
20760
  };
19059
- var intentCommand = defineCommand127({
20761
+ var intentCommand = defineCommand129({
19060
20762
  meta: {
19061
20763
  name: "intent",
19062
20764
  description: `Classify Google Search intent for keywords. Returns intent type and confidence.
@@ -19104,7 +20806,7 @@ Examples:
19104
20806
  });
19105
20807
 
19106
20808
  // src/commands/research/keyword-gap.ts
19107
- import { defineCommand as defineCommand128 } from "citty";
20809
+ import { defineCommand as defineCommand130 } from "citty";
19108
20810
  registerSchema({
19109
20811
  command: "research.keyword-gap",
19110
20812
  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.",
@@ -19133,7 +20835,7 @@ var FIELDS7 = {
19133
20835
  cpc: "Cost per click USD",
19134
20836
  their_position: "Competitor's ranking position"
19135
20837
  };
19136
- var keywordGapCommand = defineCommand128({
20838
+ var keywordGapCommand = defineCommand130({
19137
20839
  meta: {
19138
20840
  name: "keyword-gap",
19139
20841
  description: `Find keywords a competitor has that you don't. Supports pagination via --offset.
@@ -19207,7 +20909,7 @@ Examples:
19207
20909
  });
19208
20910
 
19209
20911
  // src/commands/research/keywords-for-site.ts
19210
- import { defineCommand as defineCommand129 } from "citty";
20912
+ import { defineCommand as defineCommand131 } from "citty";
19211
20913
  registerSchema({
19212
20914
  command: "research.keywords-for-site",
19213
20915
  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.",
@@ -19240,7 +20942,7 @@ var FIELDS8 = {
19240
20942
  competition: "LOW, MEDIUM, or HIGH",
19241
20943
  competition_index: "Competition score 0-100"
19242
20944
  };
19243
- var keywordsForSiteCommand = defineCommand129({
20945
+ var keywordsForSiteCommand = defineCommand131({
19244
20946
  meta: {
19245
20947
  name: "keywords-for-site",
19246
20948
  description: `Get keywords a competitor targets in Google. Use --type to filter paid/organic.
@@ -19293,7 +20995,7 @@ Examples:
19293
20995
  });
19294
20996
 
19295
20997
  // src/commands/research/languages.ts
19296
- import { defineCommand as defineCommand130 } from "citty";
20998
+ import { defineCommand as defineCommand132 } from "citty";
19297
20999
  registerSchema({
19298
21000
  command: "research.languages",
19299
21001
  description: "List all supported language codes for --language flag in research commands.",
@@ -19323,7 +21025,7 @@ var FIELDS9 = {
19323
21025
  code: "Language code to pass as --language",
19324
21026
  name: "Language name (also accepted by --language)"
19325
21027
  };
19326
- var languagesCommand2 = defineCommand130({
21028
+ var languagesCommand2 = defineCommand132({
19327
21029
  meta: {
19328
21030
  name: "languages",
19329
21031
  description: "List all supported language codes for --language flag."
@@ -19334,7 +21036,7 @@ var languagesCommand2 = defineCommand130({
19334
21036
  });
19335
21037
 
19336
21038
  // src/commands/research/lighthouse.ts
19337
- import { defineCommand as defineCommand131 } from "citty";
21039
+ import { defineCommand as defineCommand133 } from "citty";
19338
21040
  registerSchema({
19339
21041
  command: "research.lighthouse",
19340
21042
  description: "Landing page performance audit. Returns metrics that affect Google Ads Quality Score and CPC.",
@@ -19353,7 +21055,7 @@ var FIELDS10 = {
19353
21055
  speed_index_ms: "Speed Index in ms (good: < 3400)",
19354
21056
  interactive_ms: "Time to Interactive in ms (good: < 3800)"
19355
21057
  };
19356
- var lighthouseCommand = defineCommand131({
21058
+ var lighthouseCommand = defineCommand133({
19357
21059
  meta: {
19358
21060
  name: "lighthouse",
19359
21061
  description: `Landing page performance audit. Metrics affecting Google Ads Quality Score.
@@ -19391,7 +21093,7 @@ Examples:
19391
21093
  });
19392
21094
 
19393
21095
  // src/commands/research/relevant-pages.ts
19394
- import { defineCommand as defineCommand132 } from "citty";
21096
+ import { defineCommand as defineCommand134 } from "citty";
19395
21097
  registerSchema({
19396
21098
  command: "research.relevant-pages",
19397
21099
  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).",
@@ -19417,7 +21119,7 @@ var FIELDS11 = {
19417
21119
  keywords: "Total organic keywords the page ranks for",
19418
21120
  top_10: "Keywords in positions 1-10"
19419
21121
  };
19420
- var relevantPagesCommand = defineCommand132({
21122
+ var relevantPagesCommand = defineCommand134({
19421
21123
  meta: {
19422
21124
  name: "relevant-pages",
19423
21125
  description: `Get the top pages of a competitor domain with traffic data.
@@ -19463,7 +21165,7 @@ Examples:
19463
21165
  });
19464
21166
 
19465
21167
  // src/commands/research/web.ts
19466
- import { defineCommand as defineCommand133 } from "citty";
21168
+ import { defineCommand as defineCommand135 } from "citty";
19467
21169
  registerSchema({
19468
21170
  command: "research.web",
19469
21171
  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).",
@@ -19514,7 +21216,7 @@ async function runDeepResearch(question) {
19514
21216
  }
19515
21217
  throw new Error("Deep research timed out");
19516
21218
  }
19517
- var webCommand = defineCommand133({
21219
+ var webCommand = defineCommand135({
19518
21220
  meta: {
19519
21221
  name: "web",
19520
21222
  description: `Search the web with AI to answer any open-ended marketing question. Uses live internet data via Google Search.
@@ -19574,7 +21276,7 @@ Examples:
19574
21276
  });
19575
21277
 
19576
21278
  // src/commands/research/index.ts
19577
- var researchCommand = defineCommand134({
21279
+ var researchCommand = defineCommand136({
19578
21280
  meta: {
19579
21281
  name: "research",
19580
21282
  description: `Competitive intelligence and AI-powered research commands.
@@ -19614,10 +21316,10 @@ Examples:
19614
21316
  });
19615
21317
 
19616
21318
  // src/commands/scheduled-actions/index.ts
19617
- import { defineCommand as defineCommand141 } from "citty";
21319
+ import { defineCommand as defineCommand143 } from "citty";
19618
21320
 
19619
21321
  // src/commands/scheduled-actions/create.ts
19620
- import { defineCommand as defineCommand135 } from "citty";
21322
+ import { defineCommand as defineCommand137 } from "citty";
19621
21323
 
19622
21324
  // src/commands/scheduled-actions/shared.ts
19623
21325
  var TEMP_SCHEDULED_ACTION_PREFIX = "temp_sched_";
@@ -19732,7 +21434,7 @@ registerSchema({
19732
21434
  prompt: { type: "string", description: "Additional prompt instructions for the spawned agent", required: false }
19733
21435
  }
19734
21436
  });
19735
- var createCommand2 = defineCommand135({
21437
+ var createCommand2 = defineCommand137({
19736
21438
  meta: {
19737
21439
  name: "create",
19738
21440
  description: 'Stage a scheduled action. Example: baker scheduled-actions create --name "Weekly report" --description "..." --cron "0 9 * * MON"'
@@ -19781,7 +21483,7 @@ var createCommand2 = defineCommand135({
19781
21483
  });
19782
21484
 
19783
21485
  // src/commands/scheduled-actions/delete.ts
19784
- import { defineCommand as defineCommand136 } from "citty";
21486
+ import { defineCommand as defineCommand138 } from "citty";
19785
21487
  registerSchema({
19786
21488
  command: "scheduled-actions.delete",
19787
21489
  description: "Stage deletion of a published scheduled action or cancellation of a temp_sched_* draft creation.",
@@ -19789,7 +21491,7 @@ registerSchema({
19789
21491
  id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
19790
21492
  }
19791
21493
  });
19792
- var deleteCommand2 = defineCommand136({
21494
+ var deleteCommand2 = defineCommand138({
19793
21495
  meta: {
19794
21496
  name: "delete",
19795
21497
  description: "Stage scheduled action deletion. Example: baker scheduled-actions delete <id-or-temp_sched_id>"
@@ -19818,7 +21520,7 @@ var deleteCommand2 = defineCommand136({
19818
21520
  });
19819
21521
 
19820
21522
  // src/commands/scheduled-actions/get.ts
19821
- import { defineCommand as defineCommand137 } from "citty";
21523
+ import { defineCommand as defineCommand139 } from "citty";
19822
21524
  registerSchema({
19823
21525
  command: "scheduled-actions.get",
19824
21526
  description: "Get a published scheduled action or a temp_sched_* draft-created scheduled action.",
@@ -19826,7 +21528,7 @@ registerSchema({
19826
21528
  id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
19827
21529
  }
19828
21530
  });
19829
- var getCommand3 = defineCommand137({
21531
+ var getCommand3 = defineCommand139({
19830
21532
  meta: {
19831
21533
  name: "get",
19832
21534
  description: "Get a scheduled action. Example: baker scheduled-actions get <id-or-temp_sched_id>"
@@ -19863,13 +21565,13 @@ var getCommand3 = defineCommand137({
19863
21565
  });
19864
21566
 
19865
21567
  // src/commands/scheduled-actions/list.ts
19866
- import { defineCommand as defineCommand138 } from "citty";
21568
+ import { defineCommand as defineCommand140 } from "citty";
19867
21569
  registerSchema({
19868
21570
  command: "scheduled-actions.list",
19869
21571
  description: "List published scheduled actions. Includes draft state when BAKER_CHAT_ID is set.",
19870
21572
  args: {}
19871
21573
  });
19872
- var listCommand5 = defineCommand138({
21574
+ var listCommand5 = defineCommand140({
19873
21575
  meta: {
19874
21576
  name: "list",
19875
21577
  description: "List scheduled actions. Includes staged draft ops when BAKER_CHAT_ID is set."
@@ -19890,7 +21592,7 @@ var listCommand5 = defineCommand138({
19890
21592
  });
19891
21593
 
19892
21594
  // src/commands/scheduled-actions/trigger.ts
19893
- import { defineCommand as defineCommand139 } from "citty";
21595
+ import { defineCommand as defineCommand141 } from "citty";
19894
21596
  registerSchema({
19895
21597
  command: "scheduled-actions.trigger",
19896
21598
  description: "Immediately trigger a published scheduled action. Does not require BAKER_CHAT_ID and rejects temp_sched_* IDs.",
@@ -19898,7 +21600,7 @@ registerSchema({
19898
21600
  id: { type: "string", description: "Published scheduled action ID", required: true }
19899
21601
  }
19900
21602
  });
19901
- var triggerCommand = defineCommand139({
21603
+ var triggerCommand = defineCommand141({
19902
21604
  meta: {
19903
21605
  name: "trigger",
19904
21606
  description: "Immediately trigger a published scheduled action. Example: baker scheduled-actions trigger <id>"
@@ -19935,7 +21637,7 @@ var triggerCommand = defineCommand139({
19935
21637
  });
19936
21638
 
19937
21639
  // src/commands/scheduled-actions/update.ts
19938
- import { defineCommand as defineCommand140 } from "citty";
21640
+ import { defineCommand as defineCommand142 } from "citty";
19939
21641
  registerSchema({
19940
21642
  command: "scheduled-actions.update",
19941
21643
  description: "Stage an update to a published scheduled action or temp_sched_* draft-created scheduled action.",
@@ -19960,7 +21662,7 @@ registerSchema({
19960
21662
  prompt: { type: "string", description: "Replacement additional spawned-agent instructions", required: false }
19961
21663
  }
19962
21664
  });
19963
- var updateCommand2 = defineCommand140({
21665
+ var updateCommand2 = defineCommand142({
19964
21666
  meta: {
19965
21667
  name: "update",
19966
21668
  description: "Stage a scheduled action update. Example: baker scheduled-actions update <id> --enabled false"
@@ -20031,7 +21733,7 @@ var updateCommand2 = defineCommand140({
20031
21733
  });
20032
21734
 
20033
21735
  // src/commands/scheduled-actions/index.ts
20034
- var scheduledActionsCommand = defineCommand141({
21736
+ var scheduledActionsCommand = defineCommand143({
20035
21737
  meta: {
20036
21738
  name: "scheduled-actions",
20037
21739
  description: `Manage Scheduled Actions. Subcommands: list, get, create, update, delete, trigger.
@@ -20057,8 +21759,8 @@ Examples:
20057
21759
  });
20058
21760
 
20059
21761
  // src/commands/schema.ts
20060
- import { defineCommand as defineCommand142 } from "citty";
20061
- var schemaCommand = defineCommand142({
21762
+ import { defineCommand as defineCommand144 } from "citty";
21763
+ var schemaCommand = defineCommand144({
20062
21764
  meta: {
20063
21765
  name: "schema",
20064
21766
  description: "Inspect command argument schemas (for AI agent introspection). Lists all commands if no argument given. Example: baker schema images.search"
@@ -20094,10 +21796,10 @@ var schemaCommand = defineCommand142({
20094
21796
  });
20095
21797
 
20096
21798
  // src/commands/testimonials/index.ts
20097
- import { defineCommand as defineCommand146 } from "citty";
21799
+ import { defineCommand as defineCommand148 } from "citty";
20098
21800
 
20099
21801
  // src/commands/testimonials/get.ts
20100
- import { defineCommand as defineCommand143 } from "citty";
21802
+ import { defineCommand as defineCommand145 } from "citty";
20101
21803
  registerSchema({
20102
21804
  command: "testimonials.get",
20103
21805
  description: "Get a single testimonial by ID",
@@ -20105,7 +21807,7 @@ registerSchema({
20105
21807
  id: { type: "string", description: "Testimonial ID", required: true }
20106
21808
  }
20107
21809
  });
20108
- var getCommand4 = defineCommand143({
21810
+ var getCommand4 = defineCommand145({
20109
21811
  meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
20110
21812
  args: {
20111
21813
  id: { type: "positional", description: "Testimonial ID", required: false },
@@ -20142,7 +21844,7 @@ var getCommand4 = defineCommand143({
20142
21844
  });
20143
21845
 
20144
21846
  // src/commands/testimonials/list.ts
20145
- import { defineCommand as defineCommand144 } from "citty";
21847
+ import { defineCommand as defineCommand146 } from "citty";
20146
21848
  registerSchema({
20147
21849
  command: "testimonials.list",
20148
21850
  description: "List testimonials with optional filters.",
@@ -20172,7 +21874,7 @@ registerSchema({
20172
21874
  limit: { type: "number", description: "Max results (default 50)", required: false, default: 50 }
20173
21875
  }
20174
21876
  });
20175
- var listCommand6 = defineCommand144({
21877
+ var listCommand6 = defineCommand146({
20176
21878
  meta: {
20177
21879
  name: "list",
20178
21880
  description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
@@ -20221,7 +21923,7 @@ var listCommand6 = defineCommand144({
20221
21923
  });
20222
21924
 
20223
21925
  // src/commands/testimonials/search.ts
20224
- import { defineCommand as defineCommand145 } from "citty";
21926
+ import { defineCommand as defineCommand147 } from "citty";
20225
21927
  registerSchema({
20226
21928
  command: "testimonials.search",
20227
21929
  description: "Search testimonials by text query. Uses hybrid BM25 + vector + reranking.",
@@ -20252,7 +21954,7 @@ registerSchema({
20252
21954
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
20253
21955
  }
20254
21956
  });
20255
- var searchCommand2 = defineCommand145({
21957
+ var searchCommand2 = defineCommand147({
20256
21958
  meta: {
20257
21959
  name: "search",
20258
21960
  description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
@@ -20326,7 +22028,7 @@ var searchCommand2 = defineCommand145({
20326
22028
  var tagsCommand3 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
20327
22029
 
20328
22030
  // src/commands/testimonials/index.ts
20329
- var testimonialsCommand = defineCommand146({
22031
+ var testimonialsCommand = defineCommand148({
20330
22032
  meta: {
20331
22033
  name: "testimonials",
20332
22034
  description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
@@ -20347,10 +22049,10 @@ Examples:
20347
22049
  });
20348
22050
 
20349
22051
  // src/commands/videos/index.ts
20350
- import { defineCommand as defineCommand151 } from "citty";
22052
+ import { defineCommand as defineCommand153 } from "citty";
20351
22053
 
20352
22054
  // src/commands/videos/delete.ts
20353
- import { defineCommand as defineCommand147 } from "citty";
22055
+ import { defineCommand as defineCommand149 } from "citty";
20354
22056
  registerSchema({
20355
22057
  command: "videos.delete",
20356
22058
  description: "Delete a video by ID",
@@ -20364,7 +22066,7 @@ registerSchema({
20364
22066
  }
20365
22067
  }
20366
22068
  });
20367
- var deleteCommand3 = defineCommand147({
22069
+ var deleteCommand3 = defineCommand149({
20368
22070
  meta: {
20369
22071
  name: "delete",
20370
22072
  description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
@@ -20405,7 +22107,7 @@ var deleteCommand3 = defineCommand147({
20405
22107
  });
20406
22108
 
20407
22109
  // src/commands/videos/get.ts
20408
- import { defineCommand as defineCommand148 } from "citty";
22110
+ import { defineCommand as defineCommand150 } from "citty";
20409
22111
  registerSchema({
20410
22112
  command: "videos.get",
20411
22113
  description: "Get a single video by ID",
@@ -20413,7 +22115,7 @@ registerSchema({
20413
22115
  id: { type: "string", description: "Video ID", required: true }
20414
22116
  }
20415
22117
  });
20416
- var getCommand5 = defineCommand148({
22118
+ var getCommand5 = defineCommand150({
20417
22119
  meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
20418
22120
  args: {
20419
22121
  id: { type: "positional", description: "Video ID", required: false },
@@ -20450,7 +22152,7 @@ var getCommand5 = defineCommand148({
20450
22152
  });
20451
22153
 
20452
22154
  // src/commands/videos/search.ts
20453
- import { defineCommand as defineCommand149 } from "citty";
22155
+ import { defineCommand as defineCommand151 } from "citty";
20454
22156
  registerSchema({
20455
22157
  command: "videos.search",
20456
22158
  description: "Search videos by text query. Only returns ready videos.",
@@ -20460,7 +22162,7 @@ registerSchema({
20460
22162
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
20461
22163
  }
20462
22164
  });
20463
- var searchCommand3 = defineCommand149({
22165
+ var searchCommand3 = defineCommand151({
20464
22166
  meta: {
20465
22167
  name: "search",
20466
22168
  description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
@@ -20512,7 +22214,7 @@ var tagsCommand4 = makeTagsCommand("videos", "video", "/api/videos/tags");
20512
22214
  // src/commands/videos/upload.ts
20513
22215
  import { readFile as readFile12, stat as stat3 } from "fs/promises";
20514
22216
  import { extname as extname3 } from "path";
20515
- import { defineCommand as defineCommand150 } from "citty";
22217
+ import { defineCommand as defineCommand152 } from "citty";
20516
22218
  var MIME_MAP = {
20517
22219
  ".mp4": "video/mp4",
20518
22220
  ".mov": "video/quicktime",
@@ -20546,7 +22248,7 @@ function detectContentType(filePath) {
20546
22248
  }
20547
22249
  return mime;
20548
22250
  }
20549
- var uploadCommand2 = defineCommand150({
22251
+ var uploadCommand2 = defineCommand152({
20550
22252
  meta: {
20551
22253
  name: "upload",
20552
22254
  description: "Upload a video file to Baker via Mux direct upload. Auto-detects content type. Example: baker videos upload ./demo.mp4"
@@ -20600,7 +22302,7 @@ var uploadCommand2 = defineCommand150({
20600
22302
  });
20601
22303
 
20602
22304
  // src/commands/videos/index.ts
20603
- var videosCommand = defineCommand151({
22305
+ var videosCommand = defineCommand153({
20604
22306
  meta: {
20605
22307
  name: "videos",
20606
22308
  description: `Find and manage videos in Baker. Subcommands: search, get, upload, delete, tags.
@@ -20623,10 +22325,10 @@ Examples:
20623
22325
  });
20624
22326
 
20625
22327
  // src/commands/winning-ads/index.ts
20626
- import { defineCommand as defineCommand154 } from "citty";
22328
+ import { defineCommand as defineCommand156 } from "citty";
20627
22329
 
20628
22330
  // src/commands/winning-ads/advertisers.ts
20629
- import { defineCommand as defineCommand152 } from "citty";
22331
+ import { defineCommand as defineCommand154 } from "citty";
20630
22332
  registerSchema({
20631
22333
  command: "winning-ads.advertisers",
20632
22334
  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).",
@@ -20639,7 +22341,7 @@ registerSchema({
20639
22341
  function identity(record) {
20640
22342
  return record;
20641
22343
  }
20642
- var advertisersCommand2 = defineCommand152({
22344
+ var advertisersCommand2 = defineCommand154({
20643
22345
  meta: {
20644
22346
  name: "advertisers",
20645
22347
  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'
@@ -20690,7 +22392,7 @@ var advertisersCommand2 = defineCommand152({
20690
22392
  });
20691
22393
 
20692
22394
  // src/commands/winning-ads/search.ts
20693
- import { defineCommand as defineCommand153 } from "citty";
22395
+ import { defineCommand as defineCommand155 } from "citty";
20694
22396
  registerSchema({
20695
22397
  command: "winning-ads.search",
20696
22398
  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.",
@@ -20798,7 +22500,7 @@ function buildSearchBody(args) {
20798
22500
  }
20799
22501
  return body;
20800
22502
  }
20801
- var searchCommand4 = defineCommand153({
22503
+ var searchCommand4 = defineCommand155({
20802
22504
  meta: {
20803
22505
  name: "search",
20804
22506
  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"
@@ -20910,7 +22612,7 @@ var searchCommand4 = defineCommand153({
20910
22612
  });
20911
22613
 
20912
22614
  // src/commands/winning-ads/index.ts
20913
- var winningAdsCommand = defineCommand154({
22615
+ var winningAdsCommand = defineCommand156({
20914
22616
  meta: {
20915
22617
  name: "winning-ads",
20916
22618
  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.
@@ -20934,7 +22636,7 @@ Examples:
20934
22636
  });
20935
22637
 
20936
22638
  // src/version.ts
20937
- import { readFileSync as readFileSync10 } from "fs";
22639
+ import { readFileSync as readFileSync11 } from "fs";
20938
22640
  function packageJsonUrl() {
20939
22641
  return new URL("../package.json", import.meta.url);
20940
22642
  }
@@ -20946,11 +22648,11 @@ function parsePackageVersion(raw) {
20946
22648
  throw new Error("Invalid CLI package.json: missing version");
20947
22649
  }
20948
22650
  function getCliVersion() {
20949
- return parsePackageVersion(readFileSync10(packageJsonUrl(), "utf8"));
22651
+ return parsePackageVersion(readFileSync11(packageJsonUrl(), "utf8"));
20950
22652
  }
20951
22653
 
20952
22654
  // src/cli.ts
20953
- var main = defineCommand155({
22655
+ var main = defineCommand157({
20954
22656
  meta: {
20955
22657
  name: "baker",
20956
22658
  version: getCliVersion(),
@@ -20965,7 +22667,7 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
20965
22667
  subCommands: {
20966
22668
  actions: actionsCommand,
20967
22669
  "scheduled-actions": scheduledActionsCommand,
20968
- ads: adsCommand,
22670
+ ads: adsCommand2,
20969
22671
  ga4: ga4Command,
20970
22672
  gsc: gscCommand,
20971
22673
  research: researchCommand,