@koda-sl/baker-cli 0.112.1 → 0.113.0-dev.78e242dda

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -9,10 +9,10 @@ import {
9
9
  defaultRegistry,
10
10
  generateCatalog,
11
11
  validateCanvasDeep
12
- } from "./chunk-3JVYU72O.js";
12
+ } from "./chunk-26K7V346.js";
13
13
 
14
14
  // src/cli.ts
15
- import { defineCommand as defineCommand155, runMain } from "citty";
15
+ import { defineCommand as defineCommand157, runMain } from "citty";
16
16
 
17
17
  // src/commands/actions/index.ts
18
18
  import { defineCommand as defineCommand18 } from "citty";
@@ -2844,10 +2844,10 @@ Examples:
2844
2844
  });
2845
2845
 
2846
2846
  // src/commands/ads/index.ts
2847
- import { defineCommand as defineCommand80 } from "citty";
2847
+ import { defineCommand as defineCommand82 } from "citty";
2848
2848
 
2849
2849
  // src/commands/ads/google/index.ts
2850
- import { defineCommand as defineCommand29 } from "citty";
2850
+ import { defineCommand as defineCommand31 } from "citty";
2851
2851
 
2852
2852
  // src/commands/ads/google/accounts.ts
2853
2853
  import { defineCommand as defineCommand19 } from "citty";
@@ -3265,6 +3265,28 @@ function buildCommand(query, ctx) {
3265
3265
  return `baker ads google query "${query}" --customer-id ${ctx.customerId}`;
3266
3266
  }
3267
3267
  var CORRECTION_RULES = [
3268
+ // 0. EXPECTED_REFERENCED_FIELD_IN_SELECT_CLAUSE — some resources (e.g. campaign_budget)
3269
+ // require fields filtered in WHERE to also be selected. The error names the exact field,
3270
+ // so add it to SELECT and retry. Kept first: field-specific rules below must not shadow
3271
+ // this with an unrelated rewrite when the named field happens to match their pattern.
3272
+ {
3273
+ matchApiError: /must be present in SELECT clause:\s*'([\w.]+)'/i,
3274
+ fix: (ctx) => {
3275
+ const field = ctx.apiErrorMessage?.match(/must be present in SELECT clause:\s*'([\w.]+)'/i)?.[1];
3276
+ if (!field) {
3277
+ return {
3278
+ action: "add_required_field",
3279
+ explanation: "Add the field named in the error to the SELECT clause and retry"
3280
+ };
3281
+ }
3282
+ const corrected = ctx.originalQuery.replace(/SELECT\s+/i, `SELECT ${field}, `);
3283
+ return {
3284
+ action: "add_required_field",
3285
+ correctedCommand: buildCommand(corrected, ctx),
3286
+ explanation: `${field} is used in WHERE but this resource requires it in SELECT too \u2014 added it`
3287
+ };
3288
+ }
3289
+ },
3268
3290
  // 1. bare keyword.text → ad_group_criterion.keyword.text (leaves <resource>.keyword.text untouched)
3269
3291
  {
3270
3292
  matchQuery: /(?<![\w.])keyword\.text\b/,
@@ -3500,6 +3522,20 @@ var CORRECTION_RULES = [
3500
3522
  };
3501
3523
  }
3502
3524
  },
3525
+ // 15b. asset.<type>_asset.final_urls → asset.final_urls (final URLs live on the asset
3526
+ // itself; the typed sub-message only carries type-specific fields like link_text)
3527
+ {
3528
+ matchQuery: /asset\.\w+_asset\.final_(mobile_)?urls\b/,
3529
+ matchApiError: /asset\.\w+_asset\.final_(mobile_)?urls/i,
3530
+ fix: (ctx) => {
3531
+ const corrected = ctx.originalQuery.replace(/asset\.\w+_asset\.final_(mobile_)?urls\b/g, "asset.final_$1urls");
3532
+ return {
3533
+ action: "retry_with_modified_query",
3534
+ correctedCommand: buildCommand(corrected, ctx),
3535
+ explanation: "Final URLs are on the asset itself \u2014 use asset.final_urls, not asset.<type>_asset.final_urls"
3536
+ };
3537
+ }
3538
+ },
3503
3539
  // 16. Rate limit / quota
3504
3540
  {
3505
3541
  matchApiError: /RESOURCE_EXHAUSTED|quota.*exceeded|rate.*limit/i,
@@ -3627,6 +3663,7 @@ var CORRECTION_RULES = [
3627
3663
 
3628
3664
  // src/commands/ads/google/error-parser.ts
3629
3665
  function mapErrorCode(message) {
3666
+ if (/must be present in SELECT clause/i.test(message)) return "MISSING_SELECT_FIELD";
3630
3667
  if (/field.*not.*found|unrecognized.*field|not.*valid.*field/i.test(message)) return "FIELD_NOT_FOUND";
3631
3668
  if (/not.*valid.*resource|cannot.*select.*from/i.test(message)) return "WRONG_RESOURCE";
3632
3669
  if (/operator|CONTAINS|LIKE/i.test(message)) return "INVALID_OPERATOR";
@@ -3832,11 +3869,972 @@ Examples:
3832
3869
  }
3833
3870
  });
3834
3871
 
3872
+ // src/commands/ads/google/draft.ts
3873
+ import { defineCommand as defineCommand22 } from "citty";
3874
+
3875
+ // src/commands/ads/google/write-shared.ts
3876
+ import { readFileSync as readFileSync3 } from "fs";
3877
+
3878
+ // ../api/src/ads-google/limits.ts
3879
+ var GOOGLE_ADS_LIMITS = {
3880
+ budget: {
3881
+ nameMax: 255,
3882
+ amountMicrosMin: 1
3883
+ },
3884
+ campaign: {
3885
+ nameMax: 255
3886
+ },
3887
+ adGroup: {
3888
+ nameMax: 255
3889
+ },
3890
+ keyword: {
3891
+ textMax: 80,
3892
+ wordsMax: 10
3893
+ },
3894
+ responsiveSearchAd: {
3895
+ headlinesMin: 3,
3896
+ headlinesMax: 15,
3897
+ headlineTextMax: 30,
3898
+ descriptionsMin: 2,
3899
+ descriptionsMax: 4,
3900
+ descriptionTextMax: 90,
3901
+ pathMax: 15
3902
+ },
3903
+ responsiveDisplayAd: {
3904
+ headlinesMin: 1,
3905
+ headlinesMax: 5,
3906
+ headlineTextMax: 30,
3907
+ longHeadlineTextMax: 90,
3908
+ descriptionsMin: 1,
3909
+ descriptionsMax: 5,
3910
+ descriptionTextMax: 90,
3911
+ businessNameMax: 25
3912
+ },
3913
+ sharedSet: {
3914
+ nameMax: 255
3915
+ },
3916
+ asset: {
3917
+ sitelinkLinkTextMax: 25,
3918
+ sitelinkDescriptionMax: 35,
3919
+ calloutTextMax: 25,
3920
+ structuredSnippetHeaderMax: 25,
3921
+ structuredSnippetValuesMin: 3,
3922
+ structuredSnippetValuesMax: 10
3923
+ },
3924
+ conversionAction: {
3925
+ nameMax: 255
3926
+ },
3927
+ audience: {
3928
+ nameMax: 255
3929
+ },
3930
+ biddingStrategy: {
3931
+ nameMax: 255
3932
+ },
3933
+ label: {
3934
+ nameMax: 255
3935
+ }
3936
+ };
3937
+ var KEYWORD_MATCH_TYPES = ["EXACT", "PHRASE", "BROAD"];
3938
+ var ADVERTISING_CHANNEL_TYPES = [
3939
+ "SEARCH",
3940
+ "DISPLAY",
3941
+ "SHOPPING",
3942
+ "VIDEO",
3943
+ "PERFORMANCE_MAX",
3944
+ "DEMAND_GEN",
3945
+ "MULTI_CHANNEL",
3946
+ "LOCAL",
3947
+ "SMART",
3948
+ "TRAVEL",
3949
+ "HOTEL",
3950
+ "DISCOVERY"
3951
+ ];
3952
+ var ADVERTISING_CHANNEL_SUB_TYPES = [
3953
+ "SEARCH_MOBILE_APP",
3954
+ "DISPLAY_MOBILE_APP",
3955
+ "SEARCH_EXPRESS",
3956
+ "DISPLAY_EXPRESS",
3957
+ "SHOPPING_SMART_ADS",
3958
+ "DISPLAY_GMAIL_AD",
3959
+ "DISPLAY_SMART_CAMPAIGN",
3960
+ "VIDEO_OUTSTREAM",
3961
+ "VIDEO_ACTION",
3962
+ "VIDEO_NON_SKIPPABLE",
3963
+ "APP_CAMPAIGN",
3964
+ "APP_CAMPAIGN_FOR_ENGAGEMENT",
3965
+ "LOCAL_CAMPAIGN",
3966
+ "SHOPPING_COMPARISON_LISTING_ADS",
3967
+ "SEARCH_MOBILE_APP_ENGAGEMENT",
3968
+ "TRAVEL_ACTIVITIES"
3969
+ ];
3970
+ var BIDDING_STRATEGY_TYPES = [
3971
+ "MANUAL_CPC",
3972
+ "MAXIMIZE_CONVERSIONS",
3973
+ "MAXIMIZE_CONVERSION_VALUE",
3974
+ "TARGET_SPEND",
3975
+ "TARGET_CPA",
3976
+ "TARGET_ROAS",
3977
+ "TARGET_IMPRESSION_SHARE",
3978
+ "MANUAL_CPM",
3979
+ "MANUAL_CPV",
3980
+ "PERCENT_CPC"
3981
+ ];
3982
+ var BUDGET_DELIVERY_METHODS = ["STANDARD", "ACCELERATED"];
3983
+ var AD_GROUP_TYPES = [
3984
+ "SEARCH_STANDARD",
3985
+ "DISPLAY_STANDARD",
3986
+ "SHOPPING_PRODUCT_ADS",
3987
+ "VIDEO_BUMPER",
3988
+ "VIDEO_TRUE_VIEW_IN_STREAM",
3989
+ "VIDEO_TRUE_VIEW_IN_DISPLAY",
3990
+ "VIDEO_NON_SKIPPABLE_IN_STREAM",
3991
+ "VIDEO_OUTSTREAM",
3992
+ "DEMAND_GEN_AD"
3993
+ ];
3994
+ var SHARED_SET_TYPES = [
3995
+ "NEGATIVE_KEYWORDS",
3996
+ "NEGATIVE_PLACEMENTS",
3997
+ "ACCOUNT_LEVEL_NEGATIVE_KEYWORDS"
3998
+ ];
3999
+ var STAGEABLE_CREATE_STATUSES2 = ["ENABLED", "PAUSED"];
4000
+ var PINNED_FIELDS = ["HEADLINE_1", "HEADLINE_2", "HEADLINE_3", "DESCRIPTION_1", "DESCRIPTION_2"];
4001
+ var CONVERSION_ACTION_CATEGORIES = [
4002
+ "DEFAULT",
4003
+ "PAGE_VIEW",
4004
+ "PURCHASE",
4005
+ "SIGNUP",
4006
+ "LEAD",
4007
+ "DOWNLOAD",
4008
+ "ADD_TO_CART",
4009
+ "BEGIN_CHECKOUT",
4010
+ "SUBSCRIBE_PAID",
4011
+ "PHONE_CALL_LEAD",
4012
+ "SUBMIT_LEAD_FORM",
4013
+ "BOOK_APPOINTMENT",
4014
+ "REQUEST_QUOTE",
4015
+ "CONTACT"
4016
+ ];
4017
+ var CONVERSION_ACTION_TYPES = [
4018
+ "WEBPAGE",
4019
+ "UPLOAD_CLICKS",
4020
+ "UPLOAD_CALLS",
4021
+ "WEBSITE_CALL",
4022
+ "GOOGLE_ANALYTICS_4_CUSTOM"
4023
+ ];
4024
+ var CONVERSION_COUNTING_TYPES = ["ONE_PER_CLICK", "MANY_PER_CLICK"];
4025
+ var USER_LIST_TYPES = ["CRM_BASED", "RULE_BASED", "LOGICAL", "BASIC", "LOOKALIKE"];
4026
+ var ASSET_FIELD_TYPES = [
4027
+ "SITELINK",
4028
+ "CALLOUT",
4029
+ "STRUCTURED_SNIPPET",
4030
+ "CALL",
4031
+ "PRICE",
4032
+ "PROMOTION",
4033
+ "MOBILE_APP",
4034
+ "HEADLINE",
4035
+ "DESCRIPTION",
4036
+ "LOGO",
4037
+ "MARKETING_IMAGE",
4038
+ "BUSINESS_NAME"
4039
+ ];
4040
+ var DEVICE_TYPES = ["MOBILE", "TABLET", "DESKTOP", "CONNECTED_TV", "OTHER"];
4041
+ var DAYS_OF_WEEK = ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"];
4042
+ var CAMPAIGN_OBJECTIVES = [
4043
+ "SALES",
4044
+ "LEADS",
4045
+ "WEBSITE_TRAFFIC",
4046
+ "PRODUCT_BRAND_CONSIDERATION",
4047
+ "BRAND_AWARENESS_REACH",
4048
+ "APP_PROMOTION",
4049
+ "LOCAL_STORE_VISITS"
4050
+ ];
4051
+ var MICROS_PER_UNIT = 1e6;
4052
+ function toMicros(amount) {
4053
+ return Math.round(amount * MICROS_PER_UNIT);
4054
+ }
4055
+ var PLAYBOOK_DAILY_BUDGET_FLOOR_MICROS = 10 * MICROS_PER_UNIT;
4056
+ var TEMP_REF_REGEX2 = /^g_temp_[A-Za-z0-9_-]{2,}$/;
4057
+ var NUMERIC_ID_REGEX2 = /^\d+$/;
4058
+ var RESOURCE_NAME_REGEX = /^customers\/\d+\/[A-Za-z]+\/[-\w~]+$/;
4059
+ var GEO_TARGET_CONSTANT_REGEX = /^geoTargetConstants\/\d+$/;
4060
+ var LANGUAGE_CONSTANT_REGEX = /^languageConstants\/\d+$/;
4061
+
4062
+ // ../api/src/ads-google/ops.ts
4063
+ import { z as z8 } from "zod";
4064
+ var tempRefSchema2 = z8.string().regex(TEMP_REF_REGEX2, "expected a g_temp_* reference");
4065
+ var refSchema = z8.union([
4066
+ z8.string().regex(RESOURCE_NAME_REGEX, "expected a customers/\u2026/\u2026/\u2026 resource name"),
4067
+ z8.string().regex(NUMERIC_ID_REGEX2, "expected a numeric id"),
4068
+ tempRefSchema2
4069
+ ]);
4070
+ var targetRefSchema = refSchema;
4071
+ var microsSchema = z8.number().int().positive("expected a positive micros amount");
4072
+ var httpsUrlSchema2 = z8.string().url().refine((u) => u.startsWith("https://"), "final URLs must be https");
4073
+ var customerIdSchema = z8.string().regex(NUMERIC_ID_REGEX2, "customerId must be the bare numeric customer id");
4074
+ var stageableStatusSchema2 = z8.enum(STAGEABLE_CREATE_STATUSES2);
4075
+ var matchTypeSchema = z8.enum(KEYWORD_MATCH_TYPES);
4076
+ 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");
4077
+ var budgetCreateSchema = z8.object({
4078
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.budget.nameMax),
4079
+ amountMicros: microsSchema,
4080
+ deliveryMethod: z8.enum(BUDGET_DELIVERY_METHODS).default("STANDARD"),
4081
+ explicitlyShared: z8.boolean().default(false)
4082
+ });
4083
+ var budgetUpdateSchema = z8.object({
4084
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.budget.nameMax).optional(),
4085
+ amountMicros: microsSchema.optional(),
4086
+ deliveryMethod: z8.enum(BUDGET_DELIVERY_METHODS).optional()
4087
+ }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4088
+ var biddingConfigSchema = z8.object({
4089
+ type: z8.enum(BIDDING_STRATEGY_TYPES),
4090
+ targetCpaMicros: microsSchema.optional(),
4091
+ targetRoas: z8.number().positive().optional(),
4092
+ cpcBidCeilingMicros: microsSchema.optional(),
4093
+ enhancedCpcEnabled: z8.boolean().optional()
4094
+ }).superRefine((p, ctx) => {
4095
+ if (p.type === "TARGET_CPA" && p.targetCpaMicros === void 0) {
4096
+ ctx.addIssue({ code: "custom", path: ["targetCpaMicros"], message: "TARGET_CPA needs targetCpaMicros" });
4097
+ }
4098
+ if (p.type === "TARGET_ROAS" && p.targetRoas === void 0) {
4099
+ ctx.addIssue({ code: "custom", path: ["targetRoas"], message: "TARGET_ROAS needs targetRoas" });
4100
+ }
4101
+ });
4102
+ var networkSettingsSchema = z8.object({
4103
+ targetGoogleSearch: z8.boolean().optional(),
4104
+ targetSearchNetwork: z8.boolean().optional(),
4105
+ targetContentNetwork: z8.boolean().optional(),
4106
+ targetPartnerSearchNetwork: z8.boolean().optional()
4107
+ });
4108
+ var dateSchema = z8.string().regex(/^\d{4}-\d{2}-\d{2}$/, "expected a YYYY-MM-DD date");
4109
+ var campaignCreateSchema2 = z8.object({
4110
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.campaign.nameMax),
4111
+ channelType: z8.enum(ADVERTISING_CHANNEL_TYPES),
4112
+ channelSubType: z8.enum(ADVERTISING_CHANNEL_SUB_TYPES).optional(),
4113
+ budget: refSchema,
4114
+ /** Inline standard bidding, or a portfolio strategy ref via biddingStrategy. */
4115
+ bidding: biddingConfigSchema.optional(),
4116
+ biddingStrategy: refSchema.optional(),
4117
+ networkSettings: networkSettingsSchema.optional(),
4118
+ startDate: dateSchema.optional(),
4119
+ endDate: dateSchema.optional(),
4120
+ /** Advisory Google Ads UI objective — drives warnings, not sent to the API. */
4121
+ objective: z8.enum(CAMPAIGN_OBJECTIVES).optional(),
4122
+ status: stageableStatusSchema2.default("PAUSED")
4123
+ }).superRefine((p, ctx) => {
4124
+ if (!p.bidding && !p.biddingStrategy) {
4125
+ ctx.addIssue({
4126
+ code: "custom",
4127
+ path: ["bidding"],
4128
+ message: "set an inline bidding strategy or reference a portfolio biddingStrategy"
4129
+ });
4130
+ }
4131
+ if (p.bidding && p.biddingStrategy) {
4132
+ ctx.addIssue({
4133
+ code: "custom",
4134
+ path: ["bidding"],
4135
+ message: "use inline bidding OR a portfolio biddingStrategy, not both"
4136
+ });
4137
+ }
4138
+ if (p.channelType === "PERFORMANCE_MAX" && p.bidding && p.bidding.type === "MANUAL_CPC") {
4139
+ ctx.addIssue({ code: "custom", path: ["bidding"], message: "Performance Max does not support Manual CPC" });
4140
+ }
4141
+ if (p.startDate && p.endDate && p.endDate <= p.startDate) {
4142
+ ctx.addIssue({ code: "custom", path: ["endDate"], message: "endDate must be after startDate" });
4143
+ }
4144
+ });
4145
+ var campaignUpdateSchema2 = z8.object({
4146
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.campaign.nameMax).optional(),
4147
+ budget: refSchema.optional(),
4148
+ bidding: biddingConfigSchema.optional(),
4149
+ networkSettings: networkSettingsSchema.optional(),
4150
+ startDate: dateSchema.optional(),
4151
+ endDate: dateSchema.optional(),
4152
+ status: z8.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
4153
+ }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4154
+ var adGroupCreateSchema = z8.object({
4155
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.adGroup.nameMax),
4156
+ campaign: refSchema,
4157
+ type: z8.enum(AD_GROUP_TYPES).default("SEARCH_STANDARD"),
4158
+ cpcBidMicros: microsSchema.optional(),
4159
+ status: stageableStatusSchema2.default("PAUSED")
4160
+ });
4161
+ var adGroupUpdateSchema = z8.object({
4162
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.adGroup.nameMax).optional(),
4163
+ cpcBidMicros: microsSchema.optional(),
4164
+ status: z8.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
4165
+ }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4166
+ var keywordAddSchema = z8.object({
4167
+ adGroup: refSchema,
4168
+ text: keywordTextSchema,
4169
+ matchType: matchTypeSchema,
4170
+ cpcBidMicros: microsSchema.optional(),
4171
+ finalUrls: z8.array(httpsUrlSchema2).optional(),
4172
+ status: stageableStatusSchema2.default("ENABLED")
4173
+ });
4174
+ var keywordUpdateSchema = z8.object({
4175
+ cpcBidMicros: microsSchema.optional(),
4176
+ finalUrls: z8.array(httpsUrlSchema2).optional(),
4177
+ status: z8.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
4178
+ }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4179
+ var negativeKeywordAddSchema = z8.object({
4180
+ level: z8.enum(["adGroup", "campaign"]),
4181
+ parent: refSchema,
4182
+ text: keywordTextSchema,
4183
+ matchType: matchTypeSchema
4184
+ });
4185
+ var sharedSetCreateSchema = z8.object({
4186
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.sharedSet.nameMax),
4187
+ type: z8.enum(SHARED_SET_TYPES).default("NEGATIVE_KEYWORDS")
4188
+ });
4189
+ var sharedSetMemberAddSchema = z8.object({
4190
+ sharedSet: refSchema,
4191
+ text: keywordTextSchema,
4192
+ matchType: matchTypeSchema
4193
+ });
4194
+ var campaignSharedSetAttachSchema = z8.object({
4195
+ campaign: refSchema,
4196
+ sharedSet: refSchema
4197
+ });
4198
+ var adTextAssetSchema = z8.object({
4199
+ text: z8.string().min(1),
4200
+ pinnedField: z8.enum(PINNED_FIELDS).optional()
4201
+ });
4202
+ var responsiveSearchAdSchema = z8.object({
4203
+ format: z8.literal("responsiveSearch"),
4204
+ headlines: z8.array(
4205
+ adTextAssetSchema.refine(
4206
+ (a) => a.text.length <= GOOGLE_ADS_LIMITS.responsiveSearchAd.headlineTextMax,
4207
+ "headline exceeds 30 chars"
4208
+ )
4209
+ ).min(GOOGLE_ADS_LIMITS.responsiveSearchAd.headlinesMin).max(GOOGLE_ADS_LIMITS.responsiveSearchAd.headlinesMax),
4210
+ descriptions: z8.array(
4211
+ adTextAssetSchema.refine(
4212
+ (a) => a.text.length <= GOOGLE_ADS_LIMITS.responsiveSearchAd.descriptionTextMax,
4213
+ "description exceeds 90 chars"
4214
+ )
4215
+ ).min(GOOGLE_ADS_LIMITS.responsiveSearchAd.descriptionsMin).max(GOOGLE_ADS_LIMITS.responsiveSearchAd.descriptionsMax),
4216
+ path1: z8.string().max(GOOGLE_ADS_LIMITS.responsiveSearchAd.pathMax).optional(),
4217
+ path2: z8.string().max(GOOGLE_ADS_LIMITS.responsiveSearchAd.pathMax).optional(),
4218
+ finalUrls: z8.array(httpsUrlSchema2).min(1)
4219
+ });
4220
+ var responsiveDisplayAdSchema = z8.object({
4221
+ format: z8.literal("responsiveDisplay"),
4222
+ headlines: z8.array(z8.object({ text: z8.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.headlineTextMax) })).min(1).max(5),
4223
+ longHeadline: z8.object({ text: z8.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.longHeadlineTextMax) }),
4224
+ descriptions: z8.array(z8.object({ text: z8.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.descriptionTextMax) })).min(1).max(5),
4225
+ businessName: z8.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.businessNameMax),
4226
+ marketingImageAssets: z8.array(refSchema).optional(),
4227
+ logoImageAssets: z8.array(refSchema).optional(),
4228
+ finalUrls: z8.array(httpsUrlSchema2).min(1)
4229
+ });
4230
+ var performanceMaxAssetGroupSchema = z8.object({
4231
+ format: z8.literal("performanceMaxAssetGroup"),
4232
+ name: z8.string().min(1).max(255),
4233
+ headlines: z8.array(z8.object({ text: z8.string().min(1).max(30) })).min(3).max(15),
4234
+ descriptions: z8.array(z8.object({ text: z8.string().min(1).max(90) })).min(2).max(5),
4235
+ finalUrls: z8.array(httpsUrlSchema2).min(1),
4236
+ imageAssets: z8.array(refSchema).optional(),
4237
+ logoAssets: z8.array(refSchema).optional()
4238
+ });
4239
+ var callAdSchema = z8.object({
4240
+ format: z8.literal("call"),
4241
+ countryCode: z8.string().length(2),
4242
+ phoneNumber: z8.string().min(3),
4243
+ headline1: z8.string().min(1).max(30),
4244
+ headline2: z8.string().min(1).max(30),
4245
+ description1: z8.string().min(1).max(90),
4246
+ description2: z8.string().min(1).max(90),
4247
+ businessName: z8.string().min(1).max(25),
4248
+ finalUrls: z8.array(httpsUrlSchema2).min(1)
4249
+ });
4250
+ var appAdSchema = z8.object({
4251
+ format: z8.literal("app"),
4252
+ headlines: z8.array(z8.object({ text: z8.string().min(1).max(30) })).min(1),
4253
+ descriptions: z8.array(z8.object({ text: z8.string().min(1).max(90) })).min(1)
4254
+ });
4255
+ var videoAdSchema = z8.object({
4256
+ format: z8.literal("video"),
4257
+ youtubeVideoId: z8.string().min(1),
4258
+ finalUrls: z8.array(httpsUrlSchema2).min(1)
4259
+ });
4260
+ var demandGenAdSchema = z8.object({
4261
+ format: z8.literal("demandGen"),
4262
+ headlines: z8.array(z8.object({ text: z8.string().min(1).max(40) })).min(1).max(5),
4263
+ descriptions: z8.array(z8.object({ text: z8.string().min(1).max(90) })).min(1).max(5),
4264
+ businessName: z8.string().min(1).max(25),
4265
+ finalUrls: z8.array(httpsUrlSchema2).min(1),
4266
+ imageAssets: z8.array(refSchema).optional()
4267
+ });
4268
+ var adContentSchema = z8.discriminatedUnion("format", [
4269
+ responsiveSearchAdSchema,
4270
+ responsiveDisplayAdSchema,
4271
+ performanceMaxAssetGroupSchema,
4272
+ callAdSchema,
4273
+ appAdSchema,
4274
+ videoAdSchema,
4275
+ demandGenAdSchema
4276
+ ]);
4277
+ var adCreateSchema = z8.object({
4278
+ adGroup: refSchema,
4279
+ status: stageableStatusSchema2.default("PAUSED"),
4280
+ content: adContentSchema
4281
+ });
4282
+ var adUpdateSchema = z8.object({
4283
+ status: z8.enum(["ENABLED", "PAUSED", "REMOVED"]).optional(),
4284
+ /** Whole-content replacement for RSA-like formats; re-validated against adContentSchema. */
4285
+ content: z8.record(z8.string(), z8.unknown()).optional()
4286
+ }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4287
+ var textAssetSchema = z8.object({ type: z8.literal("text"), text: z8.string().min(1) });
4288
+ var imageAssetSchema = z8.object({
4289
+ type: z8.literal("image"),
4290
+ imageId: z8.string().min(1),
4291
+ name: z8.string().optional()
4292
+ });
4293
+ var youtubeVideoAssetSchema = z8.object({
4294
+ type: z8.literal("youtubeVideo"),
4295
+ youtubeVideoId: z8.string().min(1),
4296
+ name: z8.string().optional()
4297
+ });
4298
+ var sitelinkAssetSchema = z8.object({
4299
+ type: z8.literal("sitelink"),
4300
+ linkText: z8.string().min(1).max(GOOGLE_ADS_LIMITS.asset.sitelinkLinkTextMax),
4301
+ description1: z8.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
4302
+ description2: z8.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
4303
+ finalUrls: z8.array(httpsUrlSchema2).min(1)
4304
+ });
4305
+ var calloutAssetSchema = z8.object({
4306
+ type: z8.literal("callout"),
4307
+ calloutText: z8.string().min(1).max(GOOGLE_ADS_LIMITS.asset.calloutTextMax)
4308
+ });
4309
+ var structuredSnippetAssetSchema = z8.object({
4310
+ type: z8.literal("structuredSnippet"),
4311
+ header: z8.string().min(1).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetHeaderMax),
4312
+ values: z8.array(z8.string().min(1)).min(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMin).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMax)
4313
+ });
4314
+ var callToActionAssetSchema = z8.object({ type: z8.literal("callToAction"), callToAction: z8.string().min(1) });
4315
+ var assetCreateSchema = z8.discriminatedUnion("type", [
4316
+ textAssetSchema,
4317
+ imageAssetSchema,
4318
+ youtubeVideoAssetSchema,
4319
+ sitelinkAssetSchema,
4320
+ calloutAssetSchema,
4321
+ structuredSnippetAssetSchema,
4322
+ callToActionAssetSchema
4323
+ ]);
4324
+ var assetLinkAttachSchema = z8.object({
4325
+ level: z8.enum(["campaign", "adGroup", "customer"]),
4326
+ parent: refSchema.optional(),
4327
+ asset: refSchema,
4328
+ fieldType: z8.enum(ASSET_FIELD_TYPES)
4329
+ }).superRefine((value, ctx) => {
4330
+ if (value.level !== "customer" && !value.parent) {
4331
+ ctx.addIssue({
4332
+ code: z8.ZodIssueCode.custom,
4333
+ path: ["parent"],
4334
+ message: `parent is required for a ${value.level}-level asset link (--parent-ref)`
4335
+ });
4336
+ }
4337
+ });
4338
+ var audienceCreateSchema2 = z8.object({
4339
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.audience.nameMax),
4340
+ type: z8.enum(USER_LIST_TYPES).default("BASIC"),
4341
+ description: z8.string().optional(),
4342
+ /** Customer-match members (crm-based) — file-first for large lists. */
4343
+ members: z8.array(z8.record(z8.string(), z8.string())).optional(),
4344
+ sourceFileRef: z8.string().optional()
4345
+ });
4346
+ var audienceCriterionAttachSchema = z8.object({
4347
+ level: z8.enum(["campaign", "adGroup"]),
4348
+ parent: refSchema,
4349
+ userList: refSchema,
4350
+ negative: z8.boolean().default(false)
4351
+ });
4352
+ var conversionActionCreateSchema = z8.object({
4353
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.conversionAction.nameMax),
4354
+ type: z8.enum(CONVERSION_ACTION_TYPES).default("WEBPAGE"),
4355
+ category: z8.enum(CONVERSION_ACTION_CATEGORIES).default("DEFAULT"),
4356
+ countingType: z8.enum(CONVERSION_COUNTING_TYPES).default("ONE_PER_CLICK"),
4357
+ defaultValueMicros: microsSchema.optional(),
4358
+ defaultCurrencyCode: z8.string().length(3).optional(),
4359
+ clickThroughLookbackWindowDays: z8.number().int().positive().optional(),
4360
+ viewThroughLookbackWindowDays: z8.number().int().positive().optional(),
4361
+ status: z8.enum(["ENABLED", "PAUSED"]).default("ENABLED")
4362
+ });
4363
+ var conversionActionUpdateSchema = z8.object({
4364
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.conversionAction.nameMax).optional(),
4365
+ category: z8.enum(CONVERSION_ACTION_CATEGORIES).optional(),
4366
+ countingType: z8.enum(CONVERSION_COUNTING_TYPES).optional(),
4367
+ defaultValueMicros: microsSchema.optional(),
4368
+ status: z8.enum(["ENABLED", "REMOVED", "HIDDEN"]).optional()
4369
+ }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4370
+ var biddingStrategyCreateSchema = z8.object({
4371
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.biddingStrategy.nameMax),
4372
+ config: biddingConfigSchema
4373
+ }).superRefine((p, ctx) => {
4374
+ if (p.config.type === "MANUAL_CPC") {
4375
+ ctx.addIssue({ code: "custom", path: ["config", "type"], message: "portfolio strategies cannot be Manual CPC" });
4376
+ }
4377
+ });
4378
+ var biddingStrategyUpdateSchema = z8.object({
4379
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.biddingStrategy.nameMax).optional(),
4380
+ config: biddingConfigSchema.optional()
4381
+ }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4382
+ var labelCreateSchema = z8.object({
4383
+ name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.label.nameMax),
4384
+ backgroundColor: z8.string().regex(/^#[0-9A-Fa-f]{6}$/).optional(),
4385
+ description: z8.string().optional()
4386
+ });
4387
+ var labelAttachSchema = z8.object({
4388
+ level: z8.enum(["campaign", "adGroup", "ad"]),
4389
+ parent: refSchema,
4390
+ label: refSchema
4391
+ });
4392
+ var locationCriterionSchema = z8.object({
4393
+ criterionType: z8.literal("location"),
4394
+ geoTargetConstant: z8.union([z8.string().regex(GEO_TARGET_CONSTANT_REGEX), z8.string().regex(NUMERIC_ID_REGEX2)])
4395
+ });
4396
+ var languageCriterionSchema = z8.object({
4397
+ criterionType: z8.literal("language"),
4398
+ languageConstant: z8.union([z8.string().regex(LANGUAGE_CONSTANT_REGEX), z8.string().regex(NUMERIC_ID_REGEX2)])
4399
+ });
4400
+ var adScheduleCriterionSchema = z8.object({
4401
+ criterionType: z8.literal("adSchedule"),
4402
+ dayOfWeek: z8.enum(DAYS_OF_WEEK),
4403
+ startHour: z8.number().int().min(0).max(23),
4404
+ startMinute: z8.enum(["ZERO", "FIFTEEN", "THIRTY", "FORTY_FIVE"]).default("ZERO"),
4405
+ endHour: z8.number().int().min(0).max(24),
4406
+ endMinute: z8.enum(["ZERO", "FIFTEEN", "THIRTY", "FORTY_FIVE"]).default("ZERO")
4407
+ });
4408
+ var deviceCriterionSchema = z8.object({
4409
+ criterionType: z8.literal("device"),
4410
+ device: z8.enum(DEVICE_TYPES),
4411
+ bidModifier: z8.number().min(0.1).max(10).optional()
4412
+ });
4413
+ var campaignCriterionAddSchema = z8.object({
4414
+ campaign: refSchema,
4415
+ negative: z8.boolean().default(false),
4416
+ criterion: z8.discriminatedUnion("criterionType", [
4417
+ locationCriterionSchema,
4418
+ languageCriterionSchema,
4419
+ adScheduleCriterionSchema,
4420
+ deviceCriterionSchema
4421
+ ])
4422
+ });
4423
+ var GOOGLE_DRAFT_OP_KINDS = [
4424
+ "google.budget.create",
4425
+ "google.budget.update",
4426
+ "google.campaign.create",
4427
+ "google.campaign.update",
4428
+ "google.campaign.pause",
4429
+ "google.campaign.resume",
4430
+ "google.campaign.remove",
4431
+ "google.adGroup.create",
4432
+ "google.adGroup.update",
4433
+ "google.adGroup.pause",
4434
+ "google.adGroup.resume",
4435
+ "google.adGroup.remove",
4436
+ "google.keyword.add",
4437
+ "google.keyword.update",
4438
+ "google.keyword.remove",
4439
+ "google.negativeKeyword.add",
4440
+ "google.negativeKeyword.remove",
4441
+ "google.sharedSet.create",
4442
+ "google.sharedSetMember.add",
4443
+ "google.sharedSetMember.remove",
4444
+ "google.campaignSharedSet.attach",
4445
+ "google.campaignSharedSet.detach",
4446
+ "google.ad.create",
4447
+ "google.ad.update",
4448
+ "google.ad.pause",
4449
+ "google.ad.resume",
4450
+ "google.ad.remove",
4451
+ "google.asset.create",
4452
+ "google.assetLink.attach",
4453
+ "google.assetLink.detach",
4454
+ "google.audience.create",
4455
+ "google.audienceCriterion.attach",
4456
+ "google.audienceCriterion.detach",
4457
+ "google.conversionAction.create",
4458
+ "google.conversionAction.update",
4459
+ "google.biddingStrategy.create",
4460
+ "google.biddingStrategy.update",
4461
+ "google.label.create",
4462
+ "google.label.attach",
4463
+ "google.campaignCriterion.add",
4464
+ "google.campaignCriterion.remove"
4465
+ ];
4466
+ var googleDraftOpKindSchema = z8.enum(GOOGLE_DRAFT_OP_KINDS);
4467
+ function createOp2(kind, payload) {
4468
+ return z8.object({ kind: z8.literal(kind), customerId: customerIdSchema, payload });
4469
+ }
4470
+ function updateOp2(kind, payload) {
4471
+ return z8.object({ kind: z8.literal(kind), customerId: customerIdSchema, target: targetRefSchema, payload });
4472
+ }
4473
+ function targetOp(kind) {
4474
+ return z8.object({ kind: z8.literal(kind), customerId: customerIdSchema, target: targetRefSchema });
4475
+ }
4476
+ var googleDraftOpInputSchema = z8.discriminatedUnion("kind", [
4477
+ createOp2("google.budget.create", budgetCreateSchema),
4478
+ updateOp2("google.budget.update", budgetUpdateSchema),
4479
+ createOp2("google.campaign.create", campaignCreateSchema2),
4480
+ updateOp2("google.campaign.update", campaignUpdateSchema2),
4481
+ targetOp("google.campaign.pause"),
4482
+ targetOp("google.campaign.resume"),
4483
+ targetOp("google.campaign.remove"),
4484
+ createOp2("google.adGroup.create", adGroupCreateSchema),
4485
+ updateOp2("google.adGroup.update", adGroupUpdateSchema),
4486
+ targetOp("google.adGroup.pause"),
4487
+ targetOp("google.adGroup.resume"),
4488
+ targetOp("google.adGroup.remove"),
4489
+ createOp2("google.keyword.add", keywordAddSchema),
4490
+ updateOp2("google.keyword.update", keywordUpdateSchema),
4491
+ targetOp("google.keyword.remove"),
4492
+ createOp2("google.negativeKeyword.add", negativeKeywordAddSchema),
4493
+ targetOp("google.negativeKeyword.remove"),
4494
+ createOp2("google.sharedSet.create", sharedSetCreateSchema),
4495
+ createOp2("google.sharedSetMember.add", sharedSetMemberAddSchema),
4496
+ targetOp("google.sharedSetMember.remove"),
4497
+ createOp2("google.campaignSharedSet.attach", campaignSharedSetAttachSchema),
4498
+ targetOp("google.campaignSharedSet.detach"),
4499
+ createOp2("google.ad.create", adCreateSchema),
4500
+ updateOp2("google.ad.update", adUpdateSchema),
4501
+ targetOp("google.ad.pause"),
4502
+ targetOp("google.ad.resume"),
4503
+ targetOp("google.ad.remove"),
4504
+ createOp2("google.asset.create", assetCreateSchema),
4505
+ createOp2("google.assetLink.attach", assetLinkAttachSchema),
4506
+ targetOp("google.assetLink.detach"),
4507
+ createOp2("google.audience.create", audienceCreateSchema2),
4508
+ createOp2("google.audienceCriterion.attach", audienceCriterionAttachSchema),
4509
+ targetOp("google.audienceCriterion.detach"),
4510
+ createOp2("google.conversionAction.create", conversionActionCreateSchema),
4511
+ updateOp2("google.conversionAction.update", conversionActionUpdateSchema),
4512
+ createOp2("google.biddingStrategy.create", biddingStrategyCreateSchema),
4513
+ updateOp2("google.biddingStrategy.update", biddingStrategyUpdateSchema),
4514
+ createOp2("google.label.create", labelCreateSchema),
4515
+ createOp2("google.label.attach", labelAttachSchema),
4516
+ createOp2("google.campaignCriterion.add", campaignCriterionAddSchema),
4517
+ targetOp("google.campaignCriterion.remove")
4518
+ ]);
4519
+
4520
+ // ../api/src/ads-google/wire.ts
4521
+ import { z as z9 } from "zod";
4522
+ var googleWriteModeSchema = z9.enum(["live", "simulated"]);
4523
+ var googleDraftOpResultSchema = z9.object({
4524
+ status: z9.enum(["applied", "simulated", "failed", "skipped"]),
4525
+ resourceName: z9.string().optional(),
4526
+ error: z9.string().optional(),
4527
+ skippedBecause: z9.string().optional(),
4528
+ executedAt: z9.number().optional()
4529
+ });
4530
+ var googleDraftStageRequestSchema = z9.object({
4531
+ chatId: z9.string(),
4532
+ op: googleDraftOpInputSchema
4533
+ });
4534
+ var googleDraftStageResponseSchema = z9.object({
4535
+ staged: z9.literal(true),
4536
+ ref: z9.string(),
4537
+ kind: googleDraftOpKindSchema,
4538
+ mode: googleWriteModeSchema,
4539
+ dependsOn: z9.array(z9.string()),
4540
+ summary: z9.string(),
4541
+ warnings: z9.array(z9.string()),
4542
+ /** True when the op amended an already-staged op in place instead of appending a new one. */
4543
+ amended: z9.boolean().optional()
4544
+ });
4545
+ var GOOGLE_DRAFT_BATCH_MAX = 500;
4546
+ var googleDraftStageBatchRequestSchema = z9.object({
4547
+ chatId: z9.string(),
4548
+ ops: z9.array(googleDraftOpInputSchema).min(1).max(GOOGLE_DRAFT_BATCH_MAX)
4549
+ });
4550
+ var googleDraftStageBatchResponseSchema = z9.object({
4551
+ staged: z9.literal(true),
4552
+ mode: googleWriteModeSchema,
4553
+ count: z9.number(),
4554
+ ops: z9.array(
4555
+ z9.object({
4556
+ ref: z9.string(),
4557
+ kind: googleDraftOpKindSchema,
4558
+ dependsOn: z9.array(z9.string()),
4559
+ summary: z9.string(),
4560
+ warnings: z9.array(z9.string())
4561
+ })
4562
+ )
4563
+ });
4564
+ var googleDraftOpViewSchema = z9.object({
4565
+ ref: z9.string(),
4566
+ kind: googleDraftOpKindSchema,
4567
+ customerId: z9.string(),
4568
+ target: z9.string().optional(),
4569
+ dependsOn: z9.array(z9.string()),
4570
+ summary: z9.string(),
4571
+ stagedAt: z9.number(),
4572
+ result: googleDraftOpResultSchema.optional()
4573
+ });
4574
+ var googleDraftListRequestSchema = z9.object({
4575
+ chatId: z9.string()
4576
+ });
4577
+ var googleDraftListResponseSchema = z9.object({
4578
+ status: z9.enum(["active", "publishing", "applied", "discarded", "none"]),
4579
+ mode: googleWriteModeSchema,
4580
+ count: z9.number(),
4581
+ ops: z9.array(googleDraftOpViewSchema)
4582
+ });
4583
+ var googleDraftRemoveRequestSchema = z9.object({
4584
+ chatId: z9.string(),
4585
+ ref: z9.string()
4586
+ });
4587
+ var googleDraftRemoveResponseSchema = z9.object({
4588
+ /** The requested ref plus any dependents removed by cascade. */
4589
+ removed: z9.array(z9.string())
4590
+ });
4591
+ var googleDraftClearRequestSchema = z9.object({
4592
+ chatId: z9.string()
4593
+ });
4594
+ var googleDraftClearResponseSchema = z9.object({
4595
+ cleared: z9.number()
4596
+ });
4597
+ var googleFieldErrorSchema = z9.object({
4598
+ path: z9.string(),
4599
+ message: z9.string()
4600
+ });
4601
+ var googleDraftErrorResponseSchema = z9.object({
4602
+ code: z9.string(),
4603
+ error: z9.string(),
4604
+ fields: z9.array(googleFieldErrorSchema).optional()
4605
+ });
4606
+
4607
+ // src/commands/ads/google/write-shared.ts
4608
+ function failWriteValidation(message) {
4609
+ writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
4610
+ process.exit(1);
4611
+ }
4612
+ function requireCustomerId(args) {
4613
+ const raw = args["customer-id"] ?? args.customerId;
4614
+ if (!raw || !/^\d{10}$/.test(raw)) {
4615
+ failWriteValidation("pass --customer-id as the 10-digit Google Ads customer id (no dashes)");
4616
+ }
4617
+ return raw;
4618
+ }
4619
+ function requireTarget(args, entity) {
4620
+ const positional = Array.isArray(args._) ? args._[0] : void 0;
4621
+ const target = args.id ?? args.target ?? positional;
4622
+ if (typeof target !== "string" || target.length === 0) {
4623
+ failWriteValidation(`pass the ${entity} resource name or id as the positional argument`);
4624
+ }
4625
+ return target;
4626
+ }
4627
+ function requireStringFlag(value, flag) {
4628
+ if (typeof value !== "string" || value.length === 0) {
4629
+ failWriteValidation(`${flag} is required`);
4630
+ }
4631
+ return value;
4632
+ }
4633
+ function microsFlag(value, flag) {
4634
+ if (value === void 0 || value === null || value === "") {
4635
+ return void 0;
4636
+ }
4637
+ const num = Number(value);
4638
+ if (Number.isNaN(num) || num <= 0) {
4639
+ failWriteValidation(`${flag} must be a positive amount (major currency units, e.g. 50 or 50.00)`);
4640
+ }
4641
+ return toMicros(num);
4642
+ }
4643
+ function listFlag(value) {
4644
+ if (typeof value !== "string" || value.length === 0) {
4645
+ return void 0;
4646
+ }
4647
+ const items = value.split(",").map((v) => v.trim()).filter(Boolean);
4648
+ return items.length > 0 ? items : void 0;
4649
+ }
4650
+ var MATCH_TYPES = /* @__PURE__ */ new Set(["EXACT", "PHRASE", "BROAD"]);
4651
+ function parseKeywordEntry(raw, defaultMatch) {
4652
+ const colon = raw.lastIndexOf(":");
4653
+ if (colon > 0) {
4654
+ const suffix = raw.slice(colon + 1).trim().toUpperCase();
4655
+ if (MATCH_TYPES.has(suffix)) {
4656
+ return { text: raw.slice(0, colon).trim(), matchType: suffix };
4657
+ }
4658
+ failWriteValidation(`"${raw}": ":${raw.slice(colon + 1)}" is not a match type (EXACT | PHRASE | BROAD)`);
4659
+ }
4660
+ if (!defaultMatch) {
4661
+ failWriteValidation(`"${raw}" has no match type \u2014 add a :EXACT/:PHRASE/:BROAD suffix or pass --match-type`);
4662
+ }
4663
+ return { text: raw, matchType: defaultMatch };
4664
+ }
4665
+ function rawTextEntries(value) {
4666
+ const values = Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
4667
+ return values.filter((v) => typeof v === "string").flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
4668
+ }
4669
+ function rawFileEntries(path12) {
4670
+ if (typeof path12 !== "string" || path12.length === 0) {
4671
+ return [];
4672
+ }
4673
+ return readFileSync3(path12, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
4674
+ }
4675
+ function keywordEntries(args) {
4676
+ const defaultMatch = typeof args["match-type"] === "string" ? args["match-type"].toUpperCase() : void 0;
4677
+ const raw = [...rawTextEntries(args.text), ...rawFileEntries(args.file)];
4678
+ if (raw.length === 0) {
4679
+ failWriteValidation("pass keywords via --text (comma-separated) and/or --file (one per line)");
4680
+ }
4681
+ if (raw.length > GOOGLE_DRAFT_BATCH_MAX) {
4682
+ failWriteValidation(`${raw.length} keywords exceeds the batch limit of ${GOOGLE_DRAFT_BATCH_MAX}`);
4683
+ }
4684
+ const entries = [];
4685
+ const seen = /* @__PURE__ */ new Set();
4686
+ for (const item of raw) {
4687
+ const entry = parseKeywordEntry(item, defaultMatch);
4688
+ const key = `${entry.text}\0${entry.matchType}`;
4689
+ if (!seen.has(key)) {
4690
+ seen.add(key);
4691
+ entries.push(entry);
4692
+ }
4693
+ }
4694
+ return entries;
4695
+ }
4696
+ function loadJsonFileArg(path12) {
4697
+ if (typeof path12 !== "string" || path12.length === 0) {
4698
+ return {};
4699
+ }
4700
+ try {
4701
+ const parsed = JSON.parse(readFileSync3(path12, "utf8"));
4702
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
4703
+ failWriteValidation(`${path12} must contain a JSON object`);
4704
+ }
4705
+ return parsed;
4706
+ } catch (err) {
4707
+ if (err instanceof SyntaxError) {
4708
+ failWriteValidation(`${path12} is not valid JSON: ${err.message}`);
4709
+ }
4710
+ throw err;
4711
+ }
4712
+ }
4713
+ function mergePayload(file, flags) {
4714
+ const merged = { ...file };
4715
+ for (const [key, value] of Object.entries(flags)) {
4716
+ if (value !== void 0) {
4717
+ merged[key] = value;
4718
+ }
4719
+ }
4720
+ return merged;
4721
+ }
4722
+ function handleGoogleError(err) {
4723
+ if (err instanceof ApiError) {
4724
+ writeJsonEnvelope({ ok: false, error: { code: err.code ?? "API_ERROR", message: err.message } });
4725
+ process.exit(1);
4726
+ }
4727
+ writeJsonEnvelope({
4728
+ ok: false,
4729
+ error: { code: "UNKNOWN", message: err instanceof Error ? err.message : String(err) }
4730
+ });
4731
+ process.exit(1);
4732
+ }
4733
+ async function stageGoogleOp(raw) {
4734
+ const preflight = googleDraftOpInputSchema.safeParse(raw);
4735
+ if (!preflight.success) {
4736
+ const fields = preflight.error.issues.map((issue) => ({ path: issue.path.join("."), message: issue.message }));
4737
+ writeJsonEnvelope({
4738
+ ok: false,
4739
+ error: {
4740
+ code: "VALIDATION_ERROR",
4741
+ message: fields.map((f) => f.path ? `${f.path}: ${f.message}` : f.message).join("; "),
4742
+ fields
4743
+ }
4744
+ });
4745
+ process.exit(1);
4746
+ }
4747
+ try {
4748
+ const chatId = requireChatId();
4749
+ const response = await apiPost("/api/ads/google/draft/stage", { chatId, op: preflight.data });
4750
+ writeJsonEnvelope(response);
4751
+ } catch (err) {
4752
+ handleGoogleError(err);
4753
+ }
4754
+ }
4755
+ async function stageCreate(kind, customerId, payload) {
4756
+ await stageGoogleOp({ kind, customerId, payload });
4757
+ }
4758
+ async function stageGoogleOps(rawOps) {
4759
+ if (rawOps.length === 1 && rawOps[0]) {
4760
+ await stageGoogleOp(rawOps[0]);
4761
+ return;
4762
+ }
4763
+ const ops = [];
4764
+ for (const [index, raw] of rawOps.entries()) {
4765
+ const preflight = googleDraftOpInputSchema.safeParse(raw);
4766
+ if (!preflight.success) {
4767
+ const fields = preflight.error.issues.map((issue) => ({
4768
+ path: `ops[${index}].${issue.path.join(".")}`,
4769
+ message: issue.message
4770
+ }));
4771
+ writeJsonEnvelope({
4772
+ ok: false,
4773
+ error: {
4774
+ code: "VALIDATION_ERROR",
4775
+ message: fields.map((f) => `${f.path}: ${f.message}`).join("; "),
4776
+ fields
4777
+ }
4778
+ });
4779
+ process.exit(1);
4780
+ }
4781
+ ops.push(preflight.data);
4782
+ }
4783
+ try {
4784
+ const chatId = requireChatId();
4785
+ const response = await apiPost("/api/ads/google/draft/stage-batch", { chatId, ops });
4786
+ writeJsonEnvelope(response);
4787
+ } catch (err) {
4788
+ handleGoogleError(err);
4789
+ }
4790
+ }
4791
+ async function stageUpdate(kind, customerId, target, payload) {
4792
+ await stageGoogleOp({ kind, customerId, target, payload });
4793
+ }
4794
+ async function stageTarget(kind, customerId, target) {
4795
+ await stageGoogleOp({ kind, customerId, target });
4796
+ }
4797
+ async function draftAction(path12, body) {
4798
+ try {
4799
+ const chatId = requireChatId();
4800
+ const response = await apiPost(path12, { chatId, ...body });
4801
+ writeJsonEnvelope(response);
4802
+ } catch (err) {
4803
+ handleGoogleError(err);
4804
+ }
4805
+ }
4806
+
4807
+ // src/commands/ads/google/draft.ts
4808
+ var draftCommand2 = defineCommand22({
4809
+ meta: { name: "draft", description: "List, remove, or clear staged Google Ads write ops for this chat" },
4810
+ subCommands: {
4811
+ list: defineCommand22({
4812
+ meta: { name: "list", description: "List staged ops (with lineage, mode, and results)" },
4813
+ run: async () => {
4814
+ await draftAction("/api/ads/google/draft", {});
4815
+ }
4816
+ }),
4817
+ remove: defineCommand22({
4818
+ meta: { name: "remove", description: "Remove one staged op (cascades to dependents)" },
4819
+ args: { ref: { type: "positional", description: "Staged op ref (g_temp_* or target)", required: false } },
4820
+ run: async ({ args }) => {
4821
+ await draftAction("/api/ads/google/draft/remove", { ref: requireTarget(args, "op") });
4822
+ }
4823
+ }),
4824
+ clear: defineCommand22({
4825
+ meta: { name: "clear", description: "Discard all staged ops on this chat" },
4826
+ run: async () => {
4827
+ await draftAction("/api/ads/google/draft/clear", {});
4828
+ }
4829
+ })
4830
+ }
4831
+ });
4832
+
3835
4833
  // src/commands/ads/google/keywords/index.ts
3836
- import { defineCommand as defineCommand26 } from "citty";
4834
+ import { defineCommand as defineCommand27 } from "citty";
3837
4835
 
3838
4836
  // src/commands/ads/google/keywords/discover.ts
3839
- import { defineCommand as defineCommand22 } from "citty";
4837
+ import { defineCommand as defineCommand23 } from "citty";
3840
4838
 
3841
4839
  // src/geo-context.ts
3842
4840
  var GOOGLE_ADS_LOCATIONS = [
@@ -4111,7 +5109,7 @@ function handleKeywordError(err) {
4111
5109
  writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
4112
5110
  process.exit(1);
4113
5111
  }
4114
- var discoverCommand = defineCommand22({
5112
+ var discoverCommand = defineCommand23({
4115
5113
  meta: {
4116
5114
  name: "discover",
4117
5115
  description: `Discover new keyword ideas from seed keywords or competitor URLs.
@@ -4173,7 +5171,7 @@ Examples:
4173
5171
  });
4174
5172
 
4175
5173
  // src/commands/ads/google/keywords/languages.ts
4176
- import { defineCommand as defineCommand23 } from "citty";
5174
+ import { defineCommand as defineCommand24 } from "citty";
4177
5175
  registerSchema({
4178
5176
  command: "ads.google.keywords.languages",
4179
5177
  description: "List all supported language IDs for --language flag in Google Ads keyword commands.",
@@ -4183,7 +5181,7 @@ var FIELDS = {
4183
5181
  id: "Language ID to pass as --language",
4184
5182
  name: "Language name"
4185
5183
  };
4186
- var languagesCommand = defineCommand23({
5184
+ var languagesCommand = defineCommand24({
4187
5185
  meta: {
4188
5186
  name: "languages",
4189
5187
  description: "List all supported language IDs for --language flag."
@@ -4194,7 +5192,7 @@ var languagesCommand = defineCommand23({
4194
5192
  });
4195
5193
 
4196
5194
  // src/commands/ads/google/keywords/locations.ts
4197
- import { defineCommand as defineCommand24 } from "citty";
5195
+ import { defineCommand as defineCommand25 } from "citty";
4198
5196
  registerSchema({
4199
5197
  command: "ads.google.keywords.locations",
4200
5198
  description: "List all supported geo target IDs for --location flag in Google Ads keyword commands.",
@@ -4204,7 +5202,7 @@ var FIELDS2 = {
4204
5202
  id: "Geo target ID to pass as --location",
4205
5203
  name: "Country/region name"
4206
5204
  };
4207
- var locationsCommand = defineCommand24({
5205
+ var locationsCommand = defineCommand25({
4208
5206
  meta: {
4209
5207
  name: "locations",
4210
5208
  description: "List all supported geo target IDs for --location flag."
@@ -4215,7 +5213,7 @@ var locationsCommand = defineCommand24({
4215
5213
  });
4216
5214
 
4217
5215
  // src/commands/ads/google/keywords/metrics.ts
4218
- import { defineCommand as defineCommand25 } from "citty";
5216
+ import { defineCommand as defineCommand26 } from "citty";
4219
5217
  registerSchema({
4220
5218
  command: "ads.google.keywords.metrics",
4221
5219
  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.",
@@ -4239,7 +5237,7 @@ registerSchema({
4239
5237
  output: { type: "string", description: "Format: json|csv|jsonl|md", required: false, default: "json" }
4240
5238
  }
4241
5239
  });
4242
- var metricsCommand = defineCommand25({
5240
+ var metricsCommand = defineCommand26({
4243
5241
  meta: {
4244
5242
  name: "metrics",
4245
5243
  description: `Get historical search metrics for specific keywords.
@@ -4326,7 +5324,7 @@ Examples:
4326
5324
  });
4327
5325
 
4328
5326
  // src/commands/ads/google/keywords/index.ts
4329
- var keywordsCommand = defineCommand26({
5327
+ var keywordsCommand = defineCommand27({
4330
5328
  meta: {
4331
5329
  name: "keywords",
4332
5330
  description: `Keyword research tools. Subcommands: discover, metrics, locations, languages.
@@ -4346,8 +5344,8 @@ Examples:
4346
5344
  });
4347
5345
 
4348
5346
  // src/commands/ads/google/library/index.ts
4349
- import { defineCommand as defineCommand27 } from "citty";
4350
- var listAdvertisers = defineCommand27({
5347
+ import { defineCommand as defineCommand28 } from "citty";
5348
+ var listAdvertisers = defineCommand28({
4351
5349
  meta: {
4352
5350
  name: "list-advertisers",
4353
5351
  description: "List tracked Google advertisers and their accounts"
@@ -4364,7 +5362,7 @@ var listAdvertisers = defineCommand27({
4364
5362
  }
4365
5363
  }
4366
5364
  });
4367
- var syncStatus = defineCommand27({
5365
+ var syncStatus = defineCommand28({
4368
5366
  meta: {
4369
5367
  name: "sync-status",
4370
5368
  description: "Check the sync status and ad counts of a Google account"
@@ -4384,7 +5382,7 @@ var syncStatus = defineCommand27({
4384
5382
  writeAdsJson({ ok: true, data });
4385
5383
  }
4386
5384
  });
4387
- var searchAds = defineCommand27({
5385
+ var searchAds = defineCommand28({
4388
5386
  meta: {
4389
5387
  name: "search-ads",
4390
5388
  description: "Search and filter Google ads for an account"
@@ -4441,7 +5439,7 @@ var searchAds = defineCommand27({
4441
5439
  }
4442
5440
  }
4443
5441
  });
4444
- var searchAdvertiser = defineCommand27({
5442
+ var searchAdvertiser = defineCommand28({
4445
5443
  meta: {
4446
5444
  name: "search-advertiser",
4447
5445
  description: "Search for an advertiser on the Google Ads Transparency Center"
@@ -4476,7 +5474,7 @@ var searchAdvertiser = defineCommand27({
4476
5474
  function sleep(ms) {
4477
5475
  return new Promise((resolve5) => setTimeout(resolve5, ms));
4478
5476
  }
4479
- var track = defineCommand27({
5477
+ var track = defineCommand28({
4480
5478
  meta: {
4481
5479
  name: "track",
4482
5480
  description: "Track a new Google advertiser (from search results). Waits for initial sync to complete before returning."
@@ -4534,7 +5532,7 @@ var track = defineCommand27({
4534
5532
  process.exit(1);
4535
5533
  }
4536
5534
  });
4537
- var sync = defineCommand27({
5535
+ var sync = defineCommand28({
4538
5536
  meta: {
4539
5537
  name: "sync",
4540
5538
  description: "Trigger an immediate sync for a Google account. Waits for completion before returning."
@@ -4578,7 +5576,7 @@ var sync = defineCommand27({
4578
5576
  process.exit(1);
4579
5577
  }
4580
5578
  });
4581
- var searchCompetitors = defineCommand27({
5579
+ var searchCompetitors = defineCommand28({
4582
5580
  meta: {
4583
5581
  name: "search-competitors",
4584
5582
  description: "Search for competitors running Google ads for a keyword (DataForSEO)"
@@ -4610,7 +5608,7 @@ var searchCompetitors = defineCommand27({
4610
5608
  }
4611
5609
  }
4612
5610
  });
4613
- var library = defineCommand27({
5611
+ var library = defineCommand28({
4614
5612
  meta: {
4615
5613
  name: "library",
4616
5614
  description: "Manage and search the Google Ads Library"
@@ -4627,9 +5625,9 @@ var library = defineCommand27({
4627
5625
  });
4628
5626
 
4629
5627
  // src/commands/ads/google/query.ts
4630
- import { appendFileSync, existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
5628
+ import { appendFileSync, existsSync as existsSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
4631
5629
  import { resolve } from "path";
4632
- import { defineCommand as defineCommand28 } from "citty";
5630
+ import { defineCommand as defineCommand29 } from "citty";
4633
5631
 
4634
5632
  // src/commands/ads/google/preflight.ts
4635
5633
  function buildCommand2(query, customerId) {
@@ -4650,6 +5648,24 @@ function applyAutoFixes(query, limit) {
4650
5648
  corrected = corrected.replace(/shopping_performance_view\.product_(\w+)/g, "segments.product_$1");
4651
5649
  warnings.push({ code: "FIELD_RENAMED", message: "shopping_performance_view.product_* \u2192 segments.product_*" });
4652
5650
  }
5651
+ if (/asset\.\w+_asset\.final_(mobile_)?urls\b/.test(corrected)) {
5652
+ corrected = corrected.replace(/asset\.\w+_asset\.final_(mobile_)?urls\b/g, "asset.final_$1urls");
5653
+ warnings.push({ code: "FIELD_RENAMED", message: "asset.<type>_asset.final_urls \u2192 asset.final_urls" });
5654
+ }
5655
+ if (/FROM\s+campaign_budget\b/i.test(corrected)) {
5656
+ const whereClause = corrected.split(/\bWHERE\b/i)[1] ?? "";
5657
+ const selectClause = corrected.split(/\bFROM\b/i)[0] ?? "";
5658
+ const missing = [...new Set(whereClause.match(/campaign\.[\w.]+/g) ?? [])].filter(
5659
+ (field) => !selectClause.includes(field)
5660
+ );
5661
+ if (missing.length > 0) {
5662
+ corrected = corrected.replace(/SELECT\s+/i, `SELECT ${missing.join(", ")}, `);
5663
+ warnings.push({
5664
+ code: "REQUIRED_FIELD_ADDED",
5665
+ message: `Added ${missing.join(", ")} to SELECT \u2014 campaign_budget queries must select campaign fields used in WHERE`
5666
+ });
5667
+ }
5668
+ }
4653
5669
  if (/campaign\.status\s*=\s*'ACTIVE'/i.test(corrected)) {
4654
5670
  corrected = corrected.replace(/campaign\.status\s*=\s*'ACTIVE'/gi, "campaign.status = 'ENABLED'");
4655
5671
  warnings.push({ code: "ENUM_CORRECTED", message: "campaign.status ACTIVE \u2192 ENABLED" });
@@ -4921,7 +5937,7 @@ function writeRowsToFile(filePath, rows, fields, append) {
4921
5937
  `, "utf-8");
4922
5938
  }
4923
5939
  } else if (append && existsSync3(filePath)) {
4924
- const existing = JSON.parse(readFileSync3(filePath, "utf-8"));
5940
+ const existing = JSON.parse(readFileSync4(filePath, "utf-8"));
4925
5941
  writeFileSync2(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
4926
5942
  } else {
4927
5943
  writeFileSync2(filePath, JSON.stringify(rows, null, 2), "utf-8");
@@ -5085,7 +6101,7 @@ function handleQueryError(err, finalQuery, customerId) {
5085
6101
  });
5086
6102
  process.exit(1);
5087
6103
  }
5088
- var queryCommand = defineCommand28({
6104
+ var queryCommand = defineCommand29({
5089
6105
  meta: {
5090
6106
  name: "query",
5091
6107
  description: `Run GAQL queries against Google Ads. Supports raw GAQL, presets, pagination, file export, and caching.
@@ -5142,8 +6158,537 @@ Examples:
5142
6158
  }
5143
6159
  });
5144
6160
 
6161
+ // src/commands/ads/google/write-commands.ts
6162
+ import { defineCommand as defineCommand30 } from "citty";
6163
+ var customerIdArg = { "customer-id": { type: "string", description: "10-digit Google Ads customer id" } };
6164
+ var fileArg = {
6165
+ file: { type: "string", description: "JSON file with the full op payload (flags override)" }
6166
+ };
6167
+ var budgetsCommand = defineCommand30({
6168
+ meta: { name: "budgets", description: "Stage campaign budget create/update" },
6169
+ subCommands: {
6170
+ create: defineCommand30({
6171
+ meta: { name: "create", description: "Stage a campaign budget" },
6172
+ args: {
6173
+ ...customerIdArg,
6174
+ ...fileArg,
6175
+ name: { type: "string", description: "Budget name" },
6176
+ amount: { type: "string", description: "Daily amount in major currency units (e.g. 50)" },
6177
+ delivery: { type: "string", description: "STANDARD | ACCELERATED" },
6178
+ shared: { type: "boolean", description: "Explicitly shared budget" }
6179
+ },
6180
+ run: async ({ args }) => {
6181
+ const customerId = requireCustomerId(args);
6182
+ const payload = mergePayload(loadJsonFileArg(args.file), {
6183
+ name: args.name,
6184
+ amountMicros: microsFlag(args.amount, "--amount"),
6185
+ deliveryMethod: args.delivery,
6186
+ explicitlyShared: args.shared || void 0
6187
+ });
6188
+ await stageCreate("google.budget.create", customerId, payload);
6189
+ }
6190
+ }),
6191
+ update: defineCommand30({
6192
+ meta: { name: "update", description: "Stage a budget update" },
6193
+ args: {
6194
+ ...customerIdArg,
6195
+ ...fileArg,
6196
+ name: { type: "string" },
6197
+ amount: { type: "string", description: "New daily amount in major currency units" },
6198
+ delivery: { type: "string" }
6199
+ },
6200
+ run: async ({ args }) => {
6201
+ const customerId = requireCustomerId(args);
6202
+ const target = requireTarget(args, "budget");
6203
+ const payload = mergePayload(loadJsonFileArg(args.file), {
6204
+ name: args.name,
6205
+ amountMicros: microsFlag(args.amount, "--amount"),
6206
+ deliveryMethod: args.delivery
6207
+ });
6208
+ await stageUpdate("google.budget.update", customerId, target, payload);
6209
+ }
6210
+ })
6211
+ }
6212
+ });
6213
+ function biddingFromFlags(args) {
6214
+ const type = args["bidding-strategy"];
6215
+ if (!type) {
6216
+ return void 0;
6217
+ }
6218
+ return {
6219
+ type,
6220
+ targetCpaMicros: microsFlag(args["target-cpa"], "--target-cpa"),
6221
+ targetRoas: args["target-roas"] !== void 0 ? Number(args["target-roas"]) : void 0
6222
+ };
6223
+ }
6224
+ var campaignsCommand = defineCommand30({
6225
+ meta: { name: "campaigns", description: "Stage campaign create/update/pause/resume/remove" },
6226
+ subCommands: {
6227
+ create: defineCommand30({
6228
+ meta: { name: "create", description: "Stage a campaign" },
6229
+ args: {
6230
+ ...customerIdArg,
6231
+ ...fileArg,
6232
+ name: { type: "string" },
6233
+ "channel-type": {
6234
+ type: "string",
6235
+ description: "SEARCH | DISPLAY | SHOPPING | VIDEO | PERFORMANCE_MAX | DEMAND_GEN | \u2026"
6236
+ },
6237
+ "sub-type": { type: "string", description: "Advertising channel sub-type" },
6238
+ "budget-ref": { type: "string", description: "Budget ref (g_temp_*, id, or resource name)" },
6239
+ "bidding-strategy": {
6240
+ type: "string",
6241
+ description: "MANUAL_CPC | MAXIMIZE_CONVERSIONS | TARGET_CPA | TARGET_ROAS | \u2026"
6242
+ },
6243
+ "target-cpa": { type: "string", description: "Target CPA (major units) for TARGET_CPA" },
6244
+ "target-roas": { type: "string", description: "Target ROAS (e.g. 4.0) for TARGET_ROAS" },
6245
+ objective: { type: "string", description: "Advisory UI objective (SALES, LEADS, \u2026)" },
6246
+ "start-date": { type: "string", description: "YYYY-MM-DD" },
6247
+ "end-date": { type: "string", description: "YYYY-MM-DD" },
6248
+ status: { type: "string", description: "ENABLED | PAUSED (default PAUSED)" }
6249
+ },
6250
+ run: async ({ args }) => {
6251
+ const customerId = requireCustomerId(args);
6252
+ const payload = mergePayload(loadJsonFileArg(args.file), {
6253
+ name: args.name,
6254
+ channelType: args["channel-type"],
6255
+ channelSubType: args["sub-type"],
6256
+ budget: args["budget-ref"],
6257
+ bidding: biddingFromFlags(args),
6258
+ objective: args.objective,
6259
+ startDate: args["start-date"],
6260
+ endDate: args["end-date"],
6261
+ status: args.status
6262
+ });
6263
+ await stageCreate("google.campaign.create", customerId, payload);
6264
+ }
6265
+ }),
6266
+ update: defineCommand30({
6267
+ meta: { name: "update", description: "Stage a campaign update" },
6268
+ args: {
6269
+ ...customerIdArg,
6270
+ ...fileArg,
6271
+ name: { type: "string" },
6272
+ "budget-ref": { type: "string" },
6273
+ "bidding-strategy": { type: "string" },
6274
+ "target-cpa": { type: "string" },
6275
+ "target-roas": { type: "string" },
6276
+ status: { type: "string" }
6277
+ },
6278
+ run: async ({ args }) => {
6279
+ const customerId = requireCustomerId(args);
6280
+ const target = requireTarget(args, "campaign");
6281
+ const payload = mergePayload(loadJsonFileArg(args.file), {
6282
+ name: args.name,
6283
+ budget: args["budget-ref"],
6284
+ bidding: biddingFromFlags(args),
6285
+ status: args.status
6286
+ });
6287
+ await stageUpdate("google.campaign.update", customerId, target, payload);
6288
+ }
6289
+ }),
6290
+ pause: statusCommand2("google.campaign.pause", "campaign"),
6291
+ resume: statusCommand2("google.campaign.resume", "campaign"),
6292
+ remove: statusCommand2("google.campaign.remove", "campaign")
6293
+ }
6294
+ });
6295
+ function statusCommand2(kind, entity) {
6296
+ return defineCommand30({
6297
+ meta: { name: kind.split(".")[2], description: `Stage a ${entity} ${kind.split(".")[2]}` },
6298
+ args: {
6299
+ ...customerIdArg,
6300
+ id: { type: "positional", description: `${entity} resource name or id`, required: false }
6301
+ },
6302
+ run: async ({ args }) => {
6303
+ const customerId = requireCustomerId(args);
6304
+ await stageTarget(kind, customerId, requireTarget(args, entity));
6305
+ }
6306
+ });
6307
+ }
6308
+ var adGroupsCommand = defineCommand30({
6309
+ meta: { name: "ad-groups", description: "Stage ad group create/update/pause/resume/remove" },
6310
+ subCommands: {
6311
+ create: defineCommand30({
6312
+ meta: { name: "create", description: "Stage an ad group" },
6313
+ args: {
6314
+ ...customerIdArg,
6315
+ ...fileArg,
6316
+ name: { type: "string" },
6317
+ "campaign-ref": { type: "string", description: "Campaign ref (g_temp_*, id, or resource name)" },
6318
+ type: { type: "string", description: "Ad group type (default SEARCH_STANDARD)" },
6319
+ "cpc-bid": { type: "string", description: "Default CPC bid in major units" },
6320
+ status: { type: "string" }
6321
+ },
6322
+ run: async ({ args }) => {
6323
+ const customerId = requireCustomerId(args);
6324
+ const payload = mergePayload(loadJsonFileArg(args.file), {
6325
+ name: args.name,
6326
+ campaign: args["campaign-ref"],
6327
+ type: args.type,
6328
+ cpcBidMicros: microsFlag(args["cpc-bid"], "--cpc-bid"),
6329
+ status: args.status
6330
+ });
6331
+ await stageCreate("google.adGroup.create", customerId, payload);
6332
+ }
6333
+ }),
6334
+ update: defineCommand30({
6335
+ meta: { name: "update", description: "Stage an ad group update" },
6336
+ args: {
6337
+ ...customerIdArg,
6338
+ ...fileArg,
6339
+ name: { type: "string" },
6340
+ "cpc-bid": { type: "string" },
6341
+ status: { type: "string" }
6342
+ },
6343
+ run: async ({ args }) => {
6344
+ const customerId = requireCustomerId(args);
6345
+ const target = requireTarget(args, "ad group");
6346
+ const payload = mergePayload(loadJsonFileArg(args.file), {
6347
+ name: args.name,
6348
+ cpcBidMicros: microsFlag(args["cpc-bid"], "--cpc-bid"),
6349
+ status: args.status
6350
+ });
6351
+ await stageUpdate("google.adGroup.update", customerId, target, payload);
6352
+ }
6353
+ }),
6354
+ pause: statusCommand2("google.adGroup.pause", "ad group"),
6355
+ resume: statusCommand2("google.adGroup.resume", "ad group"),
6356
+ remove: statusCommand2("google.adGroup.remove", "ad group")
6357
+ }
6358
+ });
6359
+ var keywordWriteSubcommands = {
6360
+ add: defineCommand30({
6361
+ meta: { name: "add", description: "Add keyword(s) to an ad group \u2014 one --text or a whole batch" },
6362
+ args: {
6363
+ ...customerIdArg,
6364
+ "ad-group-ref": { type: "string", description: "Ad group ref (g_temp_*, id, or resource name)" },
6365
+ text: {
6366
+ type: "string",
6367
+ description: 'Keyword text \u2014 comma-separate for a batch, optional ":EXACT|:PHRASE|:BROAD" suffix per entry'
6368
+ },
6369
+ file: { type: "string", description: "Text file with one keyword[:MATCH_TYPE] per line" },
6370
+ "match-type": { type: "string", description: "Default match type: EXACT | PHRASE | BROAD" },
6371
+ "cpc-bid": { type: "string", description: "Keyword CPC bid in major units (applies to all)" },
6372
+ "final-url": { type: "string", description: "Keyword-level final URL (applies to all)" }
6373
+ },
6374
+ run: async ({ args }) => {
6375
+ const customerId = requireCustomerId(args);
6376
+ const adGroup = requireStringFlag(args["ad-group-ref"], "--ad-group-ref");
6377
+ const cpcBidMicros = microsFlag(args["cpc-bid"], "--cpc-bid");
6378
+ const finalUrls = args["final-url"] ? [args["final-url"]] : void 0;
6379
+ await stageGoogleOps(
6380
+ keywordEntries(args).map((entry) => ({
6381
+ kind: "google.keyword.add",
6382
+ customerId,
6383
+ payload: { adGroup, text: entry.text, matchType: entry.matchType, cpcBidMicros, finalUrls }
6384
+ }))
6385
+ );
6386
+ }
6387
+ }),
6388
+ update: defineCommand30({
6389
+ meta: { name: "update", description: "Update a keyword" },
6390
+ args: { ...customerIdArg, "cpc-bid": { type: "string" }, status: { type: "string" } },
6391
+ run: async ({ args }) => {
6392
+ const customerId = requireCustomerId(args);
6393
+ await stageUpdate("google.keyword.update", customerId, requireTarget(args, "keyword"), {
6394
+ cpcBidMicros: microsFlag(args["cpc-bid"], "--cpc-bid"),
6395
+ status: args.status
6396
+ });
6397
+ }
6398
+ }),
6399
+ remove: statusCommand2("google.keyword.remove", "keyword")
6400
+ };
6401
+ var negativeKeywordsCommand = defineCommand30({
6402
+ meta: { name: "negative-keywords", description: "Stage negative keyword add/remove (ad-group or campaign level)" },
6403
+ subCommands: {
6404
+ add: defineCommand30({
6405
+ meta: { name: "add", description: "Add negative keyword(s) \u2014 one --text or a whole batch" },
6406
+ args: {
6407
+ ...customerIdArg,
6408
+ level: { type: "string", description: "adGroup | campaign" },
6409
+ "parent-ref": { type: "string", description: "Ad group or campaign ref" },
6410
+ text: {
6411
+ type: "string",
6412
+ description: 'Keyword text \u2014 comma-separate for a batch, optional ":MATCH_TYPE" suffix per entry'
6413
+ },
6414
+ file: { type: "string", description: "Text file with one keyword[:MATCH_TYPE] per line" },
6415
+ "match-type": { type: "string", description: "Default match type: EXACT | PHRASE | BROAD" }
6416
+ },
6417
+ run: async ({ args }) => {
6418
+ const customerId = requireCustomerId(args);
6419
+ const level = requireStringFlag(args.level, "--level");
6420
+ const parent = requireStringFlag(args["parent-ref"], "--parent-ref");
6421
+ await stageGoogleOps(
6422
+ keywordEntries(args).map((entry) => ({
6423
+ kind: "google.negativeKeyword.add",
6424
+ customerId,
6425
+ payload: { level, parent, text: entry.text, matchType: entry.matchType }
6426
+ }))
6427
+ );
6428
+ }
6429
+ }),
6430
+ remove: statusCommand2("google.negativeKeyword.remove", "negative keyword")
6431
+ }
6432
+ });
6433
+ var keywordListsCommand = defineCommand30({
6434
+ meta: { name: "keyword-lists", description: "Stage shared negative keyword lists (create/add/attach/detach)" },
6435
+ subCommands: {
6436
+ create: defineCommand30({
6437
+ meta: { name: "create", description: "Create a shared negative keyword list" },
6438
+ args: {
6439
+ ...customerIdArg,
6440
+ name: { type: "string" },
6441
+ type: {
6442
+ type: "string",
6443
+ description: "NEGATIVE_KEYWORDS (default) | NEGATIVE_PLACEMENTS | ACCOUNT_LEVEL_NEGATIVE_KEYWORDS"
6444
+ }
6445
+ },
6446
+ run: async ({ args }) => {
6447
+ const customerId = requireCustomerId(args);
6448
+ await stageCreate("google.sharedSet.create", customerId, {
6449
+ name: requireStringFlag(args.name, "--name"),
6450
+ type: args.type
6451
+ });
6452
+ }
6453
+ }),
6454
+ add: defineCommand30({
6455
+ meta: { name: "add", description: "Add keyword(s) to a shared list \u2014 one --text or a whole batch" },
6456
+ args: {
6457
+ ...customerIdArg,
6458
+ "list-ref": { type: "string", description: "Shared set ref" },
6459
+ text: {
6460
+ type: "string",
6461
+ description: 'Keyword text \u2014 comma-separate for a batch, optional ":MATCH_TYPE" suffix per entry'
6462
+ },
6463
+ file: { type: "string", description: "Text file with one keyword[:MATCH_TYPE] per line" },
6464
+ "match-type": { type: "string", description: "Default match type: EXACT | PHRASE | BROAD" }
6465
+ },
6466
+ run: async ({ args }) => {
6467
+ const customerId = requireCustomerId(args);
6468
+ const sharedSet = requireStringFlag(args["list-ref"], "--list-ref");
6469
+ await stageGoogleOps(
6470
+ keywordEntries(args).map((entry) => ({
6471
+ kind: "google.sharedSetMember.add",
6472
+ customerId,
6473
+ payload: { sharedSet, text: entry.text, matchType: entry.matchType }
6474
+ }))
6475
+ );
6476
+ }
6477
+ }),
6478
+ attach: defineCommand30({
6479
+ meta: { name: "attach", description: "Attach a keyword list to a campaign" },
6480
+ args: { ...customerIdArg, "campaign-ref": { type: "string" }, "list-ref": { type: "string" } },
6481
+ run: async ({ args }) => {
6482
+ const customerId = requireCustomerId(args);
6483
+ await stageCreate("google.campaignSharedSet.attach", customerId, {
6484
+ campaign: requireStringFlag(args["campaign-ref"], "--campaign-ref"),
6485
+ sharedSet: requireStringFlag(args["list-ref"], "--list-ref")
6486
+ });
6487
+ }
6488
+ }),
6489
+ detach: statusCommand2("google.campaignSharedSet.detach", "campaign shared set")
6490
+ }
6491
+ });
6492
+ function rsaContentFromFlags(args) {
6493
+ const headlines = listFlag(args.headlines);
6494
+ const descriptions = listFlag(args.descriptions);
6495
+ if (!headlines || !descriptions) {
6496
+ failWriteValidation("responsive search ads need --headlines and --descriptions (comma-separated), or use --file");
6497
+ }
6498
+ const finalUrls = listFlag(args["final-url"]);
6499
+ if (!finalUrls) {
6500
+ failWriteValidation("--final-url is required for a responsive search ad");
6501
+ }
6502
+ return {
6503
+ format: "responsiveSearch",
6504
+ headlines: headlines.map((text) => ({ text })),
6505
+ descriptions: descriptions.map((text) => ({ text })),
6506
+ path1: args.path1,
6507
+ path2: args.path2,
6508
+ finalUrls
6509
+ };
6510
+ }
6511
+ var adsCommand = defineCommand30({
6512
+ meta: { name: "ads", description: "Stage ad create/update/pause/resume/remove" },
6513
+ subCommands: {
6514
+ create: defineCommand30({
6515
+ meta: { name: "create", description: "Stage an ad (responsive search via flags; other formats via --file)" },
6516
+ args: {
6517
+ ...customerIdArg,
6518
+ ...fileArg,
6519
+ "ad-group-ref": { type: "string", description: "Ad group ref" },
6520
+ format: {
6521
+ type: "string",
6522
+ description: "responsiveSearch (default) | responsiveDisplay | performanceMaxAssetGroup | call | app | video | demandGen"
6523
+ },
6524
+ headlines: { type: "string", description: "Comma-separated headlines (RSA)" },
6525
+ descriptions: { type: "string", description: "Comma-separated descriptions (RSA)" },
6526
+ path1: { type: "string" },
6527
+ path2: { type: "string" },
6528
+ "final-url": { type: "string", description: "Comma-separated final URLs" },
6529
+ status: { type: "string" }
6530
+ },
6531
+ run: async ({ args }) => {
6532
+ const customerId = requireCustomerId(args);
6533
+ const file = loadJsonFileArg(args.file);
6534
+ const format = args.format ?? "responsiveSearch";
6535
+ const content = file.content ?? (format === "responsiveSearch" ? rsaContentFromFlags(args) : failWriteValidation(`--format ${format} needs --file with the ad content`));
6536
+ await stageCreate("google.ad.create", customerId, {
6537
+ adGroup: requireStringFlag(args["ad-group-ref"] ?? file.adGroup, "--ad-group-ref"),
6538
+ status: args.status ?? file.status,
6539
+ content
6540
+ });
6541
+ }
6542
+ }),
6543
+ update: defineCommand30({
6544
+ meta: { name: "update", description: "Stage an ad update" },
6545
+ args: { ...customerIdArg, ...fileArg, status: { type: "string" } },
6546
+ run: async ({ args }) => {
6547
+ const customerId = requireCustomerId(args);
6548
+ const file = loadJsonFileArg(args.file);
6549
+ await stageUpdate(
6550
+ "google.ad.update",
6551
+ customerId,
6552
+ requireTarget(args, "ad"),
6553
+ mergePayload(file, { status: args.status })
6554
+ );
6555
+ }
6556
+ }),
6557
+ pause: statusCommand2("google.ad.pause", "ad"),
6558
+ resume: statusCommand2("google.ad.resume", "ad"),
6559
+ remove: statusCommand2("google.ad.remove", "ad")
6560
+ }
6561
+ });
6562
+ function fileCreateCommand(name, kind, description) {
6563
+ return defineCommand30({
6564
+ meta: { name, description },
6565
+ args: { ...customerIdArg, ...fileArg },
6566
+ run: async ({ args }) => {
6567
+ const customerId = requireCustomerId(args);
6568
+ const payload = loadJsonFileArg(args.file);
6569
+ if (Object.keys(payload).length === 0) {
6570
+ failWriteValidation(`${kind} needs --file with the op payload`);
6571
+ }
6572
+ await stageGoogleOp({ kind, customerId, payload });
6573
+ }
6574
+ });
6575
+ }
6576
+ var assetsCommand = defineCommand30({
6577
+ meta: { name: "assets", description: "Stage asset create + asset-link attach/detach (via --file)" },
6578
+ subCommands: {
6579
+ create: fileCreateCommand(
6580
+ "create",
6581
+ "google.asset.create",
6582
+ "Stage an asset (text/image/sitelink/callout/structuredSnippet/\u2026)"
6583
+ ),
6584
+ attach: fileCreateCommand("attach", "google.assetLink.attach", "Attach an asset to a campaign/adGroup/customer"),
6585
+ detach: statusCommand2("google.assetLink.detach", "asset link")
6586
+ }
6587
+ });
6588
+ var audiencesCommand = defineCommand30({
6589
+ meta: { name: "audiences", description: "Stage audience (user list) create + criterion attach/detach (via --file)" },
6590
+ subCommands: {
6591
+ create: fileCreateCommand("create", "google.audience.create", "Stage a user-list audience"),
6592
+ attach: fileCreateCommand(
6593
+ "attach",
6594
+ "google.audienceCriterion.attach",
6595
+ "Target/exclude an audience on a campaign/adGroup"
6596
+ ),
6597
+ detach: statusCommand2("google.audienceCriterion.detach", "audience criterion")
6598
+ }
6599
+ });
6600
+ var conversionsCommand = defineCommand30({
6601
+ meta: { name: "conversions", description: "Stage conversion action create/update (via --file)" },
6602
+ subCommands: {
6603
+ create: fileCreateCommand("create", "google.conversionAction.create", "Stage a conversion action"),
6604
+ update: defineCommand30({
6605
+ meta: { name: "update", description: "Stage a conversion action update" },
6606
+ args: { ...customerIdArg, ...fileArg },
6607
+ run: async ({ args }) => {
6608
+ const customerId = requireCustomerId(args);
6609
+ await stageUpdate(
6610
+ "google.conversionAction.update",
6611
+ customerId,
6612
+ requireTarget(args, "conversion action"),
6613
+ loadJsonFileArg(args.file)
6614
+ );
6615
+ }
6616
+ })
6617
+ }
6618
+ });
6619
+ var biddingStrategiesCommand = defineCommand30({
6620
+ meta: { name: "bidding-strategies", description: "Stage portfolio bidding strategy create/update (via --file)" },
6621
+ subCommands: {
6622
+ create: fileCreateCommand("create", "google.biddingStrategy.create", "Stage a portfolio bidding strategy"),
6623
+ update: defineCommand30({
6624
+ meta: { name: "update", description: "Stage a portfolio bidding strategy update" },
6625
+ args: { ...customerIdArg, ...fileArg },
6626
+ run: async ({ args }) => {
6627
+ const customerId = requireCustomerId(args);
6628
+ await stageUpdate(
6629
+ "google.biddingStrategy.update",
6630
+ customerId,
6631
+ requireTarget(args, "bidding strategy"),
6632
+ loadJsonFileArg(args.file)
6633
+ );
6634
+ }
6635
+ })
6636
+ }
6637
+ });
6638
+ var labelsCommand = defineCommand30({
6639
+ meta: { name: "labels", description: "Stage label create + attach (via --file)" },
6640
+ subCommands: {
6641
+ create: defineCommand30({
6642
+ meta: { name: "create", description: "Create a label" },
6643
+ args: {
6644
+ ...customerIdArg,
6645
+ name: { type: "string" },
6646
+ "background-color": { type: "string" },
6647
+ description: { type: "string" }
6648
+ },
6649
+ run: async ({ args }) => {
6650
+ const customerId = requireCustomerId(args);
6651
+ await stageCreate("google.label.create", customerId, {
6652
+ name: requireStringFlag(args.name, "--name"),
6653
+ backgroundColor: args["background-color"],
6654
+ description: args.description
6655
+ });
6656
+ }
6657
+ }),
6658
+ attach: fileCreateCommand("attach", "google.label.attach", "Attach a label to a campaign/adGroup/ad")
6659
+ }
6660
+ });
6661
+ var campaignCriteriaCommand = defineCommand30({
6662
+ meta: {
6663
+ name: "campaign-criteria",
6664
+ description: "Stage campaign criteria (location/language/adSchedule/device) add/remove (via --file)"
6665
+ },
6666
+ subCommands: {
6667
+ add: fileCreateCommand("add", "google.campaignCriterion.add", "Add a campaign criterion"),
6668
+ remove: statusCommand2("google.campaignCriterion.remove", "campaign criterion")
6669
+ }
6670
+ });
6671
+ var googleWriteCommands = {
6672
+ budgets: budgetsCommand,
6673
+ campaigns: campaignsCommand,
6674
+ "ad-groups": adGroupsCommand,
6675
+ "negative-keywords": negativeKeywordsCommand,
6676
+ "keyword-lists": keywordListsCommand,
6677
+ ads: adsCommand,
6678
+ assets: assetsCommand,
6679
+ audiences: audiencesCommand,
6680
+ conversions: conversionsCommand,
6681
+ "bidding-strategies": biddingStrategiesCommand,
6682
+ labels: labelsCommand,
6683
+ "campaign-criteria": campaignCriteriaCommand
6684
+ };
6685
+
5145
6686
  // src/commands/ads/google/index.ts
5146
- var googleCommand = defineCommand29({
6687
+ var keywordsWithWrites = defineCommand31({
6688
+ meta: keywordsCommand.meta,
6689
+ subCommands: { ...keywordsCommand.subCommands, ...keywordWriteSubcommands }
6690
+ });
6691
+ var googleCommand = defineCommand31({
5147
6692
  meta: {
5148
6693
  name: "google",
5149
6694
  description: `Google Ads commands. Query campaigns, keywords, search terms, and more via GAQL.
@@ -5158,20 +6703,28 @@ Examples:
5158
6703
  baker ads google query --preset campaign-performance --customer-id 1234567890
5159
6704
  baker ads google currency --customer-id 1234567890
5160
6705
  baker ads google keywords discover --customer-id 1234567890 --seeds "running shoes"
5161
- baker ads google library list-advertisers \u2014 list tracked Google advertisers`
6706
+ baker ads google library list-advertisers \u2014 list tracked Google advertisers
6707
+
6708
+ Staged writes (never touch Google until the chat is published):
6709
+ baker ads google budgets create --customer-id 1234567890 --name "Search" --amount 50
6710
+ baker ads google campaigns create --customer-id 1234567890 --name "Brand" --channel-type SEARCH --budget-ref g_temp_\u2026 --bidding-strategy MANUAL_CPC
6711
+ baker ads google keyword-lists create --customer-id 1234567890 --name "Brand exclusions"
6712
+ baker ads google draft list \u2014 review staged Google Ads changes`
5162
6713
  },
5163
6714
  subCommands: {
5164
6715
  accounts: accountsCommand,
5165
6716
  currency: currencyCommand,
5166
6717
  changes: changesCommand,
5167
6718
  query: queryCommand,
5168
- keywords: keywordsCommand,
5169
- library
6719
+ keywords: keywordsWithWrites,
6720
+ library,
6721
+ ...googleWriteCommands,
6722
+ draft: draftCommand2
5170
6723
  }
5171
6724
  });
5172
6725
 
5173
6726
  // src/commands/ads/linkedin/index.ts
5174
- import { defineCommand as defineCommand49 } from "citty";
6727
+ import { defineCommand as defineCommand51 } from "citty";
5175
6728
 
5176
6729
  // src/commands/ads/linkedin/schemas.ts
5177
6730
  registerSchema({
@@ -5832,7 +7385,7 @@ registerSchema({
5832
7385
  });
5833
7386
 
5834
7387
  // src/commands/ads/linkedin/account.ts
5835
- import { defineCommand as defineCommand30 } from "citty";
7388
+ import { defineCommand as defineCommand32 } from "citty";
5836
7389
 
5837
7390
  // src/commands/ads/linkedin/shared.ts
5838
7391
  var DAY_MS2 = 864e5;
@@ -5935,7 +7488,7 @@ function resolveStatusFilter(args) {
5935
7488
  }
5936
7489
 
5937
7490
  // src/commands/ads/linkedin/account.ts
5938
- var accountCommand = defineCommand30({
7491
+ var accountCommand = defineCommand32({
5939
7492
  meta: {
5940
7493
  name: "account",
5941
7494
  description: `Single LinkedIn ad account detail (currency, status, type).
@@ -5969,9 +7522,9 @@ Examples:
5969
7522
  });
5970
7523
 
5971
7524
  // src/commands/ads/linkedin/accounts.ts
5972
- import { defineCommand as defineCommand31 } from "citty";
7525
+ import { defineCommand as defineCommand33 } from "citty";
5973
7526
  var ACCOUNTS_TTL_MS = 60 * 60 * 1e3;
5974
- var accountsCommand2 = defineCommand31({
7527
+ var accountsCommand2 = defineCommand33({
5975
7528
  meta: {
5976
7529
  name: "accounts",
5977
7530
  description: `List LinkedIn ad accounts in this company's connected scope.
@@ -6019,7 +7572,7 @@ Examples:
6019
7572
  });
6020
7573
 
6021
7574
  // src/commands/ads/linkedin/analytics.ts
6022
- import { defineCommand as defineCommand32 } from "citty";
7575
+ import { defineCommand as defineCommand34 } from "citty";
6023
7576
 
6024
7577
  // src/commands/ads/linkedin/presets.ts
6025
7578
  var INTENTS = {
@@ -6291,7 +7844,7 @@ function numberOf(v) {
6291
7844
  }
6292
7845
  return 0;
6293
7846
  }
6294
- var analyticsCommand = defineCommand32({
7847
+ var analyticsCommand = defineCommand34({
6295
7848
  meta: {
6296
7849
  name: "analytics",
6297
7850
  description: `Performance reporting \u2014 the workhorse for AI agents.
@@ -6418,8 +7971,8 @@ Examples \u2014 common AI questions:
6418
7971
  });
6419
7972
 
6420
7973
  // src/commands/ads/linkedin/audience-size.ts
6421
- import { readFileSync as readFileSync4 } from "fs";
6422
- import { defineCommand as defineCommand33 } from "citty";
7974
+ import { readFileSync as readFileSync5 } from "fs";
7975
+ import { defineCommand as defineCommand35 } from "citty";
6423
7976
  function loadTargeting(args) {
6424
7977
  const inline = args.targeting;
6425
7978
  if (inline) {
@@ -6432,7 +7985,7 @@ function loadTargeting(args) {
6432
7985
  const file = args["targeting-file"];
6433
7986
  if (file) {
6434
7987
  try {
6435
- return JSON.parse(readFileSync4(file, "utf-8"));
7988
+ return JSON.parse(readFileSync5(file, "utf-8"));
6436
7989
  } catch (e) {
6437
7990
  handleLinkedinError(
6438
7991
  new Error(`Failed to read --targeting-file: ${e instanceof Error ? e.message : "I/O error"}`)
@@ -6441,7 +7994,7 @@ function loadTargeting(args) {
6441
7994
  }
6442
7995
  handleLinkedinError(new Error("Pass --targeting-file <path> or --targeting '{...JSON...}'"));
6443
7996
  }
6444
- var audienceSizeCommand = defineCommand33({
7997
+ var audienceSizeCommand = defineCommand35({
6445
7998
  meta: {
6446
7999
  name: "audience-size",
6447
8000
  description: `Estimate audience size for a targeting payload \u2014 pre-launch sanity check.
@@ -6486,7 +8039,7 @@ Examples:
6486
8039
  });
6487
8040
 
6488
8041
  // src/commands/ads/linkedin/audit.ts
6489
- import { defineCommand as defineCommand34 } from "citty";
8042
+ import { defineCommand as defineCommand36 } from "citty";
6490
8043
  var SEVERITY_RANK = {
6491
8044
  critical: 0,
6492
8045
  high: 1,
@@ -6545,7 +8098,7 @@ function noteOf(f) {
6545
8098
  const fix = f.fix?.explanation ?? "";
6546
8099
  return [fix, ev].filter(Boolean).join(" \u2014 ");
6547
8100
  }
6548
- var auditCommand = defineCommand34({
8101
+ var auditCommand = defineCommand36({
6549
8102
  meta: {
6550
8103
  name: "audit",
6551
8104
  description: `Run a LinkedIn Ads playbook audit \u2014 30+ checks across Settings, Tracking,
@@ -6611,8 +8164,8 @@ Examples:
6611
8164
  });
6612
8165
 
6613
8166
  // src/commands/ads/linkedin/bid-pricing.ts
6614
- import { readFileSync as readFileSync5 } from "fs";
6615
- import { defineCommand as defineCommand35 } from "citty";
8167
+ import { readFileSync as readFileSync6 } from "fs";
8168
+ import { defineCommand as defineCommand37 } from "citty";
6616
8169
  function loadTargeting2(args) {
6617
8170
  const inline = args.targeting;
6618
8171
  if (inline) {
@@ -6625,7 +8178,7 @@ function loadTargeting2(args) {
6625
8178
  const file = args["targeting-file"];
6626
8179
  if (file) {
6627
8180
  try {
6628
- return JSON.parse(readFileSync5(file, "utf-8"));
8181
+ return JSON.parse(readFileSync6(file, "utf-8"));
6629
8182
  } catch (e) {
6630
8183
  handleLinkedinError(
6631
8184
  new Error(`Failed to read --targeting-file: ${e instanceof Error ? e.message : "I/O error"}`)
@@ -6634,7 +8187,7 @@ function loadTargeting2(args) {
6634
8187
  }
6635
8188
  handleLinkedinError(new Error("Pass --targeting-file <path> or --targeting '{...JSON...}'"));
6636
8189
  }
6637
- var bidPricingCommand = defineCommand35({
8190
+ var bidPricingCommand = defineCommand37({
6638
8191
  meta: {
6639
8192
  name: "bid-pricing",
6640
8193
  description: `Get LinkedIn's suggested bid range for a targeting + objective + cost type.
@@ -6684,40 +8237,40 @@ Examples:
6684
8237
  });
6685
8238
 
6686
8239
  // src/commands/ads/linkedin/campaign-groups.ts
6687
- import { defineCommand as defineCommand37 } from "citty";
8240
+ import { defineCommand as defineCommand39 } from "citty";
6688
8241
 
6689
8242
  // src/commands/ads/linkedin/write-commands.ts
6690
- import { defineCommand as defineCommand36 } from "citty";
8243
+ import { defineCommand as defineCommand38 } from "citty";
6691
8244
 
6692
8245
  // src/commands/ads/linkedin/write-shared.ts
6693
8246
  import { createHash as createHash2 } from "crypto";
6694
- import { readFileSync as readFileSync6 } from "fs";
8247
+ import { readFileSync as readFileSync7 } from "fs";
6695
8248
  function bareAccountId(args) {
6696
8249
  const raw = resolveAccountIdArg(args);
6697
8250
  return raw.replace(/^urn:li:sponsoredAccount:/, "").replace(/^sponsoredAccount:/, "");
6698
8251
  }
6699
- function failWriteValidation(message) {
8252
+ function failWriteValidation2(message) {
6700
8253
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
6701
8254
  process.exit(1);
6702
8255
  }
6703
- function loadJsonFileArg(path12) {
8256
+ function loadJsonFileArg2(path12) {
6704
8257
  if (typeof path12 !== "string" || path12.length === 0) {
6705
8258
  return {};
6706
8259
  }
6707
8260
  try {
6708
- const parsed = JSON.parse(readFileSync6(path12, "utf8"));
8261
+ const parsed = JSON.parse(readFileSync7(path12, "utf8"));
6709
8262
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
6710
- failWriteValidation(`${path12} must contain a JSON object`);
8263
+ failWriteValidation2(`${path12} must contain a JSON object`);
6711
8264
  }
6712
8265
  return parsed;
6713
8266
  } catch (err) {
6714
8267
  if (err instanceof SyntaxError) {
6715
- failWriteValidation(`${path12} is not valid JSON: ${err.message}`);
8268
+ failWriteValidation2(`${path12} is not valid JSON: ${err.message}`);
6716
8269
  }
6717
8270
  throw err;
6718
8271
  }
6719
8272
  }
6720
- function mergePayload(file, flags) {
8273
+ function mergePayload2(file, flags) {
6721
8274
  const merged = { ...file };
6722
8275
  for (const [key, value] of Object.entries(flags)) {
6723
8276
  if (value !== void 0) {
@@ -6734,7 +8287,7 @@ function parseMoneyFlag(amount, currency, flag) {
6734
8287
  return { amount: String(amount) };
6735
8288
  }
6736
8289
  if (typeof currency !== "string" || currency.length !== 3) {
6737
- failWriteValidation(`${flag} got an invalid --currency (expected a 3-letter code like EUR)`);
8290
+ failWriteValidation2(`${flag} got an invalid --currency (expected a 3-letter code like EUR)`);
6738
8291
  }
6739
8292
  return { amount: String(amount), currencyCode: currency.toUpperCase() };
6740
8293
  }
@@ -6748,7 +8301,7 @@ function parseDateFlag(value, flag) {
6748
8301
  }
6749
8302
  const parsed = Date.parse(raw);
6750
8303
  if (Number.isNaN(parsed)) {
6751
- failWriteValidation(`${flag} must be an ISO date (2026-07-10) or epoch milliseconds`);
8304
+ failWriteValidation2(`${flag} must be an ISO date (2026-07-10) or epoch milliseconds`);
6752
8305
  }
6753
8306
  return parsed;
6754
8307
  }
@@ -6763,7 +8316,7 @@ function parseOnOffFlag(value, flag) {
6763
8316
  if (raw === "off" || raw === "false") {
6764
8317
  return false;
6765
8318
  }
6766
- failWriteValidation(`${flag} must be on|off`);
8319
+ failWriteValidation2(`${flag} must be on|off`);
6767
8320
  }
6768
8321
  function parseLocaleFlag(value) {
6769
8322
  if (value === void 0 || value === null || value === "") {
@@ -6771,7 +8324,7 @@ function parseLocaleFlag(value) {
6771
8324
  }
6772
8325
  const match = /^([a-z]{2})[_-]([A-Za-z]{2})$/.exec(String(value));
6773
8326
  if (!match) {
6774
- failWriteValidation("--locale must look like en_US (language_COUNTRY)");
8327
+ failWriteValidation2("--locale must look like en_US (language_COUNTRY)");
6775
8328
  }
6776
8329
  return { language: match[1], country: match[2].toUpperCase() };
6777
8330
  }
@@ -6779,10 +8332,10 @@ function loadTargetingFileArg(path12) {
6779
8332
  if (typeof path12 !== "string" || path12.length === 0) {
6780
8333
  return void 0;
6781
8334
  }
6782
- const parsed = loadJsonFileArg(path12);
8335
+ const parsed = loadJsonFileArg2(path12);
6783
8336
  const criteria = parsed.targetingCriteria ?? parsed;
6784
8337
  if (!criteria.include) {
6785
- failWriteValidation(
8338
+ failWriteValidation2(
6786
8339
  `${path12} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
6787
8340
  );
6788
8341
  }
@@ -6822,10 +8375,10 @@ function parseListFileArg(path12, maxRows) {
6822
8375
  if (typeof path12 !== "string" || path12.length === 0) {
6823
8376
  return void 0;
6824
8377
  }
6825
- const raw = readFileSync6(path12, "utf8");
8378
+ const raw = readFileSync7(path12, "utf8");
6826
8379
  const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
6827
8380
  if (lines.length < 2) {
6828
- failWriteValidation(`${path12} needs a header row and at least one data row`);
8381
+ failWriteValidation2(`${path12} needs a header row and at least one data row`);
6829
8382
  }
6830
8383
  const columns = parseCsvLine(lines[0]).map((column) => column.trim());
6831
8384
  const rows = [];
@@ -6844,7 +8397,7 @@ function parseListFileArg(path12, maxRows) {
6844
8397
  }
6845
8398
  }
6846
8399
  if (rows.length > maxRows) {
6847
- failWriteValidation(`${path12} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
8400
+ failWriteValidation2(`${path12} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
6848
8401
  }
6849
8402
  return { columns, rows };
6850
8403
  }
@@ -6880,10 +8433,10 @@ async function stageStatusChange(input) {
6880
8433
  const payload = input.kind === "creative.update" ? { intendedStatus: input.status } : { status: input.status };
6881
8434
  await stageOp({ kind: input.kind, accountId: input.accountId, target: input.target, payload });
6882
8435
  }
6883
- function requireTarget(args, entity) {
8436
+ function requireTarget2(args, entity) {
6884
8437
  const target = args.id ?? args.target;
6885
8438
  if (typeof target !== "string" || target.length === 0) {
6886
- failWriteValidation(`pass the ${entity} id or URN as the positional argument`);
8439
+ failWriteValidation2(`pass the ${entity} id or URN as the positional argument`);
6887
8440
  }
6888
8441
  return target;
6889
8442
  }
@@ -6902,7 +8455,7 @@ function runScheduleFromFlags(args) {
6902
8455
  }
6903
8456
  return { ...start !== void 0 ? { start } : {}, ...end !== void 0 ? { end } : {} };
6904
8457
  }
6905
- var campaignGroupsCreateCommand = defineCommand36({
8458
+ var campaignGroupsCreateCommand = defineCommand38({
6906
8459
  meta: {
6907
8460
  name: "create",
6908
8461
  description: `Stage a new campaign group. ${STAGED_NOTE}
@@ -6920,7 +8473,7 @@ Example: baker ads linkedin campaign-groups create --name "Q3 ABM" --start 2026-
6920
8473
  },
6921
8474
  run: async ({ args }) => {
6922
8475
  const accountId = bareAccountId(args);
6923
- const payload = mergePayload(loadJsonFileArg(args.file), {
8476
+ const payload = mergePayload2(loadJsonFileArg2(args.file), {
6924
8477
  name: args.name,
6925
8478
  runSchedule: runScheduleFromFlags(args),
6926
8479
  totalBudget: parseMoneyFlag(args["total-budget"], args.currency, "--total-budget"),
@@ -6929,7 +8482,7 @@ Example: baker ads linkedin campaign-groups create --name "Q3 ABM" --start 2026-
6929
8482
  await stageOp({ kind: "campaignGroup.create", accountId, payload });
6930
8483
  }
6931
8484
  });
6932
- var campaignGroupsUpdateCommand = defineCommand36({
8485
+ var campaignGroupsUpdateCommand = defineCommand38({
6933
8486
  meta: {
6934
8487
  name: "update",
6935
8488
  description: `Stage changes to an existing campaign group. ${STAGED_NOTE}
@@ -6949,7 +8502,7 @@ Example: baker ads linkedin campaign-groups update 635137195 --total-budget 8000
6949
8502
  },
6950
8503
  run: async ({ args }) => {
6951
8504
  const accountId = bareAccountId(args);
6952
- const payload = mergePayload(loadJsonFileArg(args.file), {
8505
+ const payload = mergePayload2(loadJsonFileArg2(args.file), {
6953
8506
  name: args.name,
6954
8507
  runSchedule: runScheduleFromFlags(args),
6955
8508
  totalBudget: parseMoneyFlag(args["total-budget"], args.currency, "--total-budget"),
@@ -6958,7 +8511,7 @@ Example: baker ads linkedin campaign-groups update 635137195 --total-budget 8000
6958
8511
  await stageOp({
6959
8512
  kind: "campaignGroup.update",
6960
8513
  accountId,
6961
- target: requireTarget(args, "campaign group"),
8514
+ target: requireTarget2(args, "campaign group"),
6962
8515
  payload
6963
8516
  });
6964
8517
  }
@@ -7007,7 +8560,7 @@ var campaignFlagArgs = {
7007
8560
  status: { type: "string", description: "DRAFT|ACTIVE|PAUSED" },
7008
8561
  file: { type: "string", description: "JSON file with the full payload; flags override file keys" }
7009
8562
  };
7010
- var campaignsCreateCommand = defineCommand36({
8563
+ var campaignsCreateCommand = defineCommand38({
7011
8564
  meta: {
7012
8565
  name: "create",
7013
8566
  description: `Stage a new campaign. ${STAGED_NOTE}
@@ -7017,14 +8570,14 @@ Example: baker ads linkedin campaigns create --name "ABM Tier-1" --group li_temp
7017
8570
  args: campaignFlagArgs,
7018
8571
  run: async ({ args }) => {
7019
8572
  const accountId = bareAccountId(args);
7020
- const payload = mergePayload(loadJsonFileArg(args.file), campaignPayloadFromFlags(args));
8573
+ const payload = mergePayload2(loadJsonFileArg2(args.file), campaignPayloadFromFlags(args));
7021
8574
  if (payload.locale === void 0) {
7022
8575
  payload.locale = { country: "US", language: "en" };
7023
8576
  }
7024
8577
  await stageOp({ kind: "campaign.create", accountId, payload });
7025
8578
  }
7026
8579
  });
7027
- var campaignsUpdateCommand = defineCommand36({
8580
+ var campaignsUpdateCommand = defineCommand38({
7028
8581
  meta: {
7029
8582
  name: "update",
7030
8583
  description: `Stage changes to an existing campaign (budget, bid, targeting, flags, schedule, status). ${STAGED_NOTE}
@@ -7042,18 +8595,18 @@ Example: baker ads linkedin campaigns update 123456 --daily-budget 100 --currenc
7042
8595
  flags.type = void 0;
7043
8596
  flags.locale = void 0;
7044
8597
  flags.associatedEntity = void 0;
7045
- const payload = mergePayload(loadJsonFileArg(args.file), flags);
8598
+ const payload = mergePayload2(loadJsonFileArg2(args.file), flags);
7046
8599
  await stageOp({
7047
8600
  kind: "campaign.update",
7048
8601
  accountId,
7049
- target: requireTarget(args, "campaign"),
8602
+ target: requireTarget2(args, "campaign"),
7050
8603
  payload
7051
8604
  });
7052
8605
  }
7053
8606
  });
7054
8607
  function statusSugarCommand(entity, kind, name) {
7055
8608
  const status = name === "pause" ? "PAUSED" : name === "resume" ? "ACTIVE" : "ARCHIVED";
7056
- return defineCommand36({
8609
+ return defineCommand38({
7057
8610
  meta: {
7058
8611
  name,
7059
8612
  description: `Stage a status change to ${status}. ${STAGED_NOTE}
@@ -7067,7 +8620,7 @@ Example: baker ads linkedin ${entity} ${name} 123456`
7067
8620
  await stageStatusChange({
7068
8621
  kind,
7069
8622
  accountId: bareAccountId(args),
7070
- target: requireTarget(args, entity.replace(/-/g, " ").replace(/s$/, "")),
8623
+ target: requireTarget2(args, entity.replace(/-/g, " ").replace(/s$/, "")),
7071
8624
  status
7072
8625
  });
7073
8626
  }
@@ -7081,7 +8634,7 @@ var campaignGroupsResumeCommand = statusSugarCommand("campaign-groups", "campaig
7081
8634
  var creativesPauseCommand = statusSugarCommand("creatives", "creative.update", "pause");
7082
8635
  var creativesResumeCommand = statusSugarCommand("creatives", "creative.update", "resume");
7083
8636
  function duplicateCommand(entity, cliGroup) {
7084
- return defineCommand36({
8637
+ return defineCommand38({
7085
8638
  meta: {
7086
8639
  name: "duplicate",
7087
8640
  description: `Stage a copy of an existing ${entity} as a new DRAFT create (playbook: duplicate, never link-to-original). ${STAGED_NOTE}
@@ -7096,14 +8649,14 @@ Example: baker ads linkedin ${cliGroup} duplicate 123456 --name "New variant"`
7096
8649
  run: async ({ args }) => {
7097
8650
  try {
7098
8651
  const chatId = requireChatId();
7099
- const overrides = mergePayload(loadJsonFileArg(args.file), { name: args.name });
8652
+ const overrides = mergePayload2(loadJsonFileArg2(args.file), { name: args.name });
7100
8653
  const response = await apiPost(
7101
8654
  "/api/ads/linkedin/draft/duplicate",
7102
8655
  {
7103
8656
  chatId,
7104
8657
  accountId: bareAccountId(args),
7105
8658
  entity,
7106
- sourceId: requireTarget(args, entity),
8659
+ sourceId: requireTarget2(args, entity),
7107
8660
  ...Object.keys(overrides).length > 0 ? { overrides } : {}
7108
8661
  }
7109
8662
  );
@@ -7116,7 +8669,7 @@ Example: baker ads linkedin ${cliGroup} duplicate 123456 --name "New variant"`
7116
8669
  }
7117
8670
  var campaignsDuplicateCommand = duplicateCommand("campaign", "campaigns");
7118
8671
  var campaignGroupsDuplicateCommand = duplicateCommand("campaignGroup", "campaign-groups");
7119
- var creativesDuplicateCommand = defineCommand36({
8672
+ var creativesDuplicateCommand = defineCommand38({
7120
8673
  meta: {
7121
8674
  name: "duplicate",
7122
8675
  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}
@@ -7154,10 +8707,10 @@ Examples:
7154
8707
  run: async ({ args }) => {
7155
8708
  try {
7156
8709
  const chatId = requireChatId();
7157
- const file = loadJsonFileArg(args.file);
8710
+ const file = loadJsonFileArg2(args.file);
7158
8711
  const fileContent = file.content !== null && typeof file.content === "object" && !Array.isArray(file.content) ? file.content : {};
7159
8712
  const content = { ...fileContent, ...creativeContentPatch(args) };
7160
- const overrides = mergePayload(file, {
8713
+ const overrides = mergePayload2(file, {
7161
8714
  campaign: args.campaign,
7162
8715
  intendedStatus: args["intended-status"] ? String(args["intended-status"]).toUpperCase() : void 0,
7163
8716
  content: Object.keys(content).length > 0 ? content : void 0
@@ -7168,7 +8721,7 @@ Examples:
7168
8721
  chatId,
7169
8722
  accountId: bareAccountId(args),
7170
8723
  entity: "creative",
7171
- sourceId: requireTarget(args, "creative"),
8724
+ sourceId: requireTarget2(args, "creative"),
7172
8725
  ...Object.keys(overrides).length > 0 ? { overrides } : {},
7173
8726
  ...args.replace ? { replace: true } : {}
7174
8727
  }
@@ -7193,7 +8746,7 @@ var CREATIVE_FORMATS = [
7193
8746
  "event",
7194
8747
  "article"
7195
8748
  ];
7196
- var creativesCreateCommand = defineCommand36({
8749
+ var creativesCreateCommand = defineCommand38({
7197
8750
  meta: {
7198
8751
  name: "create",
7199
8752
  description: `Stage a new creative (ad). ${STAGED_NOTE}
@@ -7229,13 +8782,13 @@ Examples:
7229
8782
  run: async ({ args }) => {
7230
8783
  const accountId = bareAccountId(args);
7231
8784
  if (!args.campaign) {
7232
- failWriteValidation("--campaign is required (id, URN, or li_temp_* ref)");
8785
+ failWriteValidation2("--campaign is required (id, URN, or li_temp_* ref)");
7233
8786
  }
7234
8787
  const format = args.format ? String(args.format) : void 0;
7235
8788
  if (!format || !CREATIVE_FORMATS.includes(format)) {
7236
- failWriteValidation(`--format must be one of ${CREATIVE_FORMATS.join("|")}`);
8789
+ failWriteValidation2(`--format must be one of ${CREATIVE_FORMATS.join("|")}`);
7237
8790
  }
7238
- const content = mergePayload(loadJsonFileArg(args.file), {
8791
+ const content = mergePayload2(loadJsonFileArg2(args.file), {
7239
8792
  format,
7240
8793
  commentary: args.intro,
7241
8794
  imageId: args["image-id"],
@@ -7294,7 +8847,7 @@ function creativeContentPatch(args) {
7294
8847
  }
7295
8848
  return patch;
7296
8849
  }
7297
- var creativesUpdateCommand = defineCommand36({
8850
+ var creativesUpdateCommand = defineCommand38({
7298
8851
  meta: {
7299
8852
  name: "update",
7300
8853
  description: `Stage changes to an existing creative, or amend a creative staged in this chat by passing its li_temp_* ref. ${STAGED_NOTE}
@@ -7326,13 +8879,13 @@ Examples:
7326
8879
  },
7327
8880
  run: async ({ args }) => {
7328
8881
  const accountId = bareAccountId(args);
7329
- const target = requireTarget(args, "creative");
7330
- const file = loadJsonFileArg(args.file);
8882
+ const target = requireTarget2(args, "creative");
8883
+ const file = loadJsonFileArg2(args.file);
7331
8884
  const contentPatch = creativeContentPatch(args);
7332
8885
  const intendedStatus = args["intended-status"] ? String(args["intended-status"]).toUpperCase() : void 0;
7333
8886
  const fileContent = file.content !== null && typeof file.content === "object" && !Array.isArray(file.content) ? file.content : {};
7334
8887
  const content = { ...fileContent, ...contentPatch };
7335
- const payload = mergePayload(file, {
8888
+ const payload = mergePayload2(file, {
7336
8889
  intendedStatus,
7337
8890
  name: args.name,
7338
8891
  content: Object.keys(content).length > 0 ? content : void 0
@@ -7342,7 +8895,7 @@ Examples:
7342
8895
  });
7343
8896
  var AUDIENCE_TYPES2 = ["company-list", "user-list", "retargeting", "engagement"];
7344
8897
  var INLINE_ROWS_MAX = 1e4;
7345
- var audiencesCreateCommand = defineCommand36({
8898
+ var audiencesCreateCommand = defineCommand38({
7346
8899
  meta: {
7347
8900
  name: "create",
7348
8901
  description: `Stage a new matched audience. ${STAGED_NOTE}
@@ -7359,7 +8912,7 @@ Example: baker ads linkedin audiences create --name "ABM Tier-1" --type company-
7359
8912
  run: async ({ args }) => {
7360
8913
  const accountId = bareAccountId(args);
7361
8914
  const list = parseListFileArg(args["list-file"], INLINE_ROWS_MAX);
7362
- const raw = args.file ? loadJsonFileArg(args.file) : void 0;
8915
+ const raw = args.file ? loadJsonFileArg2(args.file) : void 0;
7363
8916
  await stageOp({
7364
8917
  kind: "audience.create",
7365
8918
  accountId,
@@ -7372,7 +8925,7 @@ Example: baker ads linkedin audiences create --name "ABM Tier-1" --type company-
7372
8925
  });
7373
8926
  }
7374
8927
  });
7375
- var audiencesUploadCommand = defineCommand36({
8928
+ var audiencesUploadCommand = defineCommand38({
7376
8929
  meta: {
7377
8930
  name: "upload",
7378
8931
  description: `Stage a list upload into an existing audience segment. ${STAGED_NOTE}
@@ -7387,20 +8940,20 @@ Example: baker ads linkedin audiences upload urn:li:dmpSegment:42 --list-file mo
7387
8940
  const accountId = bareAccountId(args);
7388
8941
  const list = parseListFileArg(args["list-file"], INLINE_ROWS_MAX);
7389
8942
  if (!list) {
7390
- failWriteValidation("--list-file is required");
8943
+ failWriteValidation2("--list-file is required");
7391
8944
  }
7392
8945
  await stageOp({
7393
8946
  kind: "audience.uploadList",
7394
8947
  accountId,
7395
8948
  payload: {
7396
- segment: requireTarget(args, "audience segment"),
8949
+ segment: requireTarget2(args, "audience segment"),
7397
8950
  listColumns: list.columns,
7398
8951
  listRows: list.rows
7399
8952
  }
7400
8953
  });
7401
8954
  }
7402
8955
  });
7403
- var audiencesCommand = defineCommand36({
8956
+ var audiencesCommand2 = defineCommand38({
7404
8957
  meta: {
7405
8958
  name: "audiences",
7406
8959
  description: "Stage LinkedIn matched-audience changes (create lists, upload rows). Staged until publish \u2014 never hits the API directly."
@@ -7410,7 +8963,7 @@ var audiencesCommand = defineCommand36({
7410
8963
  upload: audiencesUploadCommand
7411
8964
  }
7412
8965
  });
7413
- var conversionsCreateCommand = defineCommand36({
8966
+ var conversionsCreateCommand = defineCommand38({
7414
8967
  meta: {
7415
8968
  name: "create",
7416
8969
  description: `Stage a new conversion rule. ${STAGED_NOTE}
@@ -7429,7 +8982,7 @@ Example: baker ads linkedin conversions create --name "Demo booked" --type LEAD
7429
8982
  },
7430
8983
  run: async ({ args }) => {
7431
8984
  const accountId = bareAccountId(args);
7432
- const payload = mergePayload(loadJsonFileArg(args.file), {
8985
+ const payload = mergePayload2(loadJsonFileArg2(args.file), {
7433
8986
  name: args.name,
7434
8987
  type: args.type ? String(args.type).toUpperCase() : void 0,
7435
8988
  conversionMethod: args.method ? String(args.method).toUpperCase() : void 0,
@@ -7441,7 +8994,7 @@ Example: baker ads linkedin conversions create --name "Demo booked" --type LEAD
7441
8994
  await stageOp({ kind: "conversion.create", accountId, payload });
7442
8995
  }
7443
8996
  });
7444
- var conversionsUpdateCommand = defineCommand36({
8997
+ var conversionsUpdateCommand = defineCommand38({
7445
8998
  meta: {
7446
8999
  name: "update",
7447
9000
  description: `Stage changes to a conversion rule (windows, name, enabled). ${STAGED_NOTE}
@@ -7459,7 +9012,7 @@ Example: baker ads linkedin conversions update 104988516 --post-click-window 30
7459
9012
  },
7460
9013
  run: async ({ args }) => {
7461
9014
  const accountId = bareAccountId(args);
7462
- const payload = mergePayload(loadJsonFileArg(args.file), {
9015
+ const payload = mergePayload2(loadJsonFileArg2(args.file), {
7463
9016
  name: args.name,
7464
9017
  postClickAttributionWindowSize: args["post-click-window"] ? Number(args["post-click-window"]) : void 0,
7465
9018
  viewThroughAttributionWindowSize: args["view-window"] ? Number(args["view-window"]) : void 0,
@@ -7469,12 +9022,12 @@ Example: baker ads linkedin conversions update 104988516 --post-click-window 30
7469
9022
  await stageOp({
7470
9023
  kind: "conversion.update",
7471
9024
  accountId,
7472
- target: requireTarget(args, "conversion rule"),
9025
+ target: requireTarget2(args, "conversion rule"),
7473
9026
  payload
7474
9027
  });
7475
9028
  }
7476
9029
  });
7477
- var leadFormsCreateCommand = defineCommand36({
9030
+ var leadFormsCreateCommand = defineCommand38({
7478
9031
  meta: {
7479
9032
  name: "create",
7480
9033
  description: `Stage a new Lead Gen Form from a JSON file. ${STAGED_NOTE}
@@ -7487,11 +9040,11 @@ The file needs: name, headline (\u226460), privacyPolicyUrl, questions[] (\u2264
7487
9040
  },
7488
9041
  run: async ({ args }) => {
7489
9042
  const accountId = bareAccountId(args);
7490
- const payload = mergePayload(loadJsonFileArg(args.file), { name: args.name });
9043
+ const payload = mergePayload2(loadJsonFileArg2(args.file), { name: args.name });
7491
9044
  await stageOp({ kind: "leadForm.create", accountId, payload });
7492
9045
  }
7493
9046
  });
7494
- var leadFormsUpdateCommand = defineCommand36({
9047
+ var leadFormsUpdateCommand = defineCommand38({
7495
9048
  meta: {
7496
9049
  name: "update",
7497
9050
  description: `Stage changes to a Lead Gen Form from a JSON file. ${STAGED_NOTE}`
@@ -7504,16 +9057,16 @@ var leadFormsUpdateCommand = defineCommand36({
7504
9057
  },
7505
9058
  run: async ({ args }) => {
7506
9059
  const accountId = bareAccountId(args);
7507
- const payload = mergePayload({ raw: loadJsonFileArg(args.file) }, { name: args.name });
9060
+ const payload = mergePayload2({ raw: loadJsonFileArg2(args.file) }, { name: args.name });
7508
9061
  await stageOp({
7509
9062
  kind: "leadForm.update",
7510
9063
  accountId,
7511
- target: requireTarget(args, "lead form"),
9064
+ target: requireTarget2(args, "lead form"),
7512
9065
  payload
7513
9066
  });
7514
9067
  }
7515
9068
  });
7516
- var leadFormsCommand = defineCommand36({
9069
+ var leadFormsCommand = defineCommand38({
7517
9070
  meta: {
7518
9071
  name: "lead-forms",
7519
9072
  description: "Stage LinkedIn Lead Gen Form changes (file-first). Staged until publish \u2014 never hits the API directly."
@@ -7525,7 +9078,7 @@ var leadFormsCommand = defineCommand36({
7525
9078
  });
7526
9079
 
7527
9080
  // src/commands/ads/linkedin/campaign-groups.ts
7528
- var campaignGroupsCommand = defineCommand37({
9081
+ var campaignGroupsCommand = defineCommand39({
7529
9082
  meta: {
7530
9083
  name: "campaign-groups",
7531
9084
  description: `List LinkedIn campaign groups, or stage writes (create/update/pause/resume/duplicate).
@@ -7576,8 +9129,8 @@ Examples:
7576
9129
  });
7577
9130
 
7578
9131
  // src/commands/ads/linkedin/campaigns.ts
7579
- import { defineCommand as defineCommand38 } from "citty";
7580
- var campaignsCommand = defineCommand38({
9132
+ import { defineCommand as defineCommand40 } from "citty";
9133
+ var campaignsCommand2 = defineCommand40({
7581
9134
  meta: {
7582
9135
  name: "campaigns",
7583
9136
  description: `List LinkedIn campaigns, or stage writes (create/update/pause/resume/archive/duplicate).
@@ -7638,8 +9191,8 @@ Examples:
7638
9191
  });
7639
9192
 
7640
9193
  // src/commands/ads/linkedin/conversation.ts
7641
- import { defineCommand as defineCommand39 } from "citty";
7642
- var conversationCommand = defineCommand39({
9194
+ import { defineCommand as defineCommand41 } from "citty";
9195
+ var conversationCommand = defineCommand41({
7643
9196
  meta: {
7644
9197
  name: "conversation",
7645
9198
  description: `Per-button click rates inside Sponsored Messaging / Conversation Ads.
@@ -7702,7 +9255,7 @@ Examples:
7702
9255
  });
7703
9256
 
7704
9257
  // src/commands/ads/linkedin/conversions.ts
7705
- import { defineCommand as defineCommand40 } from "citty";
9258
+ import { defineCommand as defineCommand42 } from "citty";
7706
9259
  var DAY_MS3 = 864e5;
7707
9260
  function healthOf(rules) {
7708
9261
  const enabled = rules.filter((r) => r.enabled !== false);
@@ -7728,7 +9281,7 @@ function healthOf(rules) {
7728
9281
  wrongLeadDedup: wrongDedup
7729
9282
  };
7730
9283
  }
7731
- var listCmd = defineCommand40({
9284
+ var listCmd = defineCommand42({
7732
9285
  meta: {
7733
9286
  name: "list",
7734
9287
  description: `List conversion rules on the account.`
@@ -7756,7 +9309,7 @@ var listCmd = defineCommand40({
7756
9309
  }
7757
9310
  }
7758
9311
  });
7759
- var healthCmd = defineCommand40({
9312
+ var healthCmd = defineCommand42({
7760
9313
  meta: {
7761
9314
  name: "health",
7762
9315
  description: `5-point Insight Tag / CAPI health check (playbook \xA707).
@@ -7786,7 +9339,7 @@ Surfaces:
7786
9339
  }
7787
9340
  }
7788
9341
  });
7789
- var conversionsCommand = defineCommand40({
9342
+ var conversionsCommand2 = defineCommand42({
7790
9343
  meta: {
7791
9344
  name: "conversions",
7792
9345
  description: `Conversion rules \u2014 Insight Tag and Conversions API.
@@ -7805,8 +9358,8 @@ Subcommands:
7805
9358
  });
7806
9359
 
7807
9360
  // src/commands/ads/linkedin/creatives.ts
7808
- import { defineCommand as defineCommand41 } from "citty";
7809
- var creativesCommand = defineCommand41({
9361
+ import { defineCommand as defineCommand43 } from "citty";
9362
+ var creativesCommand = defineCommand43({
7810
9363
  meta: {
7811
9364
  name: "creatives",
7812
9365
  description: `List LinkedIn creatives (ads), or stage writes (create/update/pause/resume/duplicate).
@@ -7865,7 +9418,7 @@ Examples:
7865
9418
  });
7866
9419
 
7867
9420
  // src/commands/ads/linkedin/demographics.ts
7868
- import { defineCommand as defineCommand42 } from "citty";
9421
+ import { defineCommand as defineCommand44 } from "citty";
7869
9422
  var DEFAULT_PIVOTS = ["job-title", "company", "industry", "seniority", "job-function", "company-size"];
7870
9423
  function numberOf2(v) {
7871
9424
  if (typeof v === "number") return Number.isFinite(v) ? v : 0;
@@ -7878,7 +9431,7 @@ function numberOf2(v) {
7878
9431
  function topByImpressions(rows, limit) {
7879
9432
  return [...rows].sort((a, b) => numberOf2(b.impressions) - numberOf2(a.impressions)).slice(0, limit);
7880
9433
  }
7881
- var demographicsCommand = defineCommand42({
9434
+ var demographicsCommand = defineCommand44({
7882
9435
  meta: {
7883
9436
  name: "demographics",
7884
9437
  description: `Sweep all firmographic pivots in one command \u2014 LinkedIn's superpower.
@@ -7975,7 +9528,7 @@ function resolveRange(args) {
7975
9528
  }
7976
9529
 
7977
9530
  // src/commands/ads/linkedin/draft.ts
7978
- import { defineCommand as defineCommand43 } from "citty";
9531
+ import { defineCommand as defineCommand45 } from "citty";
7979
9532
  async function listDraft() {
7980
9533
  try {
7981
9534
  const chatId = requireChatId();
@@ -7987,14 +9540,14 @@ async function listDraft() {
7987
9540
  handleLinkedinError(err);
7988
9541
  }
7989
9542
  }
7990
- var listCommand3 = defineCommand43({
9543
+ var listCommand3 = defineCommand45({
7991
9544
  meta: {
7992
9545
  name: "list",
7993
9546
  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"
7994
9547
  },
7995
9548
  run: listDraft
7996
9549
  });
7997
- var removeCommand2 = defineCommand43({
9550
+ var removeCommand2 = defineCommand45({
7998
9551
  meta: {
7999
9552
  name: "remove",
8000
9553
  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"
@@ -8019,7 +9572,7 @@ var removeCommand2 = defineCommand43({
8019
9572
  }
8020
9573
  }
8021
9574
  });
8022
- var clearCommand2 = defineCommand43({
9575
+ var clearCommand2 = defineCommand45({
8023
9576
  meta: {
8024
9577
  name: "clear",
8025
9578
  description: "Discard ALL staged LinkedIn ops in this chat's draft \u2014 nothing will apply on publish. Example: baker ads linkedin draft clear"
@@ -8036,7 +9589,7 @@ var clearCommand2 = defineCommand43({
8036
9589
  }
8037
9590
  }
8038
9591
  });
8039
- var linkedinDraftCommand = defineCommand43({
9592
+ var linkedinDraftCommand = defineCommand45({
8040
9593
  meta: {
8041
9594
  name: "draft",
8042
9595
  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."
@@ -8050,8 +9603,8 @@ var linkedinDraftCommand = defineCommand43({
8050
9603
  });
8051
9604
 
8052
9605
  // src/commands/ads/linkedin/facets.ts
8053
- import { defineCommand as defineCommand44 } from "citty";
8054
- var listCmd2 = defineCommand44({
9606
+ import { defineCommand as defineCommand46 } from "citty";
9607
+ var listCmd2 = defineCommand46({
8055
9608
  meta: {
8056
9609
  name: "list",
8057
9610
  description: `List every targeting facet LinkedIn supports.
@@ -8079,7 +9632,7 @@ seniorities, titles, employers, growthRate, companyCategory, skills, etc.).`
8079
9632
  }
8080
9633
  }
8081
9634
  });
8082
- var valuesCmd = defineCommand44({
9635
+ var valuesCmd = defineCommand46({
8083
9636
  meta: {
8084
9637
  name: "values",
8085
9638
  description: `Look up entity values for a single facet \u2014 full list or typeahead search.
@@ -8120,7 +9673,7 @@ or the full URN (urn:li:adTargetingFacet:industries).`
8120
9673
  }
8121
9674
  }
8122
9675
  });
8123
- var facetsCommand = defineCommand44({
9676
+ var facetsCommand = defineCommand46({
8124
9677
  meta: {
8125
9678
  name: "facets",
8126
9679
  description: `LinkedIn targeting facets and entity lookup.
@@ -8137,8 +9690,8 @@ Subcommands:
8137
9690
  });
8138
9691
 
8139
9692
  // src/commands/ads/linkedin/forecast.ts
8140
- import { readFileSync as readFileSync7 } from "fs";
8141
- import { defineCommand as defineCommand45 } from "citty";
9693
+ import { readFileSync as readFileSync8 } from "fs";
9694
+ import { defineCommand as defineCommand47 } from "citty";
8142
9695
  function loadTargeting3(args) {
8143
9696
  const inline = args.targeting;
8144
9697
  if (inline) {
@@ -8151,7 +9704,7 @@ function loadTargeting3(args) {
8151
9704
  const file = args["targeting-file"];
8152
9705
  if (file) {
8153
9706
  try {
8154
- return JSON.parse(readFileSync7(file, "utf-8"));
9707
+ return JSON.parse(readFileSync8(file, "utf-8"));
8155
9708
  } catch (e) {
8156
9709
  handleLinkedinError(
8157
9710
  new Error(`Failed to read --targeting-file: ${e instanceof Error ? e.message : "I/O error"}`)
@@ -8168,7 +9721,7 @@ function parseMoney(raw) {
8168
9721
  }
8169
9722
  return { amount: m[1] ?? "0", currencyCode: m[2] ?? "USD" };
8170
9723
  }
8171
- var forecastCommand = defineCommand45({
9724
+ var forecastCommand = defineCommand47({
8172
9725
  meta: {
8173
9726
  name: "forecast",
8174
9727
  description: `Forecast reach + impressions + clicks + spend for a hypothetical campaign.
@@ -8215,9 +9768,9 @@ Examples:
8215
9768
  });
8216
9769
 
8217
9770
  // src/commands/ads/linkedin/leads.ts
8218
- import { defineCommand as defineCommand46 } from "citty";
9771
+ import { defineCommand as defineCommand48 } from "citty";
8219
9772
  var DAY_MS4 = 864e5;
8220
- var leadsCommand = defineCommand46({
9773
+ var leadsCommand = defineCommand48({
8221
9774
  meta: {
8222
9775
  name: "leads",
8223
9776
  description: `List Lead Gen Form responses (playbook \xA707).
@@ -8277,7 +9830,7 @@ Examples:
8277
9830
  });
8278
9831
 
8279
9832
  // src/commands/ads/linkedin/resolve.ts
8280
- import { defineCommand as defineCommand47 } from "citty";
9833
+ import { defineCommand as defineCommand49 } from "citty";
8281
9834
  function toOrgUrn(raw) {
8282
9835
  const trimmed = raw.trim();
8283
9836
  if (trimmed.length === 0) {
@@ -8288,7 +9841,7 @@ function toOrgUrn(raw) {
8288
9841
  }
8289
9842
  return /^\d+$/.test(trimmed) ? `urn:li:organization:${trimmed}` : null;
8290
9843
  }
8291
- var resolveCommand = defineCommand47({
9844
+ var resolveCommand = defineCommand49({
8292
9845
  meta: {
8293
9846
  name: "resolve",
8294
9847
  description: `Resolve organization URNs to company names.
@@ -8330,8 +9883,8 @@ couldn't be resolved \u2014 typically an org outside LinkedIn's targetable set.`
8330
9883
  });
8331
9884
 
8332
9885
  // src/commands/ads/linkedin/top-companies.ts
8333
- import { defineCommand as defineCommand48 } from "citty";
8334
- var topCompaniesCommand = defineCommand48({
9886
+ import { defineCommand as defineCommand50 } from "citty";
9887
+ var topCompaniesCommand = defineCommand50({
8335
9888
  meta: {
8336
9889
  name: "top-companies",
8337
9890
  description: `Top companies whose employees saw / clicked / converted on a campaign.
@@ -8402,7 +9955,7 @@ Examples:
8402
9955
  });
8403
9956
 
8404
9957
  // src/commands/ads/linkedin/index.ts
8405
- var linkedinCommand = defineCommand49({
9958
+ var linkedinCommand = defineCommand51({
8406
9959
  meta: {
8407
9960
  name: "linkedin",
8408
9961
  description: `LinkedIn Marketing API \u2014 AI-first command surface for B2B ad insights.
@@ -8447,9 +10000,9 @@ Account ID format:
8447
10000
  accounts: accountsCommand2,
8448
10001
  account: accountCommand,
8449
10002
  "campaign-groups": campaignGroupsCommand,
8450
- campaigns: campaignsCommand,
10003
+ campaigns: campaignsCommand2,
8451
10004
  creatives: creativesCommand,
8452
- audiences: audiencesCommand,
10005
+ audiences: audiencesCommand2,
8453
10006
  "lead-forms": leadFormsCommand,
8454
10007
  draft: linkedinDraftCommand,
8455
10008
  analytics: analyticsCommand,
@@ -8461,17 +10014,17 @@ Account ID format:
8461
10014
  "bid-pricing": bidPricingCommand,
8462
10015
  forecast: forecastCommand,
8463
10016
  leads: leadsCommand,
8464
- conversions: conversionsCommand,
10017
+ conversions: conversionsCommand2,
8465
10018
  conversation: conversationCommand,
8466
10019
  audit: auditCommand
8467
10020
  }
8468
10021
  });
8469
10022
 
8470
10023
  // src/commands/ads/meta/index.ts
8471
- import { defineCommand as defineCommand62 } from "citty";
10024
+ import { defineCommand as defineCommand64 } from "citty";
8472
10025
 
8473
10026
  // src/commands/ads/meta/account.ts
8474
- import { defineCommand as defineCommand50 } from "citty";
10027
+ import { defineCommand as defineCommand52 } from "citty";
8475
10028
 
8476
10029
  // src/commands/ads/meta/shared.ts
8477
10030
  var DAY_MS5 = 864e5;
@@ -8550,7 +10103,7 @@ function resolveEffectiveStatus(args) {
8550
10103
  }
8551
10104
 
8552
10105
  // src/commands/ads/meta/account.ts
8553
- var accountCommand2 = defineCommand50({
10106
+ var accountCommand2 = defineCommand52({
8554
10107
  meta: {
8555
10108
  name: "account",
8556
10109
  description: `Show single Meta ad account detail (currency, timezone, balance, business).
@@ -8577,8 +10130,8 @@ Examples:
8577
10130
  });
8578
10131
 
8579
10132
  // src/commands/ads/meta/accounts.ts
8580
- import { defineCommand as defineCommand51 } from "citty";
8581
- var accountsCommand3 = defineCommand51({
10133
+ import { defineCommand as defineCommand53 } from "citty";
10134
+ var accountsCommand3 = defineCommand53({
8582
10135
  meta: {
8583
10136
  name: "accounts",
8584
10137
  description: `List Meta ad accounts in this company's connected scope.
@@ -8626,8 +10179,8 @@ Examples:
8626
10179
  });
8627
10180
 
8628
10181
  // src/commands/ads/meta/activities.ts
8629
- import { defineCommand as defineCommand52 } from "citty";
8630
- var activitiesCommand = defineCommand52({
10182
+ import { defineCommand as defineCommand54 } from "citty";
10183
+ var activitiesCommand = defineCommand54({
8631
10184
  meta: {
8632
10185
  name: "activities",
8633
10186
  description: `Audit log of recent ad-account changes (created, paused, edited). Default lookback 7 days,
@@ -8664,8 +10217,8 @@ Examples:
8664
10217
  });
8665
10218
 
8666
10219
  // src/commands/ads/meta/ads.ts
8667
- import { defineCommand as defineCommand53 } from "citty";
8668
- var adsListCommand = defineCommand53({
10220
+ import { defineCommand as defineCommand55 } from "citty";
10221
+ var adsListCommand = defineCommand55({
8669
10222
  meta: {
8670
10223
  name: "ads",
8671
10224
  description: `List ads in a Meta ad account. Defaults to ACTIVE only \u2014 pass --all-statuses to widen.
@@ -8713,8 +10266,8 @@ Examples:
8713
10266
  });
8714
10267
 
8715
10268
  // src/commands/ads/meta/adsets.ts
8716
- import { defineCommand as defineCommand54 } from "citty";
8717
- var adsetsCommand = defineCommand54({
10269
+ import { defineCommand as defineCommand56 } from "citty";
10270
+ var adsetsCommand = defineCommand56({
8718
10271
  meta: {
8719
10272
  name: "adsets",
8720
10273
  description: `List ad sets in a Meta ad account, optionally scoped to one campaign. Defaults to ACTIVE only.
@@ -8756,8 +10309,8 @@ Examples:
8756
10309
  });
8757
10310
 
8758
10311
  // src/commands/ads/meta/audiences.ts
8759
- import { defineCommand as defineCommand55 } from "citty";
8760
- var audiencesCommand2 = defineCommand55({
10312
+ import { defineCommand as defineCommand57 } from "citty";
10313
+ var audiencesCommand3 = defineCommand57({
8761
10314
  meta: {
8762
10315
  name: "audiences",
8763
10316
  description: `List custom audiences for a Meta ad account. Includes lookalikes, website-pixel audiences,
@@ -8792,8 +10345,8 @@ Examples:
8792
10345
  });
8793
10346
 
8794
10347
  // src/commands/ads/meta/businesses.ts
8795
- import { defineCommand as defineCommand56 } from "citty";
8796
- var businessesCommand = defineCommand56({
10348
+ import { defineCommand as defineCommand58 } from "citty";
10349
+ var businessesCommand = defineCommand58({
8797
10350
  meta: {
8798
10351
  name: "businesses",
8799
10352
  description: `List Meta Business Manager accounts the connected user has access to. Required for ad-studies and product-catalogs commands.
@@ -8823,8 +10376,8 @@ Examples:
8823
10376
  });
8824
10377
 
8825
10378
  // src/commands/ads/meta/campaigns.ts
8826
- import { defineCommand as defineCommand57 } from "citty";
8827
- var campaignsCommand2 = defineCommand57({
10379
+ import { defineCommand as defineCommand59 } from "citty";
10380
+ var campaignsCommand3 = defineCommand59({
8828
10381
  meta: {
8829
10382
  name: "campaigns",
8830
10383
  description: `List campaigns for a Meta ad account. Defaults to ACTIVE only \u2014 pass --all-statuses to widen.
@@ -8868,8 +10421,8 @@ Examples:
8868
10421
  });
8869
10422
 
8870
10423
  // src/commands/ads/meta/creatives.ts
8871
- import { defineCommand as defineCommand58 } from "citty";
8872
- var creativesCommand2 = defineCommand58({
10424
+ import { defineCommand as defineCommand60 } from "citty";
10425
+ var creativesCommand2 = defineCommand60({
8873
10426
  meta: {
8874
10427
  name: "creatives",
8875
10428
  description: `List ad creatives in an account, or fetch a single creative by ID.
@@ -8913,7 +10466,7 @@ Examples:
8913
10466
  });
8914
10467
 
8915
10468
  // src/commands/ads/meta/insights.ts
8916
- import { defineCommand as defineCommand59 } from "citty";
10469
+ import { defineCommand as defineCommand61 } from "citty";
8917
10470
 
8918
10471
  // src/commands/ads/meta/presets.ts
8919
10472
  var INSIGHTS_INTENTS = {
@@ -9118,7 +10671,7 @@ function sortRowsBySpendDesc(rows) {
9118
10671
  return sb - sa;
9119
10672
  });
9120
10673
  }
9121
- var insightsCommand = defineCommand59({
10674
+ var insightsCommand = defineCommand61({
9122
10675
  meta: {
9123
10676
  name: "insights",
9124
10677
  description: `Performance reporting \u2014 the main Meta tool for AI agents.
@@ -9219,8 +10772,8 @@ Async is automatic for heavy queries; pass --async to force it, or --no-async to
9219
10772
  });
9220
10773
 
9221
10774
  // src/commands/ads/meta/pixels.ts
9222
- import { defineCommand as defineCommand60 } from "citty";
9223
- var pixelsCommand = defineCommand60({
10775
+ import { defineCommand as defineCommand62 } from "citty";
10776
+ var pixelsCommand = defineCommand62({
9224
10777
  meta: {
9225
10778
  name: "pixels",
9226
10779
  description: `List Meta Pixels for an ad account, or fetch firing stats for one pixel.
@@ -9291,7 +10844,7 @@ function emit(data, args) {
9291
10844
 
9292
10845
  // src/commands/ads/meta/preview.ts
9293
10846
  import { writeFileSync as writeFileSync3 } from "fs";
9294
- import { defineCommand as defineCommand61 } from "citty";
10847
+ import { defineCommand as defineCommand63 } from "citty";
9295
10848
  var VALID_AD_FORMATS = [
9296
10849
  "DESKTOP_FEED_STANDARD",
9297
10850
  "MOBILE_FEED_STANDARD",
@@ -9325,7 +10878,7 @@ var VALID_AD_FORMATS = [
9325
10878
  "MARKETPLACE_MOBILE",
9326
10879
  "BIZ_DISCO_FEED_MOBILE"
9327
10880
  ];
9328
- var previewCommand = defineCommand61({
10881
+ var previewCommand = defineCommand63({
9329
10882
  meta: {
9330
10883
  name: "preview",
9331
10884
  description: `Generate a Meta-hosted preview iframe for a creative or ad. Returns iframe HTML which you
@@ -9372,7 +10925,7 @@ Examples:
9372
10925
  });
9373
10926
 
9374
10927
  // src/commands/ads/meta/index.ts
9375
- var metaCommand = defineCommand62({
10928
+ var metaCommand = defineCommand64({
9376
10929
  meta: {
9377
10930
  name: "meta",
9378
10931
  description: `Meta Marketing API \u2014 AI-first command surface (Facebook + Instagram ads).
@@ -9411,11 +10964,11 @@ Audit & review:
9411
10964
  accounts: accountsCommand3,
9412
10965
  account: accountCommand2,
9413
10966
  businesses: businessesCommand,
9414
- campaigns: campaignsCommand2,
10967
+ campaigns: campaignsCommand3,
9415
10968
  adsets: adsetsCommand,
9416
10969
  ads: adsListCommand,
9417
10970
  creatives: creativesCommand2,
9418
- audiences: audiencesCommand2,
10971
+ audiences: audiencesCommand3,
9419
10972
  pixels: pixelsCommand,
9420
10973
  activities: activitiesCommand,
9421
10974
  insights: insightsCommand,
@@ -9424,10 +10977,10 @@ Audit & review:
9424
10977
  });
9425
10978
 
9426
10979
  // src/commands/ads/x/index.ts
9427
- import { defineCommand as defineCommand79 } from "citty";
10980
+ import { defineCommand as defineCommand81 } from "citty";
9428
10981
 
9429
10982
  // src/commands/ads/x/accounts.ts
9430
- import { defineCommand as defineCommand63 } from "citty";
10983
+ import { defineCommand as defineCommand65 } from "citty";
9431
10984
  registerSchema({
9432
10985
  command: "ads.x.accounts",
9433
10986
  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.",
@@ -9455,7 +11008,7 @@ function handleAccountsError2(err) {
9455
11008
  writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
9456
11009
  process.exit(1);
9457
11010
  }
9458
- var accountsCommand4 = defineCommand63({
11011
+ var accountsCommand4 = defineCommand65({
9459
11012
  meta: {
9460
11013
  name: "accounts",
9461
11014
  description: `List accessible X Ads accounts. Returns account IDs needed for all other commands.
@@ -9495,7 +11048,7 @@ Examples:
9495
11048
  });
9496
11049
 
9497
11050
  // src/commands/ads/x/active-entities.ts
9498
- import { defineCommand as defineCommand64 } from "citty";
11051
+ import { defineCommand as defineCommand66 } from "citty";
9499
11052
 
9500
11053
  // src/commands/ads/x/error-parser.ts
9501
11054
  function mapXErrorCode(message) {
@@ -9646,7 +11199,7 @@ function parseCsv(v) {
9646
11199
  const parts = v.split(",").map((s) => s.trim()).filter(Boolean);
9647
11200
  return parts.length > 0 ? parts : void 0;
9648
11201
  }
9649
- var activeEntitiesCommand = defineCommand64({
11202
+ var activeEntitiesCommand = defineCommand66({
9650
11203
  meta: {
9651
11204
  name: "active-entities",
9652
11205
  description: `List entities with metric activity in a time range.
@@ -9704,7 +11257,7 @@ Examples:
9704
11257
  });
9705
11258
 
9706
11259
  // src/commands/ads/x/audiences.ts
9707
- import { defineCommand as defineCommand65 } from "citty";
11260
+ import { defineCommand as defineCommand67 } from "citty";
9708
11261
  registerSchema({
9709
11262
  command: "ads.x.audiences",
9710
11263
  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.",
@@ -9713,7 +11266,7 @@ registerSchema({
9713
11266
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
9714
11267
  }
9715
11268
  });
9716
- var audiencesCommand3 = defineCommand65({
11269
+ var audiencesCommand4 = defineCommand67({
9717
11270
  meta: {
9718
11271
  name: "audiences",
9719
11272
  description: `List X Ads custom audiences.
@@ -9762,7 +11315,7 @@ Examples:
9762
11315
  });
9763
11316
 
9764
11317
  // src/commands/ads/x/campaigns.ts
9765
- import { defineCommand as defineCommand66 } from "citty";
11318
+ import { defineCommand as defineCommand68 } from "citty";
9766
11319
 
9767
11320
  // src/commands/ads/x/run-list.ts
9768
11321
  function buildCleanParams(opts) {
@@ -9825,7 +11378,7 @@ registerSchema({
9825
11378
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
9826
11379
  }
9827
11380
  });
9828
- var campaignsCommand3 = defineCommand66({
11381
+ var campaignsCommand4 = defineCommand68({
9829
11382
  meta: {
9830
11383
  name: "campaigns",
9831
11384
  description: `List X Ads campaigns. Returns budget, schedule, funding instrument, status.
@@ -9867,7 +11420,7 @@ Examples:
9867
11420
  });
9868
11421
 
9869
11422
  // src/commands/ads/x/cards.ts
9870
- import { defineCommand as defineCommand67 } from "citty";
11423
+ import { defineCommand as defineCommand69 } from "citty";
9871
11424
  registerSchema({
9872
11425
  command: "ads.x.cards",
9873
11426
  description: "List website cards, video cards, and carousels for an X Ads account.",
@@ -9876,7 +11429,7 @@ registerSchema({
9876
11429
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
9877
11430
  }
9878
11431
  });
9879
- var cardsCommand = defineCommand67({
11432
+ var cardsCommand = defineCommand69({
9880
11433
  meta: {
9881
11434
  name: "cards",
9882
11435
  description: `List X Ads cards (rich creatives).
@@ -9925,7 +11478,7 @@ Examples:
9925
11478
  });
9926
11479
 
9927
11480
  // src/commands/ads/x/funding.ts
9928
- import { defineCommand as defineCommand68 } from "citty";
11481
+ import { defineCommand as defineCommand70 } from "citty";
9929
11482
  registerSchema({
9930
11483
  command: "ads.x.funding",
9931
11484
  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.",
@@ -9934,7 +11487,7 @@ registerSchema({
9934
11487
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
9935
11488
  }
9936
11489
  });
9937
- var fundingCommand = defineCommand68({
11490
+ var fundingCommand = defineCommand70({
9938
11491
  meta: {
9939
11492
  name: "funding",
9940
11493
  description: `List funding instruments for an X Ads account.
@@ -9983,7 +11536,7 @@ Examples:
9983
11536
  });
9984
11537
 
9985
11538
  // src/commands/ads/x/line-items.ts
9986
- import { defineCommand as defineCommand69 } from "citty";
11539
+ import { defineCommand as defineCommand71 } from "citty";
9987
11540
  registerSchema({
9988
11541
  command: "ads.x.lineItems",
9989
11542
  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).",
@@ -9995,7 +11548,7 @@ registerSchema({
9995
11548
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
9996
11549
  }
9997
11550
  });
9998
- var lineItemsCommand = defineCommand69({
11551
+ var lineItemsCommand = defineCommand71({
9999
11552
  meta: {
10000
11553
  name: "line-items",
10001
11554
  description: `List X Ads line items (ad groups).
@@ -10036,7 +11589,7 @@ Examples:
10036
11589
  });
10037
11590
 
10038
11591
  // src/commands/ads/x/media.ts
10039
- import { defineCommand as defineCommand70 } from "citty";
11592
+ import { defineCommand as defineCommand72 } from "citty";
10040
11593
  registerSchema({
10041
11594
  command: "ads.x.media",
10042
11595
  description: "List media assets in the X Ads media library (images, GIFs, videos). Filter by media-type (IMAGE, GIF, VIDEO).",
@@ -10046,7 +11599,7 @@ registerSchema({
10046
11599
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
10047
11600
  }
10048
11601
  });
10049
- var mediaCommand = defineCommand70({
11602
+ var mediaCommand = defineCommand72({
10050
11603
  meta: {
10051
11604
  name: "media",
10052
11605
  description: `List media assets in the X Ads media library.
@@ -10098,7 +11651,7 @@ Examples:
10098
11651
  });
10099
11652
 
10100
11653
  // src/commands/ads/x/promoted-tweets.ts
10101
- import { defineCommand as defineCommand71 } from "citty";
11654
+ import { defineCommand as defineCommand73 } from "citty";
10102
11655
  registerSchema({
10103
11656
  command: "ads.x.promotedTweets",
10104
11657
  description: "List promoted tweets for an X Ads account. Returns id, line_item_id, tweet_id, approval_status. Filter by line-item-ids (CSV).",
@@ -10109,7 +11662,7 @@ registerSchema({
10109
11662
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
10110
11663
  }
10111
11664
  });
10112
- var promotedTweetsCommand = defineCommand71({
11665
+ var promotedTweetsCommand = defineCommand73({
10113
11666
  meta: {
10114
11667
  name: "promoted-tweets",
10115
11668
  description: `List X Ads promoted tweets.
@@ -10163,11 +11716,11 @@ Examples:
10163
11716
  });
10164
11717
 
10165
11718
  // src/commands/ads/x/stats/index.ts
10166
- import { defineCommand as defineCommand76 } from "citty";
11719
+ import { defineCommand as defineCommand78 } from "citty";
10167
11720
 
10168
11721
  // src/commands/ads/x/stats/job.ts
10169
11722
  import { gunzipSync } from "zlib";
10170
- import { defineCommand as defineCommand72 } from "citty";
11723
+ import { defineCommand as defineCommand74 } from "citty";
10171
11724
  var POLL_INTERVAL_MS2 = 1e4;
10172
11725
  var DEADLINE_MS = 12 * 60 * 1e3;
10173
11726
  var RESULT_CACHE_TTL_MS = 6 * 60 * 60 * 1e3;
@@ -10237,7 +11790,7 @@ async function pollUntilDone(accountId, jobId) {
10237
11790
  function buildCacheKey(body) {
10238
11791
  return `stats-job:${JSON.stringify(body)}`;
10239
11792
  }
10240
- var statsJobCommand = defineCommand72({
11793
+ var statsJobCommand = defineCommand74({
10241
11794
  meta: {
10242
11795
  name: "job",
10243
11796
  description: `Async X Ads stats job, sync from the CLI's perspective. Creates \u2192 polls \u2192 downloads \u2192 returns.
@@ -10342,7 +11895,7 @@ For fine-grained control (don't wait, poll yourself), use:
10342
11895
  });
10343
11896
 
10344
11897
  // src/commands/ads/x/stats/job-create.ts
10345
- import { defineCommand as defineCommand73 } from "citty";
11898
+ import { defineCommand as defineCommand75 } from "citty";
10346
11899
  registerSchema({
10347
11900
  command: "ads.x.statsJobCreate",
10348
11901
  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.",
@@ -10365,7 +11918,7 @@ function parseCsv3(v) {
10365
11918
  const parts = v.split(",").map((s) => s.trim()).filter(Boolean);
10366
11919
  return parts.length > 0 ? parts : void 0;
10367
11920
  }
10368
- var statsJobCreateCommand = defineCommand73({
11921
+ var statsJobCreateCommand = defineCommand75({
10369
11922
  meta: {
10370
11923
  name: "job-create",
10371
11924
  description: `Create an async X Ads stats job (up to 90 days, supports segmentation).
@@ -10428,7 +11981,7 @@ Examples:
10428
11981
  });
10429
11982
 
10430
11983
  // src/commands/ads/x/stats/job-status.ts
10431
- import { defineCommand as defineCommand74 } from "citty";
11984
+ import { defineCommand as defineCommand76 } from "citty";
10432
11985
  registerSchema({
10433
11986
  command: "ads.x.statsJobStatus",
10434
11987
  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).",
@@ -10438,7 +11991,7 @@ registerSchema({
10438
11991
  "job-ids": { type: "string", description: "CSV of job IDs", required: false }
10439
11992
  }
10440
11993
  });
10441
- var statsJobStatusCommand = defineCommand74({
11994
+ var statsJobStatusCommand = defineCommand76({
10442
11995
  meta: {
10443
11996
  name: "job-status",
10444
11997
  description: `Poll the status of an async X Ads stats job.
@@ -10479,7 +12032,7 @@ Examples:
10479
12032
  });
10480
12033
 
10481
12034
  // src/commands/ads/x/stats/sync.ts
10482
- import { defineCommand as defineCommand75 } from "citty";
12035
+ import { defineCommand as defineCommand77 } from "citty";
10483
12036
 
10484
12037
  // src/commands/ads/x/presets.ts
10485
12038
  var X_STATS_PRESETS = [
@@ -10638,7 +12191,7 @@ async function runSync(args, q) {
10638
12191
  process.exit(1);
10639
12192
  }
10640
12193
  }
10641
- var statsSyncCommand = defineCommand75({
12194
+ var statsSyncCommand = defineCommand77({
10642
12195
  meta: {
10643
12196
  name: "sync",
10644
12197
  description: `Synchronous X Ads analytics (max 7-day window).
@@ -10681,7 +12234,7 @@ Examples:
10681
12234
  });
10682
12235
 
10683
12236
  // src/commands/ads/x/stats/index.ts
10684
- var statsCommand = defineCommand76({
12237
+ var statsCommand = defineCommand78({
10685
12238
  meta: {
10686
12239
  name: "stats",
10687
12240
  description: `X Ads analytics. Sync (\u22647 days, no segmentation) or async jobs (\u226490 days, segmentable).
@@ -10709,7 +12262,7 @@ Examples:
10709
12262
  });
10710
12263
 
10711
12264
  // src/commands/ads/x/targeting-constants.ts
10712
- import { defineCommand as defineCommand77 } from "citty";
12265
+ import { defineCommand as defineCommand79 } from "citty";
10713
12266
  var ALLOWED_CONSTANTS = [
10714
12267
  "locations",
10715
12268
  "interests",
@@ -10737,7 +12290,7 @@ registerSchema({
10737
12290
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
10738
12291
  }
10739
12292
  });
10740
- var targetingConstantsCommand = defineCommand77({
12293
+ var targetingConstantsCommand = defineCommand79({
10741
12294
  meta: {
10742
12295
  name: "targeting-constants",
10743
12296
  description: `Lookup X Ads targeting constants.
@@ -10787,7 +12340,7 @@ Examples:
10787
12340
  });
10788
12341
 
10789
12342
  // src/commands/ads/x/targeting-criteria.ts
10790
- import { defineCommand as defineCommand78 } from "citty";
12343
+ import { defineCommand as defineCommand80 } from "citty";
10791
12344
  registerSchema({
10792
12345
  command: "ads.x.targetingCriteria",
10793
12346
  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.",
@@ -10797,7 +12350,7 @@ registerSchema({
10797
12350
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
10798
12351
  }
10799
12352
  });
10800
- var targetingCriteriaCommand = defineCommand78({
12353
+ var targetingCriteriaCommand = defineCommand80({
10801
12354
  meta: {
10802
12355
  name: "targeting-criteria",
10803
12356
  description: `List targeting criteria attached to line items.
@@ -10848,7 +12401,7 @@ Examples:
10848
12401
  });
10849
12402
 
10850
12403
  // src/commands/ads/x/index.ts
10851
- var xCommand = defineCommand79({
12404
+ var xCommand = defineCommand81({
10852
12405
  meta: {
10853
12406
  name: "x",
10854
12407
  description: `X (Twitter) Ads commands. Read campaigns, line items, promoted tweets, creatives, audiences, and analytics.
@@ -10872,12 +12425,12 @@ The CLI auto-detects --account-id when exactly one X Ads account is connected, o
10872
12425
  subCommands: {
10873
12426
  accounts: accountsCommand4,
10874
12427
  funding: fundingCommand,
10875
- campaigns: campaignsCommand3,
12428
+ campaigns: campaignsCommand4,
10876
12429
  "line-items": lineItemsCommand,
10877
12430
  "promoted-tweets": promotedTweetsCommand,
10878
12431
  cards: cardsCommand,
10879
12432
  media: mediaCommand,
10880
- audiences: audiencesCommand3,
12433
+ audiences: audiencesCommand4,
10881
12434
  "targeting-criteria": targetingCriteriaCommand,
10882
12435
  "targeting-constants": targetingConstantsCommand,
10883
12436
  "active-entities": activeEntitiesCommand,
@@ -10886,7 +12439,7 @@ The CLI auto-detects --account-id when exactly one X Ads account is connected, o
10886
12439
  });
10887
12440
 
10888
12441
  // src/commands/ads/index.ts
10889
- var adsCommand = defineCommand80({
12442
+ var adsCommand2 = defineCommand82({
10890
12443
  meta: {
10891
12444
  name: "ads",
10892
12445
  description: `Ad platform commands. Each platform exposes its own native command surface \u2014 no forced parity.
@@ -10916,11 +12469,11 @@ Examples:
10916
12469
  });
10917
12470
 
10918
12471
  // src/commands/canvas/index.ts
10919
- import { defineCommand as defineCommand88 } from "citty";
12472
+ import { defineCommand as defineCommand90 } from "citty";
10920
12473
 
10921
12474
  // src/commands/canvas/catalog.ts
10922
- import { defineCommand as defineCommand81 } from "citty";
10923
- var catalogCommand = defineCommand81({
12475
+ import { defineCommand as defineCommand83 } from "citty";
12476
+ var catalogCommand = defineCommand83({
10924
12477
  meta: {
10925
12478
  name: "catalog",
10926
12479
  description: "Print the agent-facing node catalog (JSON Schema). Includes every registered node grouped by category."
@@ -10937,9 +12490,9 @@ import { execFile } from "child_process";
10937
12490
  import { readdir, readFile, stat } from "fs/promises";
10938
12491
  import path from "path";
10939
12492
  import { promisify } from "util";
10940
- import { defineCommand as defineCommand82 } from "citty";
12493
+ import { defineCommand as defineCommand84 } from "citty";
10941
12494
  var execFileAsync = promisify(execFile);
10942
- var inspectCommand = defineCommand82({
12495
+ var inspectCommand = defineCommand84({
10943
12496
  meta: {
10944
12497
  name: "inspect",
10945
12498
  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."
@@ -11048,7 +12601,7 @@ async function probeDuration(filePath) {
11048
12601
  // src/commands/canvas/run.ts
11049
12602
  import { readFile as readFile2 } from "fs/promises";
11050
12603
  import path4 from "path";
11051
- import { defineCommand as defineCommand83 } from "citty";
12604
+ import { defineCommand as defineCommand85 } from "citty";
11052
12605
 
11053
12606
  // src/commands/canvas/placeholders.ts
11054
12607
  function unsuppliedPlaceholderAssets(canvas) {
@@ -11118,7 +12671,7 @@ async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
11118
12671
  }
11119
12672
 
11120
12673
  // src/commands/canvas/run.ts
11121
- var runCommand = defineCommand83({
12674
+ var runCommand = defineCommand85({
11122
12675
  meta: { name: "run", description: "Validate and execute a canvas JSON file." },
11123
12676
  args: {
11124
12677
  file: { type: "positional", required: true, description: "Path to canvas JSON" },
@@ -11214,30 +12767,30 @@ var runCommand = defineCommand83({
11214
12767
  // src/commands/canvas/scaffold-static-ad.ts
11215
12768
  import { readFile as readFile3, writeFile } from "fs/promises";
11216
12769
  import path6 from "path";
11217
- import { defineCommand as defineCommand84 } from "citty";
12770
+ import { defineCommand as defineCommand86 } from "citty";
11218
12771
 
11219
12772
  // src/engine/scaffold/staticAd.ts
11220
- import { z as z8 } from "zod";
12773
+ import { z as z10 } from "zod";
11221
12774
  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"]);
11222
12775
  var DEFAULT_ASPECT_RATIO = "9:16";
11223
- var Blueprint = z8.object({
11224
- meta: z8.object({ estimated_aspect_ratio: z8.string().optional() }).loose().optional(),
11225
- text_content: z8.array(z8.object({ text: z8.string().optional() }).loose()).optional()
12776
+ var Blueprint = z10.object({
12777
+ meta: z10.object({ estimated_aspect_ratio: z10.string().optional() }).loose().optional(),
12778
+ text_content: z10.array(z10.object({ text: z10.string().optional() }).loose()).optional()
11226
12779
  }).loose();
11227
- var ElementLocator = z8.object({
11228
- collection: z8.enum(["subjects", "people", "brands_logos"]),
11229
- index: z8.number().int().nonnegative()
12780
+ var ElementLocator = z10.object({
12781
+ collection: z10.enum(["subjects", "people", "brands_logos"]),
12782
+ index: z10.number().int().nonnegative()
11230
12783
  }).loose();
11231
- var MainElement = z8.object({
12784
+ var MainElement = z10.object({
11232
12785
  // logo | product | person | animal | badge | other
11233
- type: z8.string(),
11234
- label: z8.string().optional(),
11235
- description: z8.string().optional(),
11236
- expression: z8.string().nullable().optional(),
11237
- reason: z8.string().optional(),
12786
+ type: z10.string(),
12787
+ label: z10.string().optional(),
12788
+ description: z10.string().optional(),
12789
+ expression: z10.string().nullable().optional(),
12790
+ reason: z10.string().optional(),
11238
12791
  locator: ElementLocator.optional()
11239
12792
  }).loose();
11240
- var MainElements = z8.array(MainElement);
12793
+ var MainElements = z10.array(MainElement);
11241
12794
  function sanitizeId(raw, fallback) {
11242
12795
  const id = raw.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
11243
12796
  return /^[a-z]/.test(id) ? id : `${fallback}_${id}`.replace(/_+$/g, "") || fallback;
@@ -11560,7 +13113,7 @@ async function runVisionPasses(canvas) {
11560
13113
  return fail("read_outputs", e instanceof Error ? e.message : String(e));
11561
13114
  }
11562
13115
  }
11563
- var scaffoldStaticAdCommand = defineCommand84({
13116
+ var scaffoldStaticAdCommand = defineCommand86({
11564
13117
  meta: {
11565
13118
  name: "scaffold-static-ad",
11566
13119
  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."
@@ -11656,7 +13209,7 @@ var scaffoldStaticAdCommand = defineCommand84({
11656
13209
  // src/commands/canvas/scaffold-video.ts
11657
13210
  import { cp, mkdir, readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
11658
13211
  import path9 from "path";
11659
- import { defineCommand as defineCommand85 } from "citty";
13212
+ import { defineCommand as defineCommand87 } from "citty";
11660
13213
 
11661
13214
  // src/engine/nodes/local/lib/sceneDetect.ts
11662
13215
  import { execFile as execFile2 } from "child_process";
@@ -11761,7 +13314,7 @@ import { toCardinal as nwKo } from "n2words/ko-KR";
11761
13314
  import { toCardinal as nwNl } from "n2words/nl-NL";
11762
13315
  import { toCardinal as nwPl } from "n2words/pl-PL";
11763
13316
  import { toCardinal as nwPt } from "n2words/pt-PT";
11764
- import { z as z9 } from "zod";
13317
+ import { z as z11 } from "zod";
11765
13318
 
11766
13319
  // src/engine/scaffold/lib/shoot-modes.ts
11767
13320
  var SHOOT_MODES = [
@@ -12018,49 +13571,49 @@ function trimArgs(durationS, offsetS = 0) {
12018
13571
  "{{out.video}}"
12019
13572
  ];
12020
13573
  }
12021
- var FrameAsset = z9.object({ url: z9.string().optional() }).loose().optional();
12022
- var DialogueLine = z9.object({
12023
- speaker: z9.string().optional(),
12024
- line: z9.string().optional(),
13574
+ var FrameAsset = z11.object({ url: z11.string().optional() }).loose().optional();
13575
+ var DialogueLine = z11.object({
13576
+ speaker: z11.string().optional(),
13577
+ line: z11.string().optional(),
12025
13578
  // Absolute seconds on the source timeline (the deconstruct emits both).
12026
- start_s: z9.number().optional(),
12027
- end_s: z9.number().optional(),
12028
- delivery: z9.string().optional(),
12029
- voice_description: z9.string().optional()
13579
+ start_s: z11.number().optional(),
13580
+ end_s: z11.number().optional(),
13581
+ delivery: z11.string().optional(),
13582
+ voice_description: z11.string().optional()
12030
13583
  }).loose();
12031
- var Sfx = z9.object({
12032
- at_s: z9.number().optional(),
12033
- duration_s: z9.number().optional(),
12034
- sound_effect_prompt: z9.string().optional(),
12035
- description: z9.string().optional()
13584
+ var Sfx = z11.object({
13585
+ at_s: z11.number().optional(),
13586
+ duration_s: z11.number().optional(),
13587
+ sound_effect_prompt: z11.string().optional(),
13588
+ description: z11.string().optional()
12036
13589
  }).loose();
12037
- var CompositionRegion = z9.object({
13590
+ var CompositionRegion = z11.object({
12038
13591
  // full | top | bottom | left | right | inset
12039
- panel: z9.string().optional(),
13592
+ panel: z11.string().optional(),
12040
13593
  // 9-grid anchor for an `inset` presenter box.
12041
- position: z9.string().optional(),
12042
- is_presenter: z9.boolean().optional(),
13594
+ position: z11.string().optional(),
13595
+ is_presenter: z11.boolean().optional(),
12043
13596
  // The cast id shown/speaking in this region (routes lip-sync + element refs).
12044
- cast_ref: z9.string().optional(),
12045
- summary: z9.string().optional(),
12046
- frame_prompt: z9.string().optional(),
12047
- motion_prompt: z9.string().optional()
13597
+ cast_ref: z11.string().optional(),
13598
+ summary: z11.string().optional(),
13599
+ frame_prompt: z11.string().optional(),
13600
+ motion_prompt: z11.string().optional()
12048
13601
  }).loose();
12049
- var SceneComposition = z9.object({
13602
+ var SceneComposition = z11.object({
12050
13603
  // full_frame (default) | split_screen | pip | keyed_overlay
12051
- layout: z9.string().optional(),
13604
+ layout: z11.string().optional(),
12052
13605
  // split_screen only: vertical (top/bottom) | horizontal (left/right).
12053
- split_axis: z9.string().optional(),
12054
- regions: z9.array(CompositionRegion).optional()
13606
+ split_axis: z11.string().optional(),
13607
+ regions: z11.array(CompositionRegion).optional()
12055
13608
  }).loose();
12056
- var CameraMotion = z9.object({ movement: z9.string().optional(), detail: z9.string().optional() }).loose();
12057
- var TranscriptWord = z9.object({ text: z9.string().optional() }).loose();
12058
- var Scene = z9.object({
12059
- start_s: z9.number().optional(),
12060
- end_s: z9.number().optional(),
12061
- duration_s: z9.number().optional(),
12062
- summary: z9.string().optional(),
12063
- action_detail: z9.string().optional(),
13609
+ var CameraMotion = z11.object({ movement: z11.string().optional(), detail: z11.string().optional() }).loose();
13610
+ var TranscriptWord = z11.object({ text: z11.string().optional() }).loose();
13611
+ var Scene = z11.object({
13612
+ start_s: z11.number().optional(),
13613
+ end_s: z11.number().optional(),
13614
+ duration_s: z11.number().optional(),
13615
+ summary: z11.string().optional(),
13616
+ action_detail: z11.string().optional(),
12064
13617
  // The scene's spatial layout. Absent/full_frame ⇒ one uncut shot (default path).
12065
13618
  // A layered layout (split_screen/pip/keyed_overlay) with regions ⇒ the scaffold
12066
13619
  // builds one clip per region and stacks/overlays them into the scene picture.
@@ -12068,77 +13621,77 @@ var Scene = z9.object({
12068
13621
  // The capture "look" for this scene — selected from the ad-native shoot-mode
12069
13622
  // grammar (see lib/shoot-modes.ts). When absent the scaffold auto-derives a
12070
13623
  // UGC/product mode; a human can override per scene by setting this.
12071
- shoot_mode: z9.string().optional(),
13624
+ shoot_mode: z11.string().optional(),
12072
13625
  // Diegetic ambient the clip's native audio should carry (no music). When
12073
13626
  // absent the scene falls back to its shoot mode's default ambience.
12074
- ambient: z9.string().optional(),
13627
+ ambient: z11.string().optional(),
12075
13628
  camera_motion: CameraMotion.optional(),
12076
- start_frame_prompt: z9.string().optional(),
12077
- end_frame_prompt: z9.string().optional(),
12078
- motion_prompt: z9.string().optional(),
13629
+ start_frame_prompt: z11.string().optional(),
13630
+ end_frame_prompt: z11.string().optional(),
13631
+ motion_prompt: z11.string().optional(),
12079
13632
  // The scene's role in the ad's persuasion arc (DECON-supplied); drives the
12080
13633
  // script re-craft checklist. Inferred from position when absent.
12081
- narrative_role: z9.string().optional(),
13634
+ narrative_role: z11.string().optional(),
12082
13635
  // DECON-supplied on the HOOK scene: the engineered physical/emotional state that
12083
13636
  // makes the first frame stop the scroll (sweaty/breathless/urgent …). Injected
12084
13637
  // into the hook's start-frame description so the generator renders that state,
12085
13638
  // not a calm influencer (CCA-11).
12086
- hook_mechanic: z9.object({ mechanic: z9.string().optional(), why_it_stops_scroll: z9.string().optional() }).loose().optional(),
13639
+ hook_mechanic: z11.object({ mechanic: z11.string().optional(), why_it_stops_scroll: z11.string().optional() }).loose().optional(),
12087
13640
  // DECON-supplied per-scene location (so a gym hook isn't flattened to "home").
12088
- scene_setting: z9.string().optional(),
13641
+ scene_setting: z11.string().optional(),
12089
13642
  // How this scene cuts to the next (DECON-supplied). A recognized non-cut type
12090
13643
  // (fade/whip/zoom/dissolve/swipe) is reproduced as an ffmpeg xfade at the
12091
13644
  // boundary; cut/match_cut/none/other stay hard cuts. The last scene's value is
12092
13645
  // ignored (nothing follows it).
12093
- transition_out: z9.object({ type: z9.string().optional(), description: z9.string().optional() }).loose().optional(),
12094
- dialogue: z9.array(DialogueLine).optional(),
12095
- sfx: z9.array(Sfx).optional(),
12096
- overlays: z9.array(z9.unknown()).optional(),
12097
- floating_elements: z9.array(z9.unknown()).optional(),
12098
- transcript_slice: z9.array(TranscriptWord).optional(),
13646
+ transition_out: z11.object({ type: z11.string().optional(), description: z11.string().optional() }).loose().optional(),
13647
+ dialogue: z11.array(DialogueLine).optional(),
13648
+ sfx: z11.array(Sfx).optional(),
13649
+ overlays: z11.array(z11.unknown()).optional(),
13650
+ floating_elements: z11.array(z11.unknown()).optional(),
13651
+ transcript_slice: z11.array(TranscriptWord).optional(),
12099
13652
  start_frame_asset: FrameAsset,
12100
13653
  end_frame_asset: FrameAsset,
12101
13654
  // DECON-supplied: true when this scene is a length-split CONTINUATION of the
12102
13655
  // previous one (the SAME physical shot, broken up only because it exceeded the
12103
13656
  // clip ceiling). The scaffold then shares the splice keyframe — this scene's
12104
13657
  // start frame IS the previous scene's end frame — so the join is seamless.
12105
- continues_previous: z9.boolean().optional()
13658
+ continues_previous: z11.boolean().optional()
12106
13659
  }).loose();
12107
- var VideoBlueprint = z9.object({
12108
- source: z9.object({ aspect_ratio: z9.string().optional(), duration_s: z9.number().optional() }).loose().optional(),
12109
- global: z9.object({
12110
- music: z9.object({
12111
- present: z9.boolean().optional(),
12112
- music_prompt: z9.string().optional(),
13660
+ var VideoBlueprint = z11.object({
13661
+ source: z11.object({ aspect_ratio: z11.string().optional(), duration_s: z11.number().optional() }).loose().optional(),
13662
+ global: z11.object({
13663
+ music: z11.object({
13664
+ present: z11.boolean().optional(),
13665
+ music_prompt: z11.string().optional(),
12113
13666
  // Absolute second the music enters in the reference (the bed often
12114
13667
  // kicks in mid-ad, after the hook). We start the regenerated track here
12115
13668
  // instead of at 0 so the timing matches.
12116
- starts_at_s: z9.number().optional(),
13669
+ starts_at_s: z11.number().optional(),
12117
13670
  // Populated by the deconstruct when AudD (Shazam-style) recognizes the
12118
13671
  // reference track. We never reuse it — only style the regenerated bed.
12119
- identified_track: z9.object({ title: z9.string().optional(), artist: z9.string().optional() }).loose().nullish()
13672
+ identified_track: z11.object({ title: z11.string().optional(), artist: z11.string().optional() }).loose().nullish()
12120
13673
  }).loose().optional(),
12121
- cast: z9.array(
12122
- z9.object({
12123
- id: z9.string().optional(),
12124
- description: z9.string().optional(),
13674
+ cast: z11.array(
13675
+ z11.object({
13676
+ id: z11.string().optional(),
13677
+ description: z11.string().optional(),
12125
13678
  // The deconstruct's note on the target-market localization (e.g. "native
12126
13679
  // French speaker") — read to derive the spoken-track language code.
12127
- market_localization_note: z9.string().optional()
13680
+ market_localization_note: z11.string().optional()
12128
13681
  }).loose()
12129
13682
  ).optional(),
12130
- voiceover: z9.object({
13683
+ voiceover: z11.object({
12131
13684
  // on_camera | mixed → mouths are on screen (lip-sync candidates);
12132
13685
  // voiceover | none → narration over the picture (no lip-sync).
12133
- mode: z9.string().optional(),
12134
- voice_description: z9.string().optional(),
12135
- persona: z9.string().optional()
13686
+ mode: z11.string().optional(),
13687
+ voice_description: z11.string().optional(),
13688
+ persona: z11.string().optional()
12136
13689
  }).loose().optional(),
12137
13690
  // Visual palette — read only to colour a clean brand-card/CTA plate (the
12138
13691
  // first hex is the dominant brand colour); never to drive frame generation.
12139
- style: z9.object({ palette: z9.array(z9.object({ hex: z9.string().optional() }).loose()).optional() }).loose().optional()
13692
+ style: z11.object({ palette: z11.array(z11.object({ hex: z11.string().optional() }).loose()).optional() }).loose().optional()
12140
13693
  }).loose().optional(),
12141
- scenes: z9.array(Scene).min(1)
13694
+ scenes: z11.array(Scene).min(1)
12142
13695
  }).loose();
12143
13696
  function injectHookPhysicality(blueprint) {
12144
13697
  for (const scene of blueprint.scenes) {
@@ -12148,26 +13701,26 @@ function injectHookPhysicality(blueprint) {
12148
13701
  scene.start_frame_prompt = `${prompt} The subject's physical state IS the scroll-stopper \u2014 render it explicitly, not a calm pose: ${why}.`;
12149
13702
  }
12150
13703
  }
12151
- var AppearsItem = z9.union([z9.number(), z9.object({ scene: z9.number(), edge: z9.string().optional() }).loose()]);
12152
- var RecurringElement = z9.object({
13704
+ var AppearsItem = z11.union([z11.number(), z11.object({ scene: z11.number(), edge: z11.string().optional() }).loose()]);
13705
+ var RecurringElement = z11.object({
12153
13706
  // person | animal | product | logo | badge | other
12154
- type: z9.string(),
12155
- label: z9.string().optional(),
12156
- description: z9.string().optional(),
12157
- expression: z9.string().nullable().optional(),
13707
+ type: z11.string(),
13708
+ label: z11.string().optional(),
13709
+ description: z11.string().optional(),
13710
+ expression: z11.string().nullable().optional(),
12158
13711
  // When the element maps to a global cast entry, its stable id (for annotation).
12159
- cast_id: z9.string().nullable().optional(),
13712
+ cast_id: z11.string().nullable().optional(),
12160
13713
  // The label of another element that is the SAME individual as this one, shown
12161
13714
  // in a DIFFERENT wardrobe/persona/state (e.g. one creator playing skeptic in a
12162
13715
  // pink shirt and believer in a white shirt). Each look gets its own reference
12163
13716
  // slot, but the face/identity must stay identical across them.
12164
- same_as: z9.string().nullable().optional(),
13717
+ same_as: z11.string().nullable().optional(),
12165
13718
  // Scenes the element appears in. Either a bare list of scene indices (both
12166
13719
  // edges) or per-{scene,edge} entries. Both forms are accepted and merged.
12167
- scenes: z9.array(z9.number()).optional(),
12168
- appears_in: z9.array(AppearsItem).optional()
13720
+ scenes: z11.array(z11.number()).optional(),
13721
+ appears_in: z11.array(AppearsItem).optional()
12169
13722
  }).loose();
12170
- var RecurringElements = z9.array(RecurringElement);
13723
+ var RecurringElements = z11.array(RecurringElement);
12171
13724
  function sanitizeId2(raw, fallback) {
12172
13725
  const id = raw.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
12173
13726
  return /^[a-z]/.test(id) ? id : `${fallback}_${id}`.replace(/_+$/g, "") || fallback;
@@ -13630,25 +15183,25 @@ function buildSfxMusic(blueprint, nodes) {
13630
15183
  }
13631
15184
  return tracks;
13632
15185
  }
13633
- var OverlayStyle = z9.object({ color_hex: z9.string().optional(), background: z9.string().optional(), size: z9.string().optional() }).loose();
13634
- var Overlay = z9.object({
13635
- text: z9.string().optional(),
13636
- appears_at_s: z9.number().optional(),
13637
- duration_s: z9.number().optional(),
13638
- position: z9.string().optional(),
13639
- role: z9.string().optional(),
13640
- animation: z9.string().optional(),
13641
- animation_detail: z9.string().optional(),
15186
+ var OverlayStyle = z11.object({ color_hex: z11.string().optional(), background: z11.string().optional(), size: z11.string().optional() }).loose();
15187
+ var Overlay = z11.object({
15188
+ text: z11.string().optional(),
15189
+ appears_at_s: z11.number().optional(),
15190
+ duration_s: z11.number().optional(),
15191
+ position: z11.string().optional(),
15192
+ role: z11.string().optional(),
15193
+ animation: z11.string().optional(),
15194
+ animation_detail: z11.string().optional(),
13642
15195
  style: OverlayStyle.optional()
13643
15196
  }).loose();
13644
- var FloatingElement = z9.object({
13645
- kind: z9.string().optional(),
13646
- description: z9.string().optional(),
13647
- brand_name: z9.string().nullish(),
13648
- what_it_represents: z9.string().optional(),
13649
- appears_at_s: z9.number().optional(),
13650
- duration_s: z9.number().optional(),
13651
- position: z9.string().optional()
15197
+ var FloatingElement = z11.object({
15198
+ kind: z11.string().optional(),
15199
+ description: z11.string().optional(),
15200
+ brand_name: z11.string().nullish(),
15201
+ what_it_represents: z11.string().optional(),
15202
+ appears_at_s: z11.number().optional(),
15203
+ duration_s: z11.number().optional(),
15204
+ position: z11.string().optional()
13652
15205
  }).loose();
13653
15206
  function escapeHtml(s) {
13654
15207
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
@@ -13680,7 +15233,7 @@ function positionClass(position) {
13680
15233
  function collectCaptions(blueprint) {
13681
15234
  return blueprint.scenes.flatMap((scene) => {
13682
15235
  const sceneStart = scene.start_s ?? 0;
13683
- const overlays = z9.array(Overlay).safeParse(scene.overlays ?? []);
15236
+ const overlays = z11.array(Overlay).safeParse(scene.overlays ?? []);
13684
15237
  return overlays.success ? overlays.data.filter((ov) => Boolean(ov.text?.trim())).map((ov) => {
13685
15238
  const at = ov.appears_at_s ?? sceneStart;
13686
15239
  return { text: ov.text.trim(), at, end: at + (ov.duration_s ?? 2.5), ov };
@@ -13789,7 +15342,7 @@ function buildOverlayHtml(input) {
13789
15342
  if (ovParts.length > 0) blocks.push(ovParts.join("\n"));
13790
15343
  for (const scene of blueprint.scenes) {
13791
15344
  const sceneStart = scene.start_s ?? 0;
13792
- const floats = z9.array(FloatingElement).safeParse(scene.floating_elements ?? []);
15345
+ const floats = z11.array(FloatingElement).safeParse(scene.floating_elements ?? []);
13793
15346
  const parts = (floats.success ? floats.data.map((fe) => floatingStub(fe, sceneStart)) : []).filter(Boolean);
13794
15347
  const pip = uiPipStub(scene);
13795
15348
  if (pip) parts.push(pip);
@@ -14046,8 +15599,8 @@ function buildMotionBoard(blueprint) {
14046
15599
  const end_s = scene.end_s ?? start_s + sceneDurationS(scene);
14047
15600
  cursor = end_s;
14048
15601
  const spoken = sceneSpokenText(scene);
14049
- const overlays = z9.array(Overlay).safeParse(scene.overlays ?? []);
14050
- const floats = z9.array(FloatingElement).safeParse(scene.floating_elements ?? []);
15602
+ const overlays = z11.array(Overlay).safeParse(scene.overlays ?? []);
15603
+ const floats = z11.array(FloatingElement).safeParse(scene.floating_elements ?? []);
14051
15604
  const graphics = [
14052
15605
  ...(overlays.success ? overlays.data : []).filter((ov) => ov.text?.trim()).map((ov) => ({
14053
15606
  kind: "text",
@@ -14488,7 +16041,7 @@ async function runAnalysisPasses(deconstructCanvas, selectModel) {
14488
16041
  return fail2("deconstruct", e instanceof Error ? e.message : String(e));
14489
16042
  }
14490
16043
  }
14491
- var scaffoldVideoCommand = defineCommand85({
16044
+ var scaffoldVideoCommand = defineCommand87({
14492
16045
  meta: {
14493
16046
  name: "scaffold-video",
14494
16047
  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`."
@@ -14633,7 +16186,7 @@ var scaffoldVideoCommand = defineCommand85({
14633
16186
  // src/commands/canvas/set-prompt.ts
14634
16187
  import { readFile as readFile7, writeFile as writeFile3 } from "fs/promises";
14635
16188
  import path10 from "path";
14636
- import { defineCommand as defineCommand86 } from "citty";
16189
+ import { defineCommand as defineCommand88 } from "citty";
14637
16190
  function setNodePrompt(canvas, nodeId, text) {
14638
16191
  const nodes = canvas?.nodes;
14639
16192
  if (!Array.isArray(nodes)) throw new Error("canvas has no nodes array");
@@ -14648,7 +16201,7 @@ function setNodePrompt(canvas, nodeId, text) {
14648
16201
  newNodes[idx] = newNode;
14649
16202
  return { ...canvas, nodes: newNodes };
14650
16203
  }
14651
- var setPromptCommand = defineCommand86({
16204
+ var setPromptCommand = defineCommand88({
14652
16205
  meta: {
14653
16206
  name: "set-prompt",
14654
16207
  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."
@@ -14708,8 +16261,8 @@ var setPromptCommand = defineCommand86({
14708
16261
  // src/commands/canvas/validate.ts
14709
16262
  import { readFile as readFile8 } from "fs/promises";
14710
16263
  import path11 from "path";
14711
- import { defineCommand as defineCommand87 } from "citty";
14712
- var validateCommand = defineCommand87({
16264
+ import { defineCommand as defineCommand89 } from "citty";
16265
+ var validateCommand = defineCommand89({
14713
16266
  meta: {
14714
16267
  name: "validate",
14715
16268
  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)."
@@ -14752,7 +16305,7 @@ var validateCommand = defineCommand87({
14752
16305
  });
14753
16306
 
14754
16307
  // src/commands/canvas/index.ts
14755
- var canvasCommand = defineCommand88({
16308
+ var canvasCommand = defineCommand90({
14756
16309
  meta: {
14757
16310
  name: "canvas",
14758
16311
  description: `Run Baker creative canvas JSON files locally. Local nodes execute in-process; remote nodes POST to the Convex backend gateway.
@@ -14779,10 +16332,10 @@ Subcommands:
14779
16332
  });
14780
16333
 
14781
16334
  // src/commands/creatives/index.ts
14782
- import { defineCommand as defineCommand90 } from "citty";
16335
+ import { defineCommand as defineCommand92 } from "citty";
14783
16336
 
14784
16337
  // src/commands/creatives/publish.ts
14785
- import { defineCommand as defineCommand89 } from "citty";
16338
+ import { defineCommand as defineCommand91 } from "citty";
14786
16339
 
14787
16340
  // src/commands/images/api.ts
14788
16341
  import { readFile as readFile9 } from "fs/promises";
@@ -14905,7 +16458,7 @@ async function publishCreative(args, deps = defaultImageApiDeps) {
14905
16458
  sourceReferenceUrl
14906
16459
  });
14907
16460
  }
14908
- var publishCommand = defineCommand89({
16461
+ var publishCommand = defineCommand91({
14909
16462
  meta: {
14910
16463
  name: "publish",
14911
16464
  description: "Publish a final static creative image to Baker Creatives and print the creative reference JSON."
@@ -14951,7 +16504,7 @@ var publishCommand = defineCommand89({
14951
16504
  });
14952
16505
 
14953
16506
  // src/commands/creatives/index.ts
14954
- var creativesCommand3 = defineCommand90({
16507
+ var creativesCommand3 = defineCommand92({
14955
16508
  meta: {
14956
16509
  name: "creatives",
14957
16510
  description: `Publish static ad creatives as first-class Baker outputs.
@@ -14967,10 +16520,10 @@ Publishing uploads the image to the Company image library, applies the official
14967
16520
  });
14968
16521
 
14969
16522
  // src/commands/ga4/index.ts
14970
- import { defineCommand as defineCommand94 } from "citty";
16523
+ import { defineCommand as defineCommand96 } from "citty";
14971
16524
 
14972
16525
  // src/commands/ga4/audit.ts
14973
- import { defineCommand as defineCommand91 } from "citty";
16526
+ import { defineCommand as defineCommand93 } from "citty";
14974
16527
 
14975
16528
  // src/commands/ga4/resolve.ts
14976
16529
  async function fetchProperties(useCache = true) {
@@ -15033,7 +16586,7 @@ registerSchema({
15033
16586
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
15034
16587
  }
15035
16588
  });
15036
- var auditCommand2 = defineCommand91({
16589
+ var auditCommand2 = defineCommand93({
15037
16590
  meta: {
15038
16591
  name: "audit",
15039
16592
  description: `Run all GA4 admin health checks. Returns property config with playbook warnings.
@@ -15085,7 +16638,7 @@ Examples:
15085
16638
  });
15086
16639
 
15087
16640
  // src/commands/ga4/properties.ts
15088
- import { defineCommand as defineCommand92 } from "citty";
16641
+ import { defineCommand as defineCommand94 } from "citty";
15089
16642
  registerSchema({
15090
16643
  command: "ga4.properties",
15091
16644
  description: "List all accessible GA4 properties. Returns property IDs needed for query and audit commands. Run this first to find property IDs.",
@@ -15093,7 +16646,7 @@ registerSchema({
15093
16646
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
15094
16647
  }
15095
16648
  });
15096
- var propertiesCommand = defineCommand92({
16649
+ var propertiesCommand = defineCommand94({
15097
16650
  meta: {
15098
16651
  name: "properties",
15099
16652
  description: `List accessible GA4 properties.
@@ -15141,9 +16694,9 @@ Examples:
15141
16694
  });
15142
16695
 
15143
16696
  // src/commands/ga4/query.ts
15144
- import { appendFileSync as appendFileSync2, existsSync as existsSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "fs";
16697
+ import { appendFileSync as appendFileSync2, existsSync as existsSync5, readFileSync as readFileSync9, writeFileSync as writeFileSync4 } from "fs";
15145
16698
  import { resolve as resolve2 } from "path";
15146
- import { defineCommand as defineCommand93 } from "citty";
16699
+ import { defineCommand as defineCommand95 } from "citty";
15147
16700
 
15148
16701
  // src/commands/ga4/presets.ts
15149
16702
  var GA4_PRESETS = [
@@ -15232,7 +16785,7 @@ function writeRowsToFile2(filePath, rows, append) {
15232
16785
  writeFileSync4(filePath, content, "utf-8");
15233
16786
  }
15234
16787
  } else if (append && existsSync5(filePath)) {
15235
- const existing = JSON.parse(readFileSync8(filePath, "utf-8"));
16788
+ const existing = JSON.parse(readFileSync9(filePath, "utf-8"));
15236
16789
  writeFileSync4(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
15237
16790
  } else {
15238
16791
  writeFileSync4(filePath, JSON.stringify(rows, null, 2), "utf-8");
@@ -15275,7 +16828,7 @@ function handleError(err) {
15275
16828
  });
15276
16829
  process.exit(1);
15277
16830
  }
15278
- var queryCommand2 = defineCommand93({
16831
+ var queryCommand2 = defineCommand95({
15279
16832
  meta: {
15280
16833
  name: "query",
15281
16834
  description: `Run GA4 Data API reports. Preset-first with free-form escape hatch.
@@ -15346,7 +16899,7 @@ Free-form (escape hatch):
15346
16899
  });
15347
16900
 
15348
16901
  // src/commands/ga4/index.ts
15349
- var ga4Command = defineCommand94({
16902
+ var ga4Command = defineCommand96({
15350
16903
  meta: {
15351
16904
  name: "ga4",
15352
16905
  description: `Google Analytics 4 commands. Audit property config, run playbook-aligned reports.
@@ -15369,12 +16922,12 @@ Examples:
15369
16922
  });
15370
16923
 
15371
16924
  // src/commands/gsc/index.ts
15372
- import { defineCommand as defineCommand98 } from "citty";
16925
+ import { defineCommand as defineCommand100 } from "citty";
15373
16926
 
15374
16927
  // src/commands/gsc/query.ts
15375
- import { appendFileSync as appendFileSync3, existsSync as existsSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "fs";
16928
+ import { appendFileSync as appendFileSync3, existsSync as existsSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync5 } from "fs";
15376
16929
  import { resolve as resolve3 } from "path";
15377
- import { defineCommand as defineCommand95 } from "citty";
16930
+ import { defineCommand as defineCommand97 } from "citty";
15378
16931
 
15379
16932
  // src/commands/gsc/presets.ts
15380
16933
  var GSC_PRESETS = [
@@ -15517,7 +17070,7 @@ function writeRowsToFile3(filePath, rows, append) {
15517
17070
  writeFileSync5(filePath, content, "utf-8");
15518
17071
  }
15519
17072
  } else if (append && existsSync6(filePath)) {
15520
- const existing = JSON.parse(readFileSync9(filePath, "utf-8"));
17073
+ const existing = JSON.parse(readFileSync10(filePath, "utf-8"));
15521
17074
  writeFileSync5(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
15522
17075
  } else {
15523
17076
  writeFileSync5(filePath, JSON.stringify(rows, null, 2), "utf-8");
@@ -15562,7 +17115,7 @@ function handleError2(err) {
15562
17115
  });
15563
17116
  process.exit(1);
15564
17117
  }
15565
- var queryCommand3 = defineCommand95({
17118
+ var queryCommand3 = defineCommand97({
15566
17119
  meta: {
15567
17120
  name: "query",
15568
17121
  description: `Run GSC Search Analytics queries. Preset-first with free-form escape hatch.
@@ -15640,7 +17193,7 @@ Free-form (escape hatch):
15640
17193
  });
15641
17194
 
15642
17195
  // src/commands/gsc/sitemaps.ts
15643
- import { defineCommand as defineCommand96 } from "citty";
17196
+ import { defineCommand as defineCommand98 } from "citty";
15644
17197
  registerSchema({
15645
17198
  command: "gsc.sitemaps",
15646
17199
  description: "List sitemaps for a Search Console site. Check sitemap health and errors.",
@@ -15649,7 +17202,7 @@ registerSchema({
15649
17202
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
15650
17203
  }
15651
17204
  });
15652
- var sitemapsCommand = defineCommand96({
17205
+ var sitemapsCommand = defineCommand98({
15653
17206
  meta: {
15654
17207
  name: "sitemaps",
15655
17208
  description: `List sitemaps for a site. Check health and errors.
@@ -15699,7 +17252,7 @@ Examples:
15699
17252
  });
15700
17253
 
15701
17254
  // src/commands/gsc/sites.ts
15702
- import { defineCommand as defineCommand97 } from "citty";
17255
+ import { defineCommand as defineCommand99 } from "citty";
15703
17256
  registerSchema({
15704
17257
  command: "gsc.sites",
15705
17258
  description: "List all verified Google Search Console sites. Returns site URLs needed for query and sitemaps commands.",
@@ -15707,7 +17260,7 @@ registerSchema({
15707
17260
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
15708
17261
  }
15709
17262
  });
15710
- var sitesCommand = defineCommand97({
17263
+ var sitesCommand = defineCommand99({
15711
17264
  meta: {
15712
17265
  name: "sites",
15713
17266
  description: `List verified Search Console sites.
@@ -15755,7 +17308,7 @@ Examples:
15755
17308
  });
15756
17309
 
15757
17310
  // src/commands/gsc/index.ts
15758
- var gscCommand = defineCommand98({
17311
+ var gscCommand = defineCommand100({
15759
17312
  meta: {
15760
17313
  name: "gsc",
15761
17314
  description: `Google Search Console commands. PPC-SEO arbitrage, brand halo analysis, negative keyword discovery.
@@ -15778,10 +17331,10 @@ Examples:
15778
17331
  });
15779
17332
 
15780
17333
  // src/commands/images/index.ts
15781
- import { defineCommand as defineCommand122 } from "citty";
17334
+ import { defineCommand as defineCommand124 } from "citty";
15782
17335
 
15783
17336
  // src/commands/images/crop.ts
15784
- import { defineCommand as defineCommand99 } from "citty";
17337
+ import { defineCommand as defineCommand101 } from "citty";
15785
17338
 
15786
17339
  // src/lib/image/crop-sprite.ts
15787
17340
  import sharp from "sharp";
@@ -15906,7 +17459,7 @@ function emitError2(err) {
15906
17459
  }
15907
17460
  process.exit(1);
15908
17461
  }
15909
- var cropCommand = defineCommand99({
17462
+ var cropCommand = defineCommand101({
15910
17463
  meta: {
15911
17464
  name: "crop",
15912
17465
  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"
@@ -15942,7 +17495,7 @@ var cropCommand = defineCommand99({
15942
17495
  });
15943
17496
 
15944
17497
  // src/commands/images/delete.ts
15945
- import { defineCommand as defineCommand100 } from "citty";
17498
+ import { defineCommand as defineCommand102 } from "citty";
15946
17499
  registerSchema({
15947
17500
  command: "images.delete",
15948
17501
  description: "Delete an image by ID",
@@ -15956,7 +17509,7 @@ registerSchema({
15956
17509
  }
15957
17510
  }
15958
17511
  });
15959
- var deleteCommand = defineCommand100({
17512
+ var deleteCommand = defineCommand102({
15960
17513
  meta: {
15961
17514
  name: "delete",
15962
17515
  description: "Delete an image by ID. Use --dry-run to preview. Example: baker images delete j571abc123 --dry-run"
@@ -15997,7 +17550,7 @@ var deleteCommand = defineCommand100({
15997
17550
  });
15998
17551
 
15999
17552
  // src/commands/images/dimensions.ts
16000
- import { defineCommand as defineCommand101 } from "citty";
17553
+ import { defineCommand as defineCommand103 } from "citty";
16001
17554
 
16002
17555
  // src/lib/image/dimensions.ts
16003
17556
  import { imageSize } from "image-size";
@@ -16020,7 +17573,7 @@ registerSchema({
16020
17573
  target: { type: "string", description: "Local file path or remote http(s) URL", required: true }
16021
17574
  }
16022
17575
  });
16023
- var dimensionsCommand = defineCommand101({
17576
+ var dimensionsCommand = defineCommand103({
16024
17577
  meta: {
16025
17578
  name: "dimensions",
16026
17579
  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"
@@ -16064,7 +17617,7 @@ var dimensionsCommand = defineCommand101({
16064
17617
  });
16065
17618
 
16066
17619
  // src/commands/images/extract.ts
16067
- import { defineCommand as defineCommand102 } from "citty";
17620
+ import { defineCommand as defineCommand104 } from "citty";
16068
17621
  registerSchema({
16069
17622
  command: "images.extract",
16070
17623
  description: "Extract images from a URL via Firecrawl (formats: images).",
@@ -16080,7 +17633,7 @@ registerSchema({
16080
17633
  }
16081
17634
  }
16082
17635
  });
16083
- var extractCommand = defineCommand102({
17636
+ var extractCommand = defineCommand104({
16084
17637
  meta: {
16085
17638
  name: "extract",
16086
17639
  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"
@@ -16118,7 +17671,7 @@ var extractCommand = defineCommand102({
16118
17671
  });
16119
17672
 
16120
17673
  // src/commands/images/find.ts
16121
- import { defineCommand as defineCommand103 } from "citty";
17674
+ import { defineCommand as defineCommand105 } from "citty";
16122
17675
  registerSchema({
16123
17676
  command: "images.find",
16124
17677
  description: "Fanout image search: library first, then opted-in external providers.",
@@ -16150,7 +17703,7 @@ registerSchema({
16150
17703
  }
16151
17704
  }
16152
17705
  });
16153
- var findCommand = defineCommand103({
17706
+ var findCommand = defineCommand105({
16154
17707
  meta: {
16155
17708
  name: "find",
16156
17709
  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"
@@ -16199,7 +17752,7 @@ var findCommand = defineCommand103({
16199
17752
 
16200
17753
  // src/commands/images/generate.ts
16201
17754
  import { readFile as readFile11 } from "fs/promises";
16202
- import { defineCommand as defineCommand104 } from "citty";
17755
+ import { defineCommand as defineCommand106 } from "citty";
16203
17756
  import sharp2 from "sharp";
16204
17757
  var GENERATE_TIMEOUT_MS = 18e4;
16205
17758
  var REFERENCE_MAX_EDGE = 1536;
@@ -16302,7 +17855,7 @@ async function resolveReferences(spec) {
16302
17855
  }
16303
17856
  return out;
16304
17857
  }
16305
- var generateCommand = defineCommand104({
17858
+ var generateCommand = defineCommand106({
16306
17859
  meta: {
16307
17860
  name: "generate",
16308
17861
  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]]'"
@@ -16354,7 +17907,7 @@ var generateCommand = defineCommand104({
16354
17907
  });
16355
17908
 
16356
17909
  // src/commands/images/get.ts
16357
- import { defineCommand as defineCommand105 } from "citty";
17910
+ import { defineCommand as defineCommand107 } from "citty";
16358
17911
  registerSchema({
16359
17912
  command: "images.get",
16360
17913
  description: "Get a single image by ID",
@@ -16362,7 +17915,7 @@ registerSchema({
16362
17915
  id: { type: "string", description: "Image ID", required: true }
16363
17916
  }
16364
17917
  });
16365
- var getCommand2 = defineCommand105({
17918
+ var getCommand2 = defineCommand107({
16366
17919
  meta: { name: "get", description: "Get a single image by ID. Example: baker images get j571abc123" },
16367
17920
  args: {
16368
17921
  id: { type: "positional", description: "Image ID", required: false },
@@ -16398,7 +17951,7 @@ var getCommand2 = defineCommand105({
16398
17951
  });
16399
17952
 
16400
17953
  // src/commands/images/gif.ts
16401
- import { defineCommand as defineCommand106 } from "citty";
17954
+ import { defineCommand as defineCommand108 } from "citty";
16402
17955
  registerSchema({
16403
17956
  command: "images.gif",
16404
17957
  description: "Search Giphy for GIFs / reaction memes (paid social creative).",
@@ -16430,7 +17983,7 @@ registerSchema({
16430
17983
  }
16431
17984
  }
16432
17985
  });
16433
- var gifCommand = defineCommand106({
17986
+ var gifCommand = defineCommand108({
16434
17987
  meta: {
16435
17988
  name: "gif",
16436
17989
  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"
@@ -16477,7 +18030,7 @@ var gifCommand = defineCommand106({
16477
18030
  });
16478
18031
 
16479
18032
  // src/commands/images/google.ts
16480
- import { defineCommand as defineCommand107 } from "citty";
18033
+ import { defineCommand as defineCommand109 } from "citty";
16481
18034
  registerSchema({
16482
18035
  command: "images.google",
16483
18036
  description: "Google Images search via the official Custom Search JSON API. Unverified source \u2014 inspect before placing.",
@@ -16513,7 +18066,7 @@ registerSchema({
16513
18066
  }
16514
18067
  }
16515
18068
  });
16516
- var googleCommand2 = defineCommand107({
18069
+ var googleCommand2 = defineCommand109({
16517
18070
  meta: {
16518
18071
  name: "google",
16519
18072
  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"
@@ -16561,7 +18114,7 @@ var googleCommand2 = defineCommand107({
16561
18114
  });
16562
18115
 
16563
18116
  // src/commands/images/icon.ts
16564
- import { defineCommand as defineCommand108 } from "citty";
18117
+ import { defineCommand as defineCommand110 } from "citty";
16565
18118
  registerSchema({
16566
18119
  command: "images.icon",
16567
18120
  description: "Icon lookup via Iconify (200+ icon sets, free CDN).",
@@ -16587,7 +18140,7 @@ registerSchema({
16587
18140
  }
16588
18141
  }
16589
18142
  });
16590
- var iconCommand = defineCommand108({
18143
+ var iconCommand = defineCommand110({
16591
18144
  meta: {
16592
18145
  name: "icon",
16593
18146
  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'"
@@ -16627,7 +18180,7 @@ var iconCommand = defineCommand108({
16627
18180
  });
16628
18181
 
16629
18182
  // src/commands/images/ingest.ts
16630
- import { defineCommand as defineCommand109 } from "citty";
18183
+ import { defineCommand as defineCommand111 } from "citty";
16631
18184
  registerSchema({
16632
18185
  command: "images.ingest",
16633
18186
  description: "Ingest a remote image URL into the library (full describe + embed).",
@@ -16639,7 +18192,7 @@ registerSchema({
16639
18192
  context: { type: "string", description: "Description context hint", required: false }
16640
18193
  }
16641
18194
  });
16642
- var ingestCommand = defineCommand109({
18195
+ var ingestCommand = defineCommand111({
16643
18196
  meta: {
16644
18197
  name: "ingest",
16645
18198
  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"
@@ -16681,7 +18234,7 @@ var ingestCommand = defineCommand109({
16681
18234
  });
16682
18235
 
16683
18236
  // src/commands/images/library.ts
16684
- import { defineCommand as defineCommand110 } from "citty";
18237
+ import { defineCommand as defineCommand112 } from "citty";
16685
18238
  registerSchema({
16686
18239
  command: "images.library",
16687
18240
  description: "Search the company image library. Returns only ready images.",
@@ -16707,7 +18260,7 @@ registerSchema({
16707
18260
  }
16708
18261
  }
16709
18262
  });
16710
- var libraryCommand = defineCommand110({
18263
+ var libraryCommand = defineCommand112({
16711
18264
  meta: {
16712
18265
  name: "library",
16713
18266
  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"
@@ -16764,7 +18317,7 @@ var libraryCommand = defineCommand110({
16764
18317
  });
16765
18318
 
16766
18319
  // src/commands/images/logo.ts
16767
- import { defineCommand as defineCommand111 } from "citty";
18320
+ import { defineCommand as defineCommand113 } from "citty";
16768
18321
  registerSchema({
16769
18322
  command: "images.logo",
16770
18323
  description: "Brand logo lookup via Brandfetch CDN (fallback/404). Auto-ingests by default.",
@@ -16789,7 +18342,7 @@ registerSchema({
16789
18342
  }
16790
18343
  }
16791
18344
  });
16792
- var logoCommand = defineCommand111({
18345
+ var logoCommand = defineCommand113({
16793
18346
  meta: {
16794
18347
  name: "logo",
16795
18348
  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"
@@ -16827,7 +18380,7 @@ var logoCommand = defineCommand111({
16827
18380
  });
16828
18381
 
16829
18382
  // src/commands/images/normalize.ts
16830
- import { defineCommand as defineCommand112 } from "citty";
18383
+ import { defineCommand as defineCommand114 } from "citty";
16831
18384
 
16832
18385
  // src/lib/image/color-changer.ts
16833
18386
  import quantize from "quantize";
@@ -17559,7 +19112,7 @@ function coerceRawArgs(args) {
17559
19112
  "dry-run": bool(args["dry-run"])
17560
19113
  };
17561
19114
  }
17562
- var normalizeCommand = defineCommand112({
19115
+ var normalizeCommand = defineCommand114({
17563
19116
  meta: {
17564
19117
  name: "normalize",
17565
19118
  description: `Normalize logos / images: declarative recolor + bg removal + trim + resize. Operates on local files; writes in-place by default.
@@ -17614,7 +19167,7 @@ Examples:
17614
19167
  });
17615
19168
 
17616
19169
  // src/commands/images/pinterest.ts
17617
- import { defineCommand as defineCommand113 } from "citty";
19170
+ import { defineCommand as defineCommand115 } from "citty";
17618
19171
  registerSchema({
17619
19172
  command: "images.pinterest",
17620
19173
  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.",
@@ -17634,7 +19187,7 @@ registerSchema({
17634
19187
  }
17635
19188
  }
17636
19189
  });
17637
- var pinterestCommand = defineCommand113({
19190
+ var pinterestCommand = defineCommand115({
17638
19191
  meta: {
17639
19192
  name: "pinterest",
17640
19193
  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'"
@@ -17674,7 +19227,7 @@ var pinterestCommand = defineCommand113({
17674
19227
  });
17675
19228
 
17676
19229
  // src/commands/images/screenshot.ts
17677
- import { defineCommand as defineCommand114 } from "citty";
19230
+ import { defineCommand as defineCommand116 } from "citty";
17678
19231
  registerSchema({
17679
19232
  command: "images.screenshot",
17680
19233
  description: "Capture a website screenshot via ScreenshotOne. Auto-ingests on success.",
@@ -17690,7 +19243,7 @@ registerSchema({
17690
19243
  }
17691
19244
  }
17692
19245
  });
17693
- var screenshotCommand = defineCommand114({
19246
+ var screenshotCommand = defineCommand116({
17694
19247
  meta: {
17695
19248
  name: "screenshot",
17696
19249
  description: "Screenshot a URL via ScreenshotOne. $0.009/capture. Auto-ingests to library.\n\nExample: baker images screenshot https://stripe.com --full-page"
@@ -17740,7 +19293,7 @@ var screenshotCommand = defineCommand114({
17740
19293
  });
17741
19294
 
17742
19295
  // src/commands/images/search.ts
17743
- import { defineCommand as defineCommand115 } from "citty";
19296
+ import { defineCommand as defineCommand117 } from "citty";
17744
19297
  registerSchema({
17745
19298
  command: "images.search",
17746
19299
  description: "Search images by text query. Only returns ready images.",
@@ -17756,7 +19309,7 @@ registerSchema({
17756
19309
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
17757
19310
  }
17758
19311
  });
17759
- var searchCommand = defineCommand115({
19312
+ var searchCommand = defineCommand117({
17760
19313
  meta: {
17761
19314
  name: "search",
17762
19315
  description: "Semantic search images by text query. Uses hybrid BM25 + vector + reranking. Example: baker images search 'hero banner' --aspect-ratio 16:9 --tags logo"
@@ -17816,7 +19369,7 @@ var searchCommand = defineCommand115({
17816
19369
  });
17817
19370
 
17818
19371
  // src/commands/images/sticker.ts
17819
- import { defineCommand as defineCommand116 } from "citty";
19372
+ import { defineCommand as defineCommand118 } from "citty";
17820
19373
  registerSchema({
17821
19374
  command: "images.sticker",
17822
19375
  description: "Search Giphy stickers \u2014 transparent-background overlays for ad creative.",
@@ -17848,7 +19401,7 @@ registerSchema({
17848
19401
  }
17849
19402
  }
17850
19403
  });
17851
- var stickerCommand = defineCommand116({
19404
+ var stickerCommand = defineCommand118({
17852
19405
  meta: {
17853
19406
  name: "sticker",
17854
19407
  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"
@@ -17895,7 +19448,7 @@ var stickerCommand = defineCommand116({
17895
19448
  });
17896
19449
 
17897
19450
  // src/commands/images/stock.ts
17898
- import { defineCommand as defineCommand117 } from "citty";
19451
+ import { defineCommand as defineCommand119 } from "citty";
17899
19452
  registerSchema({
17900
19453
  command: "images.stock",
17901
19454
  description: "Stock photo, vector illustration, icon-set, and PSD search via Magnific (Freepik's developer API).",
@@ -17953,7 +19506,7 @@ registerSchema({
17953
19506
  }
17954
19507
  }
17955
19508
  });
17956
- var stockCommand = defineCommand117({
19509
+ var stockCommand = defineCommand119({
17957
19510
  meta: {
17958
19511
  name: "stock",
17959
19512
  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"
@@ -18009,7 +19562,7 @@ var stockCommand = defineCommand117({
18009
19562
  });
18010
19563
 
18011
19564
  // src/lib/tags-command.ts
18012
- import { defineCommand as defineCommand118 } from "citty";
19565
+ import { defineCommand as defineCommand120 } from "citty";
18013
19566
  function makeTagsCommand(command, label, endpoint) {
18014
19567
  registerSchema({
18015
19568
  command: `${command}.tags`,
@@ -18018,7 +19571,7 @@ function makeTagsCommand(command, label, endpoint) {
18018
19571
  output: { type: "string", description: "Output format: md|json", required: false, default: "md" }
18019
19572
  }
18020
19573
  });
18021
- return defineCommand118({
19574
+ return defineCommand120({
18022
19575
  meta: {
18023
19576
  name: "tags",
18024
19577
  description: `List the available ${label} tag names (defaults + company custom tags). Use before filtering with --tags. Example: baker ${command} tags`
@@ -18054,7 +19607,7 @@ function makeTagsCommand(command, label, endpoint) {
18054
19607
  var tagsCommand2 = makeTagsCommand("images", "image", "/api/images/tags");
18055
19608
 
18056
19609
  // src/commands/images/upload.ts
18057
- import { defineCommand as defineCommand119 } from "citty";
19610
+ import { defineCommand as defineCommand121 } from "citty";
18058
19611
  registerSchema({
18059
19612
  command: "images.upload",
18060
19613
  description: "Upload an image to the library \u2014 local file path or remote http(s) URL.",
@@ -18092,7 +19645,7 @@ registerSchema({
18092
19645
  function isRemoteUrl2(value) {
18093
19646
  return /^https?:\/\//i.test(value);
18094
19647
  }
18095
- var uploadCommand = defineCommand119({
19648
+ var uploadCommand = defineCommand121({
18096
19649
  meta: {
18097
19650
  name: "upload",
18098
19651
  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'"
@@ -18185,7 +19738,7 @@ async function uploadLocal(target, args) {
18185
19738
  }
18186
19739
 
18187
19740
  // src/commands/images/upscale.ts
18188
- import { defineCommand as defineCommand120 } from "citty";
19741
+ import { defineCommand as defineCommand122 } from "citty";
18189
19742
  registerSchema({
18190
19743
  command: "images.upscale",
18191
19744
  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).",
@@ -18200,7 +19753,7 @@ registerSchema({
18200
19753
  }
18201
19754
  });
18202
19755
  var POLL_INTERVAL_MS3 = 1500;
18203
- var upscaleCommand = defineCommand120({
19756
+ var upscaleCommand = defineCommand122({
18204
19757
  meta: {
18205
19758
  name: "upscale",
18206
19759
  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"
@@ -18255,7 +19808,7 @@ var upscaleCommand = defineCommand120({
18255
19808
  });
18256
19809
 
18257
19810
  // src/commands/images/use.ts
18258
- import { defineCommand as defineCommand121 } from "citty";
19811
+ import { defineCommand as defineCommand123 } from "citty";
18259
19812
  registerSchema({
18260
19813
  command: "images.use",
18261
19814
  description: "Ingest a URL and wait for the library record to be ready.",
@@ -18271,7 +19824,7 @@ registerSchema({
18271
19824
  }
18272
19825
  });
18273
19826
  var POLL_INTERVAL_MS4 = 1500;
18274
- var useCommand = defineCommand121({
19827
+ var useCommand = defineCommand123({
18275
19828
  meta: {
18276
19829
  name: "use",
18277
19830
  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"
@@ -18317,7 +19870,7 @@ var useCommand = defineCommand121({
18317
19870
  });
18318
19871
 
18319
19872
  // src/commands/images/index.ts
18320
- var imagesCommand = defineCommand122({
19873
+ var imagesCommand = defineCommand124({
18321
19874
  meta: {
18322
19875
  name: "images",
18323
19876
  description: `Find, source, and normalize images. Subcommands route by provider so cost + license are explicit.
@@ -18387,7 +19940,7 @@ Paid transforms (run on the Convex backend, cost-tracked):
18387
19940
  });
18388
19941
 
18389
19942
  // src/commands/mcp/index.ts
18390
- import { defineCommand as defineCommand123 } from "citty";
19943
+ import { defineCommand as defineCommand125 } from "citty";
18391
19944
  var SCOPES = ["user", "company", "org"];
18392
19945
  function parseScope(raw) {
18393
19946
  const scope = raw === void 0 ? "company" : String(raw);
@@ -18426,7 +19979,7 @@ registerSchema({
18426
19979
  description: "List the custom MCP servers this company's chats see (org + company + your own user scope).",
18427
19980
  args: {}
18428
19981
  });
18429
- var listCommand4 = defineCommand123({
19982
+ var listCommand4 = defineCommand125({
18430
19983
  meta: { name: "list", description: "List custom MCP servers visible to this company's chats." },
18431
19984
  run: async () => {
18432
19985
  try {
@@ -18451,7 +20004,7 @@ registerSchema({
18451
20004
  header: { type: "string", description: 'Auth header "Key: Value" (repeatable)', required: false }
18452
20005
  }
18453
20006
  });
18454
- var addCommand = defineCommand123({
20007
+ var addCommand = defineCommand125({
18455
20008
  meta: {
18456
20009
  name: "add",
18457
20010
  description: `Register a custom MCP server. Tools appear as mcp__<name>__* on the NEXT message.
@@ -18492,7 +20045,7 @@ registerSchema({
18492
20045
  description: "Remove a company custom MCP server by name.",
18493
20046
  args: { name: { type: "string", description: "Server name to remove", required: true } }
18494
20047
  });
18495
- var removeCommand3 = defineCommand123({
20048
+ var removeCommand3 = defineCommand125({
18496
20049
  meta: {
18497
20050
  name: "remove",
18498
20051
  description: `Remove a company custom MCP server by name.
@@ -18514,7 +20067,7 @@ Example:
18514
20067
  }
18515
20068
  }
18516
20069
  });
18517
- var mcpCommand = defineCommand123({
20070
+ var mcpCommand = defineCommand125({
18518
20071
  meta: {
18519
20072
  name: "mcp",
18520
20073
  description: `Custom MCP servers for this company \u2014 point the agent at any HTTPS MCP endpoint.
@@ -18538,10 +20091,10 @@ Examples:
18538
20091
  });
18539
20092
 
18540
20093
  // src/commands/research/index.ts
18541
- import { defineCommand as defineCommand134 } from "citty";
20094
+ import { defineCommand as defineCommand136 } from "citty";
18542
20095
 
18543
20096
  // src/commands/research/advertisers.ts
18544
- import { defineCommand as defineCommand124 } from "citty";
20097
+ import { defineCommand as defineCommand126 } from "citty";
18545
20098
 
18546
20099
  // src/commands/research/output.ts
18547
20100
  var RESEARCH_DATA_NOTE = "Estimates based on third-party SERP data \u2014 not exact figures. Use for directional insights, not precise measurement.";
@@ -18654,7 +20207,7 @@ var FIELDS3 = {
18654
20207
  etv: "Estimated traffic value (USD)",
18655
20208
  visibility: "SERP visibility score (0-1)"
18656
20209
  };
18657
- var advertisersCommand = defineCommand124({
20210
+ var advertisersCommand = defineCommand126({
18658
20211
  meta: {
18659
20212
  name: "advertisers",
18660
20213
  description: `Find domains competing for a keyword in Google SERPs.
@@ -18701,7 +20254,7 @@ Examples:
18701
20254
  });
18702
20255
 
18703
20256
  // src/commands/research/autocomplete.ts
18704
- import { defineCommand as defineCommand125 } from "citty";
20257
+ import { defineCommand as defineCommand127 } from "citty";
18705
20258
  registerSchema({
18706
20259
  command: "research.autocomplete",
18707
20260
  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).",
@@ -18724,7 +20277,7 @@ registerSchema({
18724
20277
  var FIELDS4 = {
18725
20278
  suggestion: "Autocomplete suggestion from Google"
18726
20279
  };
18727
- var autocompleteCommand = defineCommand125({
20280
+ var autocompleteCommand = defineCommand127({
18728
20281
  meta: {
18729
20282
  name: "autocomplete",
18730
20283
  description: `Get Google Autocomplete suggestions for keyword expansion.
@@ -18770,7 +20323,7 @@ Examples:
18770
20323
  });
18771
20324
 
18772
20325
  // src/commands/research/countries.ts
18773
- import { defineCommand as defineCommand126 } from "citty";
20326
+ import { defineCommand as defineCommand128 } from "citty";
18774
20327
  registerSchema({
18775
20328
  command: "research.countries",
18776
20329
  description: "List all supported country codes for --location flag in research commands.",
@@ -18827,7 +20380,7 @@ var FIELDS5 = {
18827
20380
  code: "Country code to pass as --location",
18828
20381
  name: "Country name"
18829
20382
  };
18830
- var countriesCommand = defineCommand126({
20383
+ var countriesCommand = defineCommand128({
18831
20384
  meta: {
18832
20385
  name: "countries",
18833
20386
  description: "List all supported country codes for --location flag."
@@ -18838,7 +20391,7 @@ var countriesCommand = defineCommand126({
18838
20391
  });
18839
20392
 
18840
20393
  // src/commands/research/intent.ts
18841
- import { defineCommand as defineCommand127 } from "citty";
20394
+ import { defineCommand as defineCommand129 } from "citty";
18842
20395
  registerSchema({
18843
20396
  command: "research.intent",
18844
20397
  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.",
@@ -18861,7 +20414,7 @@ var FIELDS6 = {
18861
20414
  intent: "Primary Google Search intent: informational, navigational, commercial, transactional",
18862
20415
  probability: "Confidence score 0.0-1.0"
18863
20416
  };
18864
- var intentCommand = defineCommand127({
20417
+ var intentCommand = defineCommand129({
18865
20418
  meta: {
18866
20419
  name: "intent",
18867
20420
  description: `Classify Google Search intent for keywords. Returns intent type and confidence.
@@ -18909,7 +20462,7 @@ Examples:
18909
20462
  });
18910
20463
 
18911
20464
  // src/commands/research/keyword-gap.ts
18912
- import { defineCommand as defineCommand128 } from "citty";
20465
+ import { defineCommand as defineCommand130 } from "citty";
18913
20466
  registerSchema({
18914
20467
  command: "research.keyword-gap",
18915
20468
  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.",
@@ -18938,7 +20491,7 @@ var FIELDS7 = {
18938
20491
  cpc: "Cost per click USD",
18939
20492
  their_position: "Competitor's ranking position"
18940
20493
  };
18941
- var keywordGapCommand = defineCommand128({
20494
+ var keywordGapCommand = defineCommand130({
18942
20495
  meta: {
18943
20496
  name: "keyword-gap",
18944
20497
  description: `Find keywords a competitor has that you don't. Supports pagination via --offset.
@@ -19012,7 +20565,7 @@ Examples:
19012
20565
  });
19013
20566
 
19014
20567
  // src/commands/research/keywords-for-site.ts
19015
- import { defineCommand as defineCommand129 } from "citty";
20568
+ import { defineCommand as defineCommand131 } from "citty";
19016
20569
  registerSchema({
19017
20570
  command: "research.keywords-for-site",
19018
20571
  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.",
@@ -19045,7 +20598,7 @@ var FIELDS8 = {
19045
20598
  competition: "LOW, MEDIUM, or HIGH",
19046
20599
  competition_index: "Competition score 0-100"
19047
20600
  };
19048
- var keywordsForSiteCommand = defineCommand129({
20601
+ var keywordsForSiteCommand = defineCommand131({
19049
20602
  meta: {
19050
20603
  name: "keywords-for-site",
19051
20604
  description: `Get keywords a competitor targets in Google. Use --type to filter paid/organic.
@@ -19098,7 +20651,7 @@ Examples:
19098
20651
  });
19099
20652
 
19100
20653
  // src/commands/research/languages.ts
19101
- import { defineCommand as defineCommand130 } from "citty";
20654
+ import { defineCommand as defineCommand132 } from "citty";
19102
20655
  registerSchema({
19103
20656
  command: "research.languages",
19104
20657
  description: "List all supported language codes for --language flag in research commands.",
@@ -19128,7 +20681,7 @@ var FIELDS9 = {
19128
20681
  code: "Language code to pass as --language",
19129
20682
  name: "Language name (also accepted by --language)"
19130
20683
  };
19131
- var languagesCommand2 = defineCommand130({
20684
+ var languagesCommand2 = defineCommand132({
19132
20685
  meta: {
19133
20686
  name: "languages",
19134
20687
  description: "List all supported language codes for --language flag."
@@ -19139,7 +20692,7 @@ var languagesCommand2 = defineCommand130({
19139
20692
  });
19140
20693
 
19141
20694
  // src/commands/research/lighthouse.ts
19142
- import { defineCommand as defineCommand131 } from "citty";
20695
+ import { defineCommand as defineCommand133 } from "citty";
19143
20696
  registerSchema({
19144
20697
  command: "research.lighthouse",
19145
20698
  description: "Landing page performance audit. Returns metrics that affect Google Ads Quality Score and CPC.",
@@ -19158,7 +20711,7 @@ var FIELDS10 = {
19158
20711
  speed_index_ms: "Speed Index in ms (good: < 3400)",
19159
20712
  interactive_ms: "Time to Interactive in ms (good: < 3800)"
19160
20713
  };
19161
- var lighthouseCommand = defineCommand131({
20714
+ var lighthouseCommand = defineCommand133({
19162
20715
  meta: {
19163
20716
  name: "lighthouse",
19164
20717
  description: `Landing page performance audit. Metrics affecting Google Ads Quality Score.
@@ -19196,7 +20749,7 @@ Examples:
19196
20749
  });
19197
20750
 
19198
20751
  // src/commands/research/relevant-pages.ts
19199
- import { defineCommand as defineCommand132 } from "citty";
20752
+ import { defineCommand as defineCommand134 } from "citty";
19200
20753
  registerSchema({
19201
20754
  command: "research.relevant-pages",
19202
20755
  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).",
@@ -19222,7 +20775,7 @@ var FIELDS11 = {
19222
20775
  keywords: "Total organic keywords the page ranks for",
19223
20776
  top_10: "Keywords in positions 1-10"
19224
20777
  };
19225
- var relevantPagesCommand = defineCommand132({
20778
+ var relevantPagesCommand = defineCommand134({
19226
20779
  meta: {
19227
20780
  name: "relevant-pages",
19228
20781
  description: `Get the top pages of a competitor domain with traffic data.
@@ -19268,7 +20821,7 @@ Examples:
19268
20821
  });
19269
20822
 
19270
20823
  // src/commands/research/web.ts
19271
- import { defineCommand as defineCommand133 } from "citty";
20824
+ import { defineCommand as defineCommand135 } from "citty";
19272
20825
  registerSchema({
19273
20826
  command: "research.web",
19274
20827
  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).",
@@ -19319,7 +20872,7 @@ async function runDeepResearch(question) {
19319
20872
  }
19320
20873
  throw new Error("Deep research timed out");
19321
20874
  }
19322
- var webCommand = defineCommand133({
20875
+ var webCommand = defineCommand135({
19323
20876
  meta: {
19324
20877
  name: "web",
19325
20878
  description: `Search the web with AI to answer any open-ended marketing question. Uses live internet data via Google Search.
@@ -19379,7 +20932,7 @@ Examples:
19379
20932
  });
19380
20933
 
19381
20934
  // src/commands/research/index.ts
19382
- var researchCommand = defineCommand134({
20935
+ var researchCommand = defineCommand136({
19383
20936
  meta: {
19384
20937
  name: "research",
19385
20938
  description: `Competitive intelligence and AI-powered research commands.
@@ -19419,10 +20972,10 @@ Examples:
19419
20972
  });
19420
20973
 
19421
20974
  // src/commands/scheduled-actions/index.ts
19422
- import { defineCommand as defineCommand141 } from "citty";
20975
+ import { defineCommand as defineCommand143 } from "citty";
19423
20976
 
19424
20977
  // src/commands/scheduled-actions/create.ts
19425
- import { defineCommand as defineCommand135 } from "citty";
20978
+ import { defineCommand as defineCommand137 } from "citty";
19426
20979
 
19427
20980
  // src/commands/scheduled-actions/shared.ts
19428
20981
  var TEMP_SCHEDULED_ACTION_PREFIX = "temp_sched_";
@@ -19537,7 +21090,7 @@ registerSchema({
19537
21090
  prompt: { type: "string", description: "Additional prompt instructions for the spawned agent", required: false }
19538
21091
  }
19539
21092
  });
19540
- var createCommand2 = defineCommand135({
21093
+ var createCommand2 = defineCommand137({
19541
21094
  meta: {
19542
21095
  name: "create",
19543
21096
  description: 'Stage a scheduled action. Example: baker scheduled-actions create --name "Weekly report" --description "..." --cron "0 9 * * MON"'
@@ -19586,7 +21139,7 @@ var createCommand2 = defineCommand135({
19586
21139
  });
19587
21140
 
19588
21141
  // src/commands/scheduled-actions/delete.ts
19589
- import { defineCommand as defineCommand136 } from "citty";
21142
+ import { defineCommand as defineCommand138 } from "citty";
19590
21143
  registerSchema({
19591
21144
  command: "scheduled-actions.delete",
19592
21145
  description: "Stage deletion of a published scheduled action or cancellation of a temp_sched_* draft creation.",
@@ -19594,7 +21147,7 @@ registerSchema({
19594
21147
  id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
19595
21148
  }
19596
21149
  });
19597
- var deleteCommand2 = defineCommand136({
21150
+ var deleteCommand2 = defineCommand138({
19598
21151
  meta: {
19599
21152
  name: "delete",
19600
21153
  description: "Stage scheduled action deletion. Example: baker scheduled-actions delete <id-or-temp_sched_id>"
@@ -19623,7 +21176,7 @@ var deleteCommand2 = defineCommand136({
19623
21176
  });
19624
21177
 
19625
21178
  // src/commands/scheduled-actions/get.ts
19626
- import { defineCommand as defineCommand137 } from "citty";
21179
+ import { defineCommand as defineCommand139 } from "citty";
19627
21180
  registerSchema({
19628
21181
  command: "scheduled-actions.get",
19629
21182
  description: "Get a published scheduled action or a temp_sched_* draft-created scheduled action.",
@@ -19631,7 +21184,7 @@ registerSchema({
19631
21184
  id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
19632
21185
  }
19633
21186
  });
19634
- var getCommand3 = defineCommand137({
21187
+ var getCommand3 = defineCommand139({
19635
21188
  meta: {
19636
21189
  name: "get",
19637
21190
  description: "Get a scheduled action. Example: baker scheduled-actions get <id-or-temp_sched_id>"
@@ -19668,13 +21221,13 @@ var getCommand3 = defineCommand137({
19668
21221
  });
19669
21222
 
19670
21223
  // src/commands/scheduled-actions/list.ts
19671
- import { defineCommand as defineCommand138 } from "citty";
21224
+ import { defineCommand as defineCommand140 } from "citty";
19672
21225
  registerSchema({
19673
21226
  command: "scheduled-actions.list",
19674
21227
  description: "List published scheduled actions. Includes draft state when BAKER_CHAT_ID is set.",
19675
21228
  args: {}
19676
21229
  });
19677
- var listCommand5 = defineCommand138({
21230
+ var listCommand5 = defineCommand140({
19678
21231
  meta: {
19679
21232
  name: "list",
19680
21233
  description: "List scheduled actions. Includes staged draft ops when BAKER_CHAT_ID is set."
@@ -19695,7 +21248,7 @@ var listCommand5 = defineCommand138({
19695
21248
  });
19696
21249
 
19697
21250
  // src/commands/scheduled-actions/trigger.ts
19698
- import { defineCommand as defineCommand139 } from "citty";
21251
+ import { defineCommand as defineCommand141 } from "citty";
19699
21252
  registerSchema({
19700
21253
  command: "scheduled-actions.trigger",
19701
21254
  description: "Immediately trigger a published scheduled action. Does not require BAKER_CHAT_ID and rejects temp_sched_* IDs.",
@@ -19703,7 +21256,7 @@ registerSchema({
19703
21256
  id: { type: "string", description: "Published scheduled action ID", required: true }
19704
21257
  }
19705
21258
  });
19706
- var triggerCommand = defineCommand139({
21259
+ var triggerCommand = defineCommand141({
19707
21260
  meta: {
19708
21261
  name: "trigger",
19709
21262
  description: "Immediately trigger a published scheduled action. Example: baker scheduled-actions trigger <id>"
@@ -19740,7 +21293,7 @@ var triggerCommand = defineCommand139({
19740
21293
  });
19741
21294
 
19742
21295
  // src/commands/scheduled-actions/update.ts
19743
- import { defineCommand as defineCommand140 } from "citty";
21296
+ import { defineCommand as defineCommand142 } from "citty";
19744
21297
  registerSchema({
19745
21298
  command: "scheduled-actions.update",
19746
21299
  description: "Stage an update to a published scheduled action or temp_sched_* draft-created scheduled action.",
@@ -19765,7 +21318,7 @@ registerSchema({
19765
21318
  prompt: { type: "string", description: "Replacement additional spawned-agent instructions", required: false }
19766
21319
  }
19767
21320
  });
19768
- var updateCommand2 = defineCommand140({
21321
+ var updateCommand2 = defineCommand142({
19769
21322
  meta: {
19770
21323
  name: "update",
19771
21324
  description: "Stage a scheduled action update. Example: baker scheduled-actions update <id> --enabled false"
@@ -19836,7 +21389,7 @@ var updateCommand2 = defineCommand140({
19836
21389
  });
19837
21390
 
19838
21391
  // src/commands/scheduled-actions/index.ts
19839
- var scheduledActionsCommand = defineCommand141({
21392
+ var scheduledActionsCommand = defineCommand143({
19840
21393
  meta: {
19841
21394
  name: "scheduled-actions",
19842
21395
  description: `Manage Scheduled Actions. Subcommands: list, get, create, update, delete, trigger.
@@ -19862,8 +21415,8 @@ Examples:
19862
21415
  });
19863
21416
 
19864
21417
  // src/commands/schema.ts
19865
- import { defineCommand as defineCommand142 } from "citty";
19866
- var schemaCommand = defineCommand142({
21418
+ import { defineCommand as defineCommand144 } from "citty";
21419
+ var schemaCommand = defineCommand144({
19867
21420
  meta: {
19868
21421
  name: "schema",
19869
21422
  description: "Inspect command argument schemas (for AI agent introspection). Lists all commands if no argument given. Example: baker schema images.search"
@@ -19899,10 +21452,10 @@ var schemaCommand = defineCommand142({
19899
21452
  });
19900
21453
 
19901
21454
  // src/commands/testimonials/index.ts
19902
- import { defineCommand as defineCommand146 } from "citty";
21455
+ import { defineCommand as defineCommand148 } from "citty";
19903
21456
 
19904
21457
  // src/commands/testimonials/get.ts
19905
- import { defineCommand as defineCommand143 } from "citty";
21458
+ import { defineCommand as defineCommand145 } from "citty";
19906
21459
  registerSchema({
19907
21460
  command: "testimonials.get",
19908
21461
  description: "Get a single testimonial by ID",
@@ -19910,7 +21463,7 @@ registerSchema({
19910
21463
  id: { type: "string", description: "Testimonial ID", required: true }
19911
21464
  }
19912
21465
  });
19913
- var getCommand4 = defineCommand143({
21466
+ var getCommand4 = defineCommand145({
19914
21467
  meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
19915
21468
  args: {
19916
21469
  id: { type: "positional", description: "Testimonial ID", required: false },
@@ -19947,7 +21500,7 @@ var getCommand4 = defineCommand143({
19947
21500
  });
19948
21501
 
19949
21502
  // src/commands/testimonials/list.ts
19950
- import { defineCommand as defineCommand144 } from "citty";
21503
+ import { defineCommand as defineCommand146 } from "citty";
19951
21504
  registerSchema({
19952
21505
  command: "testimonials.list",
19953
21506
  description: "List testimonials with optional filters.",
@@ -19977,7 +21530,7 @@ registerSchema({
19977
21530
  limit: { type: "number", description: "Max results (default 50)", required: false, default: 50 }
19978
21531
  }
19979
21532
  });
19980
- var listCommand6 = defineCommand144({
21533
+ var listCommand6 = defineCommand146({
19981
21534
  meta: {
19982
21535
  name: "list",
19983
21536
  description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
@@ -20026,7 +21579,7 @@ var listCommand6 = defineCommand144({
20026
21579
  });
20027
21580
 
20028
21581
  // src/commands/testimonials/search.ts
20029
- import { defineCommand as defineCommand145 } from "citty";
21582
+ import { defineCommand as defineCommand147 } from "citty";
20030
21583
  registerSchema({
20031
21584
  command: "testimonials.search",
20032
21585
  description: "Search testimonials by text query. Uses hybrid BM25 + vector + reranking.",
@@ -20057,7 +21610,7 @@ registerSchema({
20057
21610
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
20058
21611
  }
20059
21612
  });
20060
- var searchCommand2 = defineCommand145({
21613
+ var searchCommand2 = defineCommand147({
20061
21614
  meta: {
20062
21615
  name: "search",
20063
21616
  description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
@@ -20131,7 +21684,7 @@ var searchCommand2 = defineCommand145({
20131
21684
  var tagsCommand3 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
20132
21685
 
20133
21686
  // src/commands/testimonials/index.ts
20134
- var testimonialsCommand = defineCommand146({
21687
+ var testimonialsCommand = defineCommand148({
20135
21688
  meta: {
20136
21689
  name: "testimonials",
20137
21690
  description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
@@ -20152,10 +21705,10 @@ Examples:
20152
21705
  });
20153
21706
 
20154
21707
  // src/commands/videos/index.ts
20155
- import { defineCommand as defineCommand151 } from "citty";
21708
+ import { defineCommand as defineCommand153 } from "citty";
20156
21709
 
20157
21710
  // src/commands/videos/delete.ts
20158
- import { defineCommand as defineCommand147 } from "citty";
21711
+ import { defineCommand as defineCommand149 } from "citty";
20159
21712
  registerSchema({
20160
21713
  command: "videos.delete",
20161
21714
  description: "Delete a video by ID",
@@ -20169,7 +21722,7 @@ registerSchema({
20169
21722
  }
20170
21723
  }
20171
21724
  });
20172
- var deleteCommand3 = defineCommand147({
21725
+ var deleteCommand3 = defineCommand149({
20173
21726
  meta: {
20174
21727
  name: "delete",
20175
21728
  description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
@@ -20210,7 +21763,7 @@ var deleteCommand3 = defineCommand147({
20210
21763
  });
20211
21764
 
20212
21765
  // src/commands/videos/get.ts
20213
- import { defineCommand as defineCommand148 } from "citty";
21766
+ import { defineCommand as defineCommand150 } from "citty";
20214
21767
  registerSchema({
20215
21768
  command: "videos.get",
20216
21769
  description: "Get a single video by ID",
@@ -20218,7 +21771,7 @@ registerSchema({
20218
21771
  id: { type: "string", description: "Video ID", required: true }
20219
21772
  }
20220
21773
  });
20221
- var getCommand5 = defineCommand148({
21774
+ var getCommand5 = defineCommand150({
20222
21775
  meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
20223
21776
  args: {
20224
21777
  id: { type: "positional", description: "Video ID", required: false },
@@ -20255,7 +21808,7 @@ var getCommand5 = defineCommand148({
20255
21808
  });
20256
21809
 
20257
21810
  // src/commands/videos/search.ts
20258
- import { defineCommand as defineCommand149 } from "citty";
21811
+ import { defineCommand as defineCommand151 } from "citty";
20259
21812
  registerSchema({
20260
21813
  command: "videos.search",
20261
21814
  description: "Search videos by text query. Only returns ready videos.",
@@ -20265,7 +21818,7 @@ registerSchema({
20265
21818
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
20266
21819
  }
20267
21820
  });
20268
- var searchCommand3 = defineCommand149({
21821
+ var searchCommand3 = defineCommand151({
20269
21822
  meta: {
20270
21823
  name: "search",
20271
21824
  description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
@@ -20317,7 +21870,7 @@ var tagsCommand4 = makeTagsCommand("videos", "video", "/api/videos/tags");
20317
21870
  // src/commands/videos/upload.ts
20318
21871
  import { readFile as readFile12, stat as stat3 } from "fs/promises";
20319
21872
  import { extname as extname3 } from "path";
20320
- import { defineCommand as defineCommand150 } from "citty";
21873
+ import { defineCommand as defineCommand152 } from "citty";
20321
21874
  var MIME_MAP = {
20322
21875
  ".mp4": "video/mp4",
20323
21876
  ".mov": "video/quicktime",
@@ -20351,7 +21904,7 @@ function detectContentType(filePath) {
20351
21904
  }
20352
21905
  return mime;
20353
21906
  }
20354
- var uploadCommand2 = defineCommand150({
21907
+ var uploadCommand2 = defineCommand152({
20355
21908
  meta: {
20356
21909
  name: "upload",
20357
21910
  description: "Upload a video file to Baker via Mux direct upload. Auto-detects content type. Example: baker videos upload ./demo.mp4"
@@ -20405,7 +21958,7 @@ var uploadCommand2 = defineCommand150({
20405
21958
  });
20406
21959
 
20407
21960
  // src/commands/videos/index.ts
20408
- var videosCommand = defineCommand151({
21961
+ var videosCommand = defineCommand153({
20409
21962
  meta: {
20410
21963
  name: "videos",
20411
21964
  description: `Find and manage videos in Baker. Subcommands: search, get, upload, delete, tags.
@@ -20428,10 +21981,10 @@ Examples:
20428
21981
  });
20429
21982
 
20430
21983
  // src/commands/winning-ads/index.ts
20431
- import { defineCommand as defineCommand154 } from "citty";
21984
+ import { defineCommand as defineCommand156 } from "citty";
20432
21985
 
20433
21986
  // src/commands/winning-ads/advertisers.ts
20434
- import { defineCommand as defineCommand152 } from "citty";
21987
+ import { defineCommand as defineCommand154 } from "citty";
20435
21988
  registerSchema({
20436
21989
  command: "winning-ads.advertisers",
20437
21990
  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).",
@@ -20444,7 +21997,7 @@ registerSchema({
20444
21997
  function identity(record) {
20445
21998
  return record;
20446
21999
  }
20447
- var advertisersCommand2 = defineCommand152({
22000
+ var advertisersCommand2 = defineCommand154({
20448
22001
  meta: {
20449
22002
  name: "advertisers",
20450
22003
  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'
@@ -20495,7 +22048,7 @@ var advertisersCommand2 = defineCommand152({
20495
22048
  });
20496
22049
 
20497
22050
  // src/commands/winning-ads/search.ts
20498
- import { defineCommand as defineCommand153 } from "citty";
22051
+ import { defineCommand as defineCommand155 } from "citty";
20499
22052
  registerSchema({
20500
22053
  command: "winning-ads.search",
20501
22054
  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.",
@@ -20603,7 +22156,7 @@ function buildSearchBody(args) {
20603
22156
  }
20604
22157
  return body;
20605
22158
  }
20606
- var searchCommand4 = defineCommand153({
22159
+ var searchCommand4 = defineCommand155({
20607
22160
  meta: {
20608
22161
  name: "search",
20609
22162
  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"
@@ -20715,7 +22268,7 @@ var searchCommand4 = defineCommand153({
20715
22268
  });
20716
22269
 
20717
22270
  // src/commands/winning-ads/index.ts
20718
- var winningAdsCommand = defineCommand154({
22271
+ var winningAdsCommand = defineCommand156({
20719
22272
  meta: {
20720
22273
  name: "winning-ads",
20721
22274
  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.
@@ -20739,7 +22292,7 @@ Examples:
20739
22292
  });
20740
22293
 
20741
22294
  // src/version.ts
20742
- import { readFileSync as readFileSync10 } from "fs";
22295
+ import { readFileSync as readFileSync11 } from "fs";
20743
22296
  function packageJsonUrl() {
20744
22297
  return new URL("../package.json", import.meta.url);
20745
22298
  }
@@ -20751,11 +22304,11 @@ function parsePackageVersion(raw) {
20751
22304
  throw new Error("Invalid CLI package.json: missing version");
20752
22305
  }
20753
22306
  function getCliVersion() {
20754
- return parsePackageVersion(readFileSync10(packageJsonUrl(), "utf8"));
22307
+ return parsePackageVersion(readFileSync11(packageJsonUrl(), "utf8"));
20755
22308
  }
20756
22309
 
20757
22310
  // src/cli.ts
20758
- var main = defineCommand155({
22311
+ var main = defineCommand157({
20759
22312
  meta: {
20760
22313
  name: "baker",
20761
22314
  version: getCliVersion(),
@@ -20770,7 +22323,7 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
20770
22323
  subCommands: {
20771
22324
  actions: actionsCommand,
20772
22325
  "scheduled-actions": scheduledActionsCommand,
20773
- ads: adsCommand,
22326
+ ads: adsCommand2,
20774
22327
  ga4: ga4Command,
20775
22328
  gsc: gscCommand,
20776
22329
  research: researchCommand,