@productmaker/mcp 8.1.0 → 8.2.0

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.
Files changed (4) hide show
  1. package/README.md +8 -0
  2. package/dist/http.js +1618 -799
  3. package/dist/stdio.js +1602 -783
  4. package/package.json +1 -1
package/dist/stdio.js CHANGED
@@ -90,6 +90,23 @@ var VideoPreset = z.enum([
90
90
  ]);
91
91
  var VoiceId = z.string();
92
92
  var _VIDEO_MODEL_SET = new Set(VideoModel.options);
93
+ var BROLL_VIDEO_MODES = new Set(VideoModel.options);
94
+ var PersistedVideoMode = z.enum([
95
+ ...VideoModel.options,
96
+ "avatar_talking",
97
+ "hybrid",
98
+ "sora"
99
+ ]);
100
+ var PersistedVideoModel = z.enum([
101
+ ...VideoModel.options,
102
+ "sora",
103
+ "infinitalk"
104
+ ]);
105
+ var PLAN_VIDEO_MODES = [
106
+ ...VideoModel.options,
107
+ "avatar_talking",
108
+ "hybrid"
109
+ ];
93
110
 
94
111
  // ../../packages/types/src/video-creation.ts
95
112
  import { z as z3 } from "zod";
@@ -1060,40 +1077,206 @@ var VideoTier = z8.preprocess((v) => v === "grok" ? "single_call" : v, z8.enum([
1060
1077
  "single_call"
1061
1078
  ]));
1062
1079
  var DEFAULT_VIDEO_TIER = "single_call";
1080
+ var WritableVideoTier = VideoTier.refine((tier) => tier !== "legacy", {
1081
+ message: "VIDEO_TIER_RETIRED"
1082
+ });
1063
1083
 
1064
- // ../../packages/types/src/image-provider.ts
1065
- var GPT_IMAGE_2_RATIOS_BLOCKED_ABOVE_1K = [
1066
- "4:5",
1067
- "5:4"
1084
+ // ../../packages/types/src/image-models.ts
1085
+ var IMAGE_RESOLUTIONS = [
1086
+ "1k",
1087
+ "2k",
1088
+ "4k"
1068
1089
  ];
1069
- var GPT_IMAGE_2_5_RATIOS_BLOCKED_ABOVE_1K = [
1070
- "4:5",
1071
- "5:4",
1072
- "27:16",
1073
- "16:27",
1074
- "9:8",
1075
- "8:9"
1090
+ var GPT_IMAGE_2_5_TOKENS = {
1091
+ "1k": "gpt-image-2-5:1k",
1092
+ "2k": "gpt-image-2-5:2k",
1093
+ "4k": "gpt-image-2-5:4k"
1094
+ };
1095
+ var GPT_IMAGE_2_TOKENS = {
1096
+ "1k": "gpt-image-2:1k",
1097
+ "2k": "gpt-image-2:2k",
1098
+ "4k": "gpt-image-2:4k"
1099
+ };
1100
+ var GPT_IMAGE_2_5 = {
1101
+ id: "gpt-image-2.5",
1102
+ status: "active",
1103
+ renderedBy: "gpt-image-2.5",
1104
+ tokens: GPT_IMAGE_2_5_TOKENS,
1105
+ kie: {
1106
+ imageToImage: [
1107
+ "gpt-image-2-5-sunburst-image-to-image",
1108
+ "gpt-image-2-5-flare-image-to-image"
1109
+ ],
1110
+ textToImage: [
1111
+ "gpt-image-2-5-sunburst-text-to-image",
1112
+ "gpt-image-2-5-flare-text-to-image"
1113
+ ],
1114
+ shorthands: [
1115
+ "gpt-image-2-5"
1116
+ ]
1117
+ },
1118
+ fal: {
1119
+ edit: "openai/gpt-image-2.5/sunburst/edit",
1120
+ textToImage: "openai/gpt-image-2.5/sunburst/text-to-image",
1121
+ quality: {
1122
+ "1k": "low",
1123
+ "2k": "medium",
1124
+ "4k": "high"
1125
+ },
1126
+ ourCostCents: {
1127
+ "1k": 1.5,
1128
+ "2k": 6.1,
1129
+ "4k": 17.8
1130
+ }
1131
+ },
1132
+ // Docs KIE de gpt-image-2-5 (sunburst/flare): 27:16, 16:27, 9:8, 8:9 solo 1K;
1133
+ // 4:5 y 5:4 también bloqueados por encima de 1K.
1134
+ ratiosBlockedAbove1k: [
1135
+ "4:5",
1136
+ "5:4",
1137
+ "27:16",
1138
+ "16:27",
1139
+ "9:8",
1140
+ "8:9"
1141
+ ],
1142
+ ledgerSuffix: {
1143
+ "1k": "gpt-image-2",
1144
+ "2k": "gpt-image-2:medium",
1145
+ "4k": "gpt-image-2:high"
1146
+ },
1147
+ falLedgerSuffix: {
1148
+ "1k": "gpt-image-2:1k",
1149
+ "2k": "gpt-image-2:2k",
1150
+ "4k": "gpt-image-2:4k"
1151
+ }
1152
+ };
1153
+ var GPT_IMAGE_2 = {
1154
+ ...GPT_IMAGE_2_5,
1155
+ id: "gpt-image-2",
1156
+ status: "retired",
1157
+ renderedBy: GPT_IMAGE_2_5.id,
1158
+ tokens: GPT_IMAGE_2_TOKENS,
1159
+ kie: {
1160
+ imageToImage: [
1161
+ "gpt-image-2-image-to-image"
1162
+ ],
1163
+ textToImage: [
1164
+ "gpt-image-2-text-to-image"
1165
+ ],
1166
+ shorthands: [
1167
+ "gpt-image-2"
1168
+ ]
1169
+ },
1170
+ ratiosBlockedAbove1k: [
1171
+ "4:5",
1172
+ "5:4"
1173
+ ]
1174
+ };
1175
+ var IMAGE_MODELS = [
1176
+ GPT_IMAGE_2_5,
1177
+ GPT_IMAGE_2
1076
1178
  ];
1077
- function gptImage2SupportsTier(aspectRatio, tier) {
1078
- if (tier === "gpt-image-2:1k" || tier === "gpt-image-2-5:1k") return true;
1079
- if (tier.startsWith("gpt-image-2-5:")) {
1080
- return !GPT_IMAGE_2_5_RATIOS_BLOCKED_ABOVE_1K.includes(aspectRatio);
1179
+ var ACTIVE_IMAGE_MODEL = GPT_IMAGE_2_5;
1180
+ var IMAGE_WRITE_TOKENS = GPT_IMAGE_2_5_TOKENS;
1181
+ var LEGACY_IMAGE_TOKENS = GPT_IMAGE_2_TOKENS;
1182
+ var PUBLIC_IMAGE_QUALITY_INPUTS = [
1183
+ IMAGE_WRITE_TOKENS["1k"],
1184
+ IMAGE_WRITE_TOKENS["2k"],
1185
+ LEGACY_IMAGE_TOKENS["1k"],
1186
+ LEGACY_IMAGE_TOKENS["2k"],
1187
+ "image:1k",
1188
+ "image:2k"
1189
+ ];
1190
+ function entryById(id) {
1191
+ const found = IMAGE_MODELS.find((entry) => entry.id === id);
1192
+ if (!found) throw new Error(`IMAGE_MODEL_UNKNOWN:${id}`);
1193
+ return found;
1194
+ }
1195
+ __name(entryById, "entryById");
1196
+ function resolveImageToken(raw) {
1197
+ if (typeof raw !== "string") return null;
1198
+ let normalized = raw.trim().toLowerCase();
1199
+ let viaFal = false;
1200
+ if (normalized.startsWith("fal:")) {
1201
+ viaFal = true;
1202
+ normalized = normalized.slice("fal:".length);
1203
+ }
1204
+ for (const resolution of IMAGE_RESOLUTIONS) {
1205
+ if (normalized === `image:${resolution}`) {
1206
+ return {
1207
+ resolution,
1208
+ model: ACTIVE_IMAGE_MODEL,
1209
+ declared: ACTIVE_IMAGE_MODEL,
1210
+ spelling: "intent",
1211
+ viaFal
1212
+ };
1213
+ }
1081
1214
  }
1082
- return !GPT_IMAGE_2_RATIOS_BLOCKED_ABOVE_1K.includes(aspectRatio);
1215
+ for (const entry of IMAGE_MODELS) {
1216
+ for (const resolution of IMAGE_RESOLUTIONS) {
1217
+ if (entry.tokens[resolution] === normalized) {
1218
+ return {
1219
+ resolution,
1220
+ model: entryById(entry.renderedBy),
1221
+ declared: entry,
1222
+ spelling: entry.status === "active" ? "current" : "retired",
1223
+ viaFal
1224
+ };
1225
+ }
1226
+ }
1227
+ }
1228
+ return null;
1229
+ }
1230
+ __name(resolveImageToken, "resolveImageToken");
1231
+ function imageResolutionOf(raw) {
1232
+ const token = resolveImageToken(raw);
1233
+ return token && !token.viaFal ? token.resolution : null;
1234
+ }
1235
+ __name(imageResolutionOf, "imageResolutionOf");
1236
+ function requireKieImageId(ids, index, label) {
1237
+ const id = ids[index];
1238
+ if (!id) throw new Error(`IMAGE_MODEL_NO_KIE_ID:${label}`);
1239
+ return id;
1240
+ }
1241
+ __name(requireKieImageId, "requireKieImageId");
1242
+ var KIE_FLARE_IMAGE_TO_IMAGE_MODEL = requireKieImageId(GPT_IMAGE_2_5.kie.imageToImage, 1, "flare-imageToImage");
1243
+ function canonicalImageModelInput(raw) {
1244
+ if (raw === void 0) return void 0;
1245
+ const token = resolveImageToken(raw);
1246
+ if (!token || token.viaFal || token.spelling !== "intent") return raw;
1247
+ return IMAGE_WRITE_TOKENS[token.resolution];
1248
+ }
1249
+ __name(canonicalImageModelInput, "canonicalImageModelInput");
1250
+ function imageTokenSupportsRatio(aspectRatio, rawToken) {
1251
+ const token = resolveImageToken(rawToken);
1252
+ if (!token) return true;
1253
+ if (token.resolution === "1k") return true;
1254
+ return !token.declared.ratiosBlockedAbove1k.includes(aspectRatio);
1255
+ }
1256
+ __name(imageTokenSupportsRatio, "imageTokenSupportsRatio");
1257
+
1258
+ // ../../packages/types/src/image-provider.ts
1259
+ var GPT_IMAGE_2_RATIOS_BLOCKED_ABOVE_1K = GPT_IMAGE_2.ratiosBlockedAbove1k;
1260
+ var GPT_IMAGE_2_5_RATIOS_BLOCKED_ABOVE_1K = GPT_IMAGE_2_5.ratiosBlockedAbove1k;
1261
+ function gptImage2SupportsTier(aspectRatio, tier) {
1262
+ return imageTokenSupportsRatio(aspectRatio, tier);
1083
1263
  }
1084
1264
  __name(gptImage2SupportsTier, "gptImage2SupportsTier");
1085
1265
  var IMAGE_TIER_UNSUPPORTED_FOR_RATIO_RULE = "image_tier_unsupported_for_ratio";
1086
1266
  var IMAGE_TIER_LIST = [
1087
- "gpt-image-2-5:1k",
1088
- "gpt-image-2-5:2k",
1089
- "gpt-image-2-5:4k",
1090
- "gpt-image-2:1k",
1091
- "gpt-image-2:2k",
1092
- "gpt-image-2:4k"
1267
+ ...Object.values(IMAGE_WRITE_TOKENS),
1268
+ ...Object.values(LEGACY_IMAGE_TOKENS)
1093
1269
  ];
1270
+ function isImageTier(value) {
1271
+ return IMAGE_TIER_LIST.includes(value);
1272
+ }
1273
+ __name(isImageTier, "isImageTier");
1094
1274
  function parseImageTier(imageModel) {
1095
- const normalized = imageModel.trim().toLowerCase();
1096
- return IMAGE_TIER_LIST.includes(normalized) ? normalized : null;
1275
+ const token = resolveImageToken(imageModel);
1276
+ if (!token || token.viaFal) return null;
1277
+ if (token.spelling === "intent") return IMAGE_WRITE_TOKENS[token.resolution];
1278
+ const declared = token.declared.tokens[token.resolution];
1279
+ return isImageTier(declared) ? declared : null;
1097
1280
  }
1098
1281
  __name(parseImageTier, "parseImageTier");
1099
1282
  function validateImageTierForRatio(aspectRatio, imageModel) {
@@ -3830,7 +4013,7 @@ var IngestOptions = z22.object({
3830
4013
  durationSeconds: FreeVideoOptionsSchema.shape.durationSeconds.optional(),
3831
4014
  addSubtitles: FreeVideoOptionsSchema.shape.addSubtitles.optional(),
3832
4015
  subtitleText: z22.string().transform((value) => value.trim()).pipe(z22.string().max(FREE_VIDEO_SUBTITLE_MAX_CHARS)).optional(),
3833
- videoTier: VideoTier.default(DEFAULT_VIDEO_TIER),
4016
+ videoTier: WritableVideoTier.default(DEFAULT_VIDEO_TIER),
3834
4017
  narrativeStyle: NarrativeStyle.default("review"),
3835
4018
  videoPreset: VideoPreset.optional(),
3836
4019
  multiAngleVideos: z22.boolean().default(false),
@@ -3904,7 +4087,9 @@ var IngestOptions = z22.object({
3904
4087
  aspectRatio: z22.string().optional(),
3905
4088
  brandColors: z22.string().optional(),
3906
4089
  nVariants: z22.number().int().min(1).max(6).optional(),
3907
- imageModel: z22.string().optional(),
4090
+ // O7: `image:Nk` is accepted and stored as the spelling written today
4091
+ // (IMAGE_WRITE_TOKENS); see packages/types/src/image-models.ts.
4092
+ imageModel: z22.string().optional().transform((value) => canonicalImageModelInput(value)),
3908
4093
  styleMix: z22.string().optional(),
3909
4094
  aiDecidesAll: z22.boolean().optional(),
3910
4095
  /** Opt out of the competitor-spy analysis. When false the worker skips
@@ -4023,7 +4208,7 @@ var VideoOptionsOverride = z22.object({
4023
4208
  videoStructure: VideoStructure.optional(),
4024
4209
  videoQuality: VideoQuality.optional(),
4025
4210
  videoModel: VideoModel.optional(),
4026
- videoTier: VideoTier.optional(),
4211
+ videoTier: WritableVideoTier.optional(),
4027
4212
  ugcFormat: VideoFormat.optional(),
4028
4213
  videoStyle: VideoStyle.optional(),
4029
4214
  narrativeStyle: NarrativeStyle.optional(),
@@ -4106,6 +4291,11 @@ var IngestResumePayload = z22.object({
4106
4291
  // "keep what the task has". See angle-management.service.ts resumeAfterAngles.
4107
4292
  videoStyle: VideoStyle.optional(),
4108
4293
  videoModel: VideoModel.default("veo"),
4294
+ // READ schema on purpose, unlike IngestOptions/VideoOptionsOverride: resume
4295
+ // does not write the tier — `resumeAfterAngles` projects the route from the
4296
+ // task's OWN persisted tier and ignores this field. MCP and WhatsApp echo
4297
+ // `status.videoTier`, which is still `legacy` for historical rows; refusing
4298
+ // it made those tasks impossible to resume from both channels.
4109
4299
  videoTier: VideoTier.optional(),
4110
4300
  videoStructure: VideoStructure.optional(),
4111
4301
  videoQuality: VideoQuality.optional(),
@@ -4916,17 +5106,7 @@ var VideoGenerator = z26.object({
4916
5106
  format: VideoFormat.optional(),
4917
5107
  videoStyle: VideoStyle.optional(),
4918
5108
  narrativeStyle: NarrativeStyle.optional(),
4919
- videoMode: z26.enum([
4920
- "veo",
4921
- "wan",
4922
- "bytedance",
4923
- "seedance",
4924
- "grok",
4925
- "kling",
4926
- "avatar_talking",
4927
- "hybrid",
4928
- "sora"
4929
- ]).optional(),
5109
+ videoMode: PersistedVideoMode.optional(),
4930
5110
  videoResolution: VideoResolution.optional(),
4931
5111
  videoStructure: VideoStructure.optional(),
4932
5112
  videoQuality: VideoQuality.optional(),
@@ -7291,7 +7471,8 @@ var IMAGE_QA_GATES = [
7291
7471
  "limb",
7292
7472
  "device_panel",
7293
7473
  "critical_feature",
7294
- "cross_section"
7474
+ "cross_section",
7475
+ "usage_fidelity"
7295
7476
  ];
7296
7477
  var ImageQaGate = z36.enum(IMAGE_QA_GATES);
7297
7478
  var ImageQaGateOutcome = z36.enum([
@@ -8337,6 +8518,10 @@ var GEMINI_OMNI_FLAT_USER_PRICE_CENTS = 168;
8337
8518
  // ../../packages/types/src/pricing.ts
8338
8519
  var CREDITS_PER_USD_CENT = 10;
8339
8520
  var CREDITS_PER_DOLLAR = 100 * CREDITS_PER_USD_CENT;
8521
+ var AD_CREATIVE_MODELS = {
8522
+ STANDARD: IMAGE_WRITE_TOKENS["1k"],
8523
+ PREMIUM: IMAGE_WRITE_TOKENS["2k"]
8524
+ };
8340
8525
  var KALODATA_USD_CENTS_PER_PROVIDER_CREDIT = 9;
8341
8526
  var KALODATA_PROVIDER_CREDITS_PER_SOURCE_CEILING = 7.5;
8342
8527
  var DEFAULT_PRICING = {
@@ -9295,6 +9480,27 @@ var DEFAULT_PRICING = {
9295
9480
  ourCostCents: 1.88,
9296
9481
  userPriceCents: 3.76
9297
9482
  },
9483
+ // Usage decider (role `usage-decider`: Gemini 3.8 Flash effort:'high' since
9484
+ // 05f543eae, ≤6 images + seller text, temperature 0 json_object, once per
9485
+ // classic landing, always on). Was 3¢ measured on Claude
9486
+ // Sonnet 5 (spike 2026-09-24, 17 prod tasks). NOT re-measured on Flash — no
9487
+ // local BillingEntry row carries the Flash decider yet — so it is priced as
9488
+ // the product truth (`openrouter:product-truth`, 2.2¢ measured from
9489
+ // OpenRouter usage.cost): same model, same effort, same ≤6-photo input and a
9490
+ // JSON answer of similar size. Refine from usage.cost after the e2e. Fallback
9491
+ // only (OpenRouter's usage.cost is billed when present).
9492
+ "openrouter:usage-decision": {
9493
+ ourCostCents: 2.2,
9494
+ userPriceCents: 4.4
9495
+ },
9496
+ // Usage-fidelity QA judge (records misuse; regen gated separately behind
9497
+ // always on, bounded by USAGE_FIDELITY_MAX_REGENS). Sized off landing-image-qa beside it: same
9498
+ // shape of call (1-2 images, a verdict), so quoted at the same rate until
9499
+ // it has its own BillingEntry volume to re-derive from.
9500
+ "openrouter:usage-fidelity": {
9501
+ ourCostCents: 1.88,
9502
+ userPriceCents: 3.76
9503
+ },
9298
9504
  // Landing commercial-facts extraction (gemini-3.8-flash, ONE text-only call over
9299
9505
  // the seller's offer/context/features). Sized off the image-QA key beside it,
9300
9506
  // which measured 1.88¢ at ~11.1K prompt tokens: this prompt is capped at ~3K in
@@ -10033,6 +10239,24 @@ var DEFAULT_PRICING = {
10033
10239
  ourCostCents: 0.2,
10034
10240
  userPriceCents: 0.4
10035
10241
  },
10242
+ // Product truth (Gemini 3.8 Flash effort:'high', ≤6 photos + all seller text, once per
10243
+ // extract, always on). Plan C spike 2026-09-24: 6 calls, US$0.132 total ⇒
10244
+ // 2.2¢/call measured from OpenRouter usage.cost. Replaces usage spec + functional demo +
10245
+ // product-use sheet (+ landing visual-context-fusion) on the same task. Fallback only.
10246
+ "openrouter:product-truth": {
10247
+ ourCostCents: 2.2,
10248
+ userPriceCents: 4.4
10249
+ },
10250
+ // Landing creative director, «categorías» arm (Gemini 3.8 Flash effort:'high', ≤6 photos +
10251
+ // all seller text + the section plan, once per classic landing behind
10252
+ // LANDING_DIRECTOR_ENABLED). ESTIMATE, not measured: same call shape as the product truth
10253
+ // (2.2¢) with a ~2-3x longer JSON answer (one content spec per section) ⇒ ~4¢. Replaces
10254
+ // the visual brief (4¢) + visual-context fusion (0.4¢) + usage decision (2.2¢) on that
10255
+ // landing. Refine from OpenRouter usage.cost after the e2e. Fallback only.
10256
+ "openrouter:landing-director": {
10257
+ ourCostCents: 4,
10258
+ userPriceCents: 8
10259
+ },
10036
10260
  // Unit = one reference-grouping pass over the user's product images (0.1241¢).
10037
10261
  "openrouter:product-reference-grouping": {
10038
10262
  ourCostCents: 0.15,
@@ -13550,7 +13774,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
13550
13774
  "video"
13551
13775
  ]
13552
13776
  ),
13553
- defineCapability("generate_image_creatives", "eb2c3f6a0d8974ccf33c42f2b4cc9e09918dabf29182acce1418ea2842a01ec3", "credit_consuming", "creative", [
13777
+ defineCapability("generate_image_creatives", "2f1698b623d98645b7c618a17988f3aac30f403a9c3f3dc26eb5bdbd9c6ef23e", "credit_consuming", "creative", [
13554
13778
  "credit_consuming",
13555
13779
  "state_change"
13556
13780
  ], [
@@ -14947,79 +15171,696 @@ var WhatsAppPresentationManifestSchema = z67.object({
14947
15171
  }
14948
15172
  });
14949
15173
 
14950
- // ../../packages/types/src/flight-recorder.ts
15174
+ // ../../packages/types/src/usage-decision.ts
14951
15175
  import { z as z68 } from "zod";
14952
- var FlightRecorderGenerationTypeSchema = z68.enum([
15176
+
15177
+ // ../../packages/types/src/text-clamp.ts
15178
+ function clampAtWordBoundary(value, max) {
15179
+ if (typeof value !== "string") return value;
15180
+ if (value.length <= max) return value;
15181
+ const cut = value.slice(0, max);
15182
+ const lastSpace = cut.lastIndexOf(" ");
15183
+ const atWordBoundary = lastSpace > 0 ? cut.slice(0, lastSpace) : cut;
15184
+ return atWordBoundary.replace(/[,;:\s]+$/, "");
15185
+ }
15186
+ __name(clampAtWordBoundary, "clampAtWordBoundary");
15187
+ function clampStringArray(max) {
15188
+ return (value) => {
15189
+ if (!Array.isArray(value)) return value;
15190
+ const nonEmpty = value.filter((item) => typeof item === "string" && item.trim().length > 0);
15191
+ return nonEmpty.slice(0, max);
15192
+ };
15193
+ }
15194
+ __name(clampStringArray, "clampStringArray");
15195
+
15196
+ // ../../packages/types/src/usage-decision.ts
15197
+ var USAGE_SCENE_RULE_MAX_CHARS = 240;
15198
+ var USAGE_DECISION_MAX_REQUIRED_PARTS = 6;
15199
+ var USAGE_DECISION_MAX_ALTERNATE_USES = 4;
15200
+ var USAGE_DECISION_MAX_MISUSE = 5;
15201
+ function clampRule(value) {
15202
+ return clampAtWordBoundary(value, USAGE_SCENE_RULE_MAX_CHARS);
15203
+ }
15204
+ __name(clampRule, "clampRule");
15205
+ var UsageDecisionSchema = z68.object({
15206
+ productIdentity: z68.string().min(1),
15207
+ endUser: z68.object({
15208
+ who: z68.string(),
15209
+ appliedTo: z68.string()
15210
+ }),
15211
+ promise: z68.string().min(1),
15212
+ primaryUse: z68.object({
15213
+ scene: z68.string().min(1),
15214
+ postureAndGrip: z68.string(),
15215
+ contactPoint: z68.string(),
15216
+ requiredParts: z68.preprocess(clampStringArray(USAGE_DECISION_MAX_REQUIRED_PARTS), z68.array(z68.string()).max(USAGE_DECISION_MAX_REQUIRED_PARTS))
15217
+ }),
15218
+ validAlternateUses: z68.preprocess(clampStringArray(USAGE_DECISION_MAX_ALTERNATE_USES), z68.array(z68.string()).max(USAGE_DECISION_MAX_ALTERNATE_USES)),
15219
+ misuse: z68.preprocess(clampStringArray(USAGE_DECISION_MAX_MISUSE), z68.array(z68.string().min(1)).max(USAGE_DECISION_MAX_MISUSE)),
15220
+ useSceneRule: z68.preprocess(clampRule, z68.string().min(1).max(USAGE_SCENE_RULE_MAX_CHARS)),
15221
+ /**
15222
+ * True when the promise can ONLY be shown with the primary use (the pain is bending over and
15223
+ * the product has an extension pole: without the pole there is no promise); false when the
15224
+ * valid alternates sell it equally. Drives whether an alternate use in a use scene is a
15225
+ * failure (`requirePrimary` in the usage judge) and whether the prompts' primary use is
15226
+ * mandatory. Optional and fail-safe: missing (decisions stored before the field) or not a
15227
+ * boolean ⇒ `undefined`, read as false by every caller — never a rejected decision.
15228
+ */
15229
+ primaryRequired: z68.boolean().optional().catch(void 0),
15230
+ confidence: z68.number().min(0).max(1),
15231
+ modelId: z68.string(),
15232
+ decidedAt: z68.string()
15233
+ });
15234
+
15235
+ // ../../packages/types/src/product-truth.ts
15236
+ import { z as z70 } from "zod";
15237
+
15238
+ // ../../packages/types/src/lenient-zod.ts
15239
+ import { z as z69 } from "zod";
15240
+ function trimAndClamp(value, max) {
15241
+ if (typeof value !== "string") return value;
15242
+ return clampAtWordBoundary(value.replace(/\s+/g, " ").trim(), max);
15243
+ }
15244
+ __name(trimAndClamp, "trimAndClamp");
15245
+ function lenientText(max) {
15246
+ return z69.preprocess((v) => trimAndClamp(v, max), z69.string().min(1).max(max));
15247
+ }
15248
+ __name(lenientText, "lenientText");
15249
+ function lenientOptionalText(max) {
15250
+ return z69.preprocess((v) => {
15251
+ if (typeof v !== "string") return void 0;
15252
+ const clamped = trimAndClamp(v, max);
15253
+ return typeof clamped === "string" && clamped.length > 0 ? clamped : void 0;
15254
+ }, z69.string().max(max).optional());
15255
+ }
15256
+ __name(lenientOptionalText, "lenientOptionalText");
15257
+ function lenientTextList(maxItems, maxChars) {
15258
+ return z69.preprocess((v) => {
15259
+ if (!Array.isArray(v)) return [];
15260
+ return v.map((item) => trimAndClamp(item, maxChars)).filter((item) => typeof item === "string" && item.length > 0).slice(0, maxItems);
15261
+ }, z69.array(z69.string().min(1).max(maxChars)).max(maxItems));
15262
+ }
15263
+ __name(lenientTextList, "lenientTextList");
15264
+ function lenientList(item, maxItems) {
15265
+ return z69.preprocess((v) => {
15266
+ if (!Array.isArray(v)) return [];
15267
+ return v.filter((entry) => item.safeParse(entry).success).slice(0, maxItems);
15268
+ }, z69.array(item).max(maxItems));
15269
+ }
15270
+ __name(lenientList, "lenientList");
15271
+
15272
+ // ../../packages/types/src/product-truth.ts
15273
+ var PRODUCT_TRUTH_SCHEMA_VERSION = 1;
15274
+ var PRODUCT_TRUTH_CAPS = {
15275
+ whatItIs: 160,
15276
+ deliveryForm: 120,
15277
+ distinctiveMarks: 6,
15278
+ distinctiveMarkChars: 160,
15279
+ parts: 12,
15280
+ partNameChars: 80,
15281
+ criticalFeatures: 6,
15282
+ connections: 6,
15283
+ connectionChars: 80,
15284
+ states: 4,
15285
+ stateKeyChars: 60,
15286
+ stateLabelChars: 80,
15287
+ partsPresent: 10,
15288
+ orientationInUseChars: 200,
15289
+ appliedToChars: 120,
15290
+ environmentChars: 120,
15291
+ summaryChars: 200,
15292
+ sceneChars: 300,
15293
+ postureAndGripChars: 160,
15294
+ contactPointChars: 120,
15295
+ steps: 8,
15296
+ stepNameChars: 120,
15297
+ stepInstructionChars: 300,
15298
+ visibleEffectChars: 200,
15299
+ beforeStateChars: 200,
15300
+ requiredProps: 8,
15301
+ requiredPropChars: 120,
15302
+ alternates: 3,
15303
+ misuse: 5,
15304
+ misuseChars: 200,
15305
+ mustShowFeatures: 5,
15306
+ mustShowFeatureChars: 100,
15307
+ safety: 5,
15308
+ safetyChars: 200,
15309
+ forbiddenClaims: 8,
15310
+ unsupportedClaims: 5,
15311
+ claimChars: 200,
15312
+ visualSummaryEnChars: 400
15313
+ };
15314
+ var PRODUCT_TRUTH_END_USER_AGE_BANDS = [
15315
+ "baby",
15316
+ "child",
15317
+ "teen",
15318
+ "adult",
15319
+ "any"
15320
+ ];
15321
+ var PRODUCT_TRUTH_END_USER_GENDERS = [
15322
+ "female",
15323
+ "male",
15324
+ "any"
15325
+ ];
15326
+ var PRODUCT_TRUTH_UNKNOWN_REASONS = [
15327
+ "model_unsure",
15328
+ "no_signal",
15329
+ "invalid_response",
15330
+ "provider_error"
15331
+ ];
15332
+ var text = lenientText;
15333
+ var optionalText = lenientOptionalText;
15334
+ var textList = lenientTextList;
15335
+ function toProductTruthStateKey(value) {
15336
+ if (typeof value !== "string") return void 0;
15337
+ const slug = value.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, PRODUCT_TRUTH_CAPS.stateKeyChars);
15338
+ return slug.length > 0 ? slug : void 0;
15339
+ }
15340
+ __name(toProductTruthStateKey, "toProductTruthStateKey");
15341
+ var stateKey = z70.preprocess(toProductTruthStateKey, z70.string().min(1).max(PRODUCT_TRUTH_CAPS.stateKeyChars));
15342
+ var optionalStateKey = z70.preprocess(toProductTruthStateKey, z70.string().min(1).max(PRODUCT_TRUTH_CAPS.stateKeyChars).optional());
15343
+ var AGE_BAND_ALIASES = {
15344
+ baby: "baby",
15345
+ babies: "baby",
15346
+ infant: "baby",
15347
+ infants: "baby",
15348
+ toddler: "child",
15349
+ child: "child",
15350
+ children: "child",
15351
+ kid: "child",
15352
+ kids: "child",
15353
+ teen: "teen",
15354
+ teens: "teen",
15355
+ teenager: "teen",
15356
+ teenagers: "teen",
15357
+ adult: "adult",
15358
+ adults: "adult",
15359
+ any: "any",
15360
+ all: "any",
15361
+ "all ages": "any"
15362
+ };
15363
+ var GENDER_ALIASES = {
15364
+ female: "female",
15365
+ woman: "female",
15366
+ women: "female",
15367
+ girl: "female",
15368
+ male: "male",
15369
+ man: "male",
15370
+ men: "male",
15371
+ boy: "male",
15372
+ any: "any",
15373
+ unisex: "any",
15374
+ both: "any",
15375
+ all: "any"
15376
+ };
15377
+ function matchAlias(raw, aliases) {
15378
+ if (typeof raw !== "string") return void 0;
15379
+ const text2 = raw.trim().toLowerCase();
15380
+ const exact = aliases[text2];
15381
+ if (exact) return exact;
15382
+ const words = new Set(text2.split(/[^a-z]+/).filter(Boolean));
15383
+ for (const [alias, value] of Object.entries(aliases)) {
15384
+ if (words.has(alias)) return value;
15385
+ }
15386
+ return void 0;
15387
+ }
15388
+ __name(matchAlias, "matchAlias");
15389
+ function normalizeEndUser(value) {
15390
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
15391
+ const v = value;
15392
+ const age = matchAlias(v.ageBand, AGE_BAND_ALIASES);
15393
+ const gender = matchAlias(v.gender, GENDER_ALIASES);
15394
+ if (!age || !gender || typeof v.usedByBuyer !== "boolean") return void 0;
15395
+ return {
15396
+ ageBand: age,
15397
+ gender,
15398
+ usedByBuyer: v.usedByBuyer
15399
+ };
15400
+ }
15401
+ __name(normalizeEndUser, "normalizeEndUser");
15402
+ var ProductTruthEndUserSchema = z70.object({
15403
+ ageBand: z70.enum(PRODUCT_TRUTH_END_USER_AGE_BANDS),
15404
+ gender: z70.enum(PRODUCT_TRUTH_END_USER_GENDERS),
15405
+ usedByBuyer: z70.boolean()
15406
+ });
15407
+ var MATERIAL_HINTS = ProductMorphology.shape.materialHints.unwrap().element.options;
15408
+ var DEMO_TYPES = FunctionalDemonstration.shape.demoType;
15409
+ var PartSchema = z70.object({
15410
+ name: text(PRODUCT_TRUTH_CAPS.partNameChars),
15411
+ kind: z70.enum([
15412
+ "rigid",
15413
+ "flexible",
15414
+ "joint"
15415
+ ]).catch("rigid"),
15416
+ count: z70.number().int().min(1).max(20).catch(1)
15417
+ });
15418
+ var CriticalFeatureSchema = z70.object({
15419
+ name: text(60),
15420
+ importance: text(120),
15421
+ antiPattern: optionalText(80),
15422
+ expectedCount: z70.number().int().min(1).max(20).optional().catch(void 0)
15423
+ });
15424
+ var ConnectionSchema = z70.object({
15425
+ part: text(PRODUCT_TRUTH_CAPS.connectionChars),
15426
+ attachesTo: text(PRODUCT_TRUTH_CAPS.connectionChars),
15427
+ where: optionalText(PRODUCT_TRUTH_CAPS.connectionChars)
15428
+ });
15429
+ var StateSchema = z70.object({
15430
+ key: stateKey,
15431
+ label: optionalText(PRODUCT_TRUTH_CAPS.stateLabelChars),
15432
+ partsPresent: textList(PRODUCT_TRUTH_CAPS.partsPresent, PRODUCT_TRUTH_CAPS.partNameChars),
15433
+ orientationInUse: text(PRODUCT_TRUTH_CAPS.orientationInUseChars),
15434
+ naturalOrientation: ProductNaturalOrientation.optional().catch(void 0)
15435
+ });
15436
+ var StepSchema = z70.object({
15437
+ name: text(PRODUCT_TRUTH_CAPS.stepNameChars),
15438
+ instruction: text(PRODUCT_TRUTH_CAPS.stepInstructionChars),
15439
+ kind: z70.enum([
15440
+ "setup",
15441
+ "use",
15442
+ "finish"
15443
+ ]).catch("use")
15444
+ });
15445
+ var AlternateSchema = z70.object({
15446
+ summary: text(PRODUCT_TRUTH_CAPS.summaryChars),
15447
+ stateKey: optionalStateKey,
15448
+ advertisedBySeller: z70.boolean().catch(false)
15449
+ });
15450
+ var DemoSchema = z70.object({
15451
+ demoType: DEMO_TYPES.nullable().catch(null),
15452
+ mustShowFeatures: textList(PRODUCT_TRUTH_CAPS.mustShowFeatures, PRODUCT_TRUTH_CAPS.mustShowFeatureChars),
15453
+ importance: z70.enum([
15454
+ "critical",
15455
+ "important",
15456
+ "nice_to_have"
15457
+ ]).catch("important")
15458
+ });
15459
+ var objectOrEmpty = /* @__PURE__ */ __name((v) => v && typeof v === "object" && !Array.isArray(v) ? v : {}, "objectOrEmpty");
15460
+ var ProductTruthBody = z70.object({
15461
+ identity: z70.object({
15462
+ whatItIs: text(PRODUCT_TRUTH_CAPS.whatItIs),
15463
+ deliveryForm: optionalText(PRODUCT_TRUTH_CAPS.deliveryForm),
15464
+ distinctiveMarks: textList(PRODUCT_TRUTH_CAPS.distinctiveMarks, PRODUCT_TRUTH_CAPS.distinctiveMarkChars)
15465
+ }),
15466
+ morphology: z70.preprocess(objectOrEmpty, z70.object({
15467
+ shape: ProductGeometryShape.optional().catch(void 0),
15468
+ crossSection: ProductCrossSection.optional().catch(void 0),
15469
+ cornerProfile: ProductCornerProfile.optional().catch(void 0),
15470
+ silhouetteWidthToHeightRatio: z70.number().min(0.05).max(20).optional().catch(void 0),
15471
+ parts: lenientList(PartSchema, PRODUCT_TRUTH_CAPS.parts),
15472
+ criticalFeatures: lenientList(CriticalFeatureSchema, PRODUCT_TRUTH_CAPS.criticalFeatures),
15473
+ shapeLockLevel: z70.enum([
15474
+ "strict",
15475
+ "moderate",
15476
+ "relaxed"
15477
+ ]).optional().catch(void 0),
15478
+ materialHints: z70.preprocess((v) => Array.isArray(v) ? [
15479
+ ...new Set(v.filter((m) => MATERIAL_HINTS.includes(m)))
15480
+ ].slice(0, 3) : [], z70.array(z70.enum(MATERIAL_HINTS)).max(3))
15481
+ })),
15482
+ assembly: z70.object({
15483
+ connections: lenientList(ConnectionSchema, PRODUCT_TRUTH_CAPS.connections),
15484
+ states: z70.preprocess((v) => {
15485
+ if (!Array.isArray(v)) return v;
15486
+ const seen = /* @__PURE__ */ new Set();
15487
+ return v.filter((entry) => {
15488
+ const parsed = StateSchema.safeParse(entry);
15489
+ if (!parsed.success || seen.has(parsed.data.key)) return false;
15490
+ seen.add(parsed.data.key);
15491
+ return true;
15492
+ }).slice(0, PRODUCT_TRUTH_CAPS.states);
15493
+ }, z70.array(StateSchema).min(1).max(PRODUCT_TRUTH_CAPS.states)),
15494
+ defaultStateKey: optionalStateKey
15495
+ }),
15496
+ use: z70.object({
15497
+ endUser: z70.preprocess(normalizeEndUser, ProductTruthEndUserSchema.optional()).catch(void 0),
15498
+ appliedTo: optionalText(PRODUCT_TRUTH_CAPS.appliedToChars),
15499
+ environment: optionalText(PRODUCT_TRUTH_CAPS.environmentChars),
15500
+ primary: z70.object({
15501
+ summary: text(PRODUCT_TRUTH_CAPS.summaryChars),
15502
+ scene: text(PRODUCT_TRUTH_CAPS.sceneChars),
15503
+ postureAndGrip: optionalText(PRODUCT_TRUTH_CAPS.postureAndGripChars),
15504
+ contactPoint: optionalText(PRODUCT_TRUTH_CAPS.contactPointChars),
15505
+ stateKey: optionalStateKey,
15506
+ steps: z70.preprocess((v) => Array.isArray(v) ? v.filter((s) => StepSchema.safeParse(s).success).slice(0, PRODUCT_TRUTH_CAPS.steps) : v, z70.array(StepSchema).min(1).max(PRODUCT_TRUTH_CAPS.steps)),
15507
+ visibleEffect: optionalText(PRODUCT_TRUTH_CAPS.visibleEffectChars),
15508
+ beforeState: optionalText(PRODUCT_TRUTH_CAPS.beforeStateChars),
15509
+ requiredProps: textList(PRODUCT_TRUTH_CAPS.requiredProps, PRODUCT_TRUTH_CAPS.requiredPropChars)
15510
+ }),
15511
+ alternates: lenientList(AlternateSchema, PRODUCT_TRUTH_CAPS.alternates),
15512
+ misuse: textList(PRODUCT_TRUTH_CAPS.misuse, PRODUCT_TRUTH_CAPS.misuseChars),
15513
+ demo: z70.preprocess(objectOrEmpty, DemoSchema),
15514
+ safety: textList(PRODUCT_TRUTH_CAPS.safety, PRODUCT_TRUTH_CAPS.safetyChars)
15515
+ }),
15516
+ claims: z70.preprocess(objectOrEmpty, z70.object({
15517
+ forbidden: textList(PRODUCT_TRUTH_CAPS.forbiddenClaims, PRODUCT_TRUTH_CAPS.claimChars),
15518
+ unsupported: textList(PRODUCT_TRUTH_CAPS.unsupportedClaims, PRODUCT_TRUTH_CAPS.claimChars)
15519
+ })),
15520
+ visualSummaryEn: optionalText(PRODUCT_TRUTH_CAPS.visualSummaryEnChars),
15521
+ evidence: z70.preprocess(objectOrEmpty, z70.object({
15522
+ photoIndexForState: z70.preprocess((v) => {
15523
+ const out = {};
15524
+ if (!v || typeof v !== "object" || Array.isArray(v)) return out;
15525
+ for (const [rawKey, rawIndexes] of Object.entries(v)) {
15526
+ const key = toProductTruthStateKey(rawKey);
15527
+ if (!key || !Array.isArray(rawIndexes)) continue;
15528
+ out[key] = rawIndexes.filter((i) => typeof i === "number" && Number.isInteger(i) && i >= 0 && i < 20);
15529
+ }
15530
+ return out;
15531
+ }, z70.record(z70.array(z70.number().int().min(0).max(19))))
15532
+ })),
15533
+ confidence: z70.preprocess((v) => typeof v === "number" && Number.isFinite(v) ? Math.min(1, Math.max(0, v)) : 0, z70.number().min(0).max(1))
15534
+ });
15535
+ function resolveStateRefs(body) {
15536
+ const keys = new Set(body.assembly.states.map((s) => s.key));
15537
+ const firstKey = body.assembly.states[0]?.key ?? "";
15538
+ const defaultStateKey = body.assembly.defaultStateKey && keys.has(body.assembly.defaultStateKey) ? body.assembly.defaultStateKey : firstKey;
15539
+ const primaryKey = body.use.primary.stateKey && keys.has(body.use.primary.stateKey) ? body.use.primary.stateKey : defaultStateKey;
15540
+ const photoIndexForState = Object.fromEntries(Object.entries(body.evidence.photoIndexForState).filter(([key]) => keys.has(key)));
15541
+ return {
15542
+ ...body,
15543
+ assembly: {
15544
+ ...body.assembly,
15545
+ defaultStateKey
15546
+ },
15547
+ use: {
15548
+ ...body.use,
15549
+ primary: {
15550
+ ...body.use.primary,
15551
+ stateKey: primaryKey
15552
+ },
15553
+ alternates: body.use.alternates.map((alt) => ({
15554
+ ...alt,
15555
+ stateKey: alt.stateKey && keys.has(alt.stateKey) ? alt.stateKey : defaultStateKey
15556
+ }))
15557
+ },
15558
+ evidence: {
15559
+ ...body.evidence,
15560
+ photoIndexForState
15561
+ }
15562
+ };
15563
+ }
15564
+ __name(resolveStateRefs, "resolveStateRefs");
15565
+ var ProductTruthModelResponseSchema = ProductTruthBody.transform(resolveStateRefs);
15566
+ var provenance = {
15567
+ schemaVersion: z70.literal(PRODUCT_TRUTH_SCHEMA_VERSION),
15568
+ modelId: z70.string().min(1),
15569
+ derivedAt: z70.string().min(1),
15570
+ /** Hash of (image keys + seller text + features): a reader that sees a different current
15571
+ * fingerprint treats the truth as absent. See `computeProductTruthFingerprint` in packages/ai. */
15572
+ sourceFingerprint: z70.string().min(1),
15573
+ /** The seller upload KEYS (deduped, sorted) the fingerprint was computed over. Stored so a
15574
+ * reader can recompute the CURRENT fingerprint from today's seller text + features without
15575
+ * knowing the extract job's inputs (plan Global Constraint "Invalidez"). */
15576
+ sourceImageKeys: z70.array(z70.string().min(1)).max(20).optional()
15577
+ };
15578
+ var ProductTruthKnownSchema = ProductTruthBody.extend({
15579
+ ...provenance,
15580
+ known: z70.literal(true)
15581
+ }).transform(resolveStateRefs);
15582
+ var ProductTruthUnknownSchema = z70.object({
15583
+ schemaVersion: z70.literal(PRODUCT_TRUTH_SCHEMA_VERSION),
15584
+ known: z70.literal(false),
15585
+ unknownReason: z70.enum(PRODUCT_TRUTH_UNKNOWN_REASONS),
15586
+ modelId: z70.string().optional(),
15587
+ derivedAt: z70.string().min(1),
15588
+ sourceFingerprint: z70.string().min(1),
15589
+ sourceImageKeys: z70.array(z70.string().min(1)).max(20).optional()
15590
+ });
15591
+ var ProductTruthSchema = z70.union([
15592
+ ProductTruthKnownSchema,
15593
+ ProductTruthUnknownSchema
15594
+ ]);
15595
+
15596
+ // ../../packages/types/src/landing-director.ts
15597
+ import { z as z71 } from "zod";
15598
+ var LANDING_DIRECTOR_SCHEMA_VERSION = 1;
15599
+ var LANDING_DIRECTOR_ARM = "categories";
15600
+ var LANDING_DIRECTOR_CAPS = {
15601
+ productIdentity: 200,
15602
+ parts: 8,
15603
+ partName: 40,
15604
+ promise: 200,
15605
+ endUserWho: 80,
15606
+ endUserAppliedTo: 80,
15607
+ forbiddenClaims: 10,
15608
+ claimChars: 80,
15609
+ misuse: 5,
15610
+ misuseChars: 120,
15611
+ assembledStates: 3,
15612
+ statePartsMax: 6,
15613
+ orientation: 160,
15614
+ handling: 140,
15615
+ primaryScene: 200,
15616
+ postureAndGrip: 140,
15617
+ contactPoint: 100,
15618
+ alternates: 3,
15619
+ alternateChars: 120,
15620
+ ambiguities: 4,
15621
+ ambiguityChars: 160,
15622
+ sectionKeyChars: 40,
15623
+ personWho: 80,
15624
+ personPosture: 120,
15625
+ personGrip: 120,
15626
+ scene: 450,
15627
+ panels: 4,
15628
+ panelScene: 200,
15629
+ panelCaption: 60,
15630
+ /** Rendered text: an item over its cap is DROPPED, never cut. The headline cap is 80, not
15631
+ * the design's 70: a dropped headline costs the whole director headline, and 7-10 Spanish
15632
+ * words routinely run 70-80 chars. */
15633
+ headline: 80,
15634
+ subheadline: 90,
15635
+ labels: 3,
15636
+ labelChars: 40,
15637
+ captions: 3,
15638
+ captionChars: 60,
15639
+ props: 4,
15640
+ propChars: 40,
15641
+ mustNotShow: 5,
15642
+ mustNotShowChars: 80
15643
+ };
15644
+ var STATE_KEY_PATTERN = /^[a-z][a-z_]{1,23}$/;
15645
+ function toLandingDirectorStateKey(value) {
15646
+ if (typeof value !== "string") return void 0;
15647
+ const slug = value.toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g, "").replace(/[^a-z]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 24).replace(/_+$/g, "");
15648
+ return STATE_KEY_PATTERN.test(slug) ? slug : void 0;
15649
+ }
15650
+ __name(toLandingDirectorStateKey, "toLandingDirectorStateKey");
15651
+ var stateKey2 = z71.preprocess(toLandingDirectorStateKey, z71.string().regex(STATE_KEY_PATTERN));
15652
+ function renderedOptionalText(max) {
15653
+ return z71.preprocess((v) => {
15654
+ if (typeof v !== "string") return void 0;
15655
+ const trimmed = v.replace(/\s+/g, " ").trim();
15656
+ return trimmed.length > 0 && trimmed.length <= max ? trimmed : void 0;
15657
+ }, z71.string().min(1).max(max).optional());
15658
+ }
15659
+ __name(renderedOptionalText, "renderedOptionalText");
15660
+ function renderedTextList(maxItems, maxChars) {
15661
+ return z71.preprocess((v) => {
15662
+ if (!Array.isArray(v)) return [];
15663
+ return v.map((item) => typeof item === "string" ? item.replace(/\s+/g, " ").trim() : "").filter((item) => item.length > 0 && item.length <= maxChars).slice(0, maxItems);
15664
+ }, z71.array(z71.string().min(1).max(maxChars)).max(maxItems));
15665
+ }
15666
+ __name(renderedTextList, "renderedTextList");
15667
+ var C = LANDING_DIRECTOR_CAPS;
15668
+ var PartSchema2 = z71.object({
15669
+ name: lenientText(C.partName),
15670
+ critical: z71.boolean().catch(false)
15671
+ });
15672
+ var AssembledStateSchema = z71.object({
15673
+ key: stateKey2,
15674
+ parts: lenientTextList(C.statePartsMax, C.partName),
15675
+ orientation: lenientText(C.orientation),
15676
+ handling: lenientOptionalText(C.handling)
15677
+ });
15678
+ var END_USER_GENDERS = [
15679
+ "female",
15680
+ "male",
15681
+ "any"
15682
+ ];
15683
+ var END_USER_AGE_BANDS = [
15684
+ "child",
15685
+ "teen",
15686
+ "adult",
15687
+ "senior",
15688
+ "any"
15689
+ ];
15690
+ var EndUserSchema = z71.object({
15691
+ who: lenientText(C.endUserWho),
15692
+ appliedTo: lenientOptionalText(C.endUserAppliedTo),
15693
+ gender: z71.enum(END_USER_GENDERS).catch("any"),
15694
+ ageBand: z71.enum(END_USER_AGE_BANDS).catch("any")
15695
+ });
15696
+ var LandingDirectorGlobalSchema = z71.object({
15697
+ productIdentity: lenientText(C.productIdentity),
15698
+ parts: lenientList(PartSchema2, C.parts),
15699
+ promise: lenientText(C.promise),
15700
+ endUser: EndUserSchema,
15701
+ forbiddenClaims: lenientTextList(C.forbiddenClaims, C.claimChars),
15702
+ misuse: lenientTextList(C.misuse, C.misuseChars),
15703
+ assembledStates: z71.preprocess((v) => {
15704
+ if (!Array.isArray(v)) return v;
15705
+ const seen = /* @__PURE__ */ new Set();
15706
+ return v.filter((entry) => {
15707
+ const parsed = AssembledStateSchema.safeParse(entry);
15708
+ if (!parsed.success || seen.has(parsed.data.key)) return false;
15709
+ seen.add(parsed.data.key);
15710
+ return true;
15711
+ }).slice(0, C.assembledStates);
15712
+ }, z71.array(AssembledStateSchema).min(1).max(C.assembledStates)),
15713
+ primaryUse: z71.object({
15714
+ assembledState: stateKey2,
15715
+ scene: lenientText(C.primaryScene),
15716
+ postureAndGrip: lenientText(C.postureAndGrip),
15717
+ contactPoint: lenientOptionalText(C.contactPoint)
15718
+ }),
15719
+ primaryRequired: z71.boolean().catch(false),
15720
+ validAlternateUses: lenientTextList(C.alternates, C.alternateChars),
15721
+ ambiguities: lenientTextList(C.ambiguities, C.ambiguityChars)
15722
+ });
15723
+ var LANDING_DIRECTOR_BODY_PARTS = [
15724
+ "hands",
15725
+ "face",
15726
+ "torso",
15727
+ "legs",
15728
+ "feet",
15729
+ "full_body"
15730
+ ];
15731
+ var PersonSchema = z71.object({
15732
+ who: lenientText(C.personWho),
15733
+ posture: lenientText(C.personPosture),
15734
+ grip: lenientOptionalText(C.personGrip),
15735
+ bodyPartsVisible: z71.preprocess((v) => Array.isArray(v) ? [
15736
+ ...new Set(v.filter((part) => LANDING_DIRECTOR_BODY_PARTS.includes(part)))
15737
+ ] : [], z71.array(z71.enum(LANDING_DIRECTOR_BODY_PARTS)))
15738
+ });
15739
+ var LandingDirectorTextSchema = z71.object({
15740
+ headline: renderedOptionalText(C.headline),
15741
+ subheadline: renderedOptionalText(C.subheadline),
15742
+ labels: renderedTextList(C.labels, C.labelChars),
15743
+ captions: renderedTextList(C.captions, C.captionChars)
15744
+ });
15745
+ var PanelSchema = z71.object({
15746
+ scene: lenientText(C.panelScene),
15747
+ caption: renderedOptionalText(C.panelCaption)
15748
+ });
15749
+ var PRODUCT_IN_FRAME_VALUES = [
15750
+ "none",
15751
+ "packshot",
15752
+ "in_use"
15753
+ ];
15754
+ var LandingDirectorSectionSchema = z71.object({
15755
+ sectionKey: z71.string().trim().min(1).max(C.sectionKeyChars),
15756
+ /** Present only in the «director» arm. Kept as a flag so the «categorías» validation can
15757
+ * invalidate the section (design §2.3) instead of silently dropping the model's choice. */
15758
+ hasComposition: z71.boolean().default(false),
15759
+ productInFrame: z71.enum(PRODUCT_IN_FRAME_VALUES),
15760
+ assembledState: z71.preprocess((v) => v === null || v === void 0 ? null : toLandingDirectorStateKey(v), z71.string().regex(STATE_KEY_PATTERN).nullable()),
15761
+ usesPrimary: z71.boolean().catch(false),
15762
+ person: z71.preprocess((v) => v === void 0 ? null : v, PersonSchema.nullable()),
15763
+ scene: lenientText(C.scene),
15764
+ panels: lenientList(PanelSchema, C.panels),
15765
+ textToRender: z71.preprocess((v) => v && typeof v === "object" && !Array.isArray(v) ? v : {}, LandingDirectorTextSchema),
15766
+ props: lenientTextList(C.props, C.propChars),
15767
+ mustNotShow: lenientTextList(C.mustNotShow, C.mustNotShowChars)
15768
+ });
15769
+ var LandingDirectorOutputSchema = z71.object({
15770
+ version: z71.literal(LANDING_DIRECTOR_SCHEMA_VERSION),
15771
+ confidence: z71.number().min(0).max(1),
15772
+ global: LandingDirectorGlobalSchema,
15773
+ sections: z71.array(LandingDirectorSectionSchema)
15774
+ });
15775
+ var StoredLandingDirectorSchema = z71.object({
15776
+ version: z71.literal(LANDING_DIRECTOR_SCHEMA_VERSION),
15777
+ arm: z71.literal(LANDING_DIRECTOR_ARM),
15778
+ modelId: z71.string().min(1),
15779
+ generatedAt: z71.string().min(1),
15780
+ confidence: z71.number().min(0).max(1),
15781
+ /** The plan the answer was validated against (sectionKey, or the role on classic). */
15782
+ planSectionKeys: z71.array(z71.string().min(1)),
15783
+ output: LandingDirectorOutputSchema,
15784
+ /** Sections that fell back to the category composition, and why. */
15785
+ fallbackSections: z71.array(z71.object({
15786
+ sectionKey: z71.string().min(1),
15787
+ reason: z71.string().min(1)
15788
+ }))
15789
+ });
15790
+
15791
+ // ../../packages/types/src/flight-recorder.ts
15792
+ import { z as z72 } from "zod";
15793
+ var FlightRecorderGenerationTypeSchema = z72.enum([
14953
15794
  "initial",
14954
15795
  "regeneration",
14955
15796
  "edit",
14956
15797
  "retry"
14957
15798
  ]);
14958
- var FlightRecorderProviderSchema = z68.enum([
15799
+ var FlightRecorderProviderSchema = z72.enum([
14959
15800
  "kie",
14960
15801
  "fal"
14961
15802
  ]);
14962
- var FlightRecorderElementSchema = z68.object({
14963
- name: z68.string().optional(),
14964
- description: z68.string().optional(),
14965
- frontalImageUrl: z68.string().optional(),
14966
- referenceImageUrls: z68.array(z68.string()).optional(),
14967
- videoUrl: z68.string().optional()
14968
- });
14969
- var FlightRecorderDistillationSchema = z68.object({
14970
- actorGender: z68.enum([
15803
+ var FlightRecorderElementSchema = z72.object({
15804
+ name: z72.string().optional(),
15805
+ description: z72.string().optional(),
15806
+ frontalImageUrl: z72.string().optional(),
15807
+ referenceImageUrls: z72.array(z72.string()).optional(),
15808
+ videoUrl: z72.string().optional()
15809
+ });
15810
+ var FlightRecorderDistillationSchema = z72.object({
15811
+ actorGender: z72.enum([
14971
15812
  "female",
14972
15813
  "male",
14973
15814
  "mixed"
14974
- ]).or(z68.string()).optional(),
14975
- voiceId: z68.string().optional(),
14976
- cameraMotion: z68.string().optional()
14977
- }).catchall(z68.unknown());
14978
- var FlightRecorderEntrySchema = z68.object({
14979
- schemaVersion: z68.literal(1).optional(),
14980
- id: z68.string().min(1),
14981
- taskId: z68.string().min(1),
14982
- runId: z68.string().min(1),
14983
- sequence: z68.number().int().nonnegative(),
14984
- timestamp: z68.string().min(1),
14985
- provider: FlightRecorderProviderSchema.or(z68.string()),
14986
- model: z68.string().min(1),
14987
- prompt: z68.string(),
14988
- durationSeconds: z68.number().nonnegative(),
14989
- aspectRatio: z68.string().optional(),
14990
- resolution: z68.string().optional(),
14991
- startImageUrl: z68.string().optional(),
14992
- endImageUrl: z68.string().optional(),
14993
- generateAudio: z68.boolean().optional(),
15815
+ ]).or(z72.string()).optional(),
15816
+ voiceId: z72.string().optional(),
15817
+ cameraMotion: z72.string().optional()
15818
+ }).catchall(z72.unknown());
15819
+ var FlightRecorderEntrySchema = z72.object({
15820
+ schemaVersion: z72.literal(1).optional(),
15821
+ id: z72.string().min(1),
15822
+ taskId: z72.string().min(1),
15823
+ runId: z72.string().min(1),
15824
+ sequence: z72.number().int().nonnegative(),
15825
+ timestamp: z72.string().min(1),
15826
+ provider: FlightRecorderProviderSchema.or(z72.string()),
15827
+ model: z72.string().min(1),
15828
+ prompt: z72.string(),
15829
+ durationSeconds: z72.number().nonnegative(),
15830
+ aspectRatio: z72.string().optional(),
15831
+ resolution: z72.string().optional(),
15832
+ startImageUrl: z72.string().optional(),
15833
+ endImageUrl: z72.string().optional(),
15834
+ generateAudio: z72.boolean().optional(),
14994
15835
  // Correlation & pipeline metadata
14995
- angleKey: z68.string().optional(),
14996
- sceneIndex: z68.number().int().nonnegative().optional(),
15836
+ angleKey: z72.string().optional(),
15837
+ sceneIndex: z72.number().int().nonnegative().optional(),
14997
15838
  generationType: FlightRecorderGenerationTypeSchema,
14998
- operationId: z68.string().min(1).optional(),
14999
- revisionId: z68.string().min(1).optional(),
15000
- attemptNumber: z68.number().int().nonnegative().default(1),
15839
+ operationId: z72.string().min(1).optional(),
15840
+ revisionId: z72.string().min(1).optional(),
15841
+ attemptNumber: z72.number().int().nonnegative().default(1),
15001
15842
  // Elements & Distillation
15002
- elements: z68.array(FlightRecorderElementSchema).optional(),
15843
+ elements: z72.array(FlightRecorderElementSchema).optional(),
15003
15844
  distillation: FlightRecorderDistillationSchema.optional(),
15004
15845
  // Raw payload (sanitized of secrets)
15005
- rawPayload: z68.record(z68.unknown())
15846
+ rawPayload: z72.record(z72.unknown())
15006
15847
  });
15007
- var FlightRecorderQuerySchema = z68.object({
15008
- taskId: z68.string().min(1),
15009
- runId: z68.string().optional(),
15010
- sceneIndex: z68.number().int().nonnegative().optional(),
15011
- angleKey: z68.string().optional(),
15848
+ var FlightRecorderQuerySchema = z72.object({
15849
+ taskId: z72.string().min(1),
15850
+ runId: z72.string().optional(),
15851
+ sceneIndex: z72.number().int().nonnegative().optional(),
15852
+ angleKey: z72.string().optional(),
15012
15853
  generationType: FlightRecorderGenerationTypeSchema.optional(),
15013
- cursor: z68.number().int().nonnegative().optional(),
15014
- limit: z68.number().int().positive().optional()
15854
+ cursor: z72.number().int().nonnegative().optional(),
15855
+ limit: z72.number().int().positive().optional()
15015
15856
  });
15016
- var FlightRecorderResponseSchema = z68.object({
15017
- taskId: z68.string().min(1),
15018
- runId: z68.string().min(1),
15019
- entries: z68.array(FlightRecorderEntrySchema),
15857
+ var FlightRecorderResponseSchema = z72.object({
15858
+ taskId: z72.string().min(1),
15859
+ runId: z72.string().min(1),
15860
+ entries: z72.array(FlightRecorderEntrySchema),
15020
15861
  lastCall: FlightRecorderEntrySchema.nullable(),
15021
- count: z68.number().int().nonnegative(),
15022
- nextCursor: z68.number().int().nonnegative().nullable()
15862
+ count: z72.number().int().nonnegative(),
15863
+ nextCursor: z72.number().int().nonnegative().nullable()
15023
15864
  });
15024
15865
 
15025
15866
  // src/response-body.ts
@@ -15261,7 +16102,7 @@ var ApiClient = class {
15261
16102
  };
15262
16103
 
15263
16104
  // src/index.ts
15264
- var MCP_VERSION = "8.1.0";
16105
+ var MCP_VERSION = "8.2.0";
15265
16106
 
15266
16107
  // src/meta-upload-app.ts
15267
16108
  import { readFileSync } from "fs";
@@ -15333,7 +16174,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
15333
16174
  __name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
15334
16175
 
15335
16176
  // src/tools/tasks.ts
15336
- import { z as z72 } from "zod";
16177
+ import { z as z76 } from "zod";
15337
16178
 
15338
16179
  // src/resolve-image.ts
15339
16180
  import { lookup as dnsLookup } from "dns/promises";
@@ -15894,10 +16735,10 @@ async function resolveMediaRef(ref, opts) {
15894
16735
  __name(resolveMediaRef, "resolveMediaRef");
15895
16736
 
15896
16737
  // src/tools/shared.ts
15897
- import { z as z69 } from "zod";
15898
- var Lang = z69.string().regex(/^[a-z]{2}(?:[-_][a-zA-Z]{2})?$/, "Usa un c\xF3digo de idioma BCP-47, por ejemplo es, en-US o pt-BR").max(10);
15899
- var Country = z69.string().min(2).max(3);
15900
- var LandingStrategyEnum = z69.enum([
16738
+ import { z as z73 } from "zod";
16739
+ var Lang = z73.string().regex(/^[a-z]{2}(?:[-_][a-zA-Z]{2})?$/, "Usa un c\xF3digo de idioma BCP-47, por ejemplo es, en-US o pt-BR").max(10);
16740
+ var Country = z73.string().min(2).max(3);
16741
+ var LandingStrategyEnum = z73.enum([
15901
16742
  "auto",
15902
16743
  "classic",
15903
16744
  "pain_solution",
@@ -15906,12 +16747,12 @@ var LandingStrategyEnum = z69.enum([
15906
16747
  "offer_value",
15907
16748
  "lifestyle_identity"
15908
16749
  ]);
15909
- var LandingImageFormatEnum = z69.enum([
16750
+ var LandingImageFormatEnum = z73.enum([
15910
16751
  "9:16",
15911
16752
  "4:5",
15912
16753
  "1:1"
15913
16754
  ]);
15914
- var VideoPresetEnum = z69.enum([
16755
+ var VideoPresetEnum = z73.enum([
15915
16756
  "auto",
15916
16757
  "ugc_dynamic",
15917
16758
  "ugc_how_to",
@@ -15924,21 +16765,21 @@ var VideoPresetEnum = z69.enum([
15924
16765
  "pixar_problem",
15925
16766
  "pixar_sassy"
15926
16767
  ]);
15927
- var VideoStructureEnum = z69.enum([
16768
+ var VideoStructureEnum = z73.enum([
15928
16769
  "single_take",
15929
16770
  "multi_scene"
15930
16771
  ]);
15931
- var VideoQualityEnum = z69.enum([
16772
+ var VideoQualityEnum = z73.enum([
15932
16773
  "economy",
15933
16774
  "medium",
15934
16775
  "pro"
15935
16776
  ]);
15936
- var VideoRouteIdEnum = z69.enum([
16777
+ var VideoRouteIdEnum = z73.enum([
15937
16778
  "single_take",
15938
16779
  "multi_scene",
15939
16780
  "free"
15940
16781
  ]);
15941
- var TaskCreativeVariantVideoPresetEnum = z69.enum([
16782
+ var TaskCreativeVariantVideoPresetEnum = z73.enum([
15942
16783
  "auto",
15943
16784
  "ugc_dynamic",
15944
16785
  "ugc_how_to",
@@ -15955,53 +16796,43 @@ var VIDEO_PRESET_RESOLUTION = {
15955
16796
  auto: null,
15956
16797
  ugc_dynamic: {
15957
16798
  videoStyle: "ai_dynamic",
15958
- narrativeStyle: "review",
15959
- videoModel: "veo"
16799
+ narrativeStyle: "review"
15960
16800
  },
15961
16801
  ugc_how_to: {
15962
16802
  videoStyle: "ai_dynamic",
15963
- narrativeStyle: "ugc_how_to",
15964
- videoModel: "veo"
16803
+ narrativeStyle: "ugc_how_to"
15965
16804
  },
15966
16805
  ugc_unboxing_chaos: {
15967
16806
  videoStyle: "ai_dynamic",
15968
- narrativeStyle: "ugc_unboxing_chaos",
15969
- videoModel: "veo"
16807
+ narrativeStyle: "ugc_unboxing_chaos"
15970
16808
  },
15971
16809
  problem_solution: {
15972
16810
  videoStyle: "ai_dynamic",
15973
- narrativeStyle: "problem_product_cta",
15974
- videoModel: "kling"
16811
+ narrativeStyle: "problem_product_cta"
15975
16812
  },
15976
16813
  pixar_problem: {
15977
16814
  videoStyle: "ai_dynamic",
15978
- narrativeStyle: "animated_problem_pixar",
15979
- videoModel: "kling"
16815
+ narrativeStyle: "animated_problem_pixar"
15980
16816
  },
15981
16817
  pixar_sassy: {
15982
16818
  videoStyle: "ai_dynamic",
15983
- narrativeStyle: "sassy_product_pixar",
15984
- videoModel: "seedance"
16819
+ narrativeStyle: "sassy_product_pixar"
15985
16820
  },
15986
16821
  product_showcase: {
15987
16822
  videoStyle: "product_only",
15988
- narrativeStyle: "product_showcase",
15989
- videoModel: "veo"
16823
+ narrativeStyle: "product_showcase"
15990
16824
  },
15991
16825
  wearable_showcase: {
15992
16826
  videoStyle: "ugc",
15993
- narrativeStyle: "wearable_showcase",
15994
- videoModel: "veo"
16827
+ narrativeStyle: "wearable_showcase"
15995
16828
  },
15996
16829
  cinematic: {
15997
16830
  videoStyle: "product_only",
15998
- narrativeStyle: "cinematic",
15999
- videoModel: "grok"
16831
+ narrativeStyle: "cinematic"
16000
16832
  },
16001
16833
  wild_card: {
16002
16834
  videoStyle: "product_only",
16003
- narrativeStyle: "wild_card",
16004
- videoModel: "grok"
16835
+ narrativeStyle: "wild_card"
16005
16836
  }
16006
16837
  };
16007
16838
  function resolveVideoPreset(preset) {
@@ -16009,7 +16840,7 @@ function resolveVideoPreset(preset) {
16009
16840
  return VIDEO_PRESET_RESOLUTION[preset] ?? null;
16010
16841
  }
16011
16842
  __name(resolveVideoPreset, "resolveVideoPreset");
16012
- var VideoTierEnum = z69.enum([
16843
+ var VideoTierEnum = z73.enum([
16013
16844
  "basic"
16014
16845
  ]);
16015
16846
  function resolveVideoTier(_tier) {
@@ -16049,22 +16880,22 @@ function assertSemanticVideoDurationCompatibility(structure, quality, durationSe
16049
16880
  }
16050
16881
  }
16051
16882
  __name(assertSemanticVideoDurationCompatibility, "assertSemanticVideoDurationCompatibility");
16052
- var VideoResolutionEnum = z69.enum([
16883
+ var VideoResolutionEnum = z73.enum([
16053
16884
  "480p",
16054
16885
  "720p"
16055
16886
  ]);
16056
- var CreativeGenderEnum = z69.enum([
16887
+ var CreativeGenderEnum = z73.enum([
16057
16888
  "female",
16058
16889
  "male",
16059
16890
  "mixed"
16060
16891
  ]);
16061
- var VideoStyleEnum = z69.enum([
16892
+ var VideoStyleEnum = z73.enum([
16062
16893
  "ugc",
16063
16894
  "cartoon_3d",
16064
16895
  "product_only",
16065
16896
  "ai_dynamic"
16066
16897
  ]);
16067
- var NarrativeStyleEnum = z69.enum([
16898
+ var NarrativeStyleEnum = z73.enum([
16068
16899
  "review",
16069
16900
  "ugc_how_to",
16070
16901
  "problem_product_cta",
@@ -16082,7 +16913,7 @@ var NarrativeStyleEnum = z69.enum([
16082
16913
  "ugc_demo_review",
16083
16914
  "market"
16084
16915
  ]);
16085
- var PublicNarrativeStyleEnum = z69.enum([
16916
+ var PublicNarrativeStyleEnum = z73.enum([
16086
16917
  "review",
16087
16918
  "ugc_how_to",
16088
16919
  "ugc_unboxing_chaos",
@@ -16095,7 +16926,7 @@ var PublicNarrativeStyleEnum = z69.enum([
16095
16926
  "sassy_product_pixar",
16096
16927
  "market"
16097
16928
  ]);
16098
- var VideoModelEnum = z69.enum([
16929
+ var TaskVideoModelEnum = z73.enum([
16099
16930
  "veo",
16100
16931
  "wan",
16101
16932
  "bytedance",
@@ -16103,29 +16934,29 @@ var VideoModelEnum = z69.enum([
16103
16934
  "grok",
16104
16935
  "kling"
16105
16936
  ]);
16106
- var ProductReferenceUserChoiceEnum = z69.enum([
16937
+ var ProductReferenceUserChoiceEnum = z73.enum([
16107
16938
  "same_product",
16108
16939
  "variants",
16109
16940
  "different_products",
16110
16941
  "combo_distinct"
16111
16942
  ]);
16112
- var ProductReferenceCandidateGroupingEnum = z69.enum([
16943
+ var ProductReferenceCandidateGroupingEnum = z73.enum([
16113
16944
  "same_product_same_variant",
16114
16945
  "same_product_different_variants",
16115
16946
  "different_products",
16116
16947
  "unclear"
16117
16948
  ]);
16118
- var ProductReferenceScopeEnum = z69.enum([
16949
+ var ProductReferenceScopeEnum = z73.enum([
16119
16950
  "base",
16120
16951
  "video_view_pack"
16121
16952
  ]);
16122
- var ProductReferenceResolutionDecisionEnum = z69.enum([
16953
+ var ProductReferenceResolutionDecisionEnum = z73.enum([
16123
16954
  "approve",
16124
16955
  "reject",
16125
16956
  "observed_only",
16126
16957
  "correct_view"
16127
16958
  ]);
16128
- var ProductReferenceRejectionReasonEnum = z69.enum([
16959
+ var ProductReferenceRejectionReasonEnum = z73.enum([
16129
16960
  "replacement_requested",
16130
16961
  "wrong_product_identity",
16131
16962
  "wrong_variant",
@@ -16136,13 +16967,13 @@ var ProductReferenceRejectionReasonEnum = z69.enum([
16136
16967
  "not_a_product_photo",
16137
16968
  "other"
16138
16969
  ]);
16139
- var GapDurationChoiceMirror = z69.object({
16140
- angleIndex: z69.number().int().nonnegative(),
16141
- recommendedSec: z69.union([
16142
- z69.literal(15),
16143
- z69.literal(30)
16970
+ var GapDurationChoiceMirror = z73.object({
16971
+ angleIndex: z73.number().int().nonnegative(),
16972
+ recommendedSec: z73.union([
16973
+ z73.literal(15),
16974
+ z73.literal(30)
16144
16975
  ]),
16145
- estimatedDeltaCredits: z69.number().int().nonnegative().optional()
16976
+ estimatedDeltaCredits: z73.number().int().nonnegative().optional()
16146
16977
  });
16147
16978
  function buildSelectedImageUrlsHash(urls) {
16148
16979
  const input = [
@@ -16152,13 +16983,13 @@ function buildSelectedImageUrlsHash(urls) {
16152
16983
  return `fnv1a:${hash.toString(16).padStart(8, "0")}:${urls.length}`;
16153
16984
  }
16154
16985
  __name(buildSelectedImageUrlsHash, "buildSelectedImageUrlsHash");
16155
- var ImageCreativeStyleEnum = z69.enum([
16986
+ var ImageCreativeStyleEnum = z73.enum([
16156
16987
  "studio",
16157
16988
  "floating",
16158
16989
  "ingredients",
16159
16990
  "in_use"
16160
16991
  ]);
16161
- var ImageCreativeArchetypeEnum = z69.enum([
16992
+ var ImageCreativeArchetypeEnum = z73.enum([
16162
16993
  "direct_response_product_ad",
16163
16994
  "hero_outcome",
16164
16995
  "offer_value_prop",
@@ -16167,20 +16998,20 @@ var ImageCreativeArchetypeEnum = z69.enum([
16167
16998
  "problem_solution",
16168
16999
  "lifestyle_identity"
16169
17000
  ]);
16170
- var ImageCreativeVisualTreatmentEnum = z69.enum([
17001
+ var ImageCreativeVisualTreatmentEnum = z73.enum([
16171
17002
  "performance_product_ad",
16172
17003
  "premium_dtc_carousel"
16173
17004
  ]);
16174
- var ImageCreativeAspectRatioEnum = z69.enum([
17005
+ var ImageCreativeAspectRatioEnum = z73.enum([
16175
17006
  "1:1",
16176
17007
  "4:5",
16177
17008
  "9:16",
16178
17009
  "16:9"
16179
17010
  ]);
16180
- var ImageRefSchema = z69.object({
16181
- url: z69.string().url().optional().describe('URL p\xFAblica HTTPS de la foto. Ej: una URL de Shopify CDN, Cloudinary, Imgur. \xDAsala cuando el usuario te diga "est\xE1 en X.com/foto.jpg" o cuando la foto ya est\xE9 hospedada.'),
16182
- path: z69.string().min(1).optional().describe('Ruta del archivo en el computador del usuario. Ej: "/Users/maria/Desktop/foto.jpg", "~/Pictures/camiseta.png", "C:\\Users\\Maria\\Desktop\\foto.jpg". El MCP local la lee del disco y la sube. SOLO funciona cuando el MCP corre local (stdio). NO funciona en mcp.productmaker.app (HTTP) \u2014 ah\xED usa `url`.'),
16183
- assetId: z69.string().uuid().optional().describe("ID opaco devuelto por check_media_upload. \xDAsalo para una imagen subida desde el MCP App; ProductMaker adopta el archivo directamente y el MCP nunca descarga sus bytes.")
17011
+ var ImageRefSchema = z73.object({
17012
+ url: z73.string().url().optional().describe('URL p\xFAblica HTTPS de la foto. Ej: una URL de Shopify CDN, Cloudinary, Imgur. \xDAsala cuando el usuario te diga "est\xE1 en X.com/foto.jpg" o cuando la foto ya est\xE9 hospedada.'),
17013
+ path: z73.string().min(1).optional().describe('Ruta del archivo en el computador del usuario. Ej: "/Users/maria/Desktop/foto.jpg", "~/Pictures/camiseta.png", "C:\\Users\\Maria\\Desktop\\foto.jpg". El MCP local la lee del disco y la sube. SOLO funciona cuando el MCP corre local (stdio). NO funciona en mcp.productmaker.app (HTTP) \u2014 ah\xED usa `url`.'),
17014
+ assetId: z73.string().uuid().optional().describe("ID opaco devuelto por check_media_upload. \xDAsalo para una imagen subida desde el MCP App; ProductMaker adopta el archivo directamente y el MCP nunca descarga sus bytes.")
16184
17015
  }).refine((v) => [
16185
17016
  v.url,
16186
17017
  v.path,
@@ -16188,11 +17019,11 @@ var ImageRefSchema = z69.object({
16188
17019
  ].filter(Boolean).length === 1, {
16189
17020
  message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
16190
17021
  });
16191
- var ImagesInput = z69.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
17022
+ var ImagesInput = z73.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
16192
17023
  const assetCount = images.filter((image) => Boolean(image.assetId)).length;
16193
17024
  if (assetCount > 0 && assetCount !== images.length) {
16194
17025
  ctx.addIssue({
16195
- code: z69.ZodIssueCode.custom,
17026
+ code: z73.ZodIssueCode.custom,
16196
17027
  message: "all image entries must use assetId, or all must use URL/path sources"
16197
17028
  });
16198
17029
  }
@@ -16260,14 +17091,14 @@ async function submitCreative(api, opts) {
16260
17091
  });
16261
17092
  }
16262
17093
  __name(submitCreative, "submitCreative");
16263
- var ResearchTargetCountryEnum = z69.enum([
17094
+ var ResearchTargetCountryEnum = z73.enum([
16264
17095
  "CO",
16265
17096
  "MX",
16266
17097
  "PE",
16267
17098
  "EC",
16268
17099
  "CL"
16269
17100
  ]);
16270
- var ResearchCategoryEnum = z69.enum([
17101
+ var ResearchCategoryEnum = z73.enum([
16271
17102
  "auto",
16272
17103
  "automotive",
16273
17104
  "kitchen",
@@ -16336,7 +17167,7 @@ var OVERWRITES_EXTERNAL = {
16336
17167
  idempotentHint: false,
16337
17168
  openWorldHint: false
16338
17169
  };
16339
- var DailyControlStatusEnum = z69.enum([
17170
+ var DailyControlStatusEnum = z73.enum([
16340
17171
  "ok",
16341
17172
  "sales_unavailable",
16342
17173
  "timezone_unavailable",
@@ -16349,19 +17180,19 @@ var DailyControlStatusEnum = z69.enum([
16349
17180
  "product_missing",
16350
17181
  "store_unreachable"
16351
17182
  ]);
16352
- var DailyControlLightEnum = z69.enum([
17183
+ var DailyControlLightEnum = z73.enum([
16353
17184
  "green",
16354
17185
  "amber",
16355
17186
  "red",
16356
17187
  "none"
16357
17188
  ]);
16358
- var DailyControlVerdictEnum = z69.enum([
17189
+ var DailyControlVerdictEnum = z73.enum([
16359
17190
  "scale",
16360
17191
  "hold",
16361
17192
  "kill",
16362
17193
  "insufficient_sample"
16363
17194
  ]);
16364
- var DailyControlSourceEnum = z69.enum([
17195
+ var DailyControlSourceEnum = z73.enum([
16365
17196
  "shopify",
16366
17197
  "shopify_settling",
16367
17198
  "user",
@@ -17502,29 +18333,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
17502
18333
  __name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
17503
18334
 
17504
18335
  // src/tools/media-presentation.ts
17505
- import { z as z70 } from "zod";
17506
- var HttpsPresentationUrlSchema = z70.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
18336
+ import { z as z74 } from "zod";
18337
+ var HttpsPresentationUrlSchema = z74.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
17507
18338
  var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
17508
18339
  const hostname = new URL(value).hostname.toLowerCase();
17509
18340
  return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
17510
18341
  }, "preview URL must be owned by ProductMaker");
17511
- var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z70.number().int().positive().max(maximum), "positiveIntAtMost");
17512
- var PresentationImageSchema = z70.object({
17513
- kind: z70.literal("image"),
18342
+ var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z74.number().int().positive().max(maximum), "positiveIntAtMost");
18343
+ var PresentationImageSchema = z74.object({
18344
+ kind: z74.literal("image"),
17514
18345
  url: HttpsPresentationUrlSchema,
17515
- mimeType: z70.enum([
18346
+ mimeType: z74.enum([
17516
18347
  "image/jpeg",
17517
18348
  "image/png"
17518
18349
  ]),
17519
18350
  byteSize: positiveIntAtMost(5 * 1024 * 1024),
17520
18351
  width: positiveIntAtMost(16384),
17521
18352
  height: positiveIntAtMost(16384),
17522
- alt: z70.string().trim().min(1).max(240)
18353
+ alt: z74.string().trim().min(1).max(240)
17523
18354
  }).strict();
17524
18355
  var McpMediaPresentationSchema = PresentationImageSchema;
17525
- var GalleryImageSchema = z70.object({
18356
+ var GalleryImageSchema = z74.object({
17526
18357
  url: ProductMakerPreviewUrlSchema,
17527
- alt: z70.string().trim().min(1).max(240)
18358
+ alt: z74.string().trim().min(1).max(240)
17528
18359
  });
17529
18360
  var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
17530
18361
  async function imageBlocks(image, transport) {
@@ -17674,10 +18505,10 @@ ${summary}`,
17674
18505
  __name(requirePaidCreativeConfirmation, "requirePaidCreativeConfirmation");
17675
18506
 
17676
18507
  // src/tools/winning-product-image.ts
17677
- import { z as z71 } from "zod";
17678
- var WinnerReferenceInput = z71.object({
17679
- runId: z71.string().uuid(),
17680
- candidateSourceId: z71.string().trim().min(1).max(160)
18508
+ import { z as z75 } from "zod";
18509
+ var WinnerReferenceInput = z75.object({
18510
+ runId: z75.string().uuid(),
18511
+ candidateSourceId: z75.string().trim().min(1).max(160)
17681
18512
  }).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
17682
18513
  async function resolveWinnerImages(api, winnerReference, images) {
17683
18514
  if (!winnerReference) return images;
@@ -17714,59 +18545,59 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
17714
18545
  var createServiceVideoGuidance = getProductMakerCapabilityModelGuidance("create_service_video");
17715
18546
  var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
17716
18547
  var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
17717
- var CreateProductTaskInput = z72.object({
18548
+ var CreateProductTaskInput = z76.object({
17718
18549
  images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
17719
18550
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
17720
- projectId: z72.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
17721
- productUrl: z72.string().url().optional().describe("Opcional. URL de la p\xE1gina del producto (Shopify, AliExpress, Amazon, etc.) para enriquecer el contexto. Si se omite, la IA infiere todo desde la imagen."),
18551
+ projectId: z76.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
18552
+ productUrl: z76.string().url().optional().describe("Opcional. URL de la p\xE1gina del producto (Shopify, AliExpress, Amazon, etc.) para enriquecer el contexto. Si se omite, la IA infiere todo desde la imagen."),
17722
18553
  language: Lang.describe('C\xF3digo de idioma para el contenido generado. Ejemplos: "es", "en", "pt". REQUERIDO \u2014 si el usuario no lo especific\xF3, PREG\xDANTALE antes de invocar. NUNCA infieras desde el contexto del chat ni asumas "es" por default.'),
17723
18554
  country: Country.describe('C\xF3digo ISO del pa\xEDs objetivo. Ejemplos: "CO", "MX", "US", "AR". Define moneda, m\xE9todos de pago locales y tono. REQUERIDO \u2014 si el usuario no lo especific\xF3, PREG\xDANTALE antes de invocar. NUNCA infieras desde el contexto del chat.'),
17724
- price: z72.string().min(1).max(120).optional().describe('Precio que se mostrar\xE1 en la landing y video. Formato libre \u2014 ej. "$89.900", "USD 29.99", "MXN 599". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar. Si te dice "t\xFA elige", om\xEDtelo y el backend sugiere uno.'),
17725
- compareAtPrice: z72.string().min(1).max(120).optional().describe('Opcional. Precio anterior para comunicar un descuento real en landing e im\xE1genes. Ej. "$129.000" cuando price="$89.900".'),
17726
- offer: z72.string().min(1).max(240).optional().describe('Oferta o promoci\xF3n a destacar. Ej. "2x1", "Env\xEDo gratis hoy", "50% OFF". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar (es v\xE1lido que diga "sin oferta"). Si te dice "t\xFA elige", om\xEDtelo.'),
17727
- paymentMethods: z72.string().min(1).max(240).optional().describe('Opcional. M\xE9todos de pago que puede mostrar la landing. Ej. "Tarjeta, PSE, Nequi, Contraentrega". Si se omite, la landing no muestra m\xE9todos de pago.'),
17728
- productContext: z72.string().max(3e3).optional().describe("Opcional. Informacion adicional del producto que la IA debe usar como contexto prioritario: uso real, comprador, restricciones, diferenciadores o direccion creativa. No reemplaza la investigacion de competencia; si hay competencia, guia el primer angulo y los outputs no deben contradecirlo."),
17729
- productLabel: z72.string().trim().max(80).optional().describe('Opcional. Qu\xE9 es el producto, en pocas palabras (ej. "quita pelusas para ropa"). Es AUTORITATIVO: si lo env\xEDas, la IA usa esta identidad y no la reemplaza por otra categor\xEDa. Si lo omites, la IA detecta el producto desde la imagen.'),
18555
+ price: z76.string().min(1).max(120).optional().describe('Precio que se mostrar\xE1 en la landing y video. Formato libre \u2014 ej. "$89.900", "USD 29.99", "MXN 599". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar. Si te dice "t\xFA elige", om\xEDtelo y el backend sugiere uno.'),
18556
+ compareAtPrice: z76.string().min(1).max(120).optional().describe('Opcional. Precio anterior para comunicar un descuento real en landing e im\xE1genes. Ej. "$129.000" cuando price="$89.900".'),
18557
+ offer: z76.string().min(1).max(240).optional().describe('Oferta o promoci\xF3n a destacar. Ej. "2x1", "Env\xEDo gratis hoy", "50% OFF". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar (es v\xE1lido que diga "sin oferta"). Si te dice "t\xFA elige", om\xEDtelo.'),
18558
+ paymentMethods: z76.string().min(1).max(240).optional().describe('Opcional. M\xE9todos de pago que puede mostrar la landing. Ej. "Tarjeta, PSE, Nequi, Contraentrega". Si se omite, la landing no muestra m\xE9todos de pago.'),
18559
+ productContext: z76.string().max(3e3).optional().describe("Opcional. Informacion adicional del producto que la IA debe usar como contexto prioritario: uso real, comprador, restricciones, diferenciadores o direccion creativa. No reemplaza la investigacion de competencia; si hay competencia, guia el primer angulo y los outputs no deben contradecirlo."),
18560
+ productLabel: z76.string().trim().max(80).optional().describe('Opcional. Qu\xE9 es el producto, en pocas palabras (ej. "quita pelusas para ropa"). Es AUTORITATIVO: si lo env\xEDas, la IA usa esta identidad y no la reemplaza por otra categor\xEDa. Si lo omites, la IA detecta el producto desde la imagen.'),
17730
18561
  videoPreset: VideoPresetEnum.default("auto").describe('Opcional. Tipo/narrativa del video \u2014 \xFAnico campo de "estilo" que el usuario controla. Default "auto" (la IA escoge tras analizar el producto). Todos los presets funcionan a 15s (single_call) y 30s (Multiescena), excepto "problem_solution", que requiere 30s Multiescena. Opciones: "auto", "ugc_dynamic" (review con experiencia y prueba), "ugc_how_to" (tutorial con pasos y resultado visible), "ugc_unboxing_chaos" (apertura y primera prueba), "problem_solution" (problema concreto, producto como soluci\xF3n y CTA), "product_showcase" (producto ejecutando una funci\xF3n real), "wearable_showcase" (prenda o accesorio modelado), "cinematic" (TV spot con receta cinematogr\xE1fica), "wild_card" (idea imposible: un truco visual que en la vida real no podr\xEDa pasar, y al cierre la invitaci\xF3n a comprar), "pixar_problem" (problema animado 3D), "pixar_sassy" (producto que habla). Si el usuario pide algo fuera de esta lista, p\xEDdele una opci\xF3n v\xE1lida.'),
17731
- durationSeconds: z72.union([
17732
- z72.literal(15),
17733
- z72.literal(30)
18562
+ durationSeconds: z76.union([
18563
+ z76.literal(15),
18564
+ z76.literal(30)
17734
18565
  ]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
17735
- pauseForAngleReview: z72.boolean().optional().describe("Compatibilidad heredada. MCP deriva esta pausa de aiDecidesAll: manual siempre pausa y autom\xE1tico siempre la omite. No uses este campo para saltar reviews."),
17736
- aiDecidesAll: z72.boolean().optional().describe("Mapea el toggle web \u201CDejar que la IA decida todo\u201D. Si true, ProductMaker omite reviews. Act\xEDvalo \xFAnicamente cuando el usuario lo pida expl\xEDcitamente. Omitido/false = reviews conversacionales."),
18566
+ pauseForAngleReview: z76.boolean().optional().describe("Compatibilidad heredada. MCP deriva esta pausa de aiDecidesAll: manual siempre pausa y autom\xE1tico siempre la omite. No uses este campo para saltar reviews."),
18567
+ aiDecidesAll: z76.boolean().optional().describe("Mapea el toggle web \u201CDejar que la IA decida todo\u201D. Si true, ProductMaker omite reviews. Act\xEDvalo \xFAnicamente cuando el usuario lo pida expl\xEDcitamente. Omitido/false = reviews conversacionales."),
17737
18568
  videoTier: VideoTierEnum.optional().describe('Opcional. Estilo del video. "basic" = "Realista" para 15s; al pedir durationSeconds=30 el sistema selecciona internamente Multiescena. No se expone el tier interno directamente.'),
17738
18569
  videoStructure: VideoStructureEnum.default("single_take").describe('Opcional. Formato: "single_take" = Un solo clip (generado completo; puede incluir cambios de plano) o "multi_scene" = Multiescena. Default: single_take.'),
17739
18570
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
17740
18571
  videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render. En la web se pregunta "\xBFResoluci\xF3n del video?". "480p" = excelente calidad y m\xE1s econ\xF3mico (RECOMENDADO, default si se omite); "720p" = m\xE1xima nitidez, entre 3% y 15% m\xE1s caro seg\xFAn formato y tier. Si el usuario no menciona resoluci\xF3n, OMITE este campo (el backend usa 480p).'),
17741
- videoAngleCount: z72.number().int().min(1).max(3).optional().describe("Cantidad de videos a renderizar: 1, 2 o 3. REQUERIDO cuando outputs incluye video (o se omite outputs, cuyo default incluye video); om\xEDtelo s\xF3lo cuando no se generar\xE1 video. Preg\xFAntalo incluso con aiDecidesAll=true porque cambia el costo."),
18572
+ videoAngleCount: z76.number().int().min(1).max(3).optional().describe("Cantidad de videos a renderizar: 1, 2 o 3. REQUERIDO cuando outputs incluye video (o se omite outputs, cuyo default incluye video); om\xEDtelo s\xF3lo cuando no se generar\xE1 video. Preg\xFAntalo incluso con aiDecidesAll=true porque cambia el costo."),
17742
18573
  angleNarratives: PublicNarrativeStyleEnum.array().max(3).optional().describe('Opcional. Narrativa POR \xC1NGULO (posicional). Valores actuales: "review", "ugc_how_to", "ugc_unboxing_chaos", "problem_product_cta" (problema concreto, producto como soluci\xF3n y CTA), "product_showcase", "wearable_showcase", "cinematic", "wild_card", "animated_problem_pixar", "sassy_product_pixar", "market" (narrativa an\xE1lisis de mercado: adapta el video a los patrones ganadores estudiados de la competencia; requiere competitorScanEnabled: true). angleNarratives[i] fuerza la narrativa del \xE1ngulo i; las posiciones restantes las elige la IA. La lista no puede superar videoAngleCount.'),
17743
- outputs: z72.array(z72.enum([
18574
+ outputs: z76.array(z76.enum([
17744
18575
  "landing",
17745
18576
  "video",
17746
18577
  "image"
17747
18578
  ])).min(2).max(3).optional().describe(`Opcional. Qu\xE9 outputs generar. Default: todos ["landing","video","image"]. Para 2 outputs: ["landing","image"] (sin video), ["video","image"] (sin landing), ["landing","video"] (sin imagen). ${createProductTaskSingleOutputDescription}`),
17748
- competitorScanEnabled: z72.boolean().optional().describe("Opcional. Debe enviarse true solo despu\xE9s de que el usuario acepte estudiar la competencia (o si solicita la narrativa an\xE1lisis de mercado). Si la tarea incluye video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico. Omitir no autoriza el estudio profundo."),
17749
- replicateWinnerWhenFound: z72.boolean().optional().describe("Conserva la preferencia de copiar un ganador si existe. false estudia el mercado sin reemplazar un \xE1ngulo por el anuncio ganador. No a\xF1ade una pregunta obligatoria."),
17750
- brandId: z72.string().uuid().optional().describe("Opcional. ID de una marca del usuario; si se env\xEDa, el sistema usa su voz, colores y persona para enriquecer los outputs generados."),
17751
- actorId: z72.string().trim().min(1).optional().describe("Opcional. ID de un personaje guardado (usa list_actors para verlos). Si lo env\xEDas, su foto y su voz mandan sobre la descripci\xF3n de texto."),
18579
+ competitorScanEnabled: z76.boolean().optional().describe("Opcional. Debe enviarse true solo despu\xE9s de que el usuario acepte estudiar la competencia (o si solicita la narrativa an\xE1lisis de mercado). Si la tarea incluye video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico. Omitir no autoriza el estudio profundo."),
18580
+ replicateWinnerWhenFound: z76.boolean().optional().describe("Conserva la preferencia de copiar un ganador si existe. false estudia el mercado sin reemplazar un \xE1ngulo por el anuncio ganador. No a\xF1ade una pregunta obligatoria."),
18581
+ brandId: z76.string().uuid().optional().describe("Opcional. ID de una marca del usuario; si se env\xEDa, el sistema usa su voz, colores y persona para enriquecer los outputs generados."),
18582
+ actorId: z76.string().trim().min(1).optional().describe("Opcional. ID de un personaje guardado (usa list_actors para verlos). Si lo env\xEDas, su foto y su voz mandan sobre la descripci\xF3n de texto."),
17752
18583
  creativeGender: CreativeGenderEnum.optional().describe('Opcional. QUI\xC9N APARECE EN PANTALLA en todos los creativos de la task: el presentador del video, las personas fotografiadas en la landing y la persona del anuncio. NO es la voz. M\xE1ndalo en cuanto el usuario lo diga en cualquier momento de la conversaci\xF3n y con cualquier redacci\xF3n ("quiero una mujer", "que salga un hombre", "esto es para hombres"): si no lo mandas, el g\xE9nero lo inventa la IA y el usuario recibe lo contrario de lo que pidi\xF3 sin ning\xFAn aviso. "mixed" solo cuando pida expl\xEDcitamente ambos. Si adem\xE1s mandas actorId, el personaje guardado manda sobre este campo.'),
17753
- creativeDirection: z72.string().max(500).optional().describe('Opcional. Direcci\xF3n creativa en texto libre (colores, mood, estilo) que aplica a los outputs de IMAGEN y LANDING (no al video \u2014 el estilo/ambiente del video se dirige con scriptNotes). M\xC1XIMA PRIORIDAD: anula marca, colores y estilo por defecto. Ej. "amarillo y azul, minimalista". M\xE1x 500 caracteres.'),
17754
- headline: z72.string().max(120).optional().describe("Opcional. Titular EXACTO a renderizar. Se imprime tal cual: la IA no lo reescribe, no lo acorta y no lo traduce. Se aplica a las IM\xC1GENES y a la portada de la landing de esta task (el video no lo usa; para el video usa scriptNotes). \xDAsalo cuando el copy es de marca y no es negociable. M\xE1x 120 caracteres. Si lo omites, la IA escribe el titular."),
17755
- subheadline: z72.string().max(160).optional().describe("Opcional. Subt\xEDtulo EXACTO a renderizar, misma regla que headline. Independiente: puedes fijar solo el subt\xEDtulo. M\xE1x 160 caracteres."),
18584
+ creativeDirection: z76.string().max(500).optional().describe('Opcional. Direcci\xF3n creativa en texto libre (colores, mood, estilo) que aplica a los outputs de IMAGEN y LANDING (no al video \u2014 el estilo/ambiente del video se dirige con scriptNotes). M\xC1XIMA PRIORIDAD: anula marca, colores y estilo por defecto. Ej. "amarillo y azul, minimalista". M\xE1x 500 caracteres.'),
18585
+ headline: z76.string().max(120).optional().describe("Opcional. Titular EXACTO a renderizar. Se imprime tal cual: la IA no lo reescribe, no lo acorta y no lo traduce. Se aplica a las IM\xC1GENES y a la portada de la landing de esta task (el video no lo usa; para el video usa scriptNotes). \xDAsalo cuando el copy es de marca y no es negociable. M\xE1x 120 caracteres. Si lo omites, la IA escribe el titular."),
18586
+ subheadline: z76.string().max(160).optional().describe("Opcional. Subt\xEDtulo EXACTO a renderizar, misma regla que headline. Independiente: puedes fijar solo el subt\xEDtulo. M\xE1x 160 caracteres."),
17756
18587
  landingStrategy: LandingStrategyEnum.default("classic").describe('Opcional. Estructura de la landing cl\xE1sica cuando landing est\xE1 entre outputs: "classic" (estructura original probada y recomendada; default del primer rollout), "auto" (la IA decide; experimental), "pain_solution", "social_proof" (Landing Viral: UGC, WhatsApp, Instagram y evidencia social), "benefits_clarity", "offer_value" o "lifestyle_identity". Default "classic".'),
17757
18588
  landingImageFormat: LandingImageFormatEnum.default("9:16").describe('Opcional. Formato/relaci\xF3n de aspecto de las im\xE1genes de la landing cl\xE1sica cuando landing est\xE1 entre outputs: "9:16" (vertical, por defecto), "4:5" (vertical compacto para feed) o "1:1" (cuadrado). Default "9:16".')
17758
18589
  }).strict();
17759
- var CreateServiceVideoInput = z72.object({
17760
- landingUrl: z72.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
17761
- additionalContext: z72.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
18590
+ var CreateServiceVideoInput = z76.object({
18591
+ landingUrl: z76.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
18592
+ additionalContext: z76.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
17762
18593
  language: Lang.describe("Idioma del video: es, en o pt."),
17763
- voiceId: z72.string().trim().min(1).optional().describe('Opcional. Voz de ElevenLabs para toda la narraci\xF3n. Usa "auto" para que la IA la alinee con el presentador o env\xEDa un ID concreto de la lista de voces de la web.'),
17764
- brandId: z72.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
17765
- reviewMode: z72.enum([
18594
+ voiceId: z76.string().trim().min(1).optional().describe('Opcional. Voz de ElevenLabs para toda la narraci\xF3n. Usa "auto" para que la IA la alinee con el presentador o env\xEDa un ID concreto de la lista de voces de la web.'),
18595
+ brandId: z76.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
18596
+ reviewMode: z76.enum([
17766
18597
  "automatic",
17767
18598
  "guided"
17768
18599
  ]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
17769
- videoPreset: z72.enum([
18600
+ videoPreset: z76.enum([
17770
18601
  "auto",
17771
18602
  "ugc_dynamic",
17772
18603
  "ugc_how_to",
@@ -17776,128 +18607,128 @@ var CreateServiceVideoInput = z72.object({
17776
18607
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
17777
18608
  videoResolution: VideoResolutionEnum.default("480p").describe('Opcional. Resoluci\xF3n: "480p" o "720p". 720p cuesta m\xE1s por segundo y solo est\xE1 disponible en "economy" y "pro" (Medio = 768P). Default: 480p.')
17778
18609
  }).strict();
17779
- var GetTaskStatusInput = z72.object({
17780
- taskId: z72.string().min(1),
17781
- waitSeconds: z72.number().int().min(0).max(120).optional()
18610
+ var GetTaskStatusInput = z76.object({
18611
+ taskId: z76.string().min(1),
18612
+ waitSeconds: z76.number().int().min(0).max(120).optional()
17782
18613
  });
17783
- var ListTasksInput = z72.object({
17784
- limit: z72.number().int().min(1).max(50).optional(),
17785
- offset: z72.number().int().min(0).optional(),
17786
- search: z72.string().optional()
18614
+ var ListTasksInput = z76.object({
18615
+ limit: z76.number().int().min(1).max(50).optional(),
18616
+ offset: z76.number().int().min(0).optional(),
18617
+ search: z76.string().optional()
17787
18618
  });
17788
18619
  var MCP_REVIEW_LIST_FIELD_MAX = 1500;
17789
18620
  var MCP_REVIEW_FEATURE_ITEM_MAX = 240;
17790
- var EditTaskDraftInput = z72.object({
17791
- taskId: z72.string().min(1),
17792
- angleIndex: z72.number().int().min(0),
17793
- angle: z72.object({
17794
- angle: z72.string().min(1).max(480),
17795
- buyerPersona: z72.string().min(1).max(360),
17796
- actor: z72.string().min(1).max(360).optional(),
17797
- actorId: z72.string().trim().min(1).optional().describe("Opcional. ID de un personaje guardado (usa list_actors para verlos). Si lo env\xEDas, su foto y su voz mandan sobre la descripci\xF3n de texto."),
17798
- gender: z72.enum([
18621
+ var EditTaskDraftInput = z76.object({
18622
+ taskId: z76.string().min(1),
18623
+ angleIndex: z76.number().int().min(0),
18624
+ angle: z76.object({
18625
+ angle: z76.string().min(1).max(480),
18626
+ buyerPersona: z76.string().min(1).max(360),
18627
+ actor: z76.string().min(1).max(360).optional(),
18628
+ actorId: z76.string().trim().min(1).optional().describe("Opcional. ID de un personaje guardado (usa list_actors para verlos). Si lo env\xEDas, su foto y su voz mandan sobre la descripci\xF3n de texto."),
18629
+ gender: z76.enum([
17799
18630
  "female",
17800
18631
  "male"
17801
18632
  ]).optional(),
17802
- scriptNotes: z72.string().max(2e3).optional()
18633
+ scriptNotes: z76.string().max(2e3).optional()
17803
18634
  })
17804
18635
  });
17805
- var PendingActionPayload = z72.discriminatedUnion("kind", [
17806
- z72.object({
17807
- kind: z72.literal("product_reference_set_approval"),
18636
+ var PendingActionPayload = z76.discriminatedUnion("kind", [
18637
+ z76.object({
18638
+ kind: z76.literal("product_reference_set_approval"),
17808
18639
  scope: ProductReferenceScopeEnum.optional(),
17809
- scopeKey: z72.string().min(1).max(120).optional(),
17810
- scopeSnapshotId: z72.string().uuid().optional(),
17811
- expectedScopeHash: z72.string().min(1).max(128).optional(),
18640
+ scopeKey: z76.string().min(1).max(120).optional(),
18641
+ scopeSnapshotId: z76.string().uuid().optional(),
18642
+ expectedScopeHash: z76.string().min(1).max(128).optional(),
17812
18643
  decision: ProductReferenceResolutionDecisionEnum,
17813
18644
  reason: ProductReferenceRejectionReasonEnum.optional(),
17814
- affectedRefKeys: z72.array(z72.string().min(1).max(200)).min(1).optional(),
17815
- affectedPhotoNumbers: z72.array(z72.number().int().positive()).min(1).optional(),
17816
- recoveryAction: z72.enum([
18645
+ affectedRefKeys: z76.array(z76.string().min(1).max(200)).min(1).optional(),
18646
+ affectedPhotoNumbers: z76.array(z76.number().int().positive()).min(1).optional(),
18647
+ recoveryAction: z76.enum([
17817
18648
  "remove",
17818
18649
  "replace",
17819
18650
  "upload",
17820
18651
  "return_to_selection"
17821
18652
  ]).optional()
17822
18653
  }),
17823
- z72.object({
17824
- kind: z72.literal("product_reference_confirmation"),
17825
- selectedPhotoNumbers: z72.array(z72.number().int().positive().max(5)).min(1).max(5).optional().describe("Opcional. N\xFAmeros visibles de las fotos que el usuario quiere conservar; las dem\xE1s se deseleccionan. Debe quedar al menos una."),
18654
+ z76.object({
18655
+ kind: z76.literal("product_reference_confirmation"),
18656
+ selectedPhotoNumbers: z76.array(z76.number().int().positive().max(5)).min(1).max(5).optional().describe("Opcional. N\xFAmeros visibles de las fotos que el usuario quiere conservar; las dem\xE1s se deseleccionan. Debe quedar al menos una."),
17826
18657
  userChoice: ProductReferenceUserChoiceEnum.optional(),
17827
- confirmedProductNames: z72.array(z72.string().min(1).max(120)).min(2).max(8).optional(),
18658
+ confirmedProductNames: z76.array(z76.string().min(1).max(120)).min(2).max(8).optional(),
17828
18659
  videoStructure: VideoStructureEnum.optional().describe("Opcional. Formato para reanudar el video: single_take (Un solo clip, generado completo; puede incluir cambios de plano) o multi_scene (Multiescena). El backend vuelve a validar que sea compatible con el agrupamiento confirmado."),
17829
18660
  videoQuality: VideoQualityEnum.optional().describe("Opcional. Calidad para reanudar el video: economy (Econ\xF3mico), medium (Medio) o pro. El proveedor se elige internamente y el backend vuelve a cotizar la ruta."),
17830
- useMultiSceneShowcase: z72.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
18661
+ useMultiSceneShowcase: z76.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
17831
18662
  }),
17832
- z72.object({
17833
- kind: z72.literal("angle_review_approval"),
18663
+ z76.object({
18664
+ kind: z76.literal("angle_review_approval"),
17834
18665
  // All edits are optional — empty action body just approves the
17835
18666
  // backend-generated draft as-is. Field shapes mirror the angle-review
17836
18667
  // request contracts in @packages/types/wizard.ts; the handler routes to
17837
18668
  // the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
17838
- customAngle: z72.string().min(1).max(480).optional(),
18669
+ customAngle: z76.string().min(1).max(480).optional(),
17839
18670
  // Keep the shared MCP action within the strictest downstream contract:
17840
18671
  // autopilot/image resume endpoints cap these fields at 1500 characters.
17841
- painPoints: z72.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
17842
- benefits: z72.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
18672
+ painPoints: z76.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
18673
+ benefits: z76.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
17843
18674
  // Same policy as the two fields above: the strictest downstream contract
17844
18675
  // wins. The image endpoint caps each feature at 240 while landing/video
17845
18676
  // accept 300, and this single action routes to whichever the task is — so
17846
18677
  // accepting 300 here turns a 250-character feature on an image task into
17847
18678
  // an opaque HTTP 400 after the model already believed it had been saved.
17848
- features: z72.array(z72.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
17849
- buyerPersona: z72.string().min(1).max(360).optional(),
18679
+ features: z76.array(z76.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
18680
+ buyerPersona: z76.string().min(1).max(360).optional(),
17850
18681
  narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n) requiere Multiescena de 30s: en un video de 15s en formato Un solo clip el servidor la rechaza.'),
17851
- actor: z72.string().min(1).max(360).optional().describe("Nueva descripci\xF3n del presentador. Al enviarla sin actorId, se elimina autom\xE1ticamente cualquier actor guardado previo de esos \xE1ngulos."),
17852
- actorId: z72.string().max(120).nullable().optional(),
17853
- creativeDirection: z72.string().max(2e3).optional(),
17854
- selectedAngleNumbers: z72.array(z72.number().int().positive()).min(1).max(3).optional().describe("N\xFAmeros visibles (1-based) de los \xE1ngulos que el usuario quiere renderizar. Deben ser \xFAnicos, existir en la review y no superar el videoAngleCount autorizado."),
17855
- angleEdits: z72.array(z72.object({
17856
- angleNumber: z72.number().int().positive(),
17857
- narrativeSelection: z72.enum([
18682
+ actor: z76.string().min(1).max(360).optional().describe("Nueva descripci\xF3n del presentador. Al enviarla sin actorId, se elimina autom\xE1ticamente cualquier actor guardado previo de esos \xE1ngulos."),
18683
+ actorId: z76.string().max(120).nullable().optional(),
18684
+ creativeDirection: z76.string().max(2e3).optional(),
18685
+ selectedAngleNumbers: z76.array(z76.number().int().positive()).min(1).max(3).optional().describe("N\xFAmeros visibles (1-based) de los \xE1ngulos que el usuario quiere renderizar. Deben ser \xFAnicos, existir en la review y no superar el videoAngleCount autorizado."),
18686
+ angleEdits: z76.array(z76.object({
18687
+ angleNumber: z76.number().int().positive(),
18688
+ narrativeSelection: z76.enum([
17858
18689
  "market",
17859
18690
  "guided"
17860
18691
  ]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
17861
- angle: z72.string().min(1).max(480).optional(),
17862
- buyerPersona: z72.string().min(1).max(360).optional(),
18692
+ angle: z76.string().min(1).max(480).optional(),
18693
+ buyerPersona: z76.string().min(1).max(360).optional(),
17863
18694
  narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n) requiere Multiescena de 30s: en un video de 15s en formato Un solo clip el servidor la rechaza.'),
17864
- actor: z72.string().min(1).max(360).optional(),
17865
- actorId: z72.string().max(120).nullable().optional(),
17866
- creativeDirection: z72.string().max(2e3).optional()
18695
+ actor: z76.string().min(1).max(360).optional(),
18696
+ actorId: z76.string().max(120).nullable().optional(),
18697
+ creativeDirection: z76.string().max(2e3).optional()
17867
18698
  }).strict()).max(3).optional().describe("Ediciones independientes por n\xFAmero visible de \xE1ngulo. S\xF3lo se aceptan para \xE1ngulos incluidos en selectedAngleNumbers (o en la selecci\xF3n por defecto)."),
17868
- gapDurationSeconds: z72.union([
17869
- z72.literal(15),
17870
- z72.literal(30)
18699
+ gapDurationSeconds: z76.union([
18700
+ z76.literal(15),
18701
+ z76.literal(30)
17871
18702
  ]).optional().describe("Opcional. Solo para aceptar expl\xEDcitamente la recomendaci\xF3n gapDurationChoice del status. 30 env\xEDa el override double_30s para el \xE1ngulo recomendado; 15 u omitido conserva la duraci\xF3n cotizada.")
17872
18703
  }),
17873
- z72.object({
17874
- kind: z72.literal("service_angle_approval"),
17875
- angleId: z72.string().uuid().optional(),
17876
- angleNumber: z72.number().int().positive().optional(),
17877
- content: z72.string().min(1).max(480).optional(),
17878
- creativeDirection: z72.string().min(1).max(1500).optional(),
17879
- actor: z72.string().min(1).max(360).optional()
18704
+ z76.object({
18705
+ kind: z76.literal("service_angle_approval"),
18706
+ angleId: z76.string().uuid().optional(),
18707
+ angleNumber: z76.number().int().positive().optional(),
18708
+ content: z76.string().min(1).max(480).optional(),
18709
+ creativeDirection: z76.string().min(1).max(1500).optional(),
18710
+ actor: z76.string().min(1).max(360).optional()
17880
18711
  }),
17881
- z72.object({
17882
- kind: z72.literal("service_script_approval"),
17883
- voiceovers: z72.record(z72.string(), z72.string().min(1).max(600)).optional(),
17884
- visualDirections: z72.record(z72.string(), z72.string().min(1).max(1200)).optional(),
17885
- voiceoversByScene: z72.record(z72.string(), z72.string().min(1).max(600)).optional(),
17886
- visualDirectionsByScene: z72.record(z72.string(), z72.string().min(1).max(1200)).optional()
18712
+ z76.object({
18713
+ kind: z76.literal("service_script_approval"),
18714
+ voiceovers: z76.record(z76.string(), z76.string().min(1).max(600)).optional(),
18715
+ visualDirections: z76.record(z76.string(), z76.string().min(1).max(1200)).optional(),
18716
+ voiceoversByScene: z76.record(z76.string(), z76.string().min(1).max(600)).optional(),
18717
+ visualDirectionsByScene: z76.record(z76.string(), z76.string().min(1).max(1200)).optional()
17887
18718
  })
17888
18719
  ]);
17889
- var ResolvePendingActionInput = z72.object({
17890
- taskId: z72.string().min(1),
18720
+ var ResolvePendingActionInput = z76.object({
18721
+ taskId: z76.string().min(1),
17891
18722
  action: PendingActionPayload
17892
18723
  }).strict();
17893
18724
  function resolveVariantConfirmVideoTier(action) {
17894
18725
  return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
17895
18726
  }
17896
18727
  __name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
17897
- var StatusForResolveSchema = z72.object({
18728
+ var StatusForResolveSchema = z76.object({
17898
18729
  // Metadata used to select the backend resume contract. Older API responses
17899
18730
  // may omit these fields, so the resolver keeps the generic fallback.
17900
- kind: z72.enum([
18731
+ kind: z76.enum([
17901
18732
  "autopilot",
17902
18733
  "video",
17903
18734
  "image",
@@ -17905,18 +18736,18 @@ var StatusForResolveSchema = z72.object({
17905
18736
  "mix",
17906
18737
  "service"
17907
18738
  ]).optional(),
17908
- selectedOutputs: z72.array(z72.enum([
18739
+ selectedOutputs: z76.array(z76.enum([
17909
18740
  "landing",
17910
18741
  "video",
17911
18742
  "image"
17912
18743
  ])).optional(),
17913
- videoAngleCount: z72.number().int().min(1).max(3).optional(),
17914
- ugcFormat: z72.enum([
18744
+ videoAngleCount: z76.number().int().min(1).max(3).optional(),
18745
+ ugcFormat: z76.enum([
17915
18746
  "single_8s",
17916
18747
  "single_15s",
17917
18748
  "double_30s"
17918
18749
  ]).optional(),
17919
- videoStyle: z72.enum([
18750
+ videoStyle: z76.enum([
17920
18751
  "ugc",
17921
18752
  "cartoon_3d",
17922
18753
  "product_only",
@@ -17925,79 +18756,72 @@ var StatusForResolveSchema = z72.object({
17925
18756
  videoStructure: VideoStructureEnum.optional(),
17926
18757
  videoQuality: VideoQualityEnum.optional(),
17927
18758
  videoRouteId: VideoRouteIdEnum.optional(),
17928
- videoModel: z72.enum([
17929
- "veo",
17930
- "wan",
17931
- "bytedance",
17932
- "seedance",
17933
- "grok",
17934
- "kling"
17935
- ]).optional(),
17936
- videoTier: z72.enum([
18759
+ videoModel: TaskVideoModelEnum.optional(),
18760
+ videoTier: z76.enum([
17937
18761
  "legacy",
17938
18762
  "standard",
17939
18763
  "pro",
17940
18764
  "single_call"
17941
18765
  ]).optional(),
17942
- videoResolution: z72.enum([
18766
+ videoResolution: z76.enum([
17943
18767
  "480p",
17944
18768
  "720p"
17945
18769
  ]).optional(),
17946
18770
  narrativeStyle: NarrativeStyleEnum.optional(),
17947
- pauseForVideoScriptReview: z72.boolean().optional(),
17948
- pendingUserAction: z72.object({
17949
- kind: z72.string(),
17950
- candidateGrouping: z72.string().optional(),
17951
- selectedImageUrls: z72.array(z72.string()).optional(),
17952
- proposedProductNames: z72.array(z72.string()).optional(),
18771
+ pauseForVideoScriptReview: z76.boolean().optional(),
18772
+ pendingUserAction: z76.object({
18773
+ kind: z76.string(),
18774
+ candidateGrouping: z76.string().optional(),
18775
+ selectedImageUrls: z76.array(z76.string()).optional(),
18776
+ proposedProductNames: z76.array(z76.string()).optional(),
17953
18777
  // Adaptive reference questions are server-owned. Echo only the evidence
17954
18778
  // identity and the choices shown by the current snapshot; never accept a
17955
18779
  // client-supplied reference set as authorization.
17956
- options: z72.array(ProductReferenceUserChoiceEnum).max(4).optional(),
17957
- mode: z72.enum([
18780
+ options: z76.array(ProductReferenceUserChoiceEnum).max(4).optional(),
18781
+ mode: z76.enum([
17958
18782
  "question",
17959
18783
  "visual_recovery"
17960
18784
  ]).optional(),
17961
18785
  /** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
17962
- canKeepSelection: z72.boolean().optional(),
17963
- decisionKey: z72.string().optional(),
17964
- questionOrdinal: z72.number().int().min(1).max(5).optional(),
17965
- questionCeiling: z72.union([
17966
- z72.literal(3),
17967
- z72.literal(5)
18786
+ canKeepSelection: z76.boolean().optional(),
18787
+ decisionKey: z76.string().optional(),
18788
+ questionOrdinal: z76.number().int().min(1).max(5).optional(),
18789
+ questionCeiling: z76.union([
18790
+ z76.literal(3),
18791
+ z76.literal(5)
17968
18792
  ]).optional(),
17969
- referenceEvidenceVersion: z72.number().int().positive().optional(),
17970
- expectedEvidenceHash: z72.string().optional(),
17971
- question: z72.object({
17972
- prompt: z72.string().min(1).max(240),
17973
- helpText: z72.string().min(1).max(300).optional(),
17974
- options: z72.array(z72.object({
18793
+ referenceEvidenceVersion: z76.number().int().positive().optional(),
18794
+ expectedEvidenceHash: z76.string().optional(),
18795
+ question: z76.object({
18796
+ prompt: z76.string().min(1).max(240),
18797
+ helpText: z76.string().min(1).max(300).optional(),
18798
+ options: z76.array(z76.object({
17975
18799
  value: ProductReferenceUserChoiceEnum,
17976
- label: z72.string().min(1).max(120),
17977
- description: z72.string().min(1).max(240).optional()
18800
+ label: z76.string().min(1).max(120),
18801
+ description: z76.string().min(1).max(240).optional()
17978
18802
  })).min(2).max(4)
17979
18803
  }).optional(),
17980
18804
  scope: ProductReferenceScopeEnum.optional(),
17981
- scopeKey: z72.string().optional(),
17982
- scopeSnapshotId: z72.string().uuid().optional(),
17983
- scopeHash: z72.string().optional(),
17984
- baseReferenceSetHash: z72.string().optional(),
17985
- phase: z72.enum([
18805
+ scopeKey: z76.string().optional(),
18806
+ scopeSnapshotId: z76.string().uuid().optional(),
18807
+ scopeHash: z76.string().optional(),
18808
+ baseReferenceSetHash: z76.string().optional(),
18809
+ phase: z76.enum([
17986
18810
  "preparation",
17987
18811
  "final"
17988
18812
  ]).optional(),
17989
- selectedRefKeys: z72.array(z72.string().min(1).max(200)).optional(),
17990
- allowedDecisions: z72.array(ProductReferenceResolutionDecisionEnum).optional(),
17991
- previews: z72.array(z72.object({
17992
- refKey: z72.string().min(1).max(200)
18813
+ selectedRefKeys: z76.array(z76.string().min(1).max(200)).optional(),
18814
+ allowedDecisions: z76.array(ProductReferenceResolutionDecisionEnum).optional(),
18815
+ previews: z76.array(z76.object({
18816
+ refKey: z76.string().min(1).max(200)
17993
18817
  }).passthrough()).optional(),
17994
- customAngleDraft: z72.string().optional(),
17995
- painPointsDraft: z72.string().optional(),
17996
- benefitsDraft: z72.string().optional(),
17997
- featuresDraft: z72.array(z72.string()).optional(),
17998
- angleOptions: z72.array(z72.object({
17999
- index: z72.number().int().nonnegative(),
18000
- angle: z72.string().min(1)
18818
+ customAngleDraft: z76.string().optional(),
18819
+ painPointsDraft: z76.string().optional(),
18820
+ benefitsDraft: z76.string().optional(),
18821
+ featuresDraft: z76.array(z76.string()).optional(),
18822
+ angleOptions: z76.array(z76.object({
18823
+ index: z76.number().int().nonnegative(),
18824
+ angle: z76.string().min(1)
18001
18825
  }).passthrough()).min(1).max(5).optional(),
18002
18826
  // Recommendation consumed only when the caller explicitly sends
18003
18827
  // gapDurationSeconds: 30 in the angle approval action.
@@ -18007,17 +18831,17 @@ var StatusForResolveSchema = z72.object({
18007
18831
  // keys. `actorId` (the saved custom actor the picker stored) was silently
18008
18832
  // dropped here, so the approval handler below could not echo it back on the
18009
18833
  // PATCH — the selection looked accepted and reached no render.
18010
- angles: z72.array(z72.object({
18011
- id: z72.string().uuid(),
18012
- content: z72.string(),
18013
- creativeDirection: z72.string(),
18014
- actor: z72.string(),
18015
- actorId: z72.string().nullable().optional()
18834
+ angles: z76.array(z76.object({
18835
+ id: z76.string().uuid(),
18836
+ content: z76.string(),
18837
+ creativeDirection: z76.string(),
18838
+ actor: z76.string(),
18839
+ actorId: z76.string().nullable().optional()
18016
18840
  }).passthrough()).optional(),
18017
- panels: z72.array(z72.object({
18018
- beatId: z72.string(),
18019
- voiceover: z72.string(),
18020
- visualDirection: z72.string()
18841
+ panels: z76.array(z76.object({
18842
+ beatId: z76.string(),
18843
+ voiceover: z76.string(),
18844
+ visualDirection: z76.string()
18021
18845
  }).passthrough()).optional()
18022
18846
  }).optional()
18023
18847
  }).passthrough();
@@ -18852,7 +19676,7 @@ __name(registerTaskTools, "registerTaskTools");
18852
19676
 
18853
19677
  // src/tools/creatives.ts
18854
19678
  import { randomUUID } from "crypto";
18855
- import { z as z73 } from "zod";
19679
+ import { z as z77 } from "zod";
18856
19680
  var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
18857
19681
  var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
18858
19682
  var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
@@ -18862,70 +19686,70 @@ var CreativeRefs = {
18862
19686
  images: ImagesInput,
18863
19687
  language: Lang.describe('Idioma del contenido. Ej. "es", "en", "pt". REQUERIDO \u2014 si el usuario no lo dijo, PREG\xDANTALE antes de invocar. NUNCA infieras desde el contexto del chat ni asumas un default.'),
18864
19688
  country: Country.describe('Pa\xEDs objetivo ISO. Ej. "CO", "MX", "US", "AR". Define moneda, m\xE9todos de pago y tono. REQUERIDO \u2014 si el usuario no lo dijo, PREG\xDANTALE antes de invocar. NUNCA infieras desde el contexto del chat ni asumas un default.'),
18865
- price: z73.string().min(1).max(120).optional().describe('Precio en formato libre \u2014 ej. "$89.900", "USD 29.99". Opcional pero MUY IMPACTANTE para conversi\xF3n: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar. Si el usuario te dice "t\xFA elige", omite el campo y la IA del backend sugiere uno.'),
18866
- offer: z73.string().min(1).max(240).optional().describe('Oferta a destacar \u2014 ej. "2x1", "Env\xEDo gratis", "50% OFF". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar (es v\xE1lido que diga "sin oferta"). Si el usuario te dice "t\xFA elige", omite el campo.'),
18867
- compareAtPrice: z73.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
18868
- productContext: z73.string().max(3e3).optional().describe("Opcional. Informacion adicional del producto que la IA debe usar como contexto prioritario: uso real, comprador, restricciones, diferenciadores o direccion creativa. No reemplaza la investigacion de competencia; si hay competencia, guia el primer angulo y los outputs no deben contradecirlo."),
18869
- productLabel: z73.string().trim().max(80).optional().describe('Opcional. Nombre o tipo del producto en pocas palabras (ej. "collar de oro", "quita pelusas para ropa"). Es AUTORITATIVO: la IA usa esta identidad y no la reemplaza por otra categor\xEDa. Si lo omites, la IA lo detecta desde la imagen. NO salta la extracci\xF3n.'),
18870
- buyerPersona: z73.string().optional().describe('Opcional. Descripci\xF3n del comprador objetivo. Ej. "Mujeres 35-50, profesionales urbanas". Si se omite, la IA infiere desde el \xE1ngulo y producto.'),
18871
- isCombo: z73.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
18872
- competitorScanEnabled: z73.boolean().optional().describe("Opcional. Debe enviarse true solo despu\xE9s de que el usuario acepte estudiar la competencia (o si solicita la narrativa an\xE1lisis de mercado). En video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico. Omitir no autoriza el estudio profundo."),
18873
- brandId: z73.string().uuid().optional().describe("Opcional. ID de una marca del usuario; si se env\xEDa, el sistema usa su voz, colores y persona para enriquecer el creativo.")
19689
+ price: z77.string().min(1).max(120).optional().describe('Precio en formato libre \u2014 ej. "$89.900", "USD 29.99". Opcional pero MUY IMPACTANTE para conversi\xF3n: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar. Si el usuario te dice "t\xFA elige", omite el campo y la IA del backend sugiere uno.'),
19690
+ offer: z77.string().min(1).max(240).optional().describe('Oferta a destacar \u2014 ej. "2x1", "Env\xEDo gratis", "50% OFF". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar (es v\xE1lido que diga "sin oferta"). Si el usuario te dice "t\xFA elige", omite el campo.'),
19691
+ compareAtPrice: z77.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
19692
+ productContext: z77.string().max(3e3).optional().describe("Opcional. Informacion adicional del producto que la IA debe usar como contexto prioritario: uso real, comprador, restricciones, diferenciadores o direccion creativa. No reemplaza la investigacion de competencia; si hay competencia, guia el primer angulo y los outputs no deben contradecirlo."),
19693
+ productLabel: z77.string().trim().max(80).optional().describe('Opcional. Nombre o tipo del producto en pocas palabras (ej. "collar de oro", "quita pelusas para ropa"). Es AUTORITATIVO: la IA usa esta identidad y no la reemplaza por otra categor\xEDa. Si lo omites, la IA lo detecta desde la imagen. NO salta la extracci\xF3n.'),
19694
+ buyerPersona: z77.string().optional().describe('Opcional. Descripci\xF3n del comprador objetivo. Ej. "Mujeres 35-50, profesionales urbanas". Si se omite, la IA infiere desde el \xE1ngulo y producto.'),
19695
+ isCombo: z77.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
19696
+ competitorScanEnabled: z77.boolean().optional().describe("Opcional. Debe enviarse true solo despu\xE9s de que el usuario acepte estudiar la competencia (o si solicita la narrativa an\xE1lisis de mercado). En video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico. Omitir no autoriza el estudio profundo."),
19697
+ brandId: z77.string().uuid().optional().describe("Opcional. ID de una marca del usuario; si se env\xEDa, el sistema usa su voz, colores y persona para enriquecer el creativo.")
18874
19698
  };
18875
- var VideoPresenter = z73.discriminatedUnion("mode", [
18876
- z73.object({
18877
- mode: z73.literal("none")
19699
+ var VideoPresenter = z77.discriminatedUnion("mode", [
19700
+ z77.object({
19701
+ mode: z77.literal("none")
18878
19702
  }).strict(),
18879
- z73.object({
18880
- mode: z73.literal("saved_actor"),
18881
- actorId: z73.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
19703
+ z77.object({
19704
+ mode: z77.literal("saved_actor"),
19705
+ actorId: z77.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
18882
19706
  }).strict(),
18883
- z73.object({
18884
- mode: z73.literal("described"),
18885
- description: z73.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
19707
+ z77.object({
19708
+ mode: z77.literal("described"),
19709
+ description: z77.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
18886
19710
  }).strict()
18887
19711
  ]);
18888
- var VideoCreativeSetup = z73.discriminatedUnion("mode", [
18889
- z73.object({
18890
- mode: z73.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
19712
+ var VideoCreativeSetup = z77.discriminatedUnion("mode", [
19713
+ z77.object({
19714
+ mode: z77.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
18891
19715
  }).strict(),
18892
- z73.object({
18893
- mode: z73.literal("guided"),
19716
+ z77.object({
19717
+ mode: z77.literal("guided"),
18894
19718
  videoPreset: VideoPresetEnum.default("auto").describe('Narrativa opcional. Con estudio de mercado no la preguntes: se usa "auto" y el estudio define la estructura. Sin estudio conserva la elecci\xF3n del usuario. "problem_solution" requiere 30s.'),
18895
- buyerPersona: z73.string().trim().min(1).max(360),
19719
+ buyerPersona: z77.string().trim().min(1).max(360),
18896
19720
  presenter: VideoPresenter,
18897
- creativeDirection: z73.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
19721
+ creativeDirection: z77.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
18898
19722
  }).strict()
18899
19723
  ]);
18900
- var VideoInput = z73.object({
19724
+ var VideoInput = z77.object({
18901
19725
  images: CreativeRefs.images.optional(),
18902
19726
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
18903
- title: z73.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
18904
- primaryAngle: z73.string().min(1).describe('\xC1ngulo de venta principal (frase del beneficio). Ej. "Reduce arrugas en 14 d\xEDas" o "Para quienes odian las cremas grasosas".'),
19727
+ title: z77.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
19728
+ primaryAngle: z77.string().min(1).describe('\xC1ngulo de venta principal (frase del beneficio). Ej. "Reduce arrugas en 14 d\xEDas" o "Para quienes odian las cremas grasosas".'),
18905
19729
  language: CreativeRefs.language,
18906
19730
  country: CreativeRefs.country,
18907
- aspectRatio: z73.enum([
19731
+ aspectRatio: z77.enum([
18908
19732
  "9:16",
18909
19733
  "16:9",
18910
19734
  "Auto"
18911
19735
  ]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
18912
- durationSeconds: z73.number().int().min(4).max(30).default(15).describe("Opcional. Duraci\xF3n objetivo: Un solo clip Econ\xF3mico o Medio usa 15s; Un solo clip Pro usa 15s o 30s; Multiescena usa 15s o 30s totales. La combinaci\xF3n de formato y calidad determina la ruta y el costo."),
18913
- videoAngleCount: z73.number().int().min(1).max(3).describe("Cantidad de videos a renderizar: 1, 2 o 3. Es una decisi\xF3n de costo obligatoria: preg\xFAntala incluso cuando creativeSetup.mode=automatic."),
19736
+ durationSeconds: z77.number().int().min(4).max(30).default(15).describe("Opcional. Duraci\xF3n objetivo: Un solo clip Econ\xF3mico o Medio usa 15s; Un solo clip Pro usa 15s o 30s; Multiescena usa 15s o 30s totales. La combinaci\xF3n de formato y calidad determina la ruta y el costo."),
19737
+ videoAngleCount: z77.number().int().min(1).max(3).describe("Cantidad de videos a renderizar: 1, 2 o 3. Es una decisi\xF3n de costo obligatoria: preg\xFAntala incluso cuando creativeSetup.mode=automatic."),
18914
19738
  angleNarratives: PublicNarrativeStyleEnum.array().max(3).optional().describe('Opcional. Narrativa POR \xC1NGULO (posicional). Valores actuales: "review", "ugc_how_to", "ugc_unboxing_chaos", "problem_product_cta" (problema concreto, producto como soluci\xF3n y CTA), "product_showcase", "wearable_showcase", "cinematic", "wild_card", "animated_problem_pixar", "sassy_product_pixar", "market" (narrativa an\xE1lisis de mercado: adapta el video a los patrones ganadores estudiados de la competencia; requiere competitorScanEnabled: true). angleNarratives[i] fuerza la narrativa del \xE1ngulo i; las posiciones restantes las elige la IA. La lista no puede superar videoAngleCount.'),
18915
19739
  creativeSetup: VideoCreativeSetup.describe("Configuraci\xF3n creativa obligatoria. En guided pregunta narrativa, p\xFAblico, presentador y direcci\xF3n antes de confirmar. Usa automatic s\xF3lo si el usuario deleg\xF3 todo expl\xEDcitamente."),
18916
19740
  videoStructure: VideoStructureEnum.default("single_take").describe('Opcional. Formato: "single_take" = Un solo clip (generado completo; puede incluir cambios de plano) o "multi_scene" = Multiescena (varias tomas concatenadas). Default: single_take.'),
18917
19741
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
18918
19742
  videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render: "480p" o "720p". Si se omite, se usa 480p; elige 720p expl\xEDcitamente si necesitas m\xE1s nitidez.'),
18919
- features: z73.array(z73.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
19743
+ features: z77.array(z77.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
18920
19744
  price: CreativeRefs.price,
18921
19745
  offer: CreativeRefs.offer,
18922
19746
  productContext: CreativeRefs.productContext,
18923
19747
  productLabel: CreativeRefs.productLabel,
18924
- cta: z73.string().optional().describe('Opcional. Call-to-action final del video. Ej. "Compra ahora", "Pide el tuyo hoy", "Link en bio". Si se omite, la IA escribe uno.'),
18925
- scriptNotes: z73.string().optional().describe('Opcional. Notas/restricciones para el guion (la IA las usa al redactar). Ej. "No mencionar la marca X", "Tono divertido, no cl\xEDnico", "Mencionar 2x1". NO es el guion literal: creativeSetup.mode=guided activa siempre la revisi\xF3n palabra-por-palabra con get_video_script / approve_video_script.'),
19748
+ cta: z77.string().optional().describe('Opcional. Call-to-action final del video. Ej. "Compra ahora", "Pide el tuyo hoy", "Link en bio". Si se omite, la IA escribe uno.'),
19749
+ scriptNotes: z77.string().optional().describe('Opcional. Notas/restricciones para el guion (la IA las usa al redactar). Ej. "No mencionar la marca X", "Tono divertido, no cl\xEDnico", "Mencionar 2x1". NO es el guion literal: creativeSetup.mode=guided activa siempre la revisi\xF3n palabra-por-palabra con get_video_script / approve_video_script.'),
18926
19750
  creativeGender: CreativeGenderEnum.optional().describe('Opcional. QUI\xC9N APARECE EN PANTALLA en el video: mujer ("female"), hombre ("male") o ambos ("mixed"). NO es la voz; cuando se fija, la voz se alinea sola con el personaje. M\xE1ndalo en cuanto el usuario diga qui\xE9n debe SALIR en el video, con cualquier redacci\xF3n ("quiero una mujer", "que salga un hombre", "protagonista femenina"): si no lo mandas, el g\xE9nero lo inventa la IA y el usuario puede recibir lo contrario de lo que pidi\xF3 sin ning\xFAn aviso. NO lo mandes cuando hable del P\xDABLICO COMPRADOR ("esto es para hombres", "mi p\xFAblico son mujeres", "va dirigido a mam\xE1s"): eso es a qui\xE9n se le vende, no qui\xE9n act\xFAa, y fijarlo ah\xED pinea un protagonista que nadie pidi\xF3. "mixed" solo cuando pida expl\xEDcitamente ambos, y ten en cuenta que no garantiza una mezcla: no fija ning\xFAn g\xE9nero y cada creativo elige su protagonista. No lo preguntes como paso obligatorio. Si creativeSetup.presenter.mode="saved_actor", el personaje guardado manda sobre este campo.'),
18927
19751
  competitorScanEnabled: CreativeRefs.competitorScanEnabled,
18928
- replicateWinnerWhenFound: z73.boolean().optional().describe("Conserva la preferencia de copiar un ganador si existe. false permite estudiar el mercado sin reemplazar un \xE1ngulo por el anuncio ganador. No a\xF1adas una pregunta obligatoria para este campo."),
19752
+ replicateWinnerWhenFound: z77.boolean().optional().describe("Conserva la preferencia de copiar un ganador si existe. false permite estudiar el mercado sin reemplazar un \xE1ngulo por el anuncio ganador. No a\xF1adas una pregunta obligatoria para este campo."),
18929
19753
  brandId: CreativeRefs.brandId
18930
19754
  }).strict();
18931
19755
  var FreeVideoQualityEnum = VideoQualityEnum;
@@ -18943,7 +19767,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
18943
19767
  length: 29
18944
19768
  }, (_, index) => index + 2)
18945
19769
  };
18946
- var FreeVideoModelIdEnum = z73.enum([
19770
+ var FreeVideoModelIdEnum = z77.enum([
18947
19771
  "grok-imagine-video-1-5-preview",
18948
19772
  "minimax-h3/reference-to-video",
18949
19773
  "wan/3-0-video",
@@ -18954,70 +19778,65 @@ var FREE_SELECTABLE_MODEL_IDS = [
18954
19778
  "minimax-h3/reference-to-video",
18955
19779
  "wan/3-0-video"
18956
19780
  ];
18957
- var FreeVideoInput = z73.object({
19781
+ var FreeVideoInput = z77.object({
18958
19782
  images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
18959
- rawPrompt: z73.string().trim().min(1).max(2e3).describe("Prompt o guion exacto del video. Si activas subt\xEDtulos, este mismo texto se usa como guion de subt\xEDtulos."),
19783
+ rawPrompt: z77.string().trim().min(1).max(2e3).describe("Prompt o guion exacto del video. Si activas subt\xEDtulos, este mismo texto se usa como guion de subt\xEDtulos."),
18960
19784
  language: CreativeRefs.language,
18961
19785
  quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
18962
19786
  // Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
18963
19787
  // parsed ONLY so the handler can reject it with a message naming its
18964
19788
  // replacement — dropping it silently would turn a caller's explicit
18965
19789
  // Pro++ pick into a quiet fallback to Wan.
18966
- freeProModel: z73.enum([
19790
+ freeProModel: z77.enum([
18967
19791
  "wan",
18968
19792
  "seedance"
18969
19793
  ]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
18970
19794
  modelId: FreeVideoModelIdEnum.optional().describe('Opcional. Elige expl\xEDcitamente el modelo del registro en vez del default de la calidad: "grok-imagine-video-1-5-preview" (Grok 1.5), "minimax-h3/reference-to-video" (H3 Max) o "wan/3-0-video" (Wan 3.0). Om\xEDtelo para usar el modelo por defecto de la calidad elegida. El modelo determina la duraci\xF3n permitida (Grok 6/8/10/15s, H3 Max 4-15s, Wan 2-30s) y el precio. "bytedance/seedance-2-5" est\xE1 inactivo y se rechaza con un error claro, nunca un 500.'),
18971
- durationSeconds: z73.number().int().min(2).max(30).describe("Duraci\xF3n exacta. Econ\xF3mico: 6, 8, 10 o 15s; Medio: enteros de 4 a 15s; Pro Wan: 2 a 30s; Pro++ Seedance: 4 a 30s."),
19795
+ durationSeconds: z77.number().int().min(2).max(30).describe("Duraci\xF3n exacta. Econ\xF3mico: 6, 8, 10 o 15s; Medio: enteros de 4 a 15s; Pro Wan: 2 a 30s; Pro++ Seedance: 4 a 30s."),
18972
19796
  videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
18973
- generateAiMusic: z73.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
18974
- addSubtitles: z73.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
18975
- idempotencyKey: z73.string().uuid().optional().describe("Opcional. UUID para reintentar exactamente esta misma solicitud sin crear ni cobrar otro video. Reutiliza el mismo valor si el cliente no recibi\xF3 la respuesta.")
19797
+ generateAiMusic: z77.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
19798
+ addSubtitles: z77.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
19799
+ idempotencyKey: z77.string().uuid().optional().describe("Opcional. UUID para reintentar exactamente esta misma solicitud sin crear ni cobrar otro video. Reutiliza el mismo valor si el cliente no recibi\xF3 la respuesta.")
18976
19800
  }).strict();
18977
19801
  var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
18978
- var ImageCreativeSetup = z73.discriminatedUnion("mode", [
18979
- z73.object({
18980
- mode: z73.literal("automatic")
19802
+ var ImageCreativeSetup = z77.discriminatedUnion("mode", [
19803
+ z77.object({
19804
+ mode: z77.literal("automatic")
18981
19805
  }).strict(),
18982
- z73.object({
18983
- mode: z73.literal("guided"),
18984
- creativeArchetype: z73.union([
19806
+ z77.object({
19807
+ mode: z77.literal("guided"),
19808
+ creativeArchetype: z77.union([
18985
19809
  ImageCreativeArchetypeEnum,
18986
- z73.literal("ai_decides")
19810
+ z77.literal("ai_decides")
18987
19811
  ]),
18988
- visualTreatment: z73.union([
19812
+ visualTreatment: z77.union([
18989
19813
  ImageCreativeVisualTreatmentEnum,
18990
- z73.literal("ai_decides")
19814
+ z77.literal("ai_decides")
18991
19815
  ]),
18992
19816
  aspectRatio: ImageCreativeAspectRatioEnum,
18993
- nVariants: z73.union([
18994
- z73.literal(1),
18995
- z73.literal(2),
18996
- z73.literal(3),
18997
- z73.literal(4),
18998
- z73.literal(6)
18999
- ]),
19000
- imageModel: z73.enum([
19001
- "gpt-image-2-5:1k",
19002
- "gpt-image-2-5:2k",
19003
- "gpt-image-2:1k",
19004
- "gpt-image-2:2k"
19817
+ nVariants: z77.union([
19818
+ z77.literal(1),
19819
+ z77.literal(2),
19820
+ z77.literal(3),
19821
+ z77.literal(4),
19822
+ z77.literal(6)
19005
19823
  ]),
19006
- styleMix: z73.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
19007
- generateAdCopy: z73.boolean(),
19008
- competitorScanEnabled: z73.boolean(),
19009
- productContext: z73.string().trim().min(1).max(3e3).nullable(),
19010
- creativeDirection: z73.string().trim().min(1).max(500).nullable(),
19011
- brandColors: z73.string().trim().min(1).max(240).nullable().describe('Colores en lenguaje natural, igual que en el chat web. Ej. "Azul y Dorado". null significa sin colores espec\xEDficos.'),
19012
- headline: z73.string().trim().min(1).max(120).nullable(),
19013
- subheadline: z73.string().trim().min(1).max(160).nullable()
19824
+ imageModel: z77.enum(PUBLIC_IMAGE_QUALITY_INPUTS).describe('Calidad: "image:1k" (Est\xE1ndar) o "image:2k" (Premium). Los tokens gpt-image-2-5:{1k,2k} y gpt-image-2:{1k,2k} se siguen aceptando.'),
19825
+ styleMix: z77.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
19826
+ generateAdCopy: z77.boolean(),
19827
+ competitorScanEnabled: z77.boolean(),
19828
+ productContext: z77.string().trim().min(1).max(3e3).nullable(),
19829
+ creativeDirection: z77.string().trim().min(1).max(500).nullable(),
19830
+ brandColors: z77.string().trim().min(1).max(240).nullable().describe('Colores en lenguaje natural, igual que en el chat web. Ej. "Azul y Dorado". null significa sin colores espec\xEDficos.'),
19831
+ headline: z77.string().trim().min(1).max(120).nullable(),
19832
+ subheadline: z77.string().trim().min(1).max(160).nullable()
19014
19833
  }).strict()
19015
19834
  ]).superRefine((setup, context) => {
19016
19835
  if (setup.mode !== "guided") return;
19017
19836
  const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
19018
19837
  if (needsStyleMix && setup.styleMix === null) {
19019
19838
  context.addIssue({
19020
- code: z73.ZodIssueCode.custom,
19839
+ code: z77.ZodIssueCode.custom,
19021
19840
  path: [
19022
19841
  "styleMix"
19023
19842
  ],
@@ -19026,16 +19845,16 @@ var ImageCreativeSetup = z73.discriminatedUnion("mode", [
19026
19845
  }
19027
19846
  if (!needsStyleMix && setup.styleMix !== null) {
19028
19847
  context.addIssue({
19029
- code: z73.ZodIssueCode.custom,
19848
+ code: z77.ZodIssueCode.custom,
19030
19849
  path: [
19031
19850
  "styleMix"
19032
19851
  ],
19033
19852
  message: "styleMix debe ser null cuando nVariants es 1 o 6."
19034
19853
  });
19035
19854
  }
19036
- if ((setup.imageModel === "gpt-image-2:2k" || setup.imageModel === "gpt-image-2-5:2k") && setup.aspectRatio === "4:5") {
19855
+ if (imageResolutionOf(setup.imageModel) === "2k" && setup.aspectRatio === "4:5") {
19037
19856
  context.addIssue({
19038
- code: z73.ZodIssueCode.custom,
19857
+ code: z77.ZodIssueCode.custom,
19039
19858
  path: [
19040
19859
  "aspectRatio"
19041
19860
  ],
@@ -19043,53 +19862,53 @@ var ImageCreativeSetup = z73.discriminatedUnion("mode", [
19043
19862
  });
19044
19863
  }
19045
19864
  });
19046
- var LandingCreativeSetup = z73.discriminatedUnion("mode", [
19047
- z73.object({
19048
- mode: z73.literal("automatic")
19865
+ var LandingCreativeSetup = z77.discriminatedUnion("mode", [
19866
+ z77.object({
19867
+ mode: z77.literal("automatic")
19049
19868
  }).strict(),
19050
- z73.object({
19051
- mode: z73.literal("guided"),
19869
+ z77.object({
19870
+ mode: z77.literal("guided"),
19052
19871
  landingStrategy: LandingStrategyEnum,
19053
19872
  landingImageFormat: LandingImageFormatEnum,
19054
- competitorScanEnabled: z73.boolean(),
19055
- paymentMethods: z73.string().trim().min(1).max(240).nullable(),
19056
- productContext: z73.string().trim().min(1).max(3e3).nullable(),
19057
- creativeDirection: z73.string().trim().min(1).max(500).nullable(),
19058
- headline: z73.string().trim().min(1).max(120).nullable(),
19059
- subheadline: z73.string().trim().min(1).max(160).nullable()
19873
+ competitorScanEnabled: z77.boolean(),
19874
+ paymentMethods: z77.string().trim().min(1).max(240).nullable(),
19875
+ productContext: z77.string().trim().min(1).max(3e3).nullable(),
19876
+ creativeDirection: z77.string().trim().min(1).max(500).nullable(),
19877
+ headline: z77.string().trim().min(1).max(120).nullable(),
19878
+ subheadline: z77.string().trim().min(1).max(160).nullable()
19060
19879
  }).strict()
19061
19880
  ]);
19062
- var ImageInput = z73.object({
19881
+ var ImageInput = z77.object({
19063
19882
  images: CreativeRefs.images.optional(),
19064
19883
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
19065
- productTitle: z73.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
19066
- primaryAngle: z73.string().min(1).optional().describe('Opcional. \xC1ngulo de venta principal. Si se omite, ProductMaker lo genera y creativeSetup.mode="guided" lo muestra para revisi\xF3n antes de crear las im\xE1genes.'),
19884
+ productTitle: z77.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
19885
+ primaryAngle: z77.string().min(1).optional().describe('Opcional. \xC1ngulo de venta principal. Si se omite, ProductMaker lo genera y creativeSetup.mode="guided" lo muestra para revisi\xF3n antes de crear las im\xE1genes.'),
19067
19886
  buyerPersona: CreativeRefs.buyerPersona,
19068
19887
  language: CreativeRefs.language,
19069
19888
  country: CreativeRefs.country,
19070
19889
  creativeSetup: ImageCreativeSetup.describe("Configuraci\xF3n obligatoria equivalente al wizard web. Usa guided salvo que el usuario delegue expl\xEDcitamente todo; presenta las decisiones guiadas en un \xFAnico checklist compacto."),
19071
19890
  imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
19072
- features: z73.array(z73.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
19891
+ features: z77.array(z77.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
19073
19892
  price: CreativeRefs.price,
19074
- omitPrice: z73.boolean().optional().describe("Pon true \xFAnicamente cuando el usuario pida expl\xEDcitamente una imagen sin precio. Evita que el backend reutilice un precio extra\xEDdo del producto. No lo combines con price ni compareAtPrice."),
19893
+ omitPrice: z77.boolean().optional().describe("Pon true \xFAnicamente cuando el usuario pida expl\xEDcitamente una imagen sin precio. Evita que el backend reutilice un precio extra\xEDdo del producto. No lo combines con price ni compareAtPrice."),
19075
19894
  compareAtPrice: CreativeRefs.compareAtPrice,
19076
19895
  offer: CreativeRefs.offer,
19077
19896
  productLabel: CreativeRefs.productLabel,
19078
19897
  isCombo: CreativeRefs.isCombo,
19079
19898
  brandId: CreativeRefs.brandId
19080
19899
  });
19081
- var EditImageCreativeInput = z73.object({
19082
- taskId: z73.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
19083
- variantIndex: z73.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
19084
- instruction: z73.string().min(1).max(1e3).describe('Qu\xE9 cambiar en esa imagen. Ej. "quita el badge de env\xEDo gratis", "cambia el fondo a blanco".')
19900
+ var EditImageCreativeInput = z77.object({
19901
+ taskId: z77.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
19902
+ variantIndex: z77.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
19903
+ instruction: z77.string().min(1).max(1e3).describe('Qu\xE9 cambiar en esa imagen. Ej. "quita el badge de env\xEDo gratis", "cambia el fondo a blanco".')
19085
19904
  });
19086
- var LandingInput = z73.object({
19905
+ var LandingInput = z77.object({
19087
19906
  images: CreativeRefs.images.optional(),
19088
19907
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
19089
19908
  language: CreativeRefs.language,
19090
19909
  country: CreativeRefs.country,
19091
19910
  creativeSetup: LandingCreativeSetup.describe("Configuraci\xF3n obligatoria de landing cl\xE1sica equivalente al wizard web. No expone landing editable/code mientras siga siendo admin-only."),
19092
- salesAngle: z73.string().optional().describe('Opcional. \xC1ngulo de venta principal. Ej. "Reduce arrugas en 14 d\xEDas". Si se omite, la IA lo deduce de la imagen.'),
19911
+ salesAngle: z77.string().optional().describe('Opcional. \xC1ngulo de venta principal. Ej. "Reduce arrugas en 14 d\xEDas". Si se omite, la IA lo deduce de la imagen.'),
19093
19912
  buyerPersona: CreativeRefs.buyerPersona,
19094
19913
  price: CreativeRefs.price,
19095
19914
  compareAtPrice: CreativeRefs.compareAtPrice,
@@ -19108,7 +19927,7 @@ function resolveImageSetup(setup) {
19108
19927
  },
19109
19928
  aspectRatio: setup.aspectRatio,
19110
19929
  nVariants: setup.nVariants,
19111
- imageModel: setup.imageModel,
19930
+ imageModel: canonicalImageModelInput(setup.imageModel),
19112
19931
  ...setup.nVariants === 6 ? {
19113
19932
  styleMix: true
19114
19933
  } : setup.styleMix === null ? {} : {
@@ -19351,10 +20170,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
19351
20170
  __name(registerCreativeTools, "registerCreativeTools");
19352
20171
 
19353
20172
  // src/tools/creative-variants.ts
19354
- import { z as z74 } from "zod";
20173
+ import { z as z78 } from "zod";
19355
20174
  var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
19356
20175
  var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
19357
- var LandingSectionKeyEnum = z74.enum([
20176
+ var LandingSectionKeyEnum = z78.enum([
19358
20177
  "problem_hook",
19359
20178
  "problem_cost",
19360
20179
  "solution_mechanism",
@@ -19394,24 +20213,24 @@ var LandingSectionKeyEnum = z74.enum([
19394
20213
  "lifestyle_fit",
19395
20214
  "join_lifestyle"
19396
20215
  ]);
19397
- var CreativeVariantKindEnum = z74.enum([
20216
+ var CreativeVariantKindEnum = z78.enum([
19398
20217
  "video",
19399
20218
  "image",
19400
20219
  "landing"
19401
20220
  ]);
19402
- var EstimateCreativeVariantInputBase = z74.object({
19403
- sourceTaskId: z74.string().uuid().describe("ID de la tarea original completada."),
20221
+ var EstimateCreativeVariantInputBase = z78.object({
20222
+ sourceTaskId: z78.string().uuid().describe("ID de la tarea original completada."),
19404
20223
  kind: CreativeVariantKindEnum,
19405
20224
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
19406
20225
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
19407
- nVariants: z74.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
20226
+ nVariants: z78.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
19408
20227
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
19409
- instructions: z74.string().trim().min(1).max(2e3).optional().describe("Opcional para landing. Si se env\xEDa sin sectionKey, el estimado suma la clasificaci\xF3n pagada con IA.")
20228
+ instructions: z78.string().trim().min(1).max(2e3).optional().describe("Opcional para landing. Si se env\xEDa sin sectionKey, el estimado suma la clasificaci\xF3n pagada con IA.")
19410
20229
  }).strict();
19411
20230
  var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
19412
20231
  if (input.kind === "video" && input.nVariants !== void 0) {
19413
20232
  ctx.addIssue({
19414
- code: z74.ZodIssueCode.custom,
20233
+ code: z78.ZodIssueCode.custom,
19415
20234
  path: [
19416
20235
  "nVariants"
19417
20236
  ],
@@ -19421,7 +20240,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
19421
20240
  if (input.kind !== "video") {
19422
20241
  if (input.videoPreset !== void 0) {
19423
20242
  ctx.addIssue({
19424
- code: z74.ZodIssueCode.custom,
20243
+ code: z78.ZodIssueCode.custom,
19425
20244
  path: [
19426
20245
  "videoPreset"
19427
20246
  ],
@@ -19430,7 +20249,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
19430
20249
  }
19431
20250
  if (input.videoResolution !== void 0) {
19432
20251
  ctx.addIssue({
19433
- code: z74.ZodIssueCode.custom,
20252
+ code: z78.ZodIssueCode.custom,
19434
20253
  path: [
19435
20254
  "videoResolution"
19436
20255
  ],
@@ -19440,7 +20259,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
19440
20259
  }
19441
20260
  if (input.kind !== "image" && input.nVariants !== void 0) {
19442
20261
  ctx.addIssue({
19443
- code: z74.ZodIssueCode.custom,
20262
+ code: z78.ZodIssueCode.custom,
19444
20263
  path: [
19445
20264
  "nVariants"
19446
20265
  ],
@@ -19450,7 +20269,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
19450
20269
  if (input.kind !== "landing") {
19451
20270
  if (input.sectionKey !== void 0) {
19452
20271
  ctx.addIssue({
19453
- code: z74.ZodIssueCode.custom,
20272
+ code: z78.ZodIssueCode.custom,
19454
20273
  path: [
19455
20274
  "sectionKey"
19456
20275
  ],
@@ -19459,7 +20278,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
19459
20278
  }
19460
20279
  if (input.instructions !== void 0) {
19461
20280
  ctx.addIssue({
19462
- code: z74.ZodIssueCode.custom,
20281
+ code: z78.ZodIssueCode.custom,
19463
20282
  path: [
19464
20283
  "instructions"
19465
20284
  ],
@@ -19468,31 +20287,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
19468
20287
  }
19469
20288
  }
19470
20289
  });
19471
- var CreateCreativeVariantInputBase = z74.object({
19472
- sourceTaskId: z74.string().uuid().describe("ID de la tarea original completada."),
20290
+ var CreateCreativeVariantInputBase = z78.object({
20291
+ sourceTaskId: z78.string().uuid().describe("ID de la tarea original completada."),
19473
20292
  kind: CreativeVariantKindEnum,
19474
- confirm: z74.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
19475
- clientRequestId: z74.string().uuid().describe("UUID estable y obligatorio para esta intenci\xF3n. Reutil\xEDzalo ante timeouts o transporte ambiguo. Si la API devuelve status=error, una nueva generaci\xF3n exige otra confirmaci\xF3n y un UUID nuevo."),
19476
- angle: z74.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
19477
- buyerPersona: z74.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
19478
- scriptNotes: z74.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
19479
- creativeDirection: z74.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
20293
+ confirm: z78.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
20294
+ clientRequestId: z78.string().uuid().describe("UUID estable y obligatorio para esta intenci\xF3n. Reutil\xEDzalo ante timeouts o transporte ambiguo. Si la API devuelve status=error, una nueva generaci\xF3n exige otra confirmaci\xF3n y un UUID nuevo."),
20295
+ angle: z78.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
20296
+ buyerPersona: z78.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
20297
+ scriptNotes: z78.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
20298
+ creativeDirection: z78.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
19480
20299
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
19481
20300
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
19482
- generateAiMusic: z74.boolean().optional().describe("Opcional para video."),
19483
- nVariants: z74.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
20301
+ generateAiMusic: z78.boolean().optional().describe("Opcional para video."),
20302
+ nVariants: z78.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
19484
20303
  imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
19485
20304
  creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
19486
20305
  visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
19487
20306
  aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
19488
- styleMix: z74.boolean().optional().describe("Opcional para imagen."),
20307
+ styleMix: z78.boolean().optional().describe("Opcional para imagen."),
19489
20308
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
19490
- instructions: z74.string().trim().min(1).max(2e3).optional().describe("Solicitud libre para una nueva secci\xF3n de landing. La IA la clasifica si no env\xEDas sectionKey.")
20309
+ instructions: z78.string().trim().min(1).max(2e3).optional().describe("Solicitud libre para una nueva secci\xF3n de landing. La IA la clasifica si no env\xEDas sectionKey.")
19491
20310
  }).strict();
19492
20311
  var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
19493
20312
  if ((input.kind === "video" || input.kind === "image") && !input.angle) {
19494
20313
  ctx.addIssue({
19495
- code: z74.ZodIssueCode.custom,
20314
+ code: z78.ZodIssueCode.custom,
19496
20315
  path: [
19497
20316
  "angle"
19498
20317
  ],
@@ -19501,7 +20320,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
19501
20320
  }
19502
20321
  if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
19503
20322
  ctx.addIssue({
19504
- code: z74.ZodIssueCode.custom,
20323
+ code: z78.ZodIssueCode.custom,
19505
20324
  path: [
19506
20325
  "instructions"
19507
20326
  ],
@@ -19547,7 +20366,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
19547
20366
  for (const field of fieldsByKind[input.kind]) {
19548
20367
  if (input[field] !== void 0) {
19549
20368
  ctx.addIssue({
19550
- code: z74.ZodIssueCode.custom,
20369
+ code: z78.ZodIssueCode.custom,
19551
20370
  path: [
19552
20371
  field
19553
20372
  ],
@@ -19664,32 +20483,32 @@ function registerCreativeVariantTools(server, api) {
19664
20483
  __name(registerCreativeVariantTools, "registerCreativeVariantTools");
19665
20484
 
19666
20485
  // src/tools/script-review.ts
19667
- import { z as z75 } from "zod";
20486
+ import { z as z79 } from "zod";
19668
20487
  var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
19669
20488
  var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
19670
20489
  var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
19671
- var GetVideoScriptInput = z75.object({
19672
- taskId: z75.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
19673
- angleKey: z75.string().min(1).optional().describe('Clave del \xE1ngulo cuyo guion se quiere leer (formato "angle_0", "angle_1", ...). REQUERIDO para tareas multi-angle: si se omite, el backend resuelve a "angle_0" LITERAL (no "el primer pendiente"), as\xED que en multi-angle donde angle_0 ya est\xE9 aprobado/saltado obtendr\xEDas status="approved" y nunca alcanzar\xEDas el \xE1ngulo realmente pendiente. Para single-angle puede omitirse.')
20490
+ var GetVideoScriptInput = z79.object({
20491
+ taskId: z79.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
20492
+ angleKey: z79.string().min(1).optional().describe('Clave del \xE1ngulo cuyo guion se quiere leer (formato "angle_0", "angle_1", ...). REQUERIDO para tareas multi-angle: si se omite, el backend resuelve a "angle_0" LITERAL (no "el primer pendiente"), as\xED que en multi-angle donde angle_0 ya est\xE9 aprobado/saltado obtendr\xEDas status="approved" y nunca alcanzar\xEDas el \xE1ngulo realmente pendiente. Para single-angle puede omitirse.')
19674
20493
  }).strict();
19675
20494
  var VIDEO_SCRIPT_APPROVAL_MAX_SCENES2 = 50;
19676
20495
  var VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2 = 2e3;
19677
- var ApproveSceneEdit = z75.object({
19678
- index: z75.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
19679
- dialogue: z75.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
20496
+ var ApproveSceneEdit = z79.object({
20497
+ index: z79.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
20498
+ dialogue: z79.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
19680
20499
  message: "dialogue no puede ser s\xF3lo espacios"
19681
20500
  }).describe("Di\xE1logo final de la escena. NO puede estar vac\xEDo ni ser s\xF3lo espacios. Puede ser el original sin cambios o la edici\xF3n del usuario.")
19682
20501
  }).strict();
19683
- var ApproveVideoScriptInput = z75.object({
19684
- taskId: z75.string().min(1).describe("ID de la tarea."),
19685
- angleKey: z75.string().trim().min(1).max(120).optional().describe('Mismo angleKey usado en get_video_script. REQUERIDO en multi-angle (si se omite el backend resuelve a "angle_0" literal). En single-angle puede omitirse.'),
19686
- scenes: z75.array(ApproveSceneEdit).min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_SCENES2).describe("Escenas con los di\xE1logos finales. El backend mergea por `index` \u2014 las escenas NO incluidas conservan el di\xE1logo original. Debe haber entre 1 y 50 entradas. Para cada entrada que mandes con un dialogue distinto del original, el backend valida minWords \u2264 words \u2264 maxWords y rechaza con 400 si te sales del rango.")
20502
+ var ApproveVideoScriptInput = z79.object({
20503
+ taskId: z79.string().min(1).describe("ID de la tarea."),
20504
+ angleKey: z79.string().trim().min(1).max(120).optional().describe('Mismo angleKey usado en get_video_script. REQUERIDO en multi-angle (si se omite el backend resuelve a "angle_0" literal). En single-angle puede omitirse.'),
20505
+ scenes: z79.array(ApproveSceneEdit).min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_SCENES2).describe("Escenas con los di\xE1logos finales. El backend mergea por `index` \u2014 las escenas NO incluidas conservan el di\xE1logo original. Debe haber entre 1 y 50 entradas. Para cada entrada que mandes con un dialogue distinto del original, el backend valida minWords \u2264 words \u2264 maxWords y rechaza con 400 si te sales del rango.")
19687
20506
  }).strict();
19688
- var RegenerateVideoScriptInput = z75.object({
19689
- taskId: z75.string().min(1).describe("ID de la tarea."),
19690
- angleKey: z75.string().min(1).describe('Clave del \xE1ngulo a regenerar. Single-angle: pasa "angle_0". Multi-angle: el mismo que devuelve get_video_script. NO se puede omitir \u2014 el backend lo exige siempre.'),
20507
+ var RegenerateVideoScriptInput = z79.object({
20508
+ taskId: z79.string().min(1).describe("ID de la tarea."),
20509
+ angleKey: z79.string().min(1).describe('Clave del \xE1ngulo a regenerar. Single-angle: pasa "angle_0". Multi-angle: el mismo que devuelve get_video_script. NO se puede omitir \u2014 el backend lo exige siempre.'),
19691
20510
  narrativeStyle: NarrativeStyleEnum.describe('Narrativa para el nuevo guion. Incluye valores hist\xF3ricos porque esta herramienta tambi\xE9n regenera tareas antiguas. REQUERIDO \u2014 el backend NO acepta "mantener la actual"; siempre tienes que elegir una. Si el usuario quiere re-rolear con la misma narrativa, pasa la que ya tiene el \xE1ngulo (la ves en get_video_script o en get_task_status).'),
19692
- narrativeSelection: z75.enum([
20511
+ narrativeSelection: z79.enum([
19693
20512
  "market",
19694
20513
  "guided"
19695
20514
  ]).optional().describe("Elecci\xF3n expl\xEDcita del usuario: market usa el estudio de mercado disponible; guided usa la narrativa elegida. Omitir conserva el comportamiento existente.")
@@ -19770,14 +20589,14 @@ function registerScriptReviewTools(server, api) {
19770
20589
  __name(registerScriptReviewTools, "registerScriptReviewTools");
19771
20590
 
19772
20591
  // src/tools/connections.ts
19773
- import { z as z76 } from "zod";
20592
+ import { z as z80 } from "zod";
19774
20593
  var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
19775
20594
  var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
19776
20595
  var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
19777
20596
  var listMetaDestinationsGuidance = getProductMakerCapabilityModelGuidance("list_meta_destinations");
19778
20597
  var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list_tiktok_advertisers");
19779
20598
  function registerConnectionTools(server, api) {
19780
- server.tool("list_shopify_shops", listShopifyShopsGuidance.summary + " Si la lista est\xE1 vac\xEDa, dile al usuario que conecte una tienda en productmaker.app/integrations antes de intentar publicar.", z76.object({}).shape, READS_INTERNAL, async () => {
20599
+ server.tool("list_shopify_shops", listShopifyShopsGuidance.summary + " Si la lista est\xE1 vac\xEDa, dile al usuario que conecte una tienda en productmaker.app/integrations antes de intentar publicar.", z80.object({}).shape, READS_INTERNAL, async () => {
19781
20600
  try {
19782
20601
  const r = await api.getJson("/v1/shopify/shops");
19783
20602
  return asText(r);
@@ -19785,10 +20604,10 @@ function registerConnectionTools(server, api) {
19785
20604
  throw translateError(e);
19786
20605
  }
19787
20606
  });
19788
- server.tool("list_shopify_products", listShopifyProductsGuidance.summary + ' Usa el `id` devuelto junto con `publicationMode="existing"` en `publish_to_shopify`. Si `taskId` se proporciona, la respuesta tambi\xE9n indica el producto publicado actualmente para esa tarea y tienda. No modifica Shopify.', z76.object({
19789
- shopDomain: z76.string().min(3).max(120),
19790
- query: z76.string().trim().max(120).optional(),
19791
- taskId: z76.string().uuid().optional()
20607
+ server.tool("list_shopify_products", listShopifyProductsGuidance.summary + ' Usa el `id` devuelto junto con `publicationMode="existing"` en `publish_to_shopify`. Si `taskId` se proporciona, la respuesta tambi\xE9n indica el producto publicado actualmente para esa tarea y tienda. No modifica Shopify.', z80.object({
20608
+ shopDomain: z80.string().min(3).max(120),
20609
+ query: z80.string().trim().max(120).optional(),
20610
+ taskId: z80.string().uuid().optional()
19792
20611
  }).shape, READS_EXTERNAL, async ({ shopDomain, query, taskId }) => {
19793
20612
  try {
19794
20613
  const params = new URLSearchParams({
@@ -19802,7 +20621,7 @@ function registerConnectionTools(server, api) {
19802
20621
  throw translateError(e);
19803
20622
  }
19804
20623
  });
19805
- server.tool("list_meta_ad_accounts", listMetaAdAccountsGuidance.summary + " Para publicar, prefiere `list_meta_destinations`, que tambi\xE9n devuelve el portfolio y las p\xE1ginas disponibles. Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar Meta en productmaker.app/integrations.", z76.object({}).shape, READS_EXTERNAL, async () => {
20624
+ server.tool("list_meta_ad_accounts", listMetaAdAccountsGuidance.summary + " Para publicar, prefiere `list_meta_destinations`, que tambi\xE9n devuelve el portfolio y las p\xE1ginas disponibles. Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar Meta en productmaker.app/integrations.", z80.object({}).shape, READS_EXTERNAL, async () => {
19806
20625
  try {
19807
20626
  const r = await api.getJson("/v1/facebook/ad-accounts");
19808
20627
  return asText(r);
@@ -19812,7 +20631,7 @@ function registerConnectionTools(server, api) {
19812
20631
  });
19813
20632
  server.registerTool("list_meta_destinations", {
19814
20633
  description: listMetaDestinationsGuidance.summary + " Es obligatorio llamar esta herramienta antes de publicar, mostrar las opciones y enviar al publicador el `portfolioId`, `adAccountId` y `pageId` elegidos; nunca elijas silenciosamente la primera p\xE1gina o cuenta. No modifica Meta.",
19815
- inputSchema: z76.object({}).shape,
20634
+ inputSchema: z80.object({}).shape,
19816
20635
  annotations: READS_EXTERNAL,
19817
20636
  _meta: {
19818
20637
  "openai/widgetAccessible": true
@@ -19825,7 +20644,7 @@ function registerConnectionTools(server, api) {
19825
20644
  throw translateError(e);
19826
20645
  }
19827
20646
  });
19828
- server.tool("list_tiktok_advertisers", listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.", z76.object({}).shape, READS_EXTERNAL, async () => {
20647
+ server.tool("list_tiktok_advertisers", listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.", z80.object({}).shape, READS_EXTERNAL, async () => {
19829
20648
  try {
19830
20649
  const r = await api.getJson("/v1/tiktok/advertisers");
19831
20650
  return asText(r);
@@ -19837,10 +20656,10 @@ function registerConnectionTools(server, api) {
19837
20656
  __name(registerConnectionTools, "registerConnectionTools");
19838
20657
 
19839
20658
  // src/tools/actors.ts
19840
- import { z as z77 } from "zod";
20659
+ import { z as z81 } from "zod";
19841
20660
  var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
19842
20661
  function registerActorTools(server, api) {
19843
- server.tool("list_actors", listActorsGuidance.summary + " Devuelve id, nombre, descripci\xF3n, g\xE9nero y voz. Usa el `id` como `actorId` al crear o editar una tarea. Solo aparecen los personajes listos para usar; si la lista est\xE1 vac\xEDa, dile al usuario que cree uno en productmaker.app antes de intentar asignarlo. No modifica nada.", z77.object({}).shape, READS_INTERNAL, async () => {
20662
+ server.tool("list_actors", listActorsGuidance.summary + " Devuelve id, nombre, descripci\xF3n, g\xE9nero y voz. Usa el `id` como `actorId` al crear o editar una tarea. Solo aparecen los personajes listos para usar; si la lista est\xE1 vac\xEDa, dile al usuario que cree uno en productmaker.app antes de intentar asignarlo. No modifica nada.", z81.object({}).shape, READS_INTERNAL, async () => {
19844
20663
  try {
19845
20664
  const rows = await api.getJson("/v1/actors");
19846
20665
  const actors = (Array.isArray(rows) ? rows : []).filter((actor) => actor.status === "ready").map(({ id, name, description, gender, voiceId }) => ({
@@ -19861,7 +20680,7 @@ function registerActorTools(server, api) {
19861
20680
  __name(registerActorTools, "registerActorTools");
19862
20681
 
19863
20682
  // src/tools/publish.ts
19864
- import { z as z78 } from "zod";
20683
+ import { z as z82 } from "zod";
19865
20684
 
19866
20685
  // src/tools/stable-uuid.ts
19867
20686
  import { createHash as createHash2 } from "crypto";
@@ -19933,40 +20752,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
19933
20752
  var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
19934
20753
  var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
19935
20754
  var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
19936
- var ShopifyInput = z78.object({
19937
- taskId: z78.string().min(1),
19938
- shopDomain: z78.string().min(1),
20755
+ var ShopifyInput = z82.object({
20756
+ taskId: z82.string().min(1),
20757
+ shopDomain: z82.string().min(1),
19939
20758
  /** Override: number of landing images to include. Default = ALL images the
19940
20759
  * task generated (the MCP fetches /v1/results first to count). Bounded
19941
20760
  * generously here; the backend validates each index against
19942
20761
  * landing.images.length and rejects out-of-range. */
19943
- numLandingImages: z78.number().int().min(1).max(20).optional(),
19944
- variantIndex: z78.number().int().min(0).optional(),
20762
+ numLandingImages: z82.number().int().min(1).max(20).optional(),
20763
+ variantIndex: z82.number().int().min(0).optional(),
19945
20764
  /** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
19946
20765
  * When true, the landing renders variant-picker pills; when false, it ships
19947
20766
  * a single-option product page. Defaults to false. */
19948
- showVariantPicker: z78.boolean().optional(),
20767
+ showVariantPicker: z82.boolean().optional(),
19949
20768
  /** Default `auto` updates the product previously published for this task and
19950
20769
  * shop. Use `existing` with targetProductId to choose another product, or
19951
20770
  * `new` only when the user explicitly wants a duplicate/new listing. */
19952
- publicationMode: z78.enum([
20771
+ publicationMode: z82.enum([
19953
20772
  "auto",
19954
20773
  "existing",
19955
20774
  "new"
19956
20775
  ]).optional(),
19957
20776
  /** Shopify product GID, numeric id, or admin product URL. Required when
19958
20777
  * publicationMode is `existing`. */
19959
- targetProductId: z78.string().trim().min(1).max(300).optional(),
20778
+ targetProductId: z82.string().trim().min(1).max(300).optional(),
19960
20779
  /** Add an announcement bar text above add-to-cart (optional). */
19961
- announcementBarEnabled: z78.boolean().optional(),
19962
- announcementBarText: z78.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
20780
+ announcementBarEnabled: z82.boolean().optional(),
20781
+ announcementBarText: z82.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
19963
20782
  commerceCorrection: PublishCommerceCorrectionSchema.optional().describe("Complete seller-confirmed commerce values, with the revision and fingerprint returned in recovery. Never invent missing prices or convert currency."),
19964
- confirmed: z78.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
20783
+ confirmed: z82.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
19965
20784
  });
19966
20785
  var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
19967
20786
  if (value.commerceCorrection && value.confirmed !== true) {
19968
20787
  ctx.addIssue({
19969
- code: z78.ZodIssueCode.custom,
20788
+ code: z82.ZodIssueCode.custom,
19970
20789
  path: [
19971
20790
  "confirmed"
19972
20791
  ],
@@ -19975,7 +20794,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
19975
20794
  }
19976
20795
  if (value.announcementBarEnabled && !value.announcementBarText) {
19977
20796
  ctx.addIssue({
19978
- code: z78.ZodIssueCode.custom,
20797
+ code: z82.ZodIssueCode.custom,
19979
20798
  path: [
19980
20799
  "announcementBarText"
19981
20800
  ],
@@ -19984,7 +20803,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
19984
20803
  }
19985
20804
  if (!value.announcementBarEnabled && value.announcementBarText) {
19986
20805
  ctx.addIssue({
19987
- code: z78.ZodIssueCode.custom,
20806
+ code: z82.ZodIssueCode.custom,
19988
20807
  path: [
19989
20808
  "announcementBarText"
19990
20809
  ],
@@ -19998,91 +20817,91 @@ function parseShopifyInput(rawInput) {
19998
20817
  return parsed.data;
19999
20818
  }
20000
20819
  __name(parseShopifyInput, "parseShopifyInput");
20001
- var McpCampaignConfig = z78.object({
20820
+ var McpCampaignConfig = z82.object({
20002
20821
  /** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
20003
20822
  * converts to the account currency server-side. Do NOT pre-convert: on a COP
20004
20823
  * account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
20005
- dailyBudgetUsd: z78.number().positive().optional(),
20824
+ dailyBudgetUsd: z82.number().positive().optional(),
20006
20825
  /** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
20007
20826
  * normalizes at validation). Meta accepts max 1 (single-country ad set).
20008
20827
  * TikTok takes only the first entry. */
20009
- targetCountries: z78.array(CountryIso2Schema).max(1).optional(),
20010
- campaignName: z78.string().trim().min(1).max(100).optional()
20828
+ targetCountries: z82.array(CountryIso2Schema).max(1).optional(),
20829
+ campaignName: z82.string().trim().min(1).max(100).optional()
20011
20830
  });
20012
20831
  var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
20013
- var MetaInput = z78.object({
20014
- taskId: z78.string().min(1),
20832
+ var MetaInput = z82.object({
20833
+ taskId: z82.string().min(1),
20015
20834
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
20016
- portfolioId: z78.string().trim().min(1),
20835
+ portfolioId: z82.string().trim().min(1),
20017
20836
  /** Exact Facebook Page selected from `list_meta_destinations`. */
20018
- pageId: z78.string().trim().min(1),
20837
+ pageId: z82.string().trim().min(1),
20019
20838
  adAccountId: McpAdAccountId,
20020
- pixelId: z78.string().min(1).optional(),
20021
- landingUrl: z78.string().url().optional(),
20839
+ pixelId: z82.string().min(1).optional(),
20840
+ landingUrl: z82.string().url().optional(),
20022
20841
  /** Select which angles to publish by 0-based index. Omit to publish all
20023
20842
  * successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
20024
- angleIndexes: z78.array(z78.number().int().nonnegative()).optional(),
20843
+ angleIndexes: z82.array(z82.number().int().nonnegative()).optional(),
20025
20844
  campaignConfig: McpCampaignConfig.optional(),
20026
20845
  /** Override the ad's primary text (body copy). If omitted, ProductMaker
20027
20846
  * uses the auto-generated copy attached to the task. Capped at 500 chars
20028
20847
  * (Meta's primary-text limit). */
20029
- primaryText: z78.string().trim().min(1).max(500).optional(),
20848
+ primaryText: z82.string().trim().min(1).max(500).optional(),
20030
20849
  /** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
20031
20850
  * (wa.me) instead of a landing page. */
20032
- phoneNumber: z78.string().min(8).max(32).optional()
20851
+ phoneNumber: z82.string().min(8).max(32).optional()
20033
20852
  });
20034
- var GroupedTaskSource = z78.object({
20035
- type: z78.literal("task"),
20036
- taskId: z78.string().min(1),
20037
- angleIndex: z78.number().int().min(0).optional(),
20038
- videoVariant: z78.enum([
20853
+ var GroupedTaskSource = z82.object({
20854
+ type: z82.literal("task"),
20855
+ taskId: z82.string().min(1),
20856
+ angleIndex: z82.number().int().min(0).optional(),
20857
+ videoVariant: z82.enum([
20039
20858
  "with_subtitles",
20040
20859
  "without_subtitles"
20041
20860
  ]).optional(),
20042
- imageVariantIndex: z78.number().int().min(0).optional()
20043
- });
20044
- var GroupedMediaSource = z78.object({
20045
- type: z78.literal("media"),
20046
- url: z78.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
20047
- path: z78.string().min(1).optional().describe('Local file path only when this MCP runs over stdio. On the hosted MCP, call request_media_upload and then use source.type="asset".'),
20048
- thumbnailUrl: z78.string().url().optional(),
20049
- thumbnailPath: z78.string().min(1).optional()
20861
+ imageVariantIndex: z82.number().int().min(0).optional()
20862
+ });
20863
+ var GroupedMediaSource = z82.object({
20864
+ type: z82.literal("media"),
20865
+ url: z82.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
20866
+ path: z82.string().min(1).optional().describe('Local file path only when this MCP runs over stdio. On the hosted MCP, call request_media_upload and then use source.type="asset".'),
20867
+ thumbnailUrl: z82.string().url().optional(),
20868
+ thumbnailPath: z82.string().min(1).optional()
20050
20869
  }).refine((value) => Boolean(value.url) !== Boolean(value.path), {
20051
20870
  message: "media source needs exactly one of `url` or `path`"
20052
20871
  }).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
20053
20872
  message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
20054
20873
  });
20055
- var GroupedUploadedAssetSource = z78.object({
20056
- type: z78.literal("asset"),
20874
+ var GroupedUploadedAssetSource = z82.object({
20875
+ type: z82.literal("asset"),
20057
20876
  /** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
20058
- assetId: z78.string().uuid(),
20059
- thumbnailAssetId: z78.string().uuid().optional()
20877
+ assetId: z82.string().uuid(),
20878
+ thumbnailAssetId: z82.string().uuid().optional()
20060
20879
  });
20061
- var GroupedCreative = z78.object({
20062
- type: z78.enum([
20880
+ var GroupedCreative = z82.object({
20881
+ type: z82.enum([
20063
20882
  "image",
20064
20883
  "video"
20065
20884
  ]),
20066
- source: z78.union([
20885
+ source: z82.union([
20067
20886
  GroupedTaskSource,
20068
20887
  GroupedMediaSource,
20069
20888
  GroupedUploadedAssetSource
20070
20889
  ]),
20071
- title: z78.string().max(120).optional(),
20072
- description: z78.string().max(500).optional(),
20890
+ title: z82.string().max(120).optional(),
20891
+ description: z82.string().max(500).optional(),
20073
20892
  cta: MetaCtaType.optional(),
20074
- creativeId: z78.string().min(1).optional()
20893
+ creativeId: z82.string().min(1).optional()
20075
20894
  });
20076
- var GroupedCampaignConfigBase = z78.object({
20895
+ var GroupedCampaignConfigBase = z82.object({
20077
20896
  campaignType: MetaCampaignType.default("sales"),
20078
20897
  optimizationMode: MetaOptimizationMode.default("advantage_plus"),
20079
20898
  budgetMode: MetaBudgetMode.optional(),
20080
- campaignDailyBudget: z78.number().int().positive().optional(),
20081
- adSets: z78.array(z78.object({
20082
- tempId: z78.string().min(1).max(80),
20083
- name: z78.string().min(1).max(100),
20084
- dailyBudget: z78.number().int().positive().optional(),
20085
- creativeIds: z78.array(z78.string().min(1)).min(1)
20899
+ campaignDailyBudget: z82.number().int().positive().optional(),
20900
+ adSets: z82.array(z82.object({
20901
+ tempId: z82.string().min(1).max(80),
20902
+ name: z82.string().min(1).max(100),
20903
+ dailyBudget: z82.number().int().positive().optional(),
20904
+ creativeIds: z82.array(z82.string().min(1)).min(1)
20086
20905
  })).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
20087
20906
  /**
20088
20907
  * Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
@@ -20090,17 +20909,17 @@ var GroupedCampaignConfigBase = z78.object({
20090
20909
  * opaque `invalid_literal` and made the WhatsApp destination — supported by
20091
20910
  * the API since #849 — unreachable from this tool.
20092
20911
  */
20093
- destination: z78.discriminatedUnion("type", [
20094
- z78.object({
20095
- type: z78.literal("landing"),
20096
- landingUrl: z78.string().url()
20912
+ destination: z82.discriminatedUnion("type", [
20913
+ z82.object({
20914
+ type: z82.literal("landing"),
20915
+ landingUrl: z82.string().url()
20097
20916
  }),
20098
- z78.object({
20099
- type: z78.literal("whatsapp"),
20100
- phoneNumber: z78.string().min(8).max(32)
20917
+ z82.object({
20918
+ type: z82.literal("whatsapp"),
20919
+ phoneNumber: z82.string().min(8).max(32)
20101
20920
  })
20102
20921
  ]),
20103
- saveAsDefault: z78.boolean().default(false),
20922
+ saveAsDefault: z82.boolean().default(false),
20104
20923
  budgetPolicy: MetaBudgetPolicy.optional()
20105
20924
  });
20106
20925
  function resolveBudgetMode(value) {
@@ -20114,7 +20933,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
20114
20933
  const budgetMode = resolveBudgetMode(value);
20115
20934
  if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
20116
20935
  ctx.addIssue({
20117
- code: z78.ZodIssueCode.custom,
20936
+ code: z82.ZodIssueCode.custom,
20118
20937
  path: [
20119
20938
  "campaignDailyBudget"
20120
20939
  ],
@@ -20125,7 +20944,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
20125
20944
  value.adSets.forEach((adSet, index) => {
20126
20945
  if (adSet.dailyBudget === void 0) {
20127
20946
  ctx.addIssue({
20128
- code: z78.ZodIssueCode.custom,
20947
+ code: z82.ZodIssueCode.custom,
20129
20948
  path: [
20130
20949
  "adSets",
20131
20950
  index,
@@ -20140,28 +20959,28 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
20140
20959
  ...value,
20141
20960
  budgetMode: resolveBudgetMode(value)
20142
20961
  }));
20143
- var PublishCreativesToMetaInputBase = z78.object({
20144
- creatives: z78.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
20962
+ var PublishCreativesToMetaInputBase = z82.object({
20963
+ creatives: z82.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
20145
20964
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
20146
- portfolioId: z78.string().trim().min(1),
20965
+ portfolioId: z82.string().trim().min(1),
20147
20966
  /** Exact Facebook Page selected from `list_meta_destinations`. */
20148
- pageId: z78.string().trim().min(1),
20967
+ pageId: z82.string().trim().min(1),
20149
20968
  adAccountId: McpAdAccountId,
20150
- pixelId: z78.string().min(1).optional(),
20969
+ pixelId: z82.string().min(1).optional(),
20151
20970
  /** Required unless `campaignConfig.destination` is whatsapp — see the
20152
20971
  * superRefine below. Mirrors the API's `FacebookCreateCampaignFromTasksBodySchema`. */
20153
- landingUrl: z78.string().url().optional(),
20972
+ landingUrl: z82.string().url().optional(),
20154
20973
  /** ISO-2 code or resolvable country name — mirrors the API contract
20155
20974
  * (CountryIso2Schema), which normalizes names to alpha-2 at validation. */
20156
20975
  targetCountry: CountryIso2Schema,
20157
- campaignName: z78.string().trim().min(1).max(100),
20976
+ campaignName: z82.string().trim().min(1).max(100),
20158
20977
  campaignConfig: GroupedCampaignConfig.optional()
20159
20978
  });
20160
20979
  var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
20161
20980
  const destination = value.campaignConfig?.destination;
20162
20981
  if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
20163
20982
  ctx.addIssue({
20164
- code: z78.ZodIssueCode.custom,
20983
+ code: z82.ZodIssueCode.custom,
20165
20984
  path: [
20166
20985
  "landingUrl"
20167
20986
  ],
@@ -20170,7 +20989,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
20170
20989
  }
20171
20990
  if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
20172
20991
  ctx.addIssue({
20173
- code: z78.ZodIssueCode.custom,
20992
+ code: z82.ZodIssueCode.custom,
20174
20993
  path: [
20175
20994
  "campaignConfig",
20176
20995
  "destination",
@@ -20189,16 +21008,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
20189
21008
  }
20190
21009
  return value;
20191
21010
  });
20192
- var PresignUploadResponseSchema = z78.object({
20193
- uploadUrl: z78.string().url().refine((value) => {
21011
+ var PresignUploadResponseSchema = z82.object({
21012
+ uploadUrl: z82.string().url().refine((value) => {
20194
21013
  const url = new URL(value);
20195
21014
  return !url.username && !url.password && url.protocol === "https:";
20196
21015
  }, "presigned upload URL must be HTTPS without embedded credentials"),
20197
- publicUrl: z78.string().url().refine((value) => {
21016
+ publicUrl: z82.string().url().refine((value) => {
20198
21017
  const url = new URL(value);
20199
21018
  return !url.username && !url.password;
20200
21019
  }, "public media URL must not contain embedded credentials"),
20201
- stagingAssetId: z78.string().uuid()
21020
+ stagingAssetId: z82.string().uuid()
20202
21021
  });
20203
21022
  async function uploadResolvedMedia(api, media, assetRole) {
20204
21023
  if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
@@ -20223,16 +21042,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
20223
21042
  return uploadResolvedMedia(api, media, assetRole);
20224
21043
  }
20225
21044
  __name(resolveAndUploadMedia, "resolveAndUploadMedia");
20226
- var TikTokInput = z78.object({
20227
- taskId: z78.string().min(1),
20228
- advertiserId: z78.string().min(1),
20229
- pixelId: z78.string().min(1).optional(),
20230
- landingUrl: z78.string().url().optional(),
20231
- angleIndexes: z78.array(z78.number().int().nonnegative()).optional(),
21045
+ var TikTokInput = z82.object({
21046
+ taskId: z82.string().min(1),
21047
+ advertiserId: z82.string().min(1),
21048
+ pixelId: z82.string().min(1).optional(),
21049
+ landingUrl: z82.string().url().optional(),
21050
+ angleIndexes: z82.array(z82.number().int().nonnegative()).optional(),
20232
21051
  campaignConfig: McpCampaignConfig.optional(),
20233
21052
  /** Override the ad's description (TikTok's body copy). If omitted,
20234
21053
  * ProductMaker uses the auto-generated copy attached to the task. */
20235
- primaryText: z78.string().trim().min(1).max(500).optional()
21054
+ primaryText: z82.string().trim().min(1).max(500).optional()
20236
21055
  });
20237
21056
  function registerPublishTools(server, api, opts = {}) {
20238
21057
  const transport = opts.transport ?? "http";
@@ -20560,39 +21379,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
20560
21379
 
20561
21380
  // src/tools/meta-upload.ts
20562
21381
  import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
20563
- import { z as z79 } from "zod";
21382
+ import { z as z83 } from "zod";
20564
21383
  var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
20565
- var UploadSessionInputBase = z79.object({
20566
- mediaKind: z79.enum([
21384
+ var UploadSessionInputBase = z83.object({
21385
+ mediaKind: z83.enum([
20567
21386
  "image",
20568
21387
  "video",
20569
21388
  "mixed"
20570
21389
  ]).default("mixed").describe("The kind of file the user will select. Use image for product references and landing pages, video for a single video, and mixed only when the consumer supports both."),
20571
- assetRole: z79.enum([
21390
+ assetRole: z83.enum([
20572
21391
  "media",
20573
21392
  "thumbnail"
20574
21393
  ]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
20575
- uploadPurpose: z79.enum([
21394
+ uploadPurpose: z83.enum([
20576
21395
  "product_reference",
20577
21396
  "creative",
20578
21397
  "generic"
20579
21398
  ]).default("generic").describe("The user's purpose for these files. Use product_reference for a product photo used by tasks or landings, creative for media that will become an ad or creative, and generic only when neither applies."),
20580
- maxFiles: z79.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
21399
+ maxFiles: z83.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
20581
21400
  });
20582
- var OpenAiFileReference = z79.object({
20583
- download_url: z79.string().url().describe("Required by ChatGPT's openai/fileParams schema. The App prefers getFileDownloadUrl(file_id) for a fresh URL, and the server never fetches this value."),
20584
- file_id: z79.string().min(1),
20585
- mime_type: z79.string().min(1).optional(),
20586
- file_name: z79.string().min(1).optional()
21401
+ var OpenAiFileReference = z83.object({
21402
+ download_url: z83.string().url().describe("Required by ChatGPT's openai/fileParams schema. The App prefers getFileDownloadUrl(file_id) for a fresh URL, and the server never fetches this value."),
21403
+ file_id: z83.string().min(1),
21404
+ mime_type: z83.string().min(1).optional(),
21405
+ file_name: z83.string().min(1).optional()
20587
21406
  });
20588
21407
  var UploadSessionToolInputShape = {
20589
21408
  ...UploadSessionInputBase.shape,
20590
- files: z79.array(OpenAiFileReference).max(10).optional().describe("Optional OpenAI-hosted file references provided by ChatGPT. They are only metadata for the UI bridge and are never forwarded to ProductMaker.")
21409
+ files: z83.array(OpenAiFileReference).max(10).optional().describe("Optional OpenAI-hosted file references provided by ChatGPT. They are only metadata for the UI bridge and are never forwarded to ProductMaker.")
20591
21410
  };
20592
- var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
21411
+ var UploadSessionToolInput = z83.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
20593
21412
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
20594
21413
  ctx.addIssue({
20595
- code: z79.ZodIssueCode.custom,
21414
+ code: z83.ZodIssueCode.custom,
20596
21415
  path: [
20597
21416
  "mediaKind"
20598
21417
  ],
@@ -20601,7 +21420,7 @@ var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine
20601
21420
  }
20602
21421
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
20603
21422
  ctx.addIssue({
20604
- code: z79.ZodIssueCode.custom,
21423
+ code: z83.ZodIssueCode.custom,
20605
21424
  path: [
20606
21425
  "maxFiles"
20607
21426
  ],
@@ -20610,7 +21429,7 @@ var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine
20610
21429
  }
20611
21430
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
20612
21431
  ctx.addIssue({
20613
- code: z79.ZodIssueCode.custom,
21432
+ code: z83.ZodIssueCode.custom,
20614
21433
  path: [
20615
21434
  "maxFiles"
20616
21435
  ],
@@ -20618,38 +21437,38 @@ var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine
20618
21437
  });
20619
21438
  }
20620
21439
  });
20621
- var UploadSessionResponse = z79.object({
20622
- sessionId: z79.string().uuid(),
20623
- uploadPageUrl: z79.string().url(),
20624
- mediaKind: z79.enum([
21440
+ var UploadSessionResponse = z83.object({
21441
+ sessionId: z83.string().uuid(),
21442
+ uploadPageUrl: z83.string().url(),
21443
+ mediaKind: z83.enum([
20625
21444
  "image",
20626
21445
  "video",
20627
21446
  "mixed"
20628
21447
  ]),
20629
- assetRole: z79.enum([
21448
+ assetRole: z83.enum([
20630
21449
  "media",
20631
21450
  "thumbnail"
20632
21451
  ]),
20633
- maxFiles: z79.number().int().positive(),
20634
- expiresAt: z79.string().datetime()
21452
+ maxFiles: z83.number().int().positive(),
21453
+ expiresAt: z83.string().datetime()
20635
21454
  });
20636
- var UploadStatusInput = z79.object({
20637
- sessionId: z79.string().uuid().describe("The sessionId returned by request_media_upload.")
21455
+ var UploadStatusInput = z83.object({
21456
+ sessionId: z83.string().uuid().describe("The sessionId returned by request_media_upload.")
20638
21457
  });
20639
- var UniversalUploadStatusResponse = z79.discriminatedUnion("status", [
20640
- z79.object({
20641
- status: z79.literal("pending"),
20642
- assets: z79.array(z79.never()).length(0)
21458
+ var UniversalUploadStatusResponse = z83.discriminatedUnion("status", [
21459
+ z83.object({
21460
+ status: z83.literal("pending"),
21461
+ assets: z83.array(z83.never()).length(0)
20643
21462
  }),
20644
- z79.object({
20645
- status: z79.literal("uploaded"),
20646
- assets: z79.array(z79.object({
20647
- assetId: z79.string().uuid(),
20648
- mediaKind: z79.enum([
21463
+ z83.object({
21464
+ status: z83.literal("uploaded"),
21465
+ assets: z83.array(z83.object({
21466
+ assetId: z83.string().uuid(),
21467
+ mediaKind: z83.enum([
20649
21468
  "image",
20650
21469
  "video"
20651
21470
  ]),
20652
- assetRole: z79.enum([
21471
+ assetRole: z83.enum([
20653
21472
  "media",
20654
21473
  "thumbnail"
20655
21474
  ])
@@ -20657,13 +21476,13 @@ var UniversalUploadStatusResponse = z79.discriminatedUnion("status", [
20657
21476
  })
20658
21477
  ]);
20659
21478
  var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
20660
- uploadPurpose: z79.enum([
21479
+ uploadPurpose: z83.enum([
20661
21480
  "product_reference",
20662
21481
  "creative",
20663
21482
  "generic"
20664
21483
  ]),
20665
- checkToolName: z79.literal("check_media_upload"),
20666
- resolveEndpoint: z79.string().url()
21484
+ checkToolName: z83.literal("check_media_upload"),
21485
+ resolveEndpoint: z83.string().url()
20667
21486
  });
20668
21487
  function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
20669
21488
  const url = new URL(uploadPageUrl);
@@ -20754,15 +21573,15 @@ function registerMediaUploadTools(server, api) {
20754
21573
  __name(registerMediaUploadTools, "registerMediaUploadTools");
20755
21574
 
20756
21575
  // src/tools/campaigns.ts
20757
- import { z as z80 } from "zod";
21576
+ import { z as z84 } from "zod";
20758
21577
  var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
20759
21578
  var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
20760
- var MetaStatusInput = z80.object({
20761
- campaignId: z80.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
21579
+ var MetaStatusInput = z84.object({
21580
+ campaignId: z84.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
20762
21581
  });
20763
- var TikTokStatusInput = z80.object({
20764
- campaignId: z80.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
20765
- advertiserId: z80.string().min(1).describe("The same advertiserId used to publish the campaign.")
21582
+ var TikTokStatusInput = z84.object({
21583
+ campaignId: z84.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
21584
+ advertiserId: z84.string().min(1).describe("The same advertiserId used to publish the campaign.")
20766
21585
  });
20767
21586
  function registerCampaignTools(server, api) {
20768
21587
  server.tool("get_meta_campaign_status", getMetaCampaignStatusGuidance.summary + " Llama esto DESPU\xC9S de `publish_to_meta` para confirmar que la campa\xF1a se cre\xF3 correctamente y para reportar performance al usuario. Es read-only \u2014 no modifica nada en Meta Ads Manager.", MetaStatusInput.shape, READS_EXTERNAL, async (input) => {
@@ -20859,10 +21678,10 @@ function renderTikTokStatusMarkdown(r) {
20859
21678
  __name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
20860
21679
 
20861
21680
  // ../../packages/product-economics/src/product-costing.ts
20862
- import { z as z82 } from "zod";
21681
+ import { z as z86 } from "zod";
20863
21682
 
20864
21683
  // ../../packages/product-economics/src/product-costing-countries.ts
20865
- import { z as z81 } from "zod";
21684
+ import { z as z85 } from "zod";
20866
21685
 
20867
21686
  // ../../packages/product-economics/src/product-costing-shipping-references.json
20868
21687
  var product_costing_shipping_references_default = {
@@ -20926,21 +21745,21 @@ var product_costing_shipping_references_default = {
20926
21745
  };
20927
21746
 
20928
21747
  // ../../packages/product-economics/src/product-costing-countries.ts
20929
- var ShippingReferenceSchema = z81.object({
20930
- reference: z81.number().positive(),
20931
- min: z81.number().nonnegative(),
20932
- max: z81.number().positive(),
20933
- updatedAt: z81.string().date(),
20934
- confidence: z81.enum([
21748
+ var ShippingReferenceSchema = z85.object({
21749
+ reference: z85.number().positive(),
21750
+ min: z85.number().nonnegative(),
21751
+ max: z85.number().positive(),
21752
+ updatedAt: z85.string().date(),
21753
+ confidence: z85.enum([
20935
21754
  "high",
20936
21755
  "medium",
20937
21756
  "medium-low"
20938
21757
  ]),
20939
- sources: z81.array(z81.string().url().startsWith("https://")).min(1).max(3)
21758
+ sources: z85.array(z85.string().url().startsWith("https://")).min(1).max(3)
20940
21759
  }).superRefine(({ reference, min, max }, context) => {
20941
21760
  if (min > reference || reference > max) {
20942
21761
  context.addIssue({
20943
- code: z81.ZodIssueCode.custom,
21762
+ code: z85.ZodIssueCode.custom,
20944
21763
  message: "shipping_reference_outside_range",
20945
21764
  path: [
20946
21765
  "reference"
@@ -20948,7 +21767,7 @@ var ShippingReferenceSchema = z81.object({
20948
21767
  });
20949
21768
  }
20950
21769
  });
20951
- var SHIPPING_REFERENCES = z81.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
21770
+ var SHIPPING_REFERENCES = z85.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
20952
21771
  var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
20953
21772
  var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
20954
21773
  "MX",
@@ -21130,18 +21949,18 @@ function getProductCostingCountryName(country) {
21130
21949
  __name(getProductCostingCountryName, "getProductCostingCountryName");
21131
21950
 
21132
21951
  // ../../packages/product-economics/src/product-costing.ts
21133
- var ProductCostingInputSchema = z82.object({
21134
- country: z82.string().refine(isProductCostingCountryCode, "unsupported_country"),
21135
- supplierCost: z82.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
21136
- shippingCost: z82.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
21137
- returnRate: z82.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
21138
- cancellationRate: z82.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
21139
- adsManagerCpa: z82.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
21140
- desiredMargin: z82.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
21952
+ var ProductCostingInputSchema = z86.object({
21953
+ country: z86.string().refine(isProductCostingCountryCode, "unsupported_country"),
21954
+ supplierCost: z86.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
21955
+ shippingCost: z86.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
21956
+ returnRate: z86.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
21957
+ cancellationRate: z86.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
21958
+ adsManagerCpa: z86.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
21959
+ desiredMargin: z86.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
21141
21960
  }).superRefine(({ returnRate, cancellationRate }, context) => {
21142
21961
  if (returnRate + cancellationRate >= 1) {
21143
21962
  context.addIssue({
21144
- code: z82.ZodIssueCode.custom,
21963
+ code: z86.ZodIssueCode.custom,
21145
21964
  message: "delivery_rate_positive",
21146
21965
  path: [
21147
21966
  "cancellationRate"
@@ -21238,15 +22057,15 @@ function calculateProductCosting(rawInput) {
21238
22057
  __name(calculateProductCosting, "calculateProductCosting");
21239
22058
 
21240
22059
  // src/tools/product-costing.ts
21241
- import { z as z83 } from "zod";
22060
+ import { z as z87 } from "zod";
21242
22061
  var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
21243
- var optionalAmount = /* @__PURE__ */ __name((description) => z83.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
21244
- var optionalPercent = /* @__PURE__ */ __name((description) => z83.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
21245
- var ProductCostingToolInput = z83.object({
21246
- country: z83.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
22062
+ var optionalAmount = /* @__PURE__ */ __name((description) => z87.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
22063
+ var optionalPercent = /* @__PURE__ */ __name((description) => z87.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
22064
+ var ProductCostingToolInput = z87.object({
22065
+ country: z87.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
21247
22066
  message: "Pa\xEDs no soportado por ProductMaker."
21248
22067
  }).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
21249
- supplierCost: z83.number().finite().max(Number.MAX_SAFE_INTEGER).positive().optional().describe("Costo real de una unidad con el proveedor, en la moneda del pa\xEDs. Requerido salvo que uses supplierCostCop para Colombia."),
22068
+ supplierCost: z87.number().finite().max(Number.MAX_SAFE_INTEGER).positive().optional().describe("Costo real de una unidad con el proveedor, en la moneda del pa\xEDs. Requerido salvo que uses supplierCostCop para Colombia."),
21250
22069
  supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
21251
22070
  shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
21252
22071
  shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
@@ -21405,7 +22224,7 @@ function formatPercent(value) {
21405
22224
  __name(formatPercent, "formatPercent");
21406
22225
 
21407
22226
  // src/tools/product-research.ts
21408
- import { z as z84 } from "zod";
22227
+ import { z as z88 } from "zod";
21409
22228
 
21410
22229
  // src/tools/product-research-idempotency.ts
21411
22230
  var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
@@ -21776,35 +22595,35 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
21776
22595
  ]);
21777
22596
  var POLL_INTERVAL_MS = 5e3;
21778
22597
  var MAX_WAIT_SECONDS = 120;
21779
- var FindInput = z84.object({
22598
+ var FindInput = z88.object({
21780
22599
  targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
21781
22600
  categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
21782
- confirmed: z84.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
21783
- waitSeconds: z84.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
22601
+ confirmed: z88.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
22602
+ waitSeconds: z88.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
21784
22603
  });
21785
- var GetInput = z84.object({
21786
- runId: z84.string().uuid().describe("ID del run devuelto por find_winning_products.")
22604
+ var GetInput = z88.object({
22605
+ runId: z88.string().uuid().describe("ID del run devuelto por find_winning_products.")
21787
22606
  });
21788
- var ListInput = z84.object({
21789
- limit: z84.number().int().min(1).max(20).default(10)
22607
+ var ListInput = z88.object({
22608
+ limit: z88.number().int().min(1).max(20).default(10)
21790
22609
  });
21791
- function textResult(text) {
22610
+ function textResult(text2) {
21792
22611
  return {
21793
22612
  content: [
21794
22613
  {
21795
22614
  type: "text",
21796
- text
22615
+ text: text2
21797
22616
  }
21798
22617
  ]
21799
22618
  };
21800
22619
  }
21801
22620
  __name(textResult, "textResult");
21802
- function researchResult(run, text) {
22621
+ function researchResult(run, text2) {
21803
22622
  return {
21804
22623
  content: [
21805
22624
  {
21806
22625
  type: "text",
21807
- text
22626
+ text: text2
21808
22627
  }
21809
22628
  ],
21810
22629
  structuredContent: run
@@ -21909,17 +22728,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
21909
22728
  __name(registerProductResearchTools, "registerProductResearchTools");
21910
22729
 
21911
22730
  // src/tools/dropshipping-projects.ts
21912
- import { z as z85 } from "zod";
22731
+ import { z as z89 } from "zod";
21913
22732
  var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
21914
22733
  var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
21915
22734
  var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
21916
- var ProjectId = z85.string().uuid();
21917
- var DropshippingProjectStatus = z85.enum([
22735
+ var ProjectId = z89.string().uuid();
22736
+ var DropshippingProjectStatus = z89.enum([
21918
22737
  "active",
21919
22738
  "completed",
21920
22739
  "archived"
21921
22740
  ]);
21922
- var DropshippingProjectPhase = z85.enum([
22741
+ var DropshippingProjectPhase = z89.enum([
21923
22742
  "research",
21924
22743
  "costing",
21925
22744
  "media",
@@ -21928,21 +22747,21 @@ var DropshippingProjectPhase = z85.enum([
21928
22747
  "advertising",
21929
22748
  "complete"
21930
22749
  ]);
21931
- var DropshippingRewardMilestone = z85.enum([
22750
+ var DropshippingRewardMilestone = z89.enum([
21932
22751
  "product_selected",
21933
22752
  "costing_saved",
21934
22753
  "product_media_ready",
21935
22754
  "creatives_completed",
21936
22755
  "campaign_created"
21937
22756
  ]);
21938
- var TargetCountry = z85.enum([
22757
+ var TargetCountry = z89.enum([
21939
22758
  "CO",
21940
22759
  "MX",
21941
22760
  "PE",
21942
22761
  "EC",
21943
22762
  "CL"
21944
22763
  ]);
21945
- var ResearchCategory = z85.enum([
22764
+ var ResearchCategory = z89.enum([
21946
22765
  "auto",
21947
22766
  "automotive",
21948
22767
  "kitchen",
@@ -21957,7 +22776,7 @@ var ResearchCategory = z85.enum([
21957
22776
  "garden",
21958
22777
  "cleaning"
21959
22778
  ]);
21960
- var HttpUrl3 = z85.string().url().max(2e3).refine((value) => {
22779
+ var HttpUrl3 = z89.string().url().max(2e3).refine((value) => {
21961
22780
  try {
21962
22781
  return [
21963
22782
  "http:",
@@ -21967,45 +22786,45 @@ var HttpUrl3 = z85.string().url().max(2e3).refine((value) => {
21967
22786
  return false;
21968
22787
  }
21969
22788
  }, "URL must use HTTP(S)");
21970
- var ResearchCandidateOrigin = z85.object({
21971
- type: z85.literal("research_candidate"),
22789
+ var ResearchCandidateOrigin = z89.object({
22790
+ type: z89.literal("research_candidate"),
21972
22791
  runId: ProjectId,
21973
- candidateSourceId: z85.string().min(1).max(160)
22792
+ candidateSourceId: z89.string().min(1).max(160)
21974
22793
  });
21975
- var TaskOrigin = z85.object({
21976
- type: z85.literal("task"),
22794
+ var TaskOrigin = z89.object({
22795
+ type: z89.literal("task"),
21977
22796
  taskId: ProjectId
21978
22797
  });
21979
- var ManualOrigin = z85.object({
21980
- type: z85.literal("manual"),
22798
+ var ManualOrigin = z89.object({
22799
+ type: z89.literal("manual"),
21981
22800
  clientRequestId: ProjectId,
21982
- country: z85.string().min(2).max(3).optional()
22801
+ country: z89.string().min(2).max(3).optional()
21983
22802
  });
21984
- var StartProjectInput = z85.object({
21985
- origin: z85.discriminatedUnion("type", [
22803
+ var StartProjectInput = z89.object({
22804
+ origin: z89.discriminatedUnion("type", [
21986
22805
  ResearchCandidateOrigin,
21987
22806
  TaskOrigin,
21988
22807
  ManualOrigin
21989
22808
  ]),
21990
- productName: z85.string().trim().min(1).max(240).optional(),
22809
+ productName: z89.string().trim().min(1).max(240).optional(),
21991
22810
  productUrl: HttpUrl3.optional(),
21992
- country: z85.string().min(2).max(3).optional(),
21993
- languageCode: z85.string().min(2).max(16).optional()
22811
+ country: z89.string().min(2).max(3).optional(),
22812
+ languageCode: z89.string().min(2).max(16).optional()
21994
22813
  }).strict();
21995
- var CostProjectInput = z85.object({
22814
+ var CostProjectInput = z89.object({
21996
22815
  projectId: ProjectId,
21997
- version: z85.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
21998
- country: z85.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
22816
+ version: z89.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
22817
+ country: z89.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
21999
22818
  message: "Pa\xEDs no soportado por ProductMaker."
22000
22819
  }).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
22001
- supplierCost: z85.number().finite().positive().describe("Costo real de una unidad con el proveedor, en la moneda del pa\xEDs. \xDANICO dato que debes pedirle al usuario: nunca lo inventes."),
22002
- shippingCost: z85.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
22003
- returnRate: z85.number().finite().min(0).lt(1).optional().describe("Fracci\xF3n de pedidos devueltos (0.25 = 25%). Omite para usar el valor gu\xEDa del pa\xEDs."),
22004
- cancellationRate: z85.number().finite().min(0).lt(1).optional().describe("Fracci\xF3n de pedidos cancelados (0.15 = 15%). Omite para usar el valor gu\xEDa del pa\xEDs."),
22005
- adsManagerCpa: z85.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
22006
- desiredMargin: z85.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
22007
- });
22008
- var GuideInput = z85.object({
22820
+ supplierCost: z89.number().finite().positive().describe("Costo real de una unidad con el proveedor, en la moneda del pa\xEDs. \xDANICO dato que debes pedirle al usuario: nunca lo inventes."),
22821
+ shippingCost: z89.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
22822
+ returnRate: z89.number().finite().min(0).lt(1).optional().describe("Fracci\xF3n de pedidos devueltos (0.25 = 25%). Omite para usar el valor gu\xEDa del pa\xEDs."),
22823
+ cancellationRate: z89.number().finite().min(0).lt(1).optional().describe("Fracci\xF3n de pedidos cancelados (0.15 = 15%). Omite para usar el valor gu\xEDa del pa\xEDs."),
22824
+ adsManagerCpa: z89.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
22825
+ desiredMargin: z89.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
22826
+ });
22827
+ var GuideInput = z89.object({
22009
22828
  projectId: ProjectId.optional()
22010
22829
  }).strict();
22011
22830
  var NEXT_ACTION_KINDS = [
@@ -22023,29 +22842,29 @@ var NEXT_ACTION_KINDS = [
22023
22842
  "repair_meta_campaign",
22024
22843
  "review_paused_campaign"
22025
22844
  ];
22026
- var DropshippingProjectNextAction = z85.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z85.object({
22027
- kind: z85.literal(kind),
22028
- href: z85.string().min(1)
22845
+ var DropshippingProjectNextAction = z89.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z89.object({
22846
+ kind: z89.literal(kind),
22847
+ href: z89.string().min(1)
22029
22848
  })));
22030
- var CostingInputSchema = z85.object({
22031
- country: z85.string().min(2).max(3),
22032
- supplierCost: z85.number().finite().positive(),
22033
- shippingCost: z85.number().finite().nonnegative(),
22034
- returnRate: z85.number().finite().min(0).lt(1),
22035
- cancellationRate: z85.number().finite().min(0).lt(1),
22036
- adsManagerCpa: z85.number().finite().nonnegative(),
22037
- desiredMargin: z85.number().finite().min(0).lt(1)
22849
+ var CostingInputSchema = z89.object({
22850
+ country: z89.string().min(2).max(3),
22851
+ supplierCost: z89.number().finite().positive(),
22852
+ shippingCost: z89.number().finite().nonnegative(),
22853
+ returnRate: z89.number().finite().min(0).lt(1),
22854
+ cancellationRate: z89.number().finite().min(0).lt(1),
22855
+ adsManagerCpa: z89.number().finite().nonnegative(),
22856
+ desiredMargin: z89.number().finite().min(0).lt(1)
22038
22857
  }).superRefine(({ returnRate, cancellationRate }, context) => {
22039
22858
  if (returnRate + cancellationRate >= 1) context.addIssue({
22040
- code: z85.ZodIssueCode.custom,
22859
+ code: z89.ZodIssueCode.custom,
22041
22860
  path: [
22042
22861
  "cancellationRate"
22043
22862
  ]
22044
22863
  });
22045
22864
  });
22046
- var FiniteCostingNumber = z85.number().finite();
22047
- var CostingResultSchema = z85.object({
22048
- country: z85.string().min(2).max(3),
22865
+ var FiniteCostingNumber = z89.number().finite();
22866
+ var CostingResultSchema = z89.object({
22867
+ country: z89.string().min(2).max(3),
22049
22868
  deliveryRate: FiniteCostingNumber,
22050
22869
  adjustedShippingCost: FiniteCostingNumber,
22051
22870
  adjustedCpa: FiniteCostingNumber,
@@ -22058,45 +22877,45 @@ var CostingResultSchema = z85.object({
22058
22877
  estimatedProfit: FiniteCostingNumber,
22059
22878
  actualMargin: FiniteCostingNumber,
22060
22879
  breakEvenAdsManagerCpa: FiniteCostingNumber,
22061
- wasPriceAutoAdjusted: z85.boolean(),
22062
- profitabilityStatus: z85.literal("healthy")
22063
- });
22064
- var RewardProgressSchema = z85.object({
22065
- campaignKey: z85.literal("dropshipping-launch-v1"),
22066
- totalCredits: z85.number().int().positive(),
22067
- earnedCredits: z85.number().int().nonnegative(),
22068
- milestones: z85.array(z85.object({
22880
+ wasPriceAutoAdjusted: z89.boolean(),
22881
+ profitabilityStatus: z89.literal("healthy")
22882
+ });
22883
+ var RewardProgressSchema = z89.object({
22884
+ campaignKey: z89.literal("dropshipping-launch-v1"),
22885
+ totalCredits: z89.number().int().positive(),
22886
+ earnedCredits: z89.number().int().nonnegative(),
22887
+ milestones: z89.array(z89.object({
22069
22888
  milestone: DropshippingRewardMilestone,
22070
- credits: z85.number().int().positive(),
22071
- available: z85.boolean().optional(),
22072
- earned: z85.boolean(),
22889
+ credits: z89.number().int().positive(),
22890
+ available: z89.boolean().optional(),
22891
+ earned: z89.boolean(),
22073
22892
  grantId: ProjectId.nullable(),
22074
- grantedAt: z85.string().datetime().nullable()
22893
+ grantedAt: z89.string().datetime().nullable()
22075
22894
  })).length(DropshippingRewardMilestone.options.length)
22076
22895
  });
22077
- var ProjectResponseSchema = z85.object({
22896
+ var ProjectResponseSchema = z89.object({
22078
22897
  id: ProjectId,
22079
22898
  taskId: ProjectId.nullable(),
22080
22899
  status: DropshippingProjectStatus,
22081
- originKey: z85.string().min(1),
22900
+ originKey: z89.string().min(1),
22082
22901
  researchRunId: ProjectId.nullable(),
22083
- candidateSourceId: z85.string().nullable(),
22084
- productName: z85.string().nullable(),
22902
+ candidateSourceId: z89.string().nullable(),
22903
+ productName: z89.string().nullable(),
22085
22904
  productUrl: HttpUrl3.nullable(),
22086
22905
  referenceImageUrl: HttpUrl3.nullable(),
22087
- targetCountry: z85.string().nullable(),
22088
- languageCode: z85.string().nullable(),
22089
- hasReferenceImage: z85.boolean(),
22090
- hasWinnerReferenceImage: z85.boolean(),
22906
+ targetCountry: z89.string().nullable(),
22907
+ languageCode: z89.string().nullable(),
22908
+ hasReferenceImage: z89.boolean(),
22909
+ hasWinnerReferenceImage: z89.boolean(),
22091
22910
  costingInput: CostingInputSchema.nullable(),
22092
22911
  costingResult: CostingResultSchema.nullable(),
22093
- costingVersion: z85.number().int().positive().nullable(),
22094
- version: z85.number().int().positive(),
22912
+ costingVersion: z89.number().int().positive().nullable(),
22913
+ version: z89.number().int().positive(),
22095
22914
  phase: DropshippingProjectPhase,
22096
22915
  nextAction: DropshippingProjectNextAction.nullable(),
22097
22916
  rewards: RewardProgressSchema,
22098
- createdAt: z85.string().datetime(),
22099
- updatedAt: z85.string().datetime()
22917
+ createdAt: z89.string().datetime(),
22918
+ updatedAt: z89.string().datetime()
22100
22919
  }).passthrough();
22101
22920
  var NEXT_ACTION_GUIDANCE = {
22102
22921
  cost_product: "Llama `cost_dropshipping_project` con el costo real del proveedor. Nunca lo inventes: p\xEDdeselo al usuario. Es el \xDANICO dato que debes pedirle: omite env\xEDo, devoluciones, cancelaciones, CPA y margen para que ProductMaker use los valores gu\xEDa del pa\xEDs, y luego dile al usuario cu\xE1les us\xF3 por si quiere corregirlos.",
@@ -22214,58 +23033,58 @@ function registerDropshippingProjectTools(server, api) {
22214
23033
  __name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
22215
23034
 
22216
23035
  // src/tools/daily-control.ts
22217
- import { z as z86 } from "zod";
23036
+ import { z as z90 } from "zod";
22218
23037
  var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
22219
23038
  var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
22220
23039
  var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
22221
- var ProviderCampaignIdentifier = z86.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
22222
- var DateOnly = z86.string().regex(/^\d{4}-\d{2}-\d{2}$/);
22223
- var DailyControlInput = z86.object({
23040
+ var ProviderCampaignIdentifier = z90.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
23041
+ var DateOnly = z90.string().regex(/^\d{4}-\d{2}-\d{2}$/);
23042
+ var DailyControlInput = z90.object({
22224
23043
  date: DateOnly.optional().describe("D\xEDa final de la ventana (YYYY-MM-DD). Si se omite, la ventana termina AYER en UTC \u2014 nunca hoy, porque el d\xEDa en curso est\xE1 incompleto \u2014 y el servidor puede correrla un d\xEDa m\xE1s atr\xE1s si en la zona horaria de la tienda ese d\xEDa todav\xEDa no ha cerrado."),
22225
- days: z86.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
22226
- projectId: z86.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
23044
+ days: z90.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
23045
+ projectId: z90.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
22227
23046
  }).strict();
22228
- var LinkCampaignInput = z86.object({
22229
- projectId: z86.string().uuid(),
22230
- provider: z86.enum([
23047
+ var LinkCampaignInput = z90.object({
23048
+ projectId: z90.string().uuid(),
23049
+ provider: z90.enum([
22231
23050
  "meta",
22232
23051
  "tiktok"
22233
23052
  ]),
22234
23053
  accountId: ProviderCampaignIdentifier.describe("Cuenta publicitaria del proveedor. Para Meta el servidor la IGNORA y deriva la cuenta real de la campa\xF1a \u2014 se sigue pidiendo aqu\xED solo porque TikTok s\xED la necesita para resolver la campa\xF1a."),
22235
23054
  campaignId: ProviderCampaignIdentifier
22236
23055
  }).strict();
22237
- var ReportReturnsInput = z86.object({
22238
- projectId: z86.string().uuid(),
23056
+ var ReportReturnsInput = z90.object({
23057
+ projectId: z90.string().uuid(),
22239
23058
  date: DateOnly,
22240
- returnedOrders: z86.number().int().min(0).max(1e5),
22241
- note: z86.string().trim().max(280).optional()
23059
+ returnedOrders: z90.number().int().min(0).max(1e5),
23060
+ note: z90.string().trim().max(280).optional()
22242
23061
  }).strict();
22243
- var DailyControlStatusMirror = DailyControlStatusEnum.or(z86.string());
22244
- var DailyControlLightMirror = DailyControlLightEnum.or(z86.string());
22245
- var DailyControlSourceMirror = DailyControlSourceEnum.or(z86.string());
22246
- var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z86.string());
22247
- var DailyControlDayMirror = z86.object({
22248
- date: z86.string(),
22249
- returnedOrders: z86.number(),
23062
+ var DailyControlStatusMirror = DailyControlStatusEnum.or(z90.string());
23063
+ var DailyControlLightMirror = DailyControlLightEnum.or(z90.string());
23064
+ var DailyControlSourceMirror = DailyControlSourceEnum.or(z90.string());
23065
+ var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z90.string());
23066
+ var DailyControlDayMirror = z90.object({
23067
+ date: z90.string(),
23068
+ returnedOrders: z90.number(),
22250
23069
  returnedSource: DailyControlSourceMirror,
22251
23070
  cancelledSource: DailyControlSourceMirror,
22252
- hasEstimates: z86.boolean(),
23071
+ hasEstimates: z90.boolean(),
22253
23072
  light: DailyControlLightMirror
22254
23073
  }).passthrough();
22255
- var DailyControlProductMirror = z86.object({
22256
- projectId: z86.string().uuid(),
22257
- productName: z86.string().nullable(),
23074
+ var DailyControlProductMirror = z90.object({
23075
+ projectId: z90.string().uuid(),
23076
+ productName: z90.string().nullable(),
22258
23077
  status: DailyControlStatusMirror,
22259
- statusMessage: z86.string().nullable(),
22260
- days: z86.array(DailyControlDayMirror),
23078
+ statusMessage: z90.string().nullable(),
23079
+ days: z90.array(DailyControlDayMirror),
22261
23080
  verdict: DailyControlVerdictMirror.nullable(),
22262
- rationale: z86.string().nullable()
23081
+ rationale: z90.string().nullable()
22263
23082
  }).passthrough();
22264
- var DailyControlResponseMirror = z86.object({
22265
- since: z86.string(),
22266
- until: z86.string(),
22267
- products: z86.array(DailyControlProductMirror),
22268
- archivedProjectSpend: z86.array(z86.unknown())
23083
+ var DailyControlResponseMirror = z90.object({
23084
+ since: z90.string(),
23085
+ until: z90.string(),
23086
+ products: z90.array(DailyControlProductMirror),
23087
+ archivedProjectSpend: z90.array(z90.unknown())
22269
23088
  }).passthrough();
22270
23089
  var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
22271
23090
  function withWarnings(response) {
@@ -22349,42 +23168,42 @@ function registerDailyControlTools(server, api) {
22349
23168
  __name(registerDailyControlTools, "registerDailyControlTools");
22350
23169
 
22351
23170
  // src/tools/product-control.ts
22352
- import { z as z87 } from "zod";
23171
+ import { z as z91 } from "zod";
22353
23172
  var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
22354
23173
  var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
22355
23174
  var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
22356
23175
  var setProductCostingGuidance = getProductMakerCapabilityModelGuidance("set_product_costing");
22357
23176
  var reportProductCountsGuidance = getProductMakerCapabilityModelGuidance("report_product_counts");
22358
- var DateOnly2 = z87.string().regex(/^\d{4}-\d{2}-\d{2}$/);
23177
+ var DateOnly2 = z91.string().regex(/^\d{4}-\d{2}-\d{2}$/);
22359
23178
  var IMPORT_BATCH_MAX2 = 50;
22360
- var ProductControlListInput = z87.object({
22361
- days: z87.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
23179
+ var ProductControlListInput = z91.object({
23180
+ days: z91.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
22362
23181
  date: DateOnly2.optional().describe("D\xEDa final de la ventana (YYYY-MM-DD). Si se omite, termina en el \xFAltimo d\xEDa cerrado \u2014 nunca hoy, que est\xE1 incompleto."),
22363
- shopDomain: z87.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
23182
+ shopDomain: z91.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
22364
23183
  }).strict();
22365
- var ImportableProductsInput = z87.object({
22366
- q: z87.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
22367
- after: z87.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
22368
- shopDomain: z87.string().min(1).optional()
23184
+ var ImportableProductsInput = z91.object({
23185
+ q: z91.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
23186
+ after: z91.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
23187
+ shopDomain: z91.string().min(1).optional()
22369
23188
  }).strict();
22370
- var ImportProductControlsInput = z87.object({
22371
- shopifyProductIds: z87.array(z87.string().min(1).max(64)).min(1).max(IMPORT_BATCH_MAX2).describe("Identificadores tal como vinieron de list_importable_products. NO los inventes ni los deduzcas del t\xEDtulo."),
23189
+ var ImportProductControlsInput = z91.object({
23190
+ shopifyProductIds: z91.array(z91.string().min(1).max(64)).min(1).max(IMPORT_BATCH_MAX2).describe("Identificadores tal como vinieron de list_importable_products. NO los inventes ni los deduzcas del t\xEDtulo."),
22372
23191
  // Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
22373
23192
  // sin decir a cuál archivaría el producto bajo la tienda equivocada.
22374
- shopDomain: z87.string().min(1)
23193
+ shopDomain: z91.string().min(1)
22375
23194
  }).strict();
22376
- var SetProductCostingInput = z87.object({
22377
- shopDomain: z87.string().min(1),
22378
- shopifyProductId: z87.string().min(1).max(64),
22379
- targetCountry: z87.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
22380
- supplierCost: z87.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
22381
- shippingCost: z87.number().finite().nonnegative(),
22382
- returnRate: z87.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
22383
- cancellationRate: z87.number().finite().min(0).lt(1)
23195
+ var SetProductCostingInput = z91.object({
23196
+ shopDomain: z91.string().min(1),
23197
+ shopifyProductId: z91.string().min(1).max(64),
23198
+ targetCountry: z91.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
23199
+ supplierCost: z91.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
23200
+ shippingCost: z91.number().finite().nonnegative(),
23201
+ returnRate: z91.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
23202
+ cancellationRate: z91.number().finite().min(0).lt(1)
22384
23203
  }).strict();
22385
- var Count = z87.number().int().min(0).max(1e5).nullable().optional();
22386
- var ReportProductCountsInput = z87.object({
22387
- productControlId: z87.string().uuid().describe("El identificador que devuelve get_product_control."),
23204
+ var Count = z91.number().int().min(0).max(1e5).nullable().optional();
23205
+ var ReportProductCountsInput = z91.object({
23206
+ productControlId: z91.string().uuid().describe("El identificador que devuelve get_product_control."),
22388
23207
  date: DateOnly2,
22389
23208
  orders: Count.describe("Pedidos que entraron ese d\xEDa."),
22390
23209
  cancelledOrders: Count,