@productmaker/mcp 8.11.2 → 8.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/stdio.js CHANGED
@@ -173,6 +173,14 @@ var FrankensteinSourceUploadPresignResponseSchema = z2.object({
173
173
 
174
174
  // ../../packages/types/src/product-context-limits.ts
175
175
  var PRODUCT_CONTEXT_MAX_CHARS = 3e3;
176
+ function canonicalizeLineBreaks(value) {
177
+ return value.replace(/\r\n?/g, "\n");
178
+ }
179
+ __name(canonicalizeLineBreaks, "canonicalizeLineBreaks");
180
+ function canonicalizeProductContext(value) {
181
+ return canonicalizeLineBreaks(value).trim();
182
+ }
183
+ __name(canonicalizeProductContext, "canonicalizeProductContext");
176
184
 
177
185
  // ../../packages/types/src/video-creation.ts
178
186
  var VideoCreationAspectRatio = z3.enum([
@@ -204,7 +212,7 @@ var FrankensteinVideoRequestBaseSchema = z3.object({
204
212
  generateAiMusic: z3.boolean().default(false),
205
213
  title: z3.string().trim().min(1).max(300).optional(),
206
214
  primaryAngle: z3.string().trim().max(500).optional(),
207
- productContext: z3.string().trim().max(PRODUCT_CONTEXT_MAX_CHARS).optional(),
215
+ productContext: z3.string().transform(canonicalizeProductContext).pipe(z3.string().max(PRODUCT_CONTEXT_MAX_CHARS)).optional(),
208
216
  productLabel: z3.string().trim().max(120).optional(),
209
217
  buyerPersona: z3.string().trim().max(500).optional(),
210
218
  cta: z3.string().trim().max(300).optional(),
@@ -4274,7 +4282,7 @@ var IngestOptions = z22.object({
4274
4282
  * per task. Length only, never `.uuid()` — Actor.id is a CUID. */
4275
4283
  actorId: z22.string().min(1).max(120).optional(),
4276
4284
  isCombo: z22.boolean().default(false),
4277
- productContext: z22.string().transform((value) => value.trim()).pipe(z22.string().max(PRODUCT_CONTEXT_MAX_CHARS)).optional(),
4285
+ productContext: z22.string().transform(canonicalizeProductContext).pipe(z22.string().max(PRODUCT_CONTEXT_MAX_CHARS)).optional(),
4278
4286
  creativeDirection: z22.string().transform((value) => value.trim()).pipe(z22.string().max(500)).optional(),
4279
4287
  /** Exact copy the user pinned. Rendered VERBATIM on the image creatives this task
4280
4288
  * produces and on the landing hero — never on video, which steers via scriptNotes.
@@ -5835,7 +5843,12 @@ var ShopifyPublishErrorResponse = z29.discriminatedUnion("code", [
5835
5843
  * variants, another app rewrote the product, landing too large).
5836
5844
  * `message` carries the seller's next step; never a 500.
5837
5845
  */
5838
- "SHOPIFY_PUBLISH_VERIFICATION_FAILED"
5846
+ "SHOPIFY_PUBLISH_VERIFICATION_FAILED",
5847
+ /**
5848
+ * The seller's store is frozen/paused/closed on Shopify's side (402/423
5849
+ * "Unavailable Shop"). 409; `message` says to reactivate it in Shopify.
5850
+ */
5851
+ "SHOPIFY_SHOP_UNAVAILABLE"
5839
5852
  ]),
5840
5853
  message: z29.string().optional(),
5841
5854
  authUrl: z29.string().url().optional(),
@@ -14304,6 +14317,8 @@ var ProductControlDailyCountsSchema = z69.object({
14304
14317
  var ProductControlRowSchema = z69.object({
14305
14318
  /** `null` hasta que la vendedora toca el producto por primera vez. */
14306
14319
  productControlId: z69.string().nullable(),
14320
+ /** La operación a la que pertenece; opcional para payloads anteriores. */
14321
+ operationId: z69.string().nullable().optional(),
14307
14322
  shopId: z69.string(),
14308
14323
  shopDomain: z69.string(),
14309
14324
  /** Nulo cuando el producto NO vive en Shopify: importado del archivo de un
@@ -14500,9 +14515,7 @@ var SaveProductCatalogSchema = z69.object({
14500
14515
  "tiktok"
14501
14516
  ]).nullable().optional()
14502
14517
  }).strict();
14503
- var LinkProductControlCampaignSchema = z69.object({
14504
- shopDomain: z69.string().min(1),
14505
- shopifyProductId: z69.string().min(1),
14518
+ var ProductControlCampaignFieldsSchema = z69.object({
14506
14519
  provider: z69.enum([
14507
14520
  "meta",
14508
14521
  "tiktok"
@@ -14510,6 +14523,15 @@ var LinkProductControlCampaignSchema = z69.object({
14510
14523
  accountId: z69.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/),
14511
14524
  campaignId: z69.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/)
14512
14525
  }).strict();
14526
+ var LinkProductControlCampaignSchema = z69.union([
14527
+ ProductControlCampaignFieldsSchema.extend({
14528
+ productControlId: z69.string().uuid()
14529
+ }).strict(),
14530
+ ProductControlCampaignFieldsSchema.extend({
14531
+ shopDomain: z69.string().min(1),
14532
+ shopifyProductId: z69.string().min(1)
14533
+ }).strict()
14534
+ ]);
14513
14535
  var ReportProductControlReturnsSchema = z69.object({
14514
14536
  returnedOrders: z69.number().int().min(0).max(1e5),
14515
14537
  note: z69.string().trim().max(280).optional()
@@ -17552,6 +17574,53 @@ var RegenerateVideoScriptCapabilityRequest = z79.object({
17552
17574
  ]).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.")
17553
17575
  }).strict();
17554
17576
 
17577
+ // ../../packages/types/src/dropi-financial.ts
17578
+ import { z as z80 } from "zod";
17579
+ var ConnectDropiFinancialSchema = z80.object({
17580
+ integrationKey: z80.string().trim().min(1).max(4096).regex(/^[\x21-\x7e]+$/)
17581
+ }).strict();
17582
+ var SyncDropiFinancialSchema = z80.object({
17583
+ operationId: z80.string().uuid().optional(),
17584
+ since: z80.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
17585
+ until: z80.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional()
17586
+ }).strict();
17587
+ var DropiFinancialStatusSchema = z80.object({
17588
+ enabled: z80.boolean(),
17589
+ connected: z80.boolean(),
17590
+ countryCode: z80.literal("CO"),
17591
+ environment: z80.enum([
17592
+ "sandbox",
17593
+ "production"
17594
+ ]),
17595
+ lastSyncAt: z80.string().nullable(),
17596
+ lastError: z80.string().nullable(),
17597
+ historyNext: z80.string().nullable(),
17598
+ historyUntil: z80.string().nullable(),
17599
+ changesThrough: z80.string().nullable(),
17600
+ manualNext: z80.string().nullable(),
17601
+ manual: z80.object({
17602
+ since: z80.string(),
17603
+ until: z80.string(),
17604
+ next: z80.string().nullable()
17605
+ }).nullable(),
17606
+ retentionSince: z80.string()
17607
+ });
17608
+ var DropiFinancialSyncResultSchema = z80.object({
17609
+ orders: z80.number().int().nonnegative(),
17610
+ written: z80.number().int().nonnegative(),
17611
+ updated: z80.number().int().nonnegative(),
17612
+ pending: z80.boolean(),
17613
+ next: z80.string().nullable(),
17614
+ historyNext: z80.string().nullable(),
17615
+ changesThrough: z80.string().nullable(),
17616
+ since: z80.string(),
17617
+ until: z80.string(),
17618
+ unmatched: z80.array(z80.object({
17619
+ externalProductId: z80.string(),
17620
+ orders: z80.number().int().nonnegative()
17621
+ }))
17622
+ });
17623
+
17555
17624
  // src/response-body.ts
17556
17625
  var ResponseBodyTooLargeError = class extends Error {
17557
17626
  static {
@@ -17794,7 +17863,7 @@ var ApiClient = class {
17794
17863
  };
17795
17864
 
17796
17865
  // src/index.ts
17797
- var MCP_VERSION = "8.11.2";
17866
+ var MCP_VERSION = "8.11.3";
17798
17867
 
17799
17868
  // src/meta-upload-app.ts
17800
17869
  import { readFileSync } from "fs";
@@ -17866,7 +17935,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
17866
17935
  __name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
17867
17936
 
17868
17937
  // src/tools/tasks.ts
17869
- import { z as z84 } from "zod";
17938
+ import { z as z85 } from "zod";
17870
17939
 
17871
17940
  // src/resolve-image.ts
17872
17941
  import { lookup as dnsLookup } from "dns/promises";
@@ -18427,9 +18496,9 @@ async function resolveMediaRef(ref, opts) {
18427
18496
  __name(resolveMediaRef, "resolveMediaRef");
18428
18497
 
18429
18498
  // src/tools/shared.ts
18430
- import { z as z80 } from "zod";
18431
- var Lang = z80.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);
18432
- var Country = z80.string().min(2).max(3);
18499
+ import { z as z81 } from "zod";
18500
+ var Lang = z81.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);
18501
+ var Country = z81.string().min(2).max(3);
18433
18502
  var LandingStrategyEnum = LandingStrategySchema;
18434
18503
  var LandingImageFormatEnum = LandingImageFormatSchema;
18435
18504
  var VideoPresetEnum = VideoPreset.extract([
@@ -18533,7 +18602,7 @@ function animationStyleApplies(videoPreset, angleNarratives) {
18533
18602
  return ANIMATED_VIDEO_PRESETS.has(videoPreset ?? "") || (angleNarratives ?? []).some((n) => ANIMATED_NARRATIVE_STYLES.has(n));
18534
18603
  }
18535
18604
  __name(animationStyleApplies, "animationStyleApplies");
18536
- var VideoTierEnum = z80.enum([
18605
+ var VideoTierEnum = z81.enum([
18537
18606
  "basic"
18538
18607
  ]);
18539
18608
  function resolveVideoTier(_tier) {
@@ -18591,10 +18660,10 @@ var ImageCreativeStyleEnum = ImageCreativeStyle;
18591
18660
  var ImageCreativeArchetypeEnum = ImageCreativeArchetype;
18592
18661
  var ImageCreativeVisualTreatmentEnum = ImageCreativeVisualTreatment;
18593
18662
  var ImageCreativeAspectRatioEnum = ImageCreativeAspectRatio;
18594
- var ImageRefSchema = z80.object({
18595
- url: z80.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.'),
18596
- path: z80.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`.'),
18597
- assetId: z80.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.")
18663
+ var ImageRefSchema = z81.object({
18664
+ url: z81.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.'),
18665
+ path: z81.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`.'),
18666
+ assetId: z81.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.")
18598
18667
  }).refine((v) => [
18599
18668
  v.url,
18600
18669
  v.path,
@@ -18602,11 +18671,11 @@ var ImageRefSchema = z80.object({
18602
18671
  ].filter(Boolean).length === 1, {
18603
18672
  message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
18604
18673
  });
18605
- var ImagesInput = z80.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
18674
+ var ImagesInput = z81.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
18606
18675
  const assetCount = images.filter((image) => Boolean(image.assetId)).length;
18607
18676
  if (assetCount > 0 && assetCount !== images.length) {
18608
18677
  ctx.addIssue({
18609
- code: z80.ZodIssueCode.custom,
18678
+ code: z81.ZodIssueCode.custom,
18610
18679
  message: "all image entries must use assetId, or all must use URL/path sources"
18611
18680
  });
18612
18681
  }
@@ -18679,14 +18748,14 @@ async function submitCreative(api, opts) {
18679
18748
  });
18680
18749
  }
18681
18750
  __name(submitCreative, "submitCreative");
18682
- var ResearchTargetCountryEnum = z80.enum([
18751
+ var ResearchTargetCountryEnum = z81.enum([
18683
18752
  "CO",
18684
18753
  "MX",
18685
18754
  "PE",
18686
18755
  "EC",
18687
18756
  "CL"
18688
18757
  ]);
18689
- var ResearchCategoryEnum = z80.enum([
18758
+ var ResearchCategoryEnum = z81.enum([
18690
18759
  "auto",
18691
18760
  "automotive",
18692
18761
  "kitchen",
@@ -18823,6 +18892,7 @@ var McpErrorCode = {
18823
18892
  SHOPIFY_SCOPE_UPGRADE_REQUIRED: "SHOPIFY_SCOPE_UPGRADE_REQUIRED",
18824
18893
  SHOPIFY_PUBLISH_FAILED: "SHOPIFY_PUBLISH_FAILED",
18825
18894
  SHOPIFY_NO_PUBLISHED_THEME: "SHOPIFY_NO_PUBLISHED_THEME",
18895
+ SHOPIFY_SHOP_UNAVAILABLE: "SHOPIFY_SHOP_UNAVAILABLE",
18826
18896
  SHOPIFY_THEME_STRUCTURE_UNSUPPORTED: "SHOPIFY_THEME_STRUCTURE_UNSUPPORTED",
18827
18897
  SHOPIFY_PUBLISH_INPUT_REQUIRED: "SHOPIFY_PUBLISH_INPUT_REQUIRED",
18828
18898
  SHOPIFY_PUBLISH_CONTEXT_CHANGED: "SHOPIFY_PUBLISH_CONTEXT_CHANGED",
@@ -18905,6 +18975,7 @@ var CODE_MESSAGES = {
18905
18975
  SHOPIFY_PUBLISH_VERIFICATION_FAILED: "Shopify did not keep what the publish wrote (offer variants, template or inventory), or the landing is too large. Read the error's reason to the user; retry the publish once, and if it repeats follow the step in the reason (map packs to existing variants, check apps that edit products, or trim the landing in the editor).",
18906
18976
  SHOPIFY_PUBLISH_TARGET_INCOMPATIBLE: "The selected Shopify product cannot carry the confirmed offer (missing quantity options/prices) or no longer exists. Read the error's message to the user, then retry with publicationMode:'new' to create a fresh product, or ask the user to pick a different existing product.",
18907
18977
  SHOPIFY_THEME_SETUP_REQUIRED: "The store's Shopify theme is missing the ProductMaker 'Code Landing' app block \u2014 publishing now would create a product whose page renders blank. Send the user the themeEditorDeepLink (in error data) to open the Shopify theme editor, have them confirm the Code Landing block is added and press Save, then retry publishing. This is a one-time step per store; nothing was published.",
18978
+ SHOPIFY_SHOP_UNAVAILABLE: "The user's Shopify store is unavailable (frozen, paused or closed on Shopify's side), so nothing was published. Ask the user to reactivate the store in Shopify (usually by settling the plan/billing) or reconnect it at https://productmaker.app/integrations, then retry. Retrying before that will fail the same way.",
18908
18979
  SHOPIFY_NO_PUBLISHED_THEME: "The Shopify store has no published theme, so there is nowhere to place the landing. Ask the user to publish a theme (Online Store > Themes > Publish) and retry.",
18909
18980
  SHOPIFY_THEME_STRUCTURE_UNSUPPORTED: "The active Shopify theme contains an HTML structure ProductMaker cannot process safely. Ask the user to restore a valid layout/theme.liquid or contact ProductMaker support to correct the theme, then retry.",
18910
18981
  // Meta — high-frequency
@@ -19096,6 +19167,7 @@ var INVALID_PARAM_CODES = /* @__PURE__ */ new Set([
19096
19167
  McpErrorCode.SHOPIFY_SCOPE_UPGRADE_REQUIRED,
19097
19168
  McpErrorCode.SHOPIFY_NOT_CONNECTED,
19098
19169
  McpErrorCode.SHOPIFY_NO_PUBLISHED_THEME,
19170
+ McpErrorCode.SHOPIFY_SHOP_UNAVAILABLE,
19099
19171
  McpErrorCode.SHOPIFY_THEME_STRUCTURE_UNSUPPORTED,
19100
19172
  McpErrorCode.SHOPIFY_PUBLISH_INPUT_REQUIRED,
19101
19173
  McpErrorCode.SHOPIFY_PUBLISH_CONTEXT_CHANGED,
@@ -19138,6 +19210,7 @@ var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
19138
19210
  McpErrorCode.SHOPIFY_SCOPE_UPGRADE_REQUIRED,
19139
19211
  McpErrorCode.SHOPIFY_PUBLISH_FAILED,
19140
19212
  McpErrorCode.SHOPIFY_NO_PUBLISHED_THEME,
19213
+ McpErrorCode.SHOPIFY_SHOP_UNAVAILABLE,
19141
19214
  McpErrorCode.SHOPIFY_THEME_STRUCTURE_UNSUPPORTED,
19142
19215
  // Meta
19143
19216
  McpErrorCode.META_NO_FB_PAGE,
@@ -19905,29 +19978,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
19905
19978
  __name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
19906
19979
 
19907
19980
  // src/tools/media-presentation.ts
19908
- import { z as z81 } from "zod";
19909
- var HttpsPresentationUrlSchema = z81.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
19981
+ import { z as z82 } from "zod";
19982
+ var HttpsPresentationUrlSchema = z82.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
19910
19983
  var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
19911
19984
  const hostname = new URL(value).hostname.toLowerCase();
19912
19985
  return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
19913
19986
  }, "preview URL must be owned by ProductMaker");
19914
- var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z81.number().int().positive().max(maximum), "positiveIntAtMost");
19915
- var PresentationImageSchema = z81.object({
19916
- kind: z81.literal("image"),
19987
+ var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z82.number().int().positive().max(maximum), "positiveIntAtMost");
19988
+ var PresentationImageSchema = z82.object({
19989
+ kind: z82.literal("image"),
19917
19990
  url: HttpsPresentationUrlSchema,
19918
- mimeType: z81.enum([
19991
+ mimeType: z82.enum([
19919
19992
  "image/jpeg",
19920
19993
  "image/png"
19921
19994
  ]),
19922
19995
  byteSize: positiveIntAtMost(5 * 1024 * 1024),
19923
19996
  width: positiveIntAtMost(16384),
19924
19997
  height: positiveIntAtMost(16384),
19925
- alt: z81.string().trim().min(1).max(240)
19998
+ alt: z82.string().trim().min(1).max(240)
19926
19999
  }).strict();
19927
20000
  var McpMediaPresentationSchema = PresentationImageSchema;
19928
- var GalleryImageSchema = z81.object({
20001
+ var GalleryImageSchema = z82.object({
19929
20002
  url: ProductMakerPreviewUrlSchema,
19930
- alt: z81.string().trim().min(1).max(240)
20003
+ alt: z82.string().trim().min(1).max(240)
19931
20004
  });
19932
20005
  var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
19933
20006
  async function imageBlocks(image, transport) {
@@ -20048,7 +20121,7 @@ async function buildMcpImageGalleryContent(rawItems, transport = "http") {
20048
20121
  __name(buildMcpImageGalleryContent, "buildMcpImageGalleryContent");
20049
20122
 
20050
20123
  // src/tools/animated-video.ts
20051
- import { z as z82 } from "zod";
20124
+ import { z as z83 } from "zod";
20052
20125
 
20053
20126
  // src/tools/paid-confirmation.ts
20054
20127
  function describeMarketStudyChoice(enabled) {
@@ -20261,44 +20334,44 @@ function describeAnimatedVideoPrices() {
20261
20334
  return MOTION_GRAPHICS_DURATIONS.map((d) => `${d} s = ${creditsFor(d)} cr\xE9ditos (US$${usdFor(d)})`).join(", ");
20262
20335
  }
20263
20336
  __name(describeAnimatedVideoPrices, "describeAnimatedVideoPrices");
20264
- var DurationInput = z82.union(MOTION_GRAPHICS_DURATIONS.map((d) => z82.literal(d)));
20265
- var CreateAnimatedVideoInput = z82.object({
20337
+ var DurationInput = z83.union(MOTION_GRAPHICS_DURATIONS.map((d) => z83.literal(d)));
20338
+ var CreateAnimatedVideoInput = z83.object({
20266
20339
  // Plain text, not `.url()`: users type «cal.com», and the web accepts it.
20267
20340
  // normalizeWebAddress (shared with the web) adds https:// and refuses
20268
20341
  // anything that is not a public http(s) address.
20269
- landingUrl: z82.string().trim().min(1).describe("Enlace p\xFAblico de la p\xE1gina del servicio, como lo dio el usuario (\xABcal.com\xBB o \xABhttps://cal.com\xBB). El video sale de lo que muestra esa p\xE1gina: su marca, colores y mensajes."),
20342
+ landingUrl: z83.string().trim().min(1).describe("Enlace p\xFAblico de la p\xE1gina del servicio, como lo dio el usuario (\xABcal.com\xBB o \xABhttps://cal.com\xBB). El video sale de lo que muestra esa p\xE1gina: su marca, colores y mensajes."),
20270
20343
  format: MotionGraphicsFormatSchema.describe('Formato: "vertical" (9:16, Reels/TikTok), "square" (1:1, feed) u "horizontal" (16:9, YouTube/web). Si el usuario no lo dijo, PREG\xDANTALE.'),
20271
20344
  durationSec: DurationInput.describe(`Duraci\xF3n en segundos: ${MOTION_GRAPHICS_DURATIONS.join(", ")}. Fija el precio (ver la descripci\xF3n de la herramienta). Si el usuario no la dijo, PREG\xDANTALE.`),
20272
20345
  language: MotionGraphicsLanguageSchema.describe('Idioma de los textos del video: "es", "en" o "pt".'),
20273
- notes: z82.string().trim().max(MOTION_GRAPHICS_NOTES_MAX_CHARS).optional().describe("Opcional. Indicaciones para el video en lenguaje natural (ej. enf\xF3cate en los precios, tono m\xE1s formal, menciona la prueba gratis).")
20346
+ notes: z83.string().trim().max(MOTION_GRAPHICS_NOTES_MAX_CHARS).optional().describe("Opcional. Indicaciones para el video en lenguaje natural (ej. enf\xF3cate en los precios, tono m\xE1s formal, menciona la prueba gratis).")
20274
20347
  }).strict();
20275
20348
  var FORMAT_LABELS = {
20276
20349
  vertical: "vertical 9:16",
20277
20350
  square: "cuadrado 1:1",
20278
20351
  horizontal: "horizontal 16:9"
20279
20352
  };
20280
- var AnimatedVideoResultSchema = z82.object({
20281
- status: z82.enum([
20353
+ var AnimatedVideoResultSchema = z83.object({
20354
+ status: z83.enum([
20282
20355
  "pending",
20283
20356
  "done",
20284
20357
  "error"
20285
20358
  ]),
20286
- serviceMode: z82.literal("motion_graphics"),
20287
- finalMp4Url: z82.string().optional(),
20288
- error: z82.string().optional(),
20289
- motionGraphics: z82.object({
20359
+ serviceMode: z83.literal("motion_graphics"),
20360
+ finalMp4Url: z83.string().optional(),
20361
+ error: z83.string().optional(),
20362
+ motionGraphics: z83.object({
20290
20363
  stage: MotionGraphicsStageSchema,
20291
20364
  format: MotionGraphicsFormatSchema,
20292
- durationSec: z82.number(),
20293
- width: z82.number().optional(),
20294
- height: z82.number().optional(),
20365
+ durationSec: z83.number(),
20366
+ width: z83.number().optional(),
20367
+ height: z83.number().optional(),
20295
20368
  language: MotionGraphicsLanguageSchema.optional(),
20296
- queuedAt: z82.string().optional(),
20297
- jobsAhead: z82.number().int().nonnegative().optional(),
20298
- stageStartedAt: z82.string().optional(),
20299
- renderProgress: z82.number().optional(),
20300
- activity: z82.array(MotionGraphicsActivitySchema).optional().catch(void 0),
20301
- previewUrl: z82.string().optional()
20369
+ queuedAt: z83.string().optional(),
20370
+ jobsAhead: z83.number().int().nonnegative().optional(),
20371
+ stageStartedAt: z83.string().optional(),
20372
+ renderProgress: z83.number().optional(),
20373
+ activity: z83.array(MotionGraphicsActivitySchema).optional().catch(void 0),
20374
+ previewUrl: z83.string().optional()
20302
20375
  }).passthrough()
20303
20376
  }).passthrough();
20304
20377
  function parseAnimatedVideoResult(value) {
@@ -20460,10 +20533,10 @@ function registerAnimatedVideoTools(server, api) {
20460
20533
  __name(registerAnimatedVideoTools, "registerAnimatedVideoTools");
20461
20534
 
20462
20535
  // src/tools/winning-product-image.ts
20463
- import { z as z83 } from "zod";
20464
- var WinnerReferenceInput = z83.object({
20465
- runId: z83.string().uuid(),
20466
- candidateSourceId: z83.string().trim().min(1).max(160)
20536
+ import { z as z84 } from "zod";
20537
+ var WinnerReferenceInput = z84.object({
20538
+ runId: z84.string().uuid(),
20539
+ candidateSourceId: z84.string().trim().min(1).max(160)
20467
20540
  }).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
20468
20541
  async function resolveWinnerImages(api, winnerReference, images) {
20469
20542
  if (!winnerReference) return images;
@@ -20500,60 +20573,60 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
20500
20573
  var createServiceVideoGuidance = getProductMakerCapabilityModelGuidance("create_service_video");
20501
20574
  var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
20502
20575
  var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
20503
- var CreateProductTaskInput = z84.object({
20576
+ var CreateProductTaskInput = z85.object({
20504
20577
  images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
20505
20578
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
20506
- projectId: z84.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
20507
- productUrl: z84.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."),
20579
+ projectId: z85.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
20580
+ productUrl: z85.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."),
20508
20581
  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.'),
20509
20582
  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.'),
20510
- price: z84.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.'),
20511
- compareAtPrice: z84.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".'),
20512
- offer: z84.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.'),
20513
- paymentMethods: z84.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.'),
20514
- productContext: z84.string().max(PRODUCT_CONTEXT_MAX_CHARS).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."),
20515
- productLabel: z84.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.'),
20583
+ price: z85.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.'),
20584
+ compareAtPrice: z85.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".'),
20585
+ offer: z85.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.'),
20586
+ paymentMethods: z85.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.'),
20587
+ productContext: z85.string().max(PRODUCT_CONTEXT_MAX_CHARS).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."),
20588
+ productLabel: z85.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.'),
20516
20589
  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); "problem_solution" en single_call abre sin el producto y el producto entra por referencia en su beat de soluci\xF3n. 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.'),
20517
20590
  animationStyle: AnimationStyleEnum.optional().describe('Opcional. Estilo visual SOLO para presets animados ("pixar_problem" o "pixar_sassy") \u2014 la API lo rechaza con cualquier otro preset. Opciones: "pixar_3d" (default, look 3D de pel\xEDcula animada), "claymation" (plastilina stop-motion artesanal), "wes_anderson" (tableau sim\xE9trico pastel), "sci_fi" (futurista con HUDs y ne\xF3n), "realista" (fotorrealista, fiel al producto). Si el usuario pide un look animado sin nombrar el estilo, omite el campo.'),
20518
- durationSeconds: z84.union([
20519
- z84.literal(15),
20520
- z84.literal(30)
20591
+ durationSeconds: z85.union([
20592
+ z85.literal(15),
20593
+ z85.literal(30)
20521
20594
  ]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
20522
- pauseForAngleReview: z84.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."),
20523
- aiDecidesAll: z84.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."),
20595
+ pauseForAngleReview: z85.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."),
20596
+ aiDecidesAll: z85.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."),
20524
20597
  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.'),
20525
20598
  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.'),
20526
20599
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
20527
20600
  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).'),
20528
- videoAngleCount: z84.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."),
20601
+ videoAngleCount: z85.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."),
20529
20602
  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.'),
20530
- outputs: z84.array(z84.enum([
20603
+ outputs: z85.array(z85.enum([
20531
20604
  "landing",
20532
20605
  "video",
20533
20606
  "image"
20534
20607
  ])).min(1).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}`),
20535
- competitorScanEnabled: z84.boolean().optional().describe("Opcional. Default false: omitirlo significa SIN estudio de mercado. Antes de crear, llama estimate_market_study_cost con kind=product_task, muestra al usuario el costo con y sin estudio y preg\xFAntale si lo quiere; env\xEDa true solo si lo acepta (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."),
20536
- replicateWinnerWhenFound: z84.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."),
20537
- brandId: z84.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."),
20538
- actorId: z84.string().trim().min(1).max(120).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."),
20608
+ competitorScanEnabled: z85.boolean().optional().describe("Opcional. Default false: omitirlo significa SIN estudio de mercado. Antes de crear, llama estimate_market_study_cost con kind=product_task, muestra al usuario el costo con y sin estudio y preg\xFAntale si lo quiere; env\xEDa true solo si lo acepta (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."),
20609
+ replicateWinnerWhenFound: z85.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."),
20610
+ brandId: z85.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."),
20611
+ actorId: z85.string().trim().min(1).max(120).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."),
20539
20612
  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.'),
20540
- creativeDirection: z84.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.'),
20541
- headline: z84.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."),
20542
- subheadline: z84.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."),
20613
+ creativeDirection: z85.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.'),
20614
+ headline: z85.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."),
20615
+ subheadline: z85.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."),
20543
20616
  landingStrategy: LandingStrategyEnum.optional().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".'),
20544
20617
  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".')
20545
20618
  }).strict();
20546
- var CreateServiceVideoInput = z84.object({
20547
- landingUrl: z84.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
20548
- additionalContext: z84.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
20619
+ var CreateServiceVideoInput = z85.object({
20620
+ landingUrl: z85.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
20621
+ additionalContext: z85.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
20549
20622
  language: Lang.describe("Idioma del video: es, en o pt."),
20550
- voiceId: z84.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.'),
20551
- brandId: z84.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
20552
- reviewMode: z84.enum([
20623
+ voiceId: z85.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.'),
20624
+ brandId: z85.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
20625
+ reviewMode: z85.enum([
20553
20626
  "automatic",
20554
20627
  "guided"
20555
20628
  ]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
20556
- videoPreset: z84.enum([
20629
+ videoPreset: z85.enum([
20557
20630
  "auto",
20558
20631
  "ugc_dynamic",
20559
20632
  "ugc_how_to",
@@ -20563,128 +20636,128 @@ var CreateServiceVideoInput = z84.object({
20563
20636
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
20564
20637
  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.')
20565
20638
  }).strict();
20566
- var GetTaskStatusInput = z84.object({
20567
- taskId: z84.string().min(1),
20568
- waitSeconds: z84.number().int().min(0).max(120).optional()
20639
+ var GetTaskStatusInput = z85.object({
20640
+ taskId: z85.string().min(1),
20641
+ waitSeconds: z85.number().int().min(0).max(120).optional()
20569
20642
  });
20570
- var ListTasksInput = z84.object({
20571
- limit: z84.number().int().min(1).max(50).optional(),
20572
- offset: z84.number().int().min(0).optional(),
20573
- search: z84.string().optional()
20643
+ var ListTasksInput = z85.object({
20644
+ limit: z85.number().int().min(1).max(50).optional(),
20645
+ offset: z85.number().int().min(0).optional(),
20646
+ search: z85.string().optional()
20574
20647
  });
20575
20648
  var MCP_REVIEW_LIST_FIELD_MAX = IMAGE_WIZARD_LIST_FIELD_MAX;
20576
20649
  var MCP_REVIEW_FEATURE_ITEM_MAX = IMAGE_FEATURE_ITEM_MAX;
20577
- var EditTaskDraftInput = z84.object({
20578
- taskId: z84.string().min(1),
20579
- angleIndex: z84.number().int().min(0),
20580
- angle: z84.object({
20581
- angle: z84.string().min(1).max(480),
20582
- buyerPersona: z84.string().min(1).max(360),
20583
- actor: z84.string().min(1).max(360).optional(),
20584
- actorId: z84.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."),
20585
- gender: z84.enum([
20650
+ var EditTaskDraftInput = z85.object({
20651
+ taskId: z85.string().min(1),
20652
+ angleIndex: z85.number().int().min(0),
20653
+ angle: z85.object({
20654
+ angle: z85.string().min(1).max(480),
20655
+ buyerPersona: z85.string().min(1).max(360),
20656
+ actor: z85.string().min(1).max(360).optional(),
20657
+ actorId: z85.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."),
20658
+ gender: z85.enum([
20586
20659
  "female",
20587
20660
  "male"
20588
20661
  ]).optional(),
20589
- scriptNotes: z84.string().max(2e3).optional()
20662
+ scriptNotes: z85.string().max(2e3).optional()
20590
20663
  })
20591
20664
  });
20592
- var PendingActionPayload = z84.discriminatedUnion("kind", [
20593
- z84.object({
20594
- kind: z84.literal("product_reference_set_approval"),
20665
+ var PendingActionPayload = z85.discriminatedUnion("kind", [
20666
+ z85.object({
20667
+ kind: z85.literal("product_reference_set_approval"),
20595
20668
  scope: ProductReferenceScopeEnum.optional(),
20596
- scopeKey: z84.string().min(1).max(120).optional(),
20597
- scopeSnapshotId: z84.string().uuid().optional(),
20598
- expectedScopeHash: z84.string().min(1).max(128).optional(),
20669
+ scopeKey: z85.string().min(1).max(120).optional(),
20670
+ scopeSnapshotId: z85.string().uuid().optional(),
20671
+ expectedScopeHash: z85.string().min(1).max(128).optional(),
20599
20672
  decision: ProductReferenceResolutionDecisionEnum,
20600
20673
  reason: ProductReferenceRejectionReasonEnum.optional(),
20601
- affectedRefKeys: z84.array(z84.string().min(1).max(200)).min(1).optional(),
20602
- affectedPhotoNumbers: z84.array(z84.number().int().positive()).min(1).optional(),
20603
- recoveryAction: z84.enum([
20674
+ affectedRefKeys: z85.array(z85.string().min(1).max(200)).min(1).optional(),
20675
+ affectedPhotoNumbers: z85.array(z85.number().int().positive()).min(1).optional(),
20676
+ recoveryAction: z85.enum([
20604
20677
  "remove",
20605
20678
  "replace",
20606
20679
  "upload",
20607
20680
  "return_to_selection"
20608
20681
  ]).optional()
20609
20682
  }),
20610
- z84.object({
20611
- kind: z84.literal("product_reference_confirmation"),
20612
- selectedPhotoNumbers: z84.array(z84.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."),
20683
+ z85.object({
20684
+ kind: z85.literal("product_reference_confirmation"),
20685
+ selectedPhotoNumbers: z85.array(z85.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."),
20613
20686
  userChoice: ProductReferenceUserChoiceEnum.optional(),
20614
- confirmedProductNames: z84.array(z84.string().min(1).max(120)).min(2).max(8).optional(),
20687
+ confirmedProductNames: z85.array(z85.string().min(1).max(120)).min(2).max(8).optional(),
20615
20688
  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."),
20616
20689
  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."),
20617
- useMultiSceneShowcase: z84.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
20690
+ useMultiSceneShowcase: z85.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
20618
20691
  }),
20619
- z84.object({
20620
- kind: z84.literal("angle_review_approval"),
20692
+ z85.object({
20693
+ kind: z85.literal("angle_review_approval"),
20621
20694
  // All edits are optional — empty action body just approves the
20622
20695
  // backend-generated draft as-is. Field shapes mirror the angle-review
20623
20696
  // request contracts in @packages/types/wizard.ts; the handler routes to
20624
20697
  // the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
20625
- customAngle: z84.string().min(1).max(480).optional(),
20698
+ customAngle: z85.string().min(1).max(480).optional(),
20626
20699
  // Keep the shared MCP action within the strictest downstream contract:
20627
20700
  // autopilot/image resume endpoints cap these fields at 1500 characters.
20628
- painPoints: z84.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
20629
- benefits: z84.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
20701
+ painPoints: z85.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
20702
+ benefits: z85.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
20630
20703
  // Same policy as the two fields above: the strictest downstream contract
20631
20704
  // wins. The image endpoint caps each feature at 240 while landing/video
20632
20705
  // accept 300, and this single action routes to whichever the task is — so
20633
20706
  // accepting 300 here turns a 250-character feature on an image task into
20634
20707
  // an opaque HTTP 400 after the model already believed it had been saved.
20635
- features: z84.array(z84.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
20636
- buyerPersona: z84.string().min(1).max(360).optional(),
20708
+ features: z85.array(z85.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
20709
+ buyerPersona: z85.string().min(1).max(360).optional(),
20637
20710
  narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n) funciona en ambos formatos \u2014 en Un solo clip abre sin producto y el producto entra por referencia en su beat. La familia storyteller ("animated_storyteller", "animated_inner_journey", "animated_object_soul", "animated_timeline") no est\xE1 disponible por ahora.'),
20638
- actor: z84.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."),
20639
- actorId: z84.string().max(120).nullable().optional(),
20640
- creativeDirection: z84.string().max(2e3).optional(),
20641
- selectedAngleNumbers: z84.array(z84.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."),
20642
- angleEdits: z84.array(z84.object({
20643
- angleNumber: z84.number().int().positive(),
20644
- narrativeSelection: z84.enum([
20711
+ actor: z85.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."),
20712
+ actorId: z85.string().max(120).nullable().optional(),
20713
+ creativeDirection: z85.string().max(2e3).optional(),
20714
+ selectedAngleNumbers: z85.array(z85.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."),
20715
+ angleEdits: z85.array(z85.object({
20716
+ angleNumber: z85.number().int().positive(),
20717
+ narrativeSelection: z85.enum([
20645
20718
  "market",
20646
20719
  "guided"
20647
20720
  ]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
20648
- angle: z84.string().min(1).max(480).optional(),
20649
- buyerPersona: z84.string().min(1).max(360).optional(),
20721
+ angle: z85.string().min(1).max(480).optional(),
20722
+ buyerPersona: z85.string().min(1).max(360).optional(),
20650
20723
  narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n) funciona en ambos formatos \u2014 en Un solo clip abre sin producto y el producto entra por referencia en su beat. La familia storyteller ("animated_storyteller", "animated_inner_journey", "animated_object_soul", "animated_timeline") no est\xE1 disponible por ahora.'),
20651
- actor: z84.string().min(1).max(360).optional(),
20652
- actorId: z84.string().max(120).nullable().optional(),
20653
- creativeDirection: z84.string().max(2e3).optional()
20724
+ actor: z85.string().min(1).max(360).optional(),
20725
+ actorId: z85.string().max(120).nullable().optional(),
20726
+ creativeDirection: z85.string().max(2e3).optional()
20654
20727
  }).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)."),
20655
- gapDurationSeconds: z84.union([
20656
- z84.literal(15),
20657
- z84.literal(30)
20728
+ gapDurationSeconds: z85.union([
20729
+ z85.literal(15),
20730
+ z85.literal(30)
20658
20731
  ]).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.")
20659
20732
  }),
20660
- z84.object({
20661
- kind: z84.literal("service_angle_approval"),
20662
- angleId: z84.string().uuid().optional(),
20663
- angleNumber: z84.number().int().positive().optional(),
20664
- content: z84.string().min(1).max(480).optional(),
20665
- creativeDirection: z84.string().min(1).max(1500).optional(),
20666
- actor: z84.string().min(1).max(360).optional()
20733
+ z85.object({
20734
+ kind: z85.literal("service_angle_approval"),
20735
+ angleId: z85.string().uuid().optional(),
20736
+ angleNumber: z85.number().int().positive().optional(),
20737
+ content: z85.string().min(1).max(480).optional(),
20738
+ creativeDirection: z85.string().min(1).max(1500).optional(),
20739
+ actor: z85.string().min(1).max(360).optional()
20667
20740
  }),
20668
- z84.object({
20669
- kind: z84.literal("service_script_approval"),
20670
- voiceovers: z84.record(z84.string(), z84.string().min(1).max(600)).optional(),
20671
- visualDirections: z84.record(z84.string(), z84.string().min(1).max(1200)).optional(),
20672
- voiceoversByScene: z84.record(z84.string(), z84.string().min(1).max(600)).optional(),
20673
- visualDirectionsByScene: z84.record(z84.string(), z84.string().min(1).max(1200)).optional()
20741
+ z85.object({
20742
+ kind: z85.literal("service_script_approval"),
20743
+ voiceovers: z85.record(z85.string(), z85.string().min(1).max(600)).optional(),
20744
+ visualDirections: z85.record(z85.string(), z85.string().min(1).max(1200)).optional(),
20745
+ voiceoversByScene: z85.record(z85.string(), z85.string().min(1).max(600)).optional(),
20746
+ visualDirectionsByScene: z85.record(z85.string(), z85.string().min(1).max(1200)).optional()
20674
20747
  })
20675
20748
  ]);
20676
- var ResolvePendingActionInput = z84.object({
20677
- taskId: z84.string().min(1),
20749
+ var ResolvePendingActionInput = z85.object({
20750
+ taskId: z85.string().min(1),
20678
20751
  action: PendingActionPayload
20679
20752
  }).strict();
20680
20753
  function resolveVariantConfirmVideoTier(action) {
20681
20754
  return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
20682
20755
  }
20683
20756
  __name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
20684
- var StatusForResolveSchema = z84.object({
20757
+ var StatusForResolveSchema = z85.object({
20685
20758
  // Metadata used to select the backend resume contract. Older API responses
20686
20759
  // may omit these fields, so the resolver keeps the generic fallback.
20687
- kind: z84.enum([
20760
+ kind: z85.enum([
20688
20761
  "autopilot",
20689
20762
  "video",
20690
20763
  "image",
@@ -20692,18 +20765,18 @@ var StatusForResolveSchema = z84.object({
20692
20765
  "mix",
20693
20766
  "service"
20694
20767
  ]).optional(),
20695
- selectedOutputs: z84.array(z84.enum([
20768
+ selectedOutputs: z85.array(z85.enum([
20696
20769
  "landing",
20697
20770
  "video",
20698
20771
  "image"
20699
20772
  ])).optional(),
20700
- videoAngleCount: z84.number().int().min(1).max(3).optional(),
20701
- ugcFormat: z84.enum([
20773
+ videoAngleCount: z85.number().int().min(1).max(3).optional(),
20774
+ ugcFormat: z85.enum([
20702
20775
  "single_8s",
20703
20776
  "single_15s",
20704
20777
  "double_30s"
20705
20778
  ]).optional(),
20706
- videoStyle: z84.enum([
20779
+ videoStyle: z85.enum([
20707
20780
  "ugc",
20708
20781
  "cartoon_3d",
20709
20782
  "product_only",
@@ -20713,13 +20786,13 @@ var StatusForResolveSchema = z84.object({
20713
20786
  videoQuality: VideoQualityEnum.optional(),
20714
20787
  videoRouteId: VideoRouteIdEnum.optional(),
20715
20788
  videoModel: TaskVideoModelEnum.optional(),
20716
- videoTier: z84.enum([
20789
+ videoTier: z85.enum([
20717
20790
  "legacy",
20718
20791
  "standard",
20719
20792
  "pro",
20720
20793
  "single_call"
20721
20794
  ]).optional(),
20722
- videoResolution: z84.enum([
20795
+ videoResolution: z85.enum([
20723
20796
  "480p",
20724
20797
  "720p"
20725
20798
  ]).optional(),
@@ -20727,60 +20800,60 @@ var StatusForResolveSchema = z84.object({
20727
20800
  // A task created before a narrative was blocked/hidden must still parse,
20728
20801
  // or resolve_pending_action could never approve it.
20729
20802
  narrativeStyle: NarrativeStyle.optional(),
20730
- pauseForVideoScriptReview: z84.boolean().optional(),
20731
- pendingUserAction: z84.object({
20732
- kind: z84.string(),
20733
- candidateGrouping: z84.string().optional(),
20734
- selectedImageUrls: z84.array(z84.string()).optional(),
20735
- proposedProductNames: z84.array(z84.string()).optional(),
20803
+ pauseForVideoScriptReview: z85.boolean().optional(),
20804
+ pendingUserAction: z85.object({
20805
+ kind: z85.string(),
20806
+ candidateGrouping: z85.string().optional(),
20807
+ selectedImageUrls: z85.array(z85.string()).optional(),
20808
+ proposedProductNames: z85.array(z85.string()).optional(),
20736
20809
  // Adaptive reference questions are server-owned. Echo only the evidence
20737
20810
  // identity and the choices shown by the current snapshot; never accept a
20738
20811
  // client-supplied reference set as authorization.
20739
- options: z84.array(ProductReferenceUserChoiceEnum).max(4).optional(),
20740
- mode: z84.enum([
20812
+ options: z85.array(ProductReferenceUserChoiceEnum).max(4).optional(),
20813
+ mode: z85.enum([
20741
20814
  "question",
20742
20815
  "visual_recovery"
20743
20816
  ]).optional(),
20744
20817
  /** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
20745
- canKeepSelection: z84.boolean().optional(),
20746
- decisionKey: z84.string().optional(),
20747
- questionOrdinal: z84.number().int().min(1).max(5).optional(),
20748
- questionCeiling: z84.union([
20749
- z84.literal(3),
20750
- z84.literal(5)
20818
+ canKeepSelection: z85.boolean().optional(),
20819
+ decisionKey: z85.string().optional(),
20820
+ questionOrdinal: z85.number().int().min(1).max(5).optional(),
20821
+ questionCeiling: z85.union([
20822
+ z85.literal(3),
20823
+ z85.literal(5)
20751
20824
  ]).optional(),
20752
- referenceEvidenceVersion: z84.number().int().positive().optional(),
20753
- expectedEvidenceHash: z84.string().optional(),
20754
- question: z84.object({
20755
- prompt: z84.string().min(1).max(240),
20756
- helpText: z84.string().min(1).max(300).optional(),
20757
- options: z84.array(z84.object({
20825
+ referenceEvidenceVersion: z85.number().int().positive().optional(),
20826
+ expectedEvidenceHash: z85.string().optional(),
20827
+ question: z85.object({
20828
+ prompt: z85.string().min(1).max(240),
20829
+ helpText: z85.string().min(1).max(300).optional(),
20830
+ options: z85.array(z85.object({
20758
20831
  value: ProductReferenceUserChoiceEnum,
20759
- label: z84.string().min(1).max(120),
20760
- description: z84.string().min(1).max(240).optional()
20832
+ label: z85.string().min(1).max(120),
20833
+ description: z85.string().min(1).max(240).optional()
20761
20834
  })).min(2).max(4)
20762
20835
  }).optional(),
20763
20836
  scope: ProductReferenceScopeEnum.optional(),
20764
- scopeKey: z84.string().optional(),
20765
- scopeSnapshotId: z84.string().uuid().optional(),
20766
- scopeHash: z84.string().optional(),
20767
- baseReferenceSetHash: z84.string().optional(),
20768
- phase: z84.enum([
20837
+ scopeKey: z85.string().optional(),
20838
+ scopeSnapshotId: z85.string().uuid().optional(),
20839
+ scopeHash: z85.string().optional(),
20840
+ baseReferenceSetHash: z85.string().optional(),
20841
+ phase: z85.enum([
20769
20842
  "preparation",
20770
20843
  "final"
20771
20844
  ]).optional(),
20772
- selectedRefKeys: z84.array(z84.string().min(1).max(200)).optional(),
20773
- allowedDecisions: z84.array(ProductReferenceResolutionDecisionEnum).optional(),
20774
- previews: z84.array(z84.object({
20775
- refKey: z84.string().min(1).max(200)
20845
+ selectedRefKeys: z85.array(z85.string().min(1).max(200)).optional(),
20846
+ allowedDecisions: z85.array(ProductReferenceResolutionDecisionEnum).optional(),
20847
+ previews: z85.array(z85.object({
20848
+ refKey: z85.string().min(1).max(200)
20776
20849
  }).passthrough()).optional(),
20777
- customAngleDraft: z84.string().optional(),
20778
- painPointsDraft: z84.string().optional(),
20779
- benefitsDraft: z84.string().optional(),
20780
- featuresDraft: z84.array(z84.string()).optional(),
20781
- angleOptions: z84.array(z84.object({
20782
- index: z84.number().int().nonnegative(),
20783
- angle: z84.string().min(1)
20850
+ customAngleDraft: z85.string().optional(),
20851
+ painPointsDraft: z85.string().optional(),
20852
+ benefitsDraft: z85.string().optional(),
20853
+ featuresDraft: z85.array(z85.string()).optional(),
20854
+ angleOptions: z85.array(z85.object({
20855
+ index: z85.number().int().nonnegative(),
20856
+ angle: z85.string().min(1)
20784
20857
  }).passthrough()).min(1).max(5).optional(),
20785
20858
  // Recommendation consumed only when the caller explicitly sends
20786
20859
  // gapDurationSeconds: 30 in the angle approval action.
@@ -20790,17 +20863,17 @@ var StatusForResolveSchema = z84.object({
20790
20863
  // keys. `actorId` (the saved custom actor the picker stored) was silently
20791
20864
  // dropped here, so the approval handler below could not echo it back on the
20792
20865
  // PATCH — the selection looked accepted and reached no render.
20793
- angles: z84.array(z84.object({
20794
- id: z84.string().uuid(),
20795
- content: z84.string(),
20796
- creativeDirection: z84.string(),
20797
- actor: z84.string(),
20798
- actorId: z84.string().nullable().optional()
20866
+ angles: z85.array(z85.object({
20867
+ id: z85.string().uuid(),
20868
+ content: z85.string(),
20869
+ creativeDirection: z85.string(),
20870
+ actor: z85.string(),
20871
+ actorId: z85.string().nullable().optional()
20799
20872
  }).passthrough()).optional(),
20800
- panels: z84.array(z84.object({
20801
- beatId: z84.string(),
20802
- voiceover: z84.string(),
20803
- visualDirection: z84.string()
20873
+ panels: z85.array(z85.object({
20874
+ beatId: z85.string(),
20875
+ voiceover: z85.string(),
20876
+ visualDirection: z85.string()
20804
20877
  }).passthrough()).optional()
20805
20878
  }).optional()
20806
20879
  }).passthrough();
@@ -21147,8 +21220,8 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
21147
21220
  server.registerTool("verify_landing_commerce", {
21148
21221
  description: getProductMakerCapabilityModelGuidance("verify_landing_commerce").summary + " Verifica una correcci\xF3n manual de precios, tachados o packs de una landing editable existente. Solo relee Shopify y los recibos externos; no cambia precios, inventario, SKU ni compra una edici\xF3n. Pasa taskId y editId de la edici\xF3n ya conocida; nunca inventes IDs ni pidas repetir el cambio. Devuelve el estado can\xF3nico por proveedor: conserva el aviso pendiente hasta confirmar los valores reales. Solo despu\xE9s de confirmar todos los valores, el servidor puede volver a habilitar la compra. Web guardada no demuestra publicaci\xF3n p\xFAblica ni checkout; muestra las correcciones y enlaces pendientes sin c\xF3digos t\xE9cnicos. La disponibilidad del editor conserva sus permisos actuales.",
21149
21222
  inputSchema: {
21150
- taskId: z84.string().uuid(),
21151
- editId: z84.string().uuid()
21223
+ taskId: z85.string().uuid(),
21224
+ editId: z85.string().uuid()
21152
21225
  },
21153
21226
  annotations: OVERWRITES_EXTERNAL
21154
21227
  }, async (input) => {
@@ -21787,7 +21860,7 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
21787
21860
  __name(registerTaskTools, "registerTaskTools");
21788
21861
 
21789
21862
  // src/tools/creatives.ts
21790
- import { z as z85 } from "zod";
21863
+ import { z as z86 } from "zod";
21791
21864
  var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
21792
21865
  var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
21793
21866
  var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
@@ -21798,71 +21871,71 @@ var CreativeRefs = {
21798
21871
  images: ImagesInput,
21799
21872
  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.'),
21800
21873
  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.'),
21801
- price: z85.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.'),
21802
- offer: z85.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.'),
21803
- compareAtPrice: z85.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
21804
- productContext: z85.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."),
21805
- productLabel: z85.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.'),
21806
- buyerPersona: z85.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.'),
21807
- isCombo: z85.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
21808
- competitorScanEnabled: z85.boolean().optional().describe("Opcional. Default false: omitirlo significa SIN estudio de mercado. Antes de crear, llama estimate_market_study_cost, muestra al usuario el costo con y sin estudio y preg\xFAntale si lo quiere; env\xEDa true solo si lo acepta (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."),
21809
- brandId: z85.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.")
21874
+ price: z86.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.'),
21875
+ offer: z86.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.'),
21876
+ compareAtPrice: z86.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
21877
+ productContext: z86.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."),
21878
+ productLabel: z86.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.'),
21879
+ buyerPersona: z86.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.'),
21880
+ isCombo: z86.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
21881
+ competitorScanEnabled: z86.boolean().optional().describe("Opcional. Default false: omitirlo significa SIN estudio de mercado. Antes de crear, llama estimate_market_study_cost, muestra al usuario el costo con y sin estudio y preg\xFAntale si lo quiere; env\xEDa true solo si lo acepta (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."),
21882
+ brandId: z86.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.")
21810
21883
  };
21811
- var VideoPresenter = z85.discriminatedUnion("mode", [
21812
- z85.object({
21813
- mode: z85.literal("none")
21884
+ var VideoPresenter = z86.discriminatedUnion("mode", [
21885
+ z86.object({
21886
+ mode: z86.literal("none")
21814
21887
  }).strict(),
21815
- z85.object({
21816
- mode: z85.literal("saved_actor"),
21817
- actorId: z85.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
21888
+ z86.object({
21889
+ mode: z86.literal("saved_actor"),
21890
+ actorId: z86.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
21818
21891
  }).strict(),
21819
- z85.object({
21820
- mode: z85.literal("described"),
21821
- description: z85.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
21892
+ z86.object({
21893
+ mode: z86.literal("described"),
21894
+ description: z86.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
21822
21895
  }).strict()
21823
21896
  ]);
21824
- var VideoCreativeSetup = z85.discriminatedUnion("mode", [
21825
- z85.object({
21826
- mode: z85.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
21897
+ var VideoCreativeSetup = z86.discriminatedUnion("mode", [
21898
+ z86.object({
21899
+ mode: z86.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
21827
21900
  }).strict(),
21828
- z85.object({
21829
- mode: z85.literal("guided"),
21901
+ z86.object({
21902
+ mode: z86.literal("guided"),
21830
21903
  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. Todas las narrativas funcionan en Un solo clip y Multiescena.'),
21831
- buyerPersona: z85.string().trim().min(1).max(360),
21904
+ buyerPersona: z86.string().trim().min(1).max(360),
21832
21905
  animationStyle: AnimationStyleEnum.optional().describe('Opcional. Estilo visual SOLO para presets animados ("pixar_problem" o "pixar_sassy") \u2014 la API lo rechaza con cualquier otro preset. Opciones: "pixar_3d" (default, look 3D de pel\xEDcula animada), "claymation" (plastilina stop-motion artesanal), "wes_anderson" (tableau sim\xE9trico pastel), "sci_fi" (futurista con HUDs y ne\xF3n), "realista" (fotorrealista, fiel al producto). Si el usuario pide un look animado sin nombrar el estilo, omite el campo.'),
21833
21906
  presenter: VideoPresenter,
21834
- creativeDirection: z85.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
21907
+ creativeDirection: z86.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
21835
21908
  }).strict()
21836
21909
  ]);
21837
- var VideoInput = z85.object({
21910
+ var VideoInput = z86.object({
21838
21911
  images: CreativeRefs.images.optional(),
21839
21912
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
21840
- title: z85.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
21841
- primaryAngle: z85.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".'),
21913
+ title: z86.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
21914
+ primaryAngle: z86.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".'),
21842
21915
  language: CreativeRefs.language,
21843
21916
  country: CreativeRefs.country,
21844
- aspectRatio: z85.enum([
21917
+ aspectRatio: z86.enum([
21845
21918
  "9:16",
21846
21919
  "16:9",
21847
21920
  "Auto"
21848
21921
  ]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
21849
- durationSeconds: z85.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."),
21850
- videoAngleCount: z85.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."),
21922
+ durationSeconds: z86.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."),
21923
+ videoAngleCount: z86.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."),
21851
21924
  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.'),
21852
21925
  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."),
21853
21926
  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.'),
21854
21927
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
21855
21928
  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.'),
21856
- features: z85.array(z85.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
21929
+ features: z86.array(z86.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
21857
21930
  price: CreativeRefs.price,
21858
21931
  offer: CreativeRefs.offer,
21859
21932
  productContext: CreativeRefs.productContext,
21860
21933
  productLabel: CreativeRefs.productLabel,
21861
- cta: z85.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.'),
21862
- scriptNotes: z85.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.'),
21934
+ cta: z86.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.'),
21935
+ scriptNotes: z86.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.'),
21863
21936
  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.'),
21864
21937
  competitorScanEnabled: CreativeRefs.competitorScanEnabled,
21865
- replicateWinnerWhenFound: z85.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."),
21938
+ replicateWinnerWhenFound: z86.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."),
21866
21939
  brandId: CreativeRefs.brandId
21867
21940
  }).strict();
21868
21941
  var FreeVideoQualityEnum = VideoQualityEnum;
@@ -21880,7 +21953,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
21880
21953
  length: 29
21881
21954
  }, (_, index) => index + 2)
21882
21955
  };
21883
- var FreeVideoModelIdEnum = z85.enum([
21956
+ var FreeVideoModelIdEnum = z86.enum([
21884
21957
  "grok-imagine-video-1-5-preview",
21885
21958
  "minimax-h3/reference-to-video",
21886
21959
  "wan/3-0-video",
@@ -21891,65 +21964,65 @@ var FREE_SELECTABLE_MODEL_IDS = [
21891
21964
  "minimax-h3/reference-to-video",
21892
21965
  "wan/3-0-video"
21893
21966
  ];
21894
- var FreeVideoInput = z85.object({
21967
+ var FreeVideoInput = z86.object({
21895
21968
  images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
21896
- rawPrompt: z85.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."),
21969
+ rawPrompt: z86.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."),
21897
21970
  language: CreativeRefs.language,
21898
21971
  quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
21899
21972
  // Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
21900
21973
  // parsed ONLY so the handler can reject it with a message naming its
21901
21974
  // replacement — dropping it silently would turn a caller's explicit
21902
21975
  // Pro++ pick into a quiet fallback to Wan.
21903
- freeProModel: z85.enum([
21976
+ freeProModel: z86.enum([
21904
21977
  "wan",
21905
21978
  "seedance"
21906
21979
  ]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
21907
21980
  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.'),
21908
- durationSeconds: z85.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."),
21981
+ durationSeconds: z86.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."),
21909
21982
  videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
21910
- generateAiMusic: z85.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
21911
- addSubtitles: z85.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
21912
- idempotencyKey: z85.string().uuid().optional().describe("Opcional. Se acepta por compatibilidad pero se ignora: la identidad del reintento se deriva autom\xE1ticamente de los argumentos sem\xE1nticos, as\xED que un retry con los mismos argumentos ya es idempotente sin este campo.")
21983
+ generateAiMusic: z86.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
21984
+ addSubtitles: z86.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
21985
+ idempotencyKey: z86.string().uuid().optional().describe("Opcional. Se acepta por compatibilidad pero se ignora: la identidad del reintento se deriva autom\xE1ticamente de los argumentos sem\xE1nticos, as\xED que un retry con los mismos argumentos ya es idempotente sin este campo.")
21913
21986
  }).strict();
21914
21987
  var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
21915
- var ImageCreativeSetup = z85.discriminatedUnion("mode", [
21916
- z85.object({
21917
- mode: z85.literal("automatic")
21988
+ var ImageCreativeSetup = z86.discriminatedUnion("mode", [
21989
+ z86.object({
21990
+ mode: z86.literal("automatic")
21918
21991
  }).strict(),
21919
- z85.object({
21920
- mode: z85.literal("guided"),
21921
- creativeArchetype: z85.union([
21992
+ z86.object({
21993
+ mode: z86.literal("guided"),
21994
+ creativeArchetype: z86.union([
21922
21995
  ImageCreativeArchetypeEnum,
21923
- z85.literal("ai_decides")
21996
+ z86.literal("ai_decides")
21924
21997
  ]),
21925
- visualTreatment: z85.union([
21998
+ visualTreatment: z86.union([
21926
21999
  ImageCreativeVisualTreatmentEnum,
21927
- z85.literal("ai_decides")
22000
+ z86.literal("ai_decides")
21928
22001
  ]),
21929
22002
  aspectRatio: ImageCreativeAspectRatioEnum,
21930
- nVariants: z85.union([
21931
- z85.literal(1),
21932
- z85.literal(2),
21933
- z85.literal(3),
21934
- z85.literal(4),
21935
- z85.literal(6)
22003
+ nVariants: z86.union([
22004
+ z86.literal(1),
22005
+ z86.literal(2),
22006
+ z86.literal(3),
22007
+ z86.literal(4),
22008
+ z86.literal(6)
21936
22009
  ]),
21937
- imageModel: z85.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.'),
21938
- styleMix: z85.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
21939
- generateAdCopy: z85.boolean(),
21940
- competitorScanEnabled: z85.boolean(),
21941
- productContext: z85.string().trim().min(1).max(3e3).nullable(),
21942
- creativeDirection: z85.string().trim().min(1).max(500).nullable(),
21943
- brandColors: z85.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.'),
21944
- headline: z85.string().trim().min(1).max(120).nullable(),
21945
- subheadline: z85.string().trim().min(1).max(160).nullable()
22010
+ imageModel: z86.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.'),
22011
+ styleMix: z86.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
22012
+ generateAdCopy: z86.boolean(),
22013
+ competitorScanEnabled: z86.boolean(),
22014
+ productContext: z86.string().trim().min(1).max(3e3).nullable(),
22015
+ creativeDirection: z86.string().trim().min(1).max(500).nullable(),
22016
+ brandColors: z86.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.'),
22017
+ headline: z86.string().trim().min(1).max(120).nullable(),
22018
+ subheadline: z86.string().trim().min(1).max(160).nullable()
21946
22019
  }).strict()
21947
22020
  ]).superRefine((setup, context) => {
21948
22021
  if (setup.mode !== "guided") return;
21949
22022
  const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
21950
22023
  if (needsStyleMix && setup.styleMix === null) {
21951
22024
  context.addIssue({
21952
- code: z85.ZodIssueCode.custom,
22025
+ code: z86.ZodIssueCode.custom,
21953
22026
  path: [
21954
22027
  "styleMix"
21955
22028
  ],
@@ -21958,7 +22031,7 @@ var ImageCreativeSetup = z85.discriminatedUnion("mode", [
21958
22031
  }
21959
22032
  if (!needsStyleMix && setup.styleMix !== null) {
21960
22033
  context.addIssue({
21961
- code: z85.ZodIssueCode.custom,
22034
+ code: z86.ZodIssueCode.custom,
21962
22035
  path: [
21963
22036
  "styleMix"
21964
22037
  ],
@@ -21967,7 +22040,7 @@ var ImageCreativeSetup = z85.discriminatedUnion("mode", [
21967
22040
  }
21968
22041
  if (imageResolutionOf(setup.imageModel) === "2k" && setup.aspectRatio === "4:5") {
21969
22042
  context.addIssue({
21970
- code: z85.ZodIssueCode.custom,
22043
+ code: z86.ZodIssueCode.custom,
21971
22044
  path: [
21972
22045
  "aspectRatio"
21973
22046
  ],
@@ -21975,54 +22048,54 @@ var ImageCreativeSetup = z85.discriminatedUnion("mode", [
21975
22048
  });
21976
22049
  }
21977
22050
  });
21978
- var LandingCreativeSetup = z85.discriminatedUnion("mode", [
21979
- z85.object({
21980
- mode: z85.literal("automatic")
22051
+ var LandingCreativeSetup = z86.discriminatedUnion("mode", [
22052
+ z86.object({
22053
+ mode: z86.literal("automatic")
21981
22054
  }).strict(),
21982
- z85.object({
21983
- mode: z85.literal("guided"),
22055
+ z86.object({
22056
+ mode: z86.literal("guided"),
21984
22057
  landingStrategy: LandingStrategyEnum,
21985
22058
  landingImageFormat: LandingImageFormatEnum,
21986
- competitorScanEnabled: z85.boolean(),
21987
- paymentMethods: z85.string().trim().min(1).max(240).nullable(),
21988
- productContext: z85.string().trim().min(1).max(3e3).nullable(),
21989
- creativeDirection: z85.string().trim().min(1).max(500).nullable(),
21990
- headline: z85.string().trim().min(1).max(120).nullable(),
21991
- subheadline: z85.string().trim().min(1).max(160).nullable()
22059
+ competitorScanEnabled: z86.boolean(),
22060
+ paymentMethods: z86.string().trim().min(1).max(240).nullable(),
22061
+ productContext: z86.string().trim().min(1).max(3e3).nullable(),
22062
+ creativeDirection: z86.string().trim().min(1).max(500).nullable(),
22063
+ headline: z86.string().trim().min(1).max(120).nullable(),
22064
+ subheadline: z86.string().trim().min(1).max(160).nullable()
21992
22065
  }).strict()
21993
22066
  ]);
21994
- var ImageInput = z85.object({
22067
+ var ImageInput = z86.object({
21995
22068
  images: CreativeRefs.images.optional(),
21996
22069
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
21997
- productTitle: z85.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
21998
- primaryAngle: z85.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.'),
22070
+ productTitle: z86.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
22071
+ primaryAngle: z86.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.'),
21999
22072
  buyerPersona: CreativeRefs.buyerPersona,
22000
22073
  language: CreativeRefs.language,
22001
22074
  country: CreativeRefs.country,
22002
22075
  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."),
22003
22076
  imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
22004
- features: z85.array(z85.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
22077
+ features: z86.array(z86.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
22005
22078
  price: CreativeRefs.price,
22006
- omitPrice: z85.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."),
22079
+ omitPrice: z86.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."),
22007
22080
  compareAtPrice: CreativeRefs.compareAtPrice,
22008
22081
  offer: CreativeRefs.offer,
22009
22082
  productLabel: CreativeRefs.productLabel,
22010
22083
  isCombo: CreativeRefs.isCombo,
22011
22084
  brandId: CreativeRefs.brandId
22012
22085
  });
22013
- var EditImageCreativeInput = z85.object({
22014
- taskId: z85.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
22015
- variantIndex: z85.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
22016
- clientRequestId: z85.string().min(1).max(160).optional().describe("Identidad estable de esta correcci\xF3n; reutil\xEDzala al reconciliar una respuesta perdida, no para otra instrucci\xF3n."),
22017
- instruction: z85.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".')
22086
+ var EditImageCreativeInput = z86.object({
22087
+ taskId: z86.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
22088
+ variantIndex: z86.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
22089
+ clientRequestId: z86.string().min(1).max(160).optional().describe("Identidad estable de esta correcci\xF3n; reutil\xEDzala al reconciliar una respuesta perdida, no para otra instrucci\xF3n."),
22090
+ instruction: z86.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".')
22018
22091
  });
22019
- var LandingInput = z85.object({
22092
+ var LandingInput = z86.object({
22020
22093
  images: CreativeRefs.images.optional(),
22021
22094
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
22022
22095
  language: CreativeRefs.language,
22023
22096
  country: CreativeRefs.country,
22024
22097
  creativeSetup: LandingCreativeSetup.describe("Configuraci\xF3n obligatoria de landing cl\xE1sica equivalente al wizard web. No expone landing editable/code mientras siga siendo admin-only."),
22025
- salesAngle: z85.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.'),
22098
+ salesAngle: z86.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.'),
22026
22099
  buyerPersona: CreativeRefs.buyerPersona,
22027
22100
  price: CreativeRefs.price,
22028
22101
  compareAtPrice: CreativeRefs.compareAtPrice,
@@ -22301,8 +22374,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
22301
22374
  server.registerTool("get_image_edit_status", {
22302
22375
  description: imageEditStatusGuidance.summary,
22303
22376
  inputSchema: {
22304
- taskId: z85.string().uuid(),
22305
- operationId: z85.string().uuid()
22377
+ taskId: z86.string().uuid(),
22378
+ operationId: z86.string().uuid()
22306
22379
  },
22307
22380
  annotations: READS_INTERNAL
22308
22381
  }, async (input) => {
@@ -22359,10 +22432,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
22359
22432
  __name(registerCreativeTools, "registerCreativeTools");
22360
22433
 
22361
22434
  // src/tools/creative-variants.ts
22362
- import { z as z86 } from "zod";
22435
+ import { z as z87 } from "zod";
22363
22436
  var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
22364
22437
  var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
22365
- var LandingSectionKeyEnum = z86.enum([
22438
+ var LandingSectionKeyEnum = z87.enum([
22366
22439
  "problem_hook",
22367
22440
  "problem_cost",
22368
22441
  "solution_mechanism",
@@ -22402,24 +22475,24 @@ var LandingSectionKeyEnum = z86.enum([
22402
22475
  "lifestyle_fit",
22403
22476
  "join_lifestyle"
22404
22477
  ]);
22405
- var CreativeVariantKindEnum = z86.enum([
22478
+ var CreativeVariantKindEnum = z87.enum([
22406
22479
  "video",
22407
22480
  "image",
22408
22481
  "landing"
22409
22482
  ]);
22410
- var EstimateCreativeVariantInputBase = z86.object({
22411
- sourceTaskId: z86.string().uuid().describe("ID de la tarea original completada."),
22483
+ var EstimateCreativeVariantInputBase = z87.object({
22484
+ sourceTaskId: z87.string().uuid().describe("ID de la tarea original completada."),
22412
22485
  kind: CreativeVariantKindEnum,
22413
22486
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
22414
22487
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
22415
- nVariants: z86.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
22488
+ nVariants: z87.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
22416
22489
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
22417
- instructions: z86.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.")
22490
+ instructions: z87.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.")
22418
22491
  }).strict();
22419
22492
  var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
22420
22493
  if (input.kind === "video" && input.nVariants !== void 0) {
22421
22494
  ctx.addIssue({
22422
- code: z86.ZodIssueCode.custom,
22495
+ code: z87.ZodIssueCode.custom,
22423
22496
  path: [
22424
22497
  "nVariants"
22425
22498
  ],
@@ -22429,7 +22502,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
22429
22502
  if (input.kind !== "video") {
22430
22503
  if (input.videoPreset !== void 0) {
22431
22504
  ctx.addIssue({
22432
- code: z86.ZodIssueCode.custom,
22505
+ code: z87.ZodIssueCode.custom,
22433
22506
  path: [
22434
22507
  "videoPreset"
22435
22508
  ],
@@ -22438,7 +22511,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
22438
22511
  }
22439
22512
  if (input.videoResolution !== void 0) {
22440
22513
  ctx.addIssue({
22441
- code: z86.ZodIssueCode.custom,
22514
+ code: z87.ZodIssueCode.custom,
22442
22515
  path: [
22443
22516
  "videoResolution"
22444
22517
  ],
@@ -22448,7 +22521,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
22448
22521
  }
22449
22522
  if (input.kind !== "image" && input.nVariants !== void 0) {
22450
22523
  ctx.addIssue({
22451
- code: z86.ZodIssueCode.custom,
22524
+ code: z87.ZodIssueCode.custom,
22452
22525
  path: [
22453
22526
  "nVariants"
22454
22527
  ],
@@ -22458,7 +22531,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
22458
22531
  if (input.kind !== "landing") {
22459
22532
  if (input.sectionKey !== void 0) {
22460
22533
  ctx.addIssue({
22461
- code: z86.ZodIssueCode.custom,
22534
+ code: z87.ZodIssueCode.custom,
22462
22535
  path: [
22463
22536
  "sectionKey"
22464
22537
  ],
@@ -22467,7 +22540,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
22467
22540
  }
22468
22541
  if (input.instructions !== void 0) {
22469
22542
  ctx.addIssue({
22470
- code: z86.ZodIssueCode.custom,
22543
+ code: z87.ZodIssueCode.custom,
22471
22544
  path: [
22472
22545
  "instructions"
22473
22546
  ],
@@ -22476,31 +22549,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
22476
22549
  }
22477
22550
  }
22478
22551
  });
22479
- var CreateCreativeVariantInputBase = z86.object({
22480
- sourceTaskId: z86.string().uuid().describe("ID de la tarea original completada."),
22552
+ var CreateCreativeVariantInputBase = z87.object({
22553
+ sourceTaskId: z87.string().uuid().describe("ID de la tarea original completada."),
22481
22554
  kind: CreativeVariantKindEnum,
22482
- confirm: z86.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
22483
- clientRequestId: z86.string().uuid().describe("UUID estable para esta intenci\xF3n (obligatorio por compatibilidad de contrato; el servidor deriva la identidad real del request desde los argumentos sem\xE1nticos, as\xED que un UUID nuevo en un retry NO crea una variante duplicada). Si la API devuelve status=error, una nueva generaci\xF3n exige otra confirmaci\xF3n."),
22484
- angle: z86.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
22485
- buyerPersona: z86.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
22486
- scriptNotes: z86.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
22487
- creativeDirection: z86.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
22555
+ confirm: z87.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
22556
+ clientRequestId: z87.string().uuid().describe("UUID estable para esta intenci\xF3n (obligatorio por compatibilidad de contrato; el servidor deriva la identidad real del request desde los argumentos sem\xE1nticos, as\xED que un UUID nuevo en un retry NO crea una variante duplicada). Si la API devuelve status=error, una nueva generaci\xF3n exige otra confirmaci\xF3n."),
22557
+ angle: z87.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
22558
+ buyerPersona: z87.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
22559
+ scriptNotes: z87.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
22560
+ creativeDirection: z87.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
22488
22561
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
22489
22562
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
22490
- generateAiMusic: z86.boolean().optional().describe("Opcional para video."),
22491
- nVariants: z86.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
22563
+ generateAiMusic: z87.boolean().optional().describe("Opcional para video."),
22564
+ nVariants: z87.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
22492
22565
  imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
22493
22566
  creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
22494
22567
  visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
22495
22568
  aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
22496
- styleMix: z86.boolean().optional().describe("Opcional para imagen."),
22569
+ styleMix: z87.boolean().optional().describe("Opcional para imagen."),
22497
22570
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
22498
- instructions: z86.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.")
22571
+ instructions: z87.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.")
22499
22572
  }).strict();
22500
22573
  var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
22501
22574
  if ((input.kind === "video" || input.kind === "image") && !input.angle) {
22502
22575
  ctx.addIssue({
22503
- code: z86.ZodIssueCode.custom,
22576
+ code: z87.ZodIssueCode.custom,
22504
22577
  path: [
22505
22578
  "angle"
22506
22579
  ],
@@ -22509,7 +22582,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
22509
22582
  }
22510
22583
  if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
22511
22584
  ctx.addIssue({
22512
- code: z86.ZodIssueCode.custom,
22585
+ code: z87.ZodIssueCode.custom,
22513
22586
  path: [
22514
22587
  "instructions"
22515
22588
  ],
@@ -22555,7 +22628,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
22555
22628
  for (const field of fieldsByKind[input.kind]) {
22556
22629
  if (input[field] !== void 0) {
22557
22630
  ctx.addIssue({
22558
- code: z86.ZodIssueCode.custom,
22631
+ code: z87.ZodIssueCode.custom,
22559
22632
  path: [
22560
22633
  field
22561
22634
  ],
@@ -22688,13 +22761,13 @@ function registerCreativeVariantTools(server, api) {
22688
22761
  __name(registerCreativeVariantTools, "registerCreativeVariantTools");
22689
22762
 
22690
22763
  // src/tools/script-review.ts
22691
- import { z as z87 } from "zod";
22764
+ import { z as z88 } from "zod";
22692
22765
  var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
22693
22766
  var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
22694
22767
  var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
22695
- var GetVideoScriptInput = z87.object({
22696
- taskId: z87.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
22697
- angleKey: z87.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.')
22768
+ var GetVideoScriptInput = z88.object({
22769
+ taskId: z88.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
22770
+ angleKey: z88.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.')
22698
22771
  }).strict();
22699
22772
  var ApproveVideoScriptInput = ApproveVideoScriptCapabilityRequest;
22700
22773
  var RegenerateVideoScriptInput = RegenerateVideoScriptCapabilityRequest.extend({
@@ -22777,7 +22850,7 @@ function registerScriptReviewTools(server, api) {
22777
22850
  __name(registerScriptReviewTools, "registerScriptReviewTools");
22778
22851
 
22779
22852
  // src/tools/connections.ts
22780
- import { z as z88 } from "zod";
22853
+ import { z as z89 } from "zod";
22781
22854
  var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
22782
22855
  var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
22783
22856
  var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
@@ -22786,7 +22859,7 @@ var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list
22786
22859
  function registerConnectionTools(server, api) {
22787
22860
  server.registerTool("list_shopify_shops", {
22788
22861
  description: listShopifyShopsGuidance.summary + " Si la lista est\xE1 vac\xEDa, dile al usuario que conecte una tienda en productmaker.app/integrations antes de intentar publicar.",
22789
- inputSchema: z88.object({}).shape,
22862
+ inputSchema: z89.object({}).shape,
22790
22863
  annotations: READS_INTERNAL
22791
22864
  }, async () => {
22792
22865
  try {
@@ -22798,10 +22871,10 @@ function registerConnectionTools(server, api) {
22798
22871
  });
22799
22872
  server.registerTool("list_shopify_products", {
22800
22873
  description: 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.',
22801
- inputSchema: z88.object({
22802
- shopDomain: z88.string().min(3).max(120),
22803
- query: z88.string().trim().max(120).optional(),
22804
- taskId: z88.string().uuid().optional()
22874
+ inputSchema: z89.object({
22875
+ shopDomain: z89.string().min(3).max(120),
22876
+ query: z89.string().trim().max(120).optional(),
22877
+ taskId: z89.string().uuid().optional()
22805
22878
  }).shape,
22806
22879
  annotations: READS_EXTERNAL
22807
22880
  }, async ({ shopDomain, query, taskId }) => {
@@ -22819,7 +22892,7 @@ function registerConnectionTools(server, api) {
22819
22892
  });
22820
22893
  server.registerTool("list_meta_ad_accounts", {
22821
22894
  description: 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.",
22822
- inputSchema: z88.object({}).shape,
22895
+ inputSchema: z89.object({}).shape,
22823
22896
  annotations: READS_EXTERNAL
22824
22897
  }, async () => {
22825
22898
  try {
@@ -22831,7 +22904,7 @@ function registerConnectionTools(server, api) {
22831
22904
  });
22832
22905
  server.registerTool("list_meta_destinations", {
22833
22906
  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.",
22834
- inputSchema: z88.object({}).shape,
22907
+ inputSchema: z89.object({}).shape,
22835
22908
  annotations: READS_EXTERNAL,
22836
22909
  _meta: {
22837
22910
  "openai/widgetAccessible": true
@@ -22846,7 +22919,7 @@ function registerConnectionTools(server, api) {
22846
22919
  });
22847
22920
  server.registerTool("list_tiktok_advertisers", {
22848
22921
  description: listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.",
22849
- inputSchema: z88.object({}).shape,
22922
+ inputSchema: z89.object({}).shape,
22850
22923
  annotations: READS_EXTERNAL
22851
22924
  }, async () => {
22852
22925
  try {
@@ -22860,12 +22933,12 @@ function registerConnectionTools(server, api) {
22860
22933
  __name(registerConnectionTools, "registerConnectionTools");
22861
22934
 
22862
22935
  // src/tools/actors.ts
22863
- import { z as z89 } from "zod";
22936
+ import { z as z90 } from "zod";
22864
22937
  var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
22865
22938
  function registerActorTools(server, api) {
22866
22939
  server.registerTool("list_actors", {
22867
22940
  description: 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.",
22868
- inputSchema: z89.object({}).shape,
22941
+ inputSchema: z90.object({}).shape,
22869
22942
  annotations: READS_INTERNAL
22870
22943
  }, async () => {
22871
22944
  try {
@@ -22888,7 +22961,7 @@ function registerActorTools(server, api) {
22888
22961
  __name(registerActorTools, "registerActorTools");
22889
22962
 
22890
22963
  // src/tools/publish.ts
22891
- import { z as z90 } from "zod";
22964
+ import { z as z91 } from "zod";
22892
22965
 
22893
22966
  // src/tools/meta-publish-attempt-id.ts
22894
22967
  var META_PUBLISH_NAMESPACE = "7b19c9ac-b4eb-4db1-970e-c2f24ce30b98";
@@ -22927,40 +23000,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
22927
23000
  var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
22928
23001
  var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
22929
23002
  var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
22930
- var ShopifyInput = z90.object({
22931
- taskId: z90.string().min(1),
22932
- shopDomain: z90.string().min(1),
23003
+ var ShopifyInput = z91.object({
23004
+ taskId: z91.string().min(1),
23005
+ shopDomain: z91.string().min(1),
22933
23006
  /** Override: number of landing images to include. Default = ALL images the
22934
23007
  * task generated (the MCP fetches /v1/results first to count). Bounded
22935
23008
  * generously here; the backend validates each index against
22936
23009
  * landing.images.length and rejects out-of-range. */
22937
- numLandingImages: z90.number().int().min(1).max(20).optional(),
22938
- variantIndex: z90.number().int().min(0).optional(),
23010
+ numLandingImages: z91.number().int().min(1).max(20).optional(),
23011
+ variantIndex: z91.number().int().min(0).optional(),
22939
23012
  /** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
22940
23013
  * When true, the landing renders variant-picker pills; when false, it ships
22941
23014
  * a single-option product page. Defaults to false. */
22942
- showVariantPicker: z90.boolean().optional(),
23015
+ showVariantPicker: z91.boolean().optional(),
22943
23016
  /** Default `auto` updates the product previously published for this task and
22944
23017
  * shop. Use `existing` with targetProductId to choose another product, or
22945
23018
  * `new` only when the user explicitly wants a duplicate/new listing. */
22946
- publicationMode: z90.enum([
23019
+ publicationMode: z91.enum([
22947
23020
  "auto",
22948
23021
  "existing",
22949
23022
  "new"
22950
23023
  ]).optional(),
22951
23024
  /** Shopify product GID, numeric id, or admin product URL. Required when
22952
23025
  * publicationMode is `existing`. */
22953
- targetProductId: z90.string().trim().min(1).max(300).optional(),
23026
+ targetProductId: z91.string().trim().min(1).max(300).optional(),
22954
23027
  /** Add an announcement bar text above add-to-cart (optional). */
22955
- announcementBarEnabled: z90.boolean().optional(),
22956
- announcementBarText: z90.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
23028
+ announcementBarEnabled: z91.boolean().optional(),
23029
+ announcementBarText: z91.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
22957
23030
  commerceCorrection: PublishCommerceCorrectionSchema.optional().describe("Complete seller-confirmed commerce values, with the revision and fingerprint returned in recovery. Never invent missing prices or convert currency."),
22958
- confirmed: z90.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
23031
+ confirmed: z91.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
22959
23032
  });
22960
23033
  var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
22961
23034
  if (value.commerceCorrection && value.confirmed !== true) {
22962
23035
  ctx.addIssue({
22963
- code: z90.ZodIssueCode.custom,
23036
+ code: z91.ZodIssueCode.custom,
22964
23037
  path: [
22965
23038
  "confirmed"
22966
23039
  ],
@@ -22969,7 +23042,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
22969
23042
  }
22970
23043
  if (value.announcementBarEnabled && !value.announcementBarText) {
22971
23044
  ctx.addIssue({
22972
- code: z90.ZodIssueCode.custom,
23045
+ code: z91.ZodIssueCode.custom,
22973
23046
  path: [
22974
23047
  "announcementBarText"
22975
23048
  ],
@@ -22978,7 +23051,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
22978
23051
  }
22979
23052
  if (!value.announcementBarEnabled && value.announcementBarText) {
22980
23053
  ctx.addIssue({
22981
- code: z90.ZodIssueCode.custom,
23054
+ code: z91.ZodIssueCode.custom,
22982
23055
  path: [
22983
23056
  "announcementBarText"
22984
23057
  ],
@@ -22992,91 +23065,91 @@ function parseShopifyInput(rawInput) {
22992
23065
  return parsed.data;
22993
23066
  }
22994
23067
  __name(parseShopifyInput, "parseShopifyInput");
22995
- var McpCampaignConfig = z90.object({
23068
+ var McpCampaignConfig = z91.object({
22996
23069
  /** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
22997
23070
  * converts to the account currency server-side. Do NOT pre-convert: on a COP
22998
23071
  * account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
22999
- dailyBudgetUsd: z90.number().positive().optional(),
23072
+ dailyBudgetUsd: z91.number().positive().optional(),
23000
23073
  /** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
23001
23074
  * normalizes at validation). Meta accepts max 1 (single-country ad set).
23002
23075
  * TikTok takes only the first entry. */
23003
- targetCountries: z90.array(CountryIso2Schema).max(1).optional(),
23004
- campaignName: z90.string().trim().min(1).max(100).optional()
23076
+ targetCountries: z91.array(CountryIso2Schema).max(1).optional(),
23077
+ campaignName: z91.string().trim().min(1).max(100).optional()
23005
23078
  });
23006
23079
  var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
23007
- var MetaInput = z90.object({
23008
- taskId: z90.string().min(1),
23080
+ var MetaInput = z91.object({
23081
+ taskId: z91.string().min(1),
23009
23082
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
23010
- portfolioId: z90.string().trim().min(1),
23083
+ portfolioId: z91.string().trim().min(1),
23011
23084
  /** Exact Facebook Page selected from `list_meta_destinations`. */
23012
- pageId: z90.string().trim().min(1),
23085
+ pageId: z91.string().trim().min(1),
23013
23086
  adAccountId: McpAdAccountId,
23014
- pixelId: z90.string().min(1).optional(),
23015
- landingUrl: z90.string().url().optional(),
23087
+ pixelId: z91.string().min(1).optional(),
23088
+ landingUrl: z91.string().url().optional(),
23016
23089
  /** Select which angles to publish by 0-based index. Omit to publish all
23017
23090
  * successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
23018
- angleIndexes: z90.array(z90.number().int().nonnegative()).optional(),
23091
+ angleIndexes: z91.array(z91.number().int().nonnegative()).optional(),
23019
23092
  campaignConfig: McpCampaignConfig.optional(),
23020
23093
  /** Override the ad's primary text (body copy). If omitted, ProductMaker
23021
23094
  * uses the auto-generated copy attached to the task. Capped at 500 chars
23022
23095
  * (Meta's primary-text limit). */
23023
- primaryText: z90.string().trim().min(1).max(500).optional(),
23096
+ primaryText: z91.string().trim().min(1).max(500).optional(),
23024
23097
  /** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
23025
23098
  * (wa.me) instead of a landing page. */
23026
- phoneNumber: z90.string().min(8).max(32).optional()
23099
+ phoneNumber: z91.string().min(8).max(32).optional()
23027
23100
  });
23028
- var GroupedTaskSource = z90.object({
23029
- type: z90.literal("task"),
23030
- taskId: z90.string().min(1),
23031
- angleIndex: z90.number().int().min(0).optional(),
23032
- videoVariant: z90.enum([
23101
+ var GroupedTaskSource = z91.object({
23102
+ type: z91.literal("task"),
23103
+ taskId: z91.string().min(1),
23104
+ angleIndex: z91.number().int().min(0).optional(),
23105
+ videoVariant: z91.enum([
23033
23106
  "with_subtitles",
23034
23107
  "without_subtitles"
23035
23108
  ]).optional(),
23036
- imageVariantIndex: z90.number().int().min(0).optional()
23037
- });
23038
- var GroupedMediaSource = z90.object({
23039
- type: z90.literal("media"),
23040
- url: z90.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
23041
- path: z90.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".'),
23042
- thumbnailUrl: z90.string().url().optional(),
23043
- thumbnailPath: z90.string().min(1).optional()
23109
+ imageVariantIndex: z91.number().int().min(0).optional()
23110
+ });
23111
+ var GroupedMediaSource = z91.object({
23112
+ type: z91.literal("media"),
23113
+ url: z91.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
23114
+ path: z91.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".'),
23115
+ thumbnailUrl: z91.string().url().optional(),
23116
+ thumbnailPath: z91.string().min(1).optional()
23044
23117
  }).refine((value) => Boolean(value.url) !== Boolean(value.path), {
23045
23118
  message: "media source needs exactly one of `url` or `path`"
23046
23119
  }).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
23047
23120
  message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
23048
23121
  });
23049
- var GroupedUploadedAssetSource = z90.object({
23050
- type: z90.literal("asset"),
23122
+ var GroupedUploadedAssetSource = z91.object({
23123
+ type: z91.literal("asset"),
23051
23124
  /** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
23052
- assetId: z90.string().uuid(),
23053
- thumbnailAssetId: z90.string().uuid().optional()
23125
+ assetId: z91.string().uuid(),
23126
+ thumbnailAssetId: z91.string().uuid().optional()
23054
23127
  });
23055
- var GroupedCreative = z90.object({
23056
- type: z90.enum([
23128
+ var GroupedCreative = z91.object({
23129
+ type: z91.enum([
23057
23130
  "image",
23058
23131
  "video"
23059
23132
  ]),
23060
- source: z90.union([
23133
+ source: z91.union([
23061
23134
  GroupedTaskSource,
23062
23135
  GroupedMediaSource,
23063
23136
  GroupedUploadedAssetSource
23064
23137
  ]),
23065
- title: z90.string().max(120).optional(),
23066
- description: z90.string().max(500).optional(),
23138
+ title: z91.string().max(120).optional(),
23139
+ description: z91.string().max(500).optional(),
23067
23140
  cta: MetaCtaType.optional(),
23068
- creativeId: z90.string().min(1).optional()
23141
+ creativeId: z91.string().min(1).optional()
23069
23142
  });
23070
- var GroupedCampaignConfigBase = z90.object({
23143
+ var GroupedCampaignConfigBase = z91.object({
23071
23144
  campaignType: MetaCampaignType.default("sales"),
23072
23145
  optimizationMode: MetaOptimizationMode.default("advantage_plus"),
23073
23146
  budgetMode: MetaBudgetMode.optional(),
23074
- campaignDailyBudget: z90.number().int().positive().optional(),
23075
- adSets: z90.array(z90.object({
23076
- tempId: z90.string().min(1).max(80),
23077
- name: z90.string().min(1).max(100),
23078
- dailyBudget: z90.number().int().positive().optional(),
23079
- creativeIds: z90.array(z90.string().min(1)).min(1)
23147
+ campaignDailyBudget: z91.number().int().positive().optional(),
23148
+ adSets: z91.array(z91.object({
23149
+ tempId: z91.string().min(1).max(80),
23150
+ name: z91.string().min(1).max(100),
23151
+ dailyBudget: z91.number().int().positive().optional(),
23152
+ creativeIds: z91.array(z91.string().min(1)).min(1)
23080
23153
  })).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
23081
23154
  /**
23082
23155
  * Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
@@ -23084,17 +23157,17 @@ var GroupedCampaignConfigBase = z90.object({
23084
23157
  * opaque `invalid_literal` and made the WhatsApp destination — supported by
23085
23158
  * the API since #849 — unreachable from this tool.
23086
23159
  */
23087
- destination: z90.discriminatedUnion("type", [
23088
- z90.object({
23089
- type: z90.literal("landing"),
23090
- landingUrl: z90.string().url()
23160
+ destination: z91.discriminatedUnion("type", [
23161
+ z91.object({
23162
+ type: z91.literal("landing"),
23163
+ landingUrl: z91.string().url()
23091
23164
  }),
23092
- z90.object({
23093
- type: z90.literal("whatsapp"),
23094
- phoneNumber: z90.string().min(8).max(32)
23165
+ z91.object({
23166
+ type: z91.literal("whatsapp"),
23167
+ phoneNumber: z91.string().min(8).max(32)
23095
23168
  })
23096
23169
  ]),
23097
- saveAsDefault: z90.boolean().default(false),
23170
+ saveAsDefault: z91.boolean().default(false),
23098
23171
  budgetPolicy: MetaBudgetPolicy.optional()
23099
23172
  });
23100
23173
  function resolveBudgetMode(value) {
@@ -23108,7 +23181,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
23108
23181
  const budgetMode = resolveBudgetMode(value);
23109
23182
  if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
23110
23183
  ctx.addIssue({
23111
- code: z90.ZodIssueCode.custom,
23184
+ code: z91.ZodIssueCode.custom,
23112
23185
  path: [
23113
23186
  "campaignDailyBudget"
23114
23187
  ],
@@ -23119,7 +23192,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
23119
23192
  value.adSets.forEach((adSet, index) => {
23120
23193
  if (adSet.dailyBudget === void 0) {
23121
23194
  ctx.addIssue({
23122
- code: z90.ZodIssueCode.custom,
23195
+ code: z91.ZodIssueCode.custom,
23123
23196
  path: [
23124
23197
  "adSets",
23125
23198
  index,
@@ -23134,28 +23207,28 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
23134
23207
  ...value,
23135
23208
  budgetMode: resolveBudgetMode(value)
23136
23209
  }));
23137
- var PublishCreativesToMetaInputBase = z90.object({
23138
- creatives: z90.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
23210
+ var PublishCreativesToMetaInputBase = z91.object({
23211
+ creatives: z91.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
23139
23212
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
23140
- portfolioId: z90.string().trim().min(1),
23213
+ portfolioId: z91.string().trim().min(1),
23141
23214
  /** Exact Facebook Page selected from `list_meta_destinations`. */
23142
- pageId: z90.string().trim().min(1),
23215
+ pageId: z91.string().trim().min(1),
23143
23216
  adAccountId: McpAdAccountId,
23144
- pixelId: z90.string().min(1).optional(),
23217
+ pixelId: z91.string().min(1).optional(),
23145
23218
  /** Required unless `campaignConfig.destination` is whatsapp — see the
23146
23219
  * superRefine below. Mirrors the API's `FacebookCreateCampaignFromTasksBodySchema`. */
23147
- landingUrl: z90.string().url().optional(),
23220
+ landingUrl: z91.string().url().optional(),
23148
23221
  /** ISO-2 code or resolvable country name — mirrors the API contract
23149
23222
  * (CountryIso2Schema), which normalizes names to alpha-2 at validation. */
23150
23223
  targetCountry: CountryIso2Schema,
23151
- campaignName: z90.string().trim().min(1).max(100),
23224
+ campaignName: z91.string().trim().min(1).max(100),
23152
23225
  campaignConfig: GroupedCampaignConfig.optional()
23153
23226
  });
23154
23227
  var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
23155
23228
  const destination = value.campaignConfig?.destination;
23156
23229
  if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
23157
23230
  ctx.addIssue({
23158
- code: z90.ZodIssueCode.custom,
23231
+ code: z91.ZodIssueCode.custom,
23159
23232
  path: [
23160
23233
  "landingUrl"
23161
23234
  ],
@@ -23164,7 +23237,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
23164
23237
  }
23165
23238
  if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
23166
23239
  ctx.addIssue({
23167
- code: z90.ZodIssueCode.custom,
23240
+ code: z91.ZodIssueCode.custom,
23168
23241
  path: [
23169
23242
  "campaignConfig",
23170
23243
  "destination",
@@ -23183,16 +23256,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
23183
23256
  }
23184
23257
  return value;
23185
23258
  });
23186
- var PresignUploadResponseSchema = z90.object({
23187
- uploadUrl: z90.string().url().refine((value) => {
23259
+ var PresignUploadResponseSchema = z91.object({
23260
+ uploadUrl: z91.string().url().refine((value) => {
23188
23261
  const url = new URL(value);
23189
23262
  return !url.username && !url.password && url.protocol === "https:";
23190
23263
  }, "presigned upload URL must be HTTPS without embedded credentials"),
23191
- publicUrl: z90.string().url().refine((value) => {
23264
+ publicUrl: z91.string().url().refine((value) => {
23192
23265
  const url = new URL(value);
23193
23266
  return !url.username && !url.password;
23194
23267
  }, "public media URL must not contain embedded credentials"),
23195
- stagingAssetId: z90.string().uuid()
23268
+ stagingAssetId: z91.string().uuid()
23196
23269
  });
23197
23270
  async function uploadResolvedMedia(api, media, assetRole) {
23198
23271
  if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
@@ -23217,16 +23290,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
23217
23290
  return uploadResolvedMedia(api, media, assetRole);
23218
23291
  }
23219
23292
  __name(resolveAndUploadMedia, "resolveAndUploadMedia");
23220
- var TikTokInput = z90.object({
23221
- taskId: z90.string().min(1),
23222
- advertiserId: z90.string().min(1),
23223
- pixelId: z90.string().min(1).optional(),
23224
- landingUrl: z90.string().url().optional(),
23225
- angleIndexes: z90.array(z90.number().int().nonnegative()).optional(),
23293
+ var TikTokInput = z91.object({
23294
+ taskId: z91.string().min(1),
23295
+ advertiserId: z91.string().min(1),
23296
+ pixelId: z91.string().min(1).optional(),
23297
+ landingUrl: z91.string().url().optional(),
23298
+ angleIndexes: z91.array(z91.number().int().nonnegative()).optional(),
23226
23299
  campaignConfig: McpCampaignConfig.optional(),
23227
23300
  /** Override the ad's description (TikTok's body copy). If omitted,
23228
23301
  * ProductMaker uses the auto-generated copy attached to the task. */
23229
- primaryText: z90.string().trim().min(1).max(500).optional()
23302
+ primaryText: z91.string().trim().min(1).max(500).optional()
23230
23303
  });
23231
23304
  function registerPublishTools(server, api, opts = {}) {
23232
23305
  const transport = opts.transport ?? "http";
@@ -23578,39 +23651,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
23578
23651
 
23579
23652
  // src/tools/meta-upload.ts
23580
23653
  import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
23581
- import { z as z91 } from "zod";
23654
+ import { z as z92 } from "zod";
23582
23655
  var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
23583
- var UploadSessionInputBase = z91.object({
23584
- mediaKind: z91.enum([
23656
+ var UploadSessionInputBase = z92.object({
23657
+ mediaKind: z92.enum([
23585
23658
  "image",
23586
23659
  "video",
23587
23660
  "mixed"
23588
23661
  ]).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."),
23589
- assetRole: z91.enum([
23662
+ assetRole: z92.enum([
23590
23663
  "media",
23591
23664
  "thumbnail"
23592
23665
  ]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
23593
- uploadPurpose: z91.enum([
23666
+ uploadPurpose: z92.enum([
23594
23667
  "product_reference",
23595
23668
  "creative",
23596
23669
  "generic"
23597
23670
  ]).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."),
23598
- maxFiles: z91.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
23671
+ maxFiles: z92.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
23599
23672
  });
23600
- var OpenAiFileReference = z91.object({
23601
- download_url: z91.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."),
23602
- file_id: z91.string().min(1),
23603
- mime_type: z91.string().min(1).optional(),
23604
- file_name: z91.string().min(1).optional()
23673
+ var OpenAiFileReference = z92.object({
23674
+ download_url: z92.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."),
23675
+ file_id: z92.string().min(1),
23676
+ mime_type: z92.string().min(1).optional(),
23677
+ file_name: z92.string().min(1).optional()
23605
23678
  });
23606
23679
  var UploadSessionToolInputShape = {
23607
23680
  ...UploadSessionInputBase.shape,
23608
- files: z91.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.")
23681
+ files: z92.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.")
23609
23682
  };
23610
- var UploadSessionToolInput = z91.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
23683
+ var UploadSessionToolInput = z92.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
23611
23684
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
23612
23685
  ctx.addIssue({
23613
- code: z91.ZodIssueCode.custom,
23686
+ code: z92.ZodIssueCode.custom,
23614
23687
  path: [
23615
23688
  "mediaKind"
23616
23689
  ],
@@ -23619,7 +23692,7 @@ var UploadSessionToolInput = z91.object(UploadSessionToolInputShape).superRefine
23619
23692
  }
23620
23693
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
23621
23694
  ctx.addIssue({
23622
- code: z91.ZodIssueCode.custom,
23695
+ code: z92.ZodIssueCode.custom,
23623
23696
  path: [
23624
23697
  "maxFiles"
23625
23698
  ],
@@ -23628,7 +23701,7 @@ var UploadSessionToolInput = z91.object(UploadSessionToolInputShape).superRefine
23628
23701
  }
23629
23702
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
23630
23703
  ctx.addIssue({
23631
- code: z91.ZodIssueCode.custom,
23704
+ code: z92.ZodIssueCode.custom,
23632
23705
  path: [
23633
23706
  "maxFiles"
23634
23707
  ],
@@ -23636,38 +23709,38 @@ var UploadSessionToolInput = z91.object(UploadSessionToolInputShape).superRefine
23636
23709
  });
23637
23710
  }
23638
23711
  });
23639
- var UploadSessionResponse = z91.object({
23640
- sessionId: z91.string().uuid(),
23641
- uploadPageUrl: z91.string().url(),
23642
- mediaKind: z91.enum([
23712
+ var UploadSessionResponse = z92.object({
23713
+ sessionId: z92.string().uuid(),
23714
+ uploadPageUrl: z92.string().url(),
23715
+ mediaKind: z92.enum([
23643
23716
  "image",
23644
23717
  "video",
23645
23718
  "mixed"
23646
23719
  ]),
23647
- assetRole: z91.enum([
23720
+ assetRole: z92.enum([
23648
23721
  "media",
23649
23722
  "thumbnail"
23650
23723
  ]),
23651
- maxFiles: z91.number().int().positive(),
23652
- expiresAt: z91.string().datetime()
23724
+ maxFiles: z92.number().int().positive(),
23725
+ expiresAt: z92.string().datetime()
23653
23726
  });
23654
- var UploadStatusInput = z91.object({
23655
- sessionId: z91.string().uuid().describe("The sessionId returned by request_media_upload.")
23727
+ var UploadStatusInput = z92.object({
23728
+ sessionId: z92.string().uuid().describe("The sessionId returned by request_media_upload.")
23656
23729
  });
23657
- var UniversalUploadStatusResponse = z91.discriminatedUnion("status", [
23658
- z91.object({
23659
- status: z91.literal("pending"),
23660
- assets: z91.array(z91.never()).length(0)
23730
+ var UniversalUploadStatusResponse = z92.discriminatedUnion("status", [
23731
+ z92.object({
23732
+ status: z92.literal("pending"),
23733
+ assets: z92.array(z92.never()).length(0)
23661
23734
  }),
23662
- z91.object({
23663
- status: z91.literal("uploaded"),
23664
- assets: z91.array(z91.object({
23665
- assetId: z91.string().uuid(),
23666
- mediaKind: z91.enum([
23735
+ z92.object({
23736
+ status: z92.literal("uploaded"),
23737
+ assets: z92.array(z92.object({
23738
+ assetId: z92.string().uuid(),
23739
+ mediaKind: z92.enum([
23667
23740
  "image",
23668
23741
  "video"
23669
23742
  ]),
23670
- assetRole: z91.enum([
23743
+ assetRole: z92.enum([
23671
23744
  "media",
23672
23745
  "thumbnail"
23673
23746
  ])
@@ -23675,13 +23748,13 @@ var UniversalUploadStatusResponse = z91.discriminatedUnion("status", [
23675
23748
  })
23676
23749
  ]);
23677
23750
  var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
23678
- uploadPurpose: z91.enum([
23751
+ uploadPurpose: z92.enum([
23679
23752
  "product_reference",
23680
23753
  "creative",
23681
23754
  "generic"
23682
23755
  ]),
23683
- checkToolName: z91.literal("check_media_upload"),
23684
- resolveEndpoint: z91.string().url()
23756
+ checkToolName: z92.literal("check_media_upload"),
23757
+ resolveEndpoint: z92.string().url()
23685
23758
  });
23686
23759
  function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
23687
23760
  const url = new URL(uploadPageUrl);
@@ -23772,15 +23845,15 @@ function registerMediaUploadTools(server, api) {
23772
23845
  __name(registerMediaUploadTools, "registerMediaUploadTools");
23773
23846
 
23774
23847
  // src/tools/campaigns.ts
23775
- import { z as z92 } from "zod";
23848
+ import { z as z93 } from "zod";
23776
23849
  var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
23777
23850
  var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
23778
- var MetaStatusInput = z92.object({
23779
- campaignId: z92.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
23851
+ var MetaStatusInput = z93.object({
23852
+ campaignId: z93.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
23780
23853
  });
23781
- var TikTokStatusInput = z92.object({
23782
- campaignId: z92.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
23783
- advertiserId: z92.string().min(1).describe("The same advertiserId used to publish the campaign.")
23854
+ var TikTokStatusInput = z93.object({
23855
+ campaignId: z93.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
23856
+ advertiserId: z93.string().min(1).describe("The same advertiserId used to publish the campaign.")
23784
23857
  });
23785
23858
  function registerCampaignTools(server, api) {
23786
23859
  server.registerTool("get_meta_campaign_status", {
@@ -23885,10 +23958,10 @@ function renderTikTokStatusMarkdown(r) {
23885
23958
  __name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
23886
23959
 
23887
23960
  // ../../packages/product-economics/src/product-costing.ts
23888
- import { z as z94 } from "zod";
23961
+ import { z as z95 } from "zod";
23889
23962
 
23890
23963
  // ../../packages/product-economics/src/product-costing-countries.ts
23891
- import { z as z93 } from "zod";
23964
+ import { z as z94 } from "zod";
23892
23965
 
23893
23966
  // ../../packages/product-economics/src/product-costing-shipping-references.json
23894
23967
  var product_costing_shipping_references_default = {
@@ -23952,21 +24025,21 @@ var product_costing_shipping_references_default = {
23952
24025
  };
23953
24026
 
23954
24027
  // ../../packages/product-economics/src/product-costing-countries.ts
23955
- var ShippingReferenceSchema = z93.object({
23956
- reference: z93.number().positive(),
23957
- min: z93.number().nonnegative(),
23958
- max: z93.number().positive(),
23959
- updatedAt: z93.string().date(),
23960
- confidence: z93.enum([
24028
+ var ShippingReferenceSchema = z94.object({
24029
+ reference: z94.number().positive(),
24030
+ min: z94.number().nonnegative(),
24031
+ max: z94.number().positive(),
24032
+ updatedAt: z94.string().date(),
24033
+ confidence: z94.enum([
23961
24034
  "high",
23962
24035
  "medium",
23963
24036
  "medium-low"
23964
24037
  ]),
23965
- sources: z93.array(z93.string().url().startsWith("https://")).min(1).max(3)
24038
+ sources: z94.array(z94.string().url().startsWith("https://")).min(1).max(3)
23966
24039
  }).superRefine(({ reference, min, max }, context) => {
23967
24040
  if (min > reference || reference > max) {
23968
24041
  context.addIssue({
23969
- code: z93.ZodIssueCode.custom,
24042
+ code: z94.ZodIssueCode.custom,
23970
24043
  message: "shipping_reference_outside_range",
23971
24044
  path: [
23972
24045
  "reference"
@@ -23974,7 +24047,7 @@ var ShippingReferenceSchema = z93.object({
23974
24047
  });
23975
24048
  }
23976
24049
  });
23977
- var SHIPPING_REFERENCES = z93.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
24050
+ var SHIPPING_REFERENCES = z94.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
23978
24051
  var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
23979
24052
  var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
23980
24053
  "MX",
@@ -24156,18 +24229,18 @@ function getProductCostingCountryName(country) {
24156
24229
  __name(getProductCostingCountryName, "getProductCostingCountryName");
24157
24230
 
24158
24231
  // ../../packages/product-economics/src/product-costing.ts
24159
- var ProductCostingInputSchema = z94.object({
24160
- country: z94.string().refine(isProductCostingCountryCode, "unsupported_country"),
24161
- supplierCost: z94.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
24162
- shippingCost: z94.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
24163
- returnRate: z94.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
24164
- cancellationRate: z94.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
24165
- adsManagerCpa: z94.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
24166
- desiredMargin: z94.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
24232
+ var ProductCostingInputSchema = z95.object({
24233
+ country: z95.string().refine(isProductCostingCountryCode, "unsupported_country"),
24234
+ supplierCost: z95.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
24235
+ shippingCost: z95.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
24236
+ returnRate: z95.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
24237
+ cancellationRate: z95.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
24238
+ adsManagerCpa: z95.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
24239
+ desiredMargin: z95.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
24167
24240
  }).superRefine(({ returnRate, cancellationRate }, context) => {
24168
24241
  if (returnRate + cancellationRate >= 1) {
24169
24242
  context.addIssue({
24170
- code: z94.ZodIssueCode.custom,
24243
+ code: z95.ZodIssueCode.custom,
24171
24244
  message: "delivery_rate_positive",
24172
24245
  path: [
24173
24246
  "cancellationRate"
@@ -24264,15 +24337,15 @@ function calculateProductCosting(rawInput) {
24264
24337
  __name(calculateProductCosting, "calculateProductCosting");
24265
24338
 
24266
24339
  // src/tools/product-costing.ts
24267
- import { z as z95 } from "zod";
24340
+ import { z as z96 } from "zod";
24268
24341
  var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
24269
- var optionalAmount = /* @__PURE__ */ __name((description) => z95.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
24270
- var optionalPercent = /* @__PURE__ */ __name((description) => z95.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
24271
- var ProductCostingToolInput = z95.object({
24272
- country: z95.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
24342
+ var optionalAmount = /* @__PURE__ */ __name((description) => z96.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
24343
+ var optionalPercent = /* @__PURE__ */ __name((description) => z96.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
24344
+ var ProductCostingToolInput = z96.object({
24345
+ country: z96.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
24273
24346
  message: "Pa\xEDs no soportado por ProductMaker."
24274
24347
  }).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
24275
- supplierCost: z95.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."),
24348
+ supplierCost: z96.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."),
24276
24349
  supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
24277
24350
  shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
24278
24351
  shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
@@ -24435,7 +24508,7 @@ function formatPercent(value) {
24435
24508
  __name(formatPercent, "formatPercent");
24436
24509
 
24437
24510
  // src/tools/product-research.ts
24438
- import { z as z96 } from "zod";
24511
+ import { z as z97 } from "zod";
24439
24512
 
24440
24513
  // src/tools/product-research-idempotency.ts
24441
24514
  var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
@@ -24806,17 +24879,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
24806
24879
  ]);
24807
24880
  var POLL_INTERVAL_MS = 5e3;
24808
24881
  var MAX_WAIT_SECONDS = 120;
24809
- var FindInput = z96.object({
24882
+ var FindInput = z97.object({
24810
24883
  targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
24811
24884
  categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
24812
- confirmed: z96.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
24813
- waitSeconds: z96.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
24885
+ confirmed: z97.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
24886
+ waitSeconds: z97.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
24814
24887
  });
24815
- var GetInput = z96.object({
24816
- runId: z96.string().uuid().describe("ID del run devuelto por find_winning_products.")
24888
+ var GetInput = z97.object({
24889
+ runId: z97.string().uuid().describe("ID del run devuelto por find_winning_products.")
24817
24890
  });
24818
- var ListInput = z96.object({
24819
- limit: z96.number().int().min(1).max(20).default(10)
24891
+ var ListInput = z97.object({
24892
+ limit: z97.number().int().min(1).max(20).default(10)
24820
24893
  });
24821
24894
  function textResult(text2) {
24822
24895
  return {
@@ -24955,17 +25028,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
24955
25028
  __name(registerProductResearchTools, "registerProductResearchTools");
24956
25029
 
24957
25030
  // src/tools/dropshipping-projects.ts
24958
- import { z as z97 } from "zod";
25031
+ import { z as z98 } from "zod";
24959
25032
  var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
24960
25033
  var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
24961
25034
  var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
24962
- var ProjectId = z97.string().uuid();
24963
- var DropshippingProjectStatus = z97.enum([
25035
+ var ProjectId = z98.string().uuid();
25036
+ var DropshippingProjectStatus = z98.enum([
24964
25037
  "active",
24965
25038
  "completed",
24966
25039
  "archived"
24967
25040
  ]);
24968
- var DropshippingProjectPhase = z97.enum([
25041
+ var DropshippingProjectPhase = z98.enum([
24969
25042
  "research",
24970
25043
  "costing",
24971
25044
  "media",
@@ -24974,21 +25047,21 @@ var DropshippingProjectPhase = z97.enum([
24974
25047
  "advertising",
24975
25048
  "complete"
24976
25049
  ]);
24977
- var DropshippingRewardMilestone = z97.enum([
25050
+ var DropshippingRewardMilestone = z98.enum([
24978
25051
  "product_selected",
24979
25052
  "costing_saved",
24980
25053
  "product_media_ready",
24981
25054
  "creatives_completed",
24982
25055
  "campaign_created"
24983
25056
  ]);
24984
- var TargetCountry = z97.enum([
25057
+ var TargetCountry = z98.enum([
24985
25058
  "CO",
24986
25059
  "MX",
24987
25060
  "PE",
24988
25061
  "EC",
24989
25062
  "CL"
24990
25063
  ]);
24991
- var ResearchCategory = z97.enum([
25064
+ var ResearchCategory = z98.enum([
24992
25065
  "auto",
24993
25066
  "automotive",
24994
25067
  "kitchen",
@@ -25003,7 +25076,7 @@ var ResearchCategory = z97.enum([
25003
25076
  "garden",
25004
25077
  "cleaning"
25005
25078
  ]);
25006
- var HttpUrl3 = z97.string().url().max(2e3).refine((value) => {
25079
+ var HttpUrl3 = z98.string().url().max(2e3).refine((value) => {
25007
25080
  try {
25008
25081
  return [
25009
25082
  "http:",
@@ -25013,45 +25086,45 @@ var HttpUrl3 = z97.string().url().max(2e3).refine((value) => {
25013
25086
  return false;
25014
25087
  }
25015
25088
  }, "URL must use HTTP(S)");
25016
- var ResearchCandidateOrigin = z97.object({
25017
- type: z97.literal("research_candidate"),
25089
+ var ResearchCandidateOrigin = z98.object({
25090
+ type: z98.literal("research_candidate"),
25018
25091
  runId: ProjectId,
25019
- candidateSourceId: z97.string().min(1).max(160)
25092
+ candidateSourceId: z98.string().min(1).max(160)
25020
25093
  });
25021
- var TaskOrigin = z97.object({
25022
- type: z97.literal("task"),
25094
+ var TaskOrigin = z98.object({
25095
+ type: z98.literal("task"),
25023
25096
  taskId: ProjectId
25024
25097
  });
25025
- var ManualOrigin = z97.object({
25026
- type: z97.literal("manual"),
25098
+ var ManualOrigin = z98.object({
25099
+ type: z98.literal("manual"),
25027
25100
  clientRequestId: ProjectId,
25028
- country: z97.string().min(2).max(3).optional()
25101
+ country: z98.string().min(2).max(3).optional()
25029
25102
  });
25030
- var StartProjectInput = z97.object({
25031
- origin: z97.discriminatedUnion("type", [
25103
+ var StartProjectInput = z98.object({
25104
+ origin: z98.discriminatedUnion("type", [
25032
25105
  ResearchCandidateOrigin,
25033
25106
  TaskOrigin,
25034
25107
  ManualOrigin
25035
25108
  ]),
25036
- productName: z97.string().trim().min(1).max(240).optional(),
25109
+ productName: z98.string().trim().min(1).max(240).optional(),
25037
25110
  productUrl: HttpUrl3.optional(),
25038
- country: z97.string().min(2).max(3).optional(),
25039
- languageCode: z97.string().min(2).max(16).optional()
25111
+ country: z98.string().min(2).max(3).optional(),
25112
+ languageCode: z98.string().min(2).max(16).optional()
25040
25113
  }).strict();
25041
- var CostProjectInput = z97.object({
25114
+ var CostProjectInput = z98.object({
25042
25115
  projectId: ProjectId,
25043
- version: z97.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
25044
- country: z97.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
25116
+ version: z98.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
25117
+ country: z98.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
25045
25118
  message: "Pa\xEDs no soportado por ProductMaker."
25046
25119
  }).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
25047
- supplierCost: z97.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."),
25048
- shippingCost: z97.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
25049
- returnRate: z97.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."),
25050
- cancellationRate: z97.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."),
25051
- adsManagerCpa: z97.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
25052
- desiredMargin: z97.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
25053
- });
25054
- var GuideInput = z97.object({
25120
+ supplierCost: z98.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."),
25121
+ shippingCost: z98.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
25122
+ returnRate: z98.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."),
25123
+ cancellationRate: z98.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."),
25124
+ adsManagerCpa: z98.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
25125
+ desiredMargin: z98.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
25126
+ });
25127
+ var GuideInput = z98.object({
25055
25128
  projectId: ProjectId.optional()
25056
25129
  }).strict();
25057
25130
  var NEXT_ACTION_KINDS = [
@@ -25069,29 +25142,29 @@ var NEXT_ACTION_KINDS = [
25069
25142
  "repair_meta_campaign",
25070
25143
  "review_paused_campaign"
25071
25144
  ];
25072
- var DropshippingProjectNextAction = z97.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z97.object({
25073
- kind: z97.literal(kind),
25074
- href: z97.string().min(1)
25145
+ var DropshippingProjectNextAction = z98.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z98.object({
25146
+ kind: z98.literal(kind),
25147
+ href: z98.string().min(1)
25075
25148
  })));
25076
- var CostingInputSchema = z97.object({
25077
- country: z97.string().min(2).max(3),
25078
- supplierCost: z97.number().finite().positive(),
25079
- shippingCost: z97.number().finite().nonnegative(),
25080
- returnRate: z97.number().finite().min(0).lt(1),
25081
- cancellationRate: z97.number().finite().min(0).lt(1),
25082
- adsManagerCpa: z97.number().finite().nonnegative(),
25083
- desiredMargin: z97.number().finite().min(0).lt(1)
25149
+ var CostingInputSchema = z98.object({
25150
+ country: z98.string().min(2).max(3),
25151
+ supplierCost: z98.number().finite().positive(),
25152
+ shippingCost: z98.number().finite().nonnegative(),
25153
+ returnRate: z98.number().finite().min(0).lt(1),
25154
+ cancellationRate: z98.number().finite().min(0).lt(1),
25155
+ adsManagerCpa: z98.number().finite().nonnegative(),
25156
+ desiredMargin: z98.number().finite().min(0).lt(1)
25084
25157
  }).superRefine(({ returnRate, cancellationRate }, context) => {
25085
25158
  if (returnRate + cancellationRate >= 1) context.addIssue({
25086
- code: z97.ZodIssueCode.custom,
25159
+ code: z98.ZodIssueCode.custom,
25087
25160
  path: [
25088
25161
  "cancellationRate"
25089
25162
  ]
25090
25163
  });
25091
25164
  });
25092
- var FiniteCostingNumber = z97.number().finite();
25093
- var CostingResultSchema = z97.object({
25094
- country: z97.string().min(2).max(3),
25165
+ var FiniteCostingNumber = z98.number().finite();
25166
+ var CostingResultSchema = z98.object({
25167
+ country: z98.string().min(2).max(3),
25095
25168
  deliveryRate: FiniteCostingNumber,
25096
25169
  adjustedShippingCost: FiniteCostingNumber,
25097
25170
  adjustedCpa: FiniteCostingNumber,
@@ -25104,45 +25177,45 @@ var CostingResultSchema = z97.object({
25104
25177
  estimatedProfit: FiniteCostingNumber,
25105
25178
  actualMargin: FiniteCostingNumber,
25106
25179
  breakEvenAdsManagerCpa: FiniteCostingNumber,
25107
- wasPriceAutoAdjusted: z97.boolean(),
25108
- profitabilityStatus: z97.literal("healthy")
25109
- });
25110
- var RewardProgressSchema = z97.object({
25111
- campaignKey: z97.literal("dropshipping-launch-v1"),
25112
- totalCredits: z97.number().int().positive(),
25113
- earnedCredits: z97.number().int().nonnegative(),
25114
- milestones: z97.array(z97.object({
25180
+ wasPriceAutoAdjusted: z98.boolean(),
25181
+ profitabilityStatus: z98.literal("healthy")
25182
+ });
25183
+ var RewardProgressSchema = z98.object({
25184
+ campaignKey: z98.literal("dropshipping-launch-v1"),
25185
+ totalCredits: z98.number().int().positive(),
25186
+ earnedCredits: z98.number().int().nonnegative(),
25187
+ milestones: z98.array(z98.object({
25115
25188
  milestone: DropshippingRewardMilestone,
25116
- credits: z97.number().int().positive(),
25117
- available: z97.boolean().optional(),
25118
- earned: z97.boolean(),
25189
+ credits: z98.number().int().positive(),
25190
+ available: z98.boolean().optional(),
25191
+ earned: z98.boolean(),
25119
25192
  grantId: ProjectId.nullable(),
25120
- grantedAt: z97.string().datetime().nullable()
25193
+ grantedAt: z98.string().datetime().nullable()
25121
25194
  })).length(DropshippingRewardMilestone.options.length)
25122
25195
  });
25123
- var ProjectResponseSchema = z97.object({
25196
+ var ProjectResponseSchema = z98.object({
25124
25197
  id: ProjectId,
25125
25198
  taskId: ProjectId.nullable(),
25126
25199
  status: DropshippingProjectStatus,
25127
- originKey: z97.string().min(1),
25200
+ originKey: z98.string().min(1),
25128
25201
  researchRunId: ProjectId.nullable(),
25129
- candidateSourceId: z97.string().nullable(),
25130
- productName: z97.string().nullable(),
25202
+ candidateSourceId: z98.string().nullable(),
25203
+ productName: z98.string().nullable(),
25131
25204
  productUrl: HttpUrl3.nullable(),
25132
25205
  referenceImageUrl: HttpUrl3.nullable(),
25133
- targetCountry: z97.string().nullable(),
25134
- languageCode: z97.string().nullable(),
25135
- hasReferenceImage: z97.boolean(),
25136
- hasWinnerReferenceImage: z97.boolean(),
25206
+ targetCountry: z98.string().nullable(),
25207
+ languageCode: z98.string().nullable(),
25208
+ hasReferenceImage: z98.boolean(),
25209
+ hasWinnerReferenceImage: z98.boolean(),
25137
25210
  costingInput: CostingInputSchema.nullable(),
25138
25211
  costingResult: CostingResultSchema.nullable(),
25139
- costingVersion: z97.number().int().positive().nullable(),
25140
- version: z97.number().int().positive(),
25212
+ costingVersion: z98.number().int().positive().nullable(),
25213
+ version: z98.number().int().positive(),
25141
25214
  phase: DropshippingProjectPhase,
25142
25215
  nextAction: DropshippingProjectNextAction.nullable(),
25143
25216
  rewards: RewardProgressSchema,
25144
- createdAt: z97.string().datetime(),
25145
- updatedAt: z97.string().datetime()
25217
+ createdAt: z98.string().datetime(),
25218
+ updatedAt: z98.string().datetime()
25146
25219
  }).passthrough();
25147
25220
  var NEXT_ACTION_GUIDANCE = {
25148
25221
  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.",
@@ -25262,58 +25335,58 @@ function registerDropshippingProjectTools(server, api) {
25262
25335
  __name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
25263
25336
 
25264
25337
  // src/tools/daily-control.ts
25265
- import { z as z98 } from "zod";
25338
+ import { z as z99 } from "zod";
25266
25339
  var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
25267
25340
  var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
25268
25341
  var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
25269
- var ProviderCampaignIdentifier = z98.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
25270
- var DateOnly = z98.string().regex(/^\d{4}-\d{2}-\d{2}$/);
25271
- var DailyControlInput = z98.object({
25342
+ var ProviderCampaignIdentifier = z99.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
25343
+ var DateOnly = z99.string().regex(/^\d{4}-\d{2}-\d{2}$/);
25344
+ var DailyControlInput = z99.object({
25272
25345
  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."),
25273
- days: z98.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
25274
- projectId: z98.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
25346
+ days: z99.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
25347
+ projectId: z99.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
25275
25348
  }).strict();
25276
- var LinkCampaignInput = z98.object({
25277
- projectId: z98.string().uuid(),
25278
- provider: z98.enum([
25349
+ var LinkCampaignInput = z99.object({
25350
+ projectId: z99.string().uuid(),
25351
+ provider: z99.enum([
25279
25352
  "meta",
25280
25353
  "tiktok"
25281
25354
  ]),
25282
25355
  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."),
25283
25356
  campaignId: ProviderCampaignIdentifier
25284
25357
  }).strict();
25285
- var ReportReturnsInput = z98.object({
25286
- projectId: z98.string().uuid(),
25358
+ var ReportReturnsInput = z99.object({
25359
+ projectId: z99.string().uuid(),
25287
25360
  date: DateOnly,
25288
- returnedOrders: z98.number().int().min(0).max(1e5),
25289
- note: z98.string().trim().max(280).optional()
25361
+ returnedOrders: z99.number().int().min(0).max(1e5),
25362
+ note: z99.string().trim().max(280).optional()
25290
25363
  }).strict();
25291
- var DailyControlStatusMirror = DailyControlStatusEnum.or(z98.string());
25292
- var DailyControlLightMirror = DailyControlLightEnum.or(z98.string());
25293
- var DailyControlSourceMirror = DailyControlSourceEnum.or(z98.string());
25294
- var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z98.string());
25295
- var DailyControlDayMirror = z98.object({
25296
- date: z98.string(),
25297
- returnedOrders: z98.number(),
25364
+ var DailyControlStatusMirror = DailyControlStatusEnum.or(z99.string());
25365
+ var DailyControlLightMirror = DailyControlLightEnum.or(z99.string());
25366
+ var DailyControlSourceMirror = DailyControlSourceEnum.or(z99.string());
25367
+ var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z99.string());
25368
+ var DailyControlDayMirror = z99.object({
25369
+ date: z99.string(),
25370
+ returnedOrders: z99.number(),
25298
25371
  returnedSource: DailyControlSourceMirror,
25299
25372
  cancelledSource: DailyControlSourceMirror,
25300
- hasEstimates: z98.boolean(),
25373
+ hasEstimates: z99.boolean(),
25301
25374
  light: DailyControlLightMirror
25302
25375
  }).passthrough();
25303
- var DailyControlProductMirror = z98.object({
25304
- projectId: z98.string().uuid(),
25305
- productName: z98.string().nullable(),
25376
+ var DailyControlProductMirror = z99.object({
25377
+ projectId: z99.string().uuid(),
25378
+ productName: z99.string().nullable(),
25306
25379
  status: DailyControlStatusMirror,
25307
- statusMessage: z98.string().nullable(),
25308
- days: z98.array(DailyControlDayMirror),
25380
+ statusMessage: z99.string().nullable(),
25381
+ days: z99.array(DailyControlDayMirror),
25309
25382
  verdict: DailyControlVerdictMirror.nullable(),
25310
- rationale: z98.string().nullable()
25383
+ rationale: z99.string().nullable()
25311
25384
  }).passthrough();
25312
- var DailyControlResponseMirror = z98.object({
25313
- since: z98.string(),
25314
- until: z98.string(),
25315
- products: z98.array(DailyControlProductMirror),
25316
- archivedProjectSpend: z98.array(z98.unknown())
25385
+ var DailyControlResponseMirror = z99.object({
25386
+ since: z99.string(),
25387
+ until: z99.string(),
25388
+ products: z99.array(DailyControlProductMirror),
25389
+ archivedProjectSpend: z99.array(z99.unknown())
25317
25390
  }).passthrough();
25318
25391
  var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
25319
25392
  function withWarnings(response) {
@@ -25388,7 +25461,7 @@ __name(registerDailyControlTools, "registerDailyControlTools");
25388
25461
  // src/tools/product-control.ts
25389
25462
  import { readFile, stat } from "fs/promises";
25390
25463
  import { basename as basename2, isAbsolute, resolve as resolve3 } from "path";
25391
- import { z as z99 } from "zod";
25464
+ import { z as z100 } from "zod";
25392
25465
  var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
25393
25466
  var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
25394
25467
  var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
@@ -25401,36 +25474,36 @@ var createOperationGuidance = getProductMakerCapabilityModelGuidance("create_ope
25401
25474
  var mergeProductsGuidance = getProductMakerCapabilityModelGuidance("merge_products");
25402
25475
  var syncShopifyOrdersGuidance = getProductMakerCapabilityModelGuidance("sync_shopify_orders");
25403
25476
  var importOrdersFileGuidance = getProductMakerCapabilityModelGuidance("import_orders_file");
25404
- var DateOnly2 = z99.string().regex(/^\d{4}-\d{2}-\d{2}$/);
25477
+ var DateOnly2 = z100.string().regex(/^\d{4}-\d{2}-\d{2}$/);
25405
25478
  var IMPORT_BATCH_MAX2 = 50;
25406
- var ProductControlListInput = z99.object({
25407
- days: z99.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
25479
+ var ProductControlListInput = z100.object({
25480
+ days: z100.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
25408
25481
  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."),
25409
- shopDomain: z99.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
25482
+ shopDomain: z100.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
25410
25483
  }).strict();
25411
- var ImportableProductsInput = z99.object({
25412
- q: z99.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
25413
- after: z99.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
25414
- shopDomain: z99.string().min(1).optional()
25484
+ var ImportableProductsInput = z100.object({
25485
+ q: z100.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
25486
+ after: z100.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
25487
+ shopDomain: z100.string().min(1).optional()
25415
25488
  }).strict();
25416
- var ImportProductControlsInput = z99.object({
25417
- shopifyProductIds: z99.array(z99.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."),
25489
+ var ImportProductControlsInput = z100.object({
25490
+ shopifyProductIds: z100.array(z100.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."),
25418
25491
  // Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
25419
25492
  // sin decir a cuál archivaría el producto bajo la tienda equivocada.
25420
- shopDomain: z99.string().min(1)
25493
+ shopDomain: z100.string().min(1)
25421
25494
  }).strict();
25422
- var SetProductCostingInput = z99.object({
25423
- shopDomain: z99.string().min(1),
25424
- shopifyProductId: z99.string().min(1).max(64),
25425
- targetCountry: z99.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
25426
- supplierCost: z99.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
25427
- shippingCost: z99.number().finite().nonnegative(),
25428
- returnRate: z99.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
25429
- cancellationRate: z99.number().finite().min(0).lt(1)
25495
+ var SetProductCostingInput = z100.object({
25496
+ shopDomain: z100.string().min(1),
25497
+ shopifyProductId: z100.string().min(1).max(64),
25498
+ targetCountry: z100.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
25499
+ supplierCost: z100.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
25500
+ shippingCost: z100.number().finite().nonnegative(),
25501
+ returnRate: z100.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
25502
+ cancellationRate: z100.number().finite().min(0).lt(1)
25430
25503
  }).strict();
25431
- var Count = z99.number().int().min(0).max(1e5).nullable().optional();
25432
- var ReportProductCountsInput = z99.object({
25433
- productControlId: z99.string().uuid().describe("El identificador que devuelve get_product_control."),
25504
+ var Count = z100.number().int().min(0).max(1e5).nullable().optional();
25505
+ var ReportProductCountsInput = z100.object({
25506
+ productControlId: z100.string().uuid().describe("El identificador que devuelve get_product_control."),
25434
25507
  date: DateOnly2,
25435
25508
  orders: Count.describe("Pedidos que entraron ese d\xEDa."),
25436
25509
  cancelledOrders: Count,
@@ -25440,36 +25513,36 @@ var ReportProductCountsInput = z99.object({
25440
25513
  }).strict();
25441
25514
  var MAX_ORDERS_FILE_BYTES = 8 * 1024 * 1024;
25442
25515
  var SyncShopifyOrdersInput = SyncShopifyOrdersSchema;
25443
- var ImportOrdersFileInput = z99.object({
25516
+ var ImportOrdersFileInput = z100.object({
25444
25517
  /** Ruta ABSOLUTA en la máquina de quien usa el MCP. */
25445
- path: z99.string().min(1),
25446
- operationId: z99.string().uuid().optional(),
25518
+ path: z100.string().min(1),
25519
+ operationId: z100.string().uuid().optional(),
25447
25520
  /** Solo mirar: devuelve el resumen y no escribe nada. */
25448
- dryRun: z99.boolean().optional()
25521
+ dryRun: z100.boolean().optional()
25449
25522
  }).strict();
25450
- var CreateOperationInput = z99.object({
25451
- countryCode: z99.string().length(2),
25452
- label: z99.string().trim().min(1).max(60).optional()
25523
+ var CreateOperationInput = z100.object({
25524
+ countryCode: z100.string().length(2),
25525
+ label: z100.string().trim().min(1).max(60).optional()
25453
25526
  }).strict();
25454
- var MergeProductsInput = z99.object({
25455
- sourceId: z99.string().uuid(),
25456
- targetId: z99.string().uuid()
25527
+ var MergeProductsInput = z100.object({
25528
+ sourceId: z100.string().uuid(),
25529
+ targetId: z100.string().uuid()
25457
25530
  }).strict();
25458
- var SetMonthlyExpenseInput = z99.object({
25459
- month: z99.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
25531
+ var SetMonthlyExpenseInput = z100.object({
25532
+ month: z100.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
25460
25533
  label: SaveMonthlyExpenseSchema.shape.label,
25461
- amount: z99.number().finite().min(0),
25462
- operationId: z99.string().uuid().optional()
25534
+ amount: z100.number().finite().min(0),
25535
+ operationId: z100.string().uuid().optional()
25463
25536
  }).strict();
25464
- var SetAdSpendInput = z99.object({
25465
- month: z99.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
25466
- operationId: z99.string().uuid().optional(),
25537
+ var SetAdSpendInput = z100.object({
25538
+ month: z100.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
25539
+ operationId: z100.string().uuid().optional(),
25467
25540
  /** null RETIRA la corrección; cero afirma que no pautó. */
25468
- amount: z99.number().finite().min(0).nullable()
25541
+ amount: z100.number().finite().min(0).nullable()
25469
25542
  }).strict();
25470
- var GetFinancesInput = z99.object({
25471
- month: z99.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional().describe("Mes en YYYY-MM. Si se omite, el mes en curso. Solo mes calendario."),
25472
- operationId: z99.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
25543
+ var GetFinancesInput = z100.object({
25544
+ month: z100.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional().describe("Mes en YYYY-MM. Si se omite, el mes en curso. Solo mes calendario."),
25545
+ operationId: z100.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
25473
25546
  }).strict();
25474
25547
  function registerProductControlTools(server, api, { transport = "http" } = {}) {
25475
25548
  server.registerTool("get_product_control", {
@@ -25666,27 +25739,27 @@ function registerProductControlTools(server, api, { transport = "http" } = {}) {
25666
25739
  __name(registerProductControlTools, "registerProductControlTools");
25667
25740
 
25668
25741
  // src/tools/market-study-estimate.ts
25669
- import { z as z100 } from "zod";
25742
+ import { z as z101 } from "zod";
25670
25743
  var estimateMarketStudyGuidance = getProductMakerCapabilityModelGuidance("estimate_market_study_cost");
25671
- var ProductTaskOutputEnum = z100.enum([
25744
+ var ProductTaskOutputEnum = z101.enum([
25672
25745
  "landing",
25673
25746
  "video",
25674
25747
  "image"
25675
25748
  ]);
25676
- var EstimateMarketStudyInput = z100.object({
25677
- kind: z100.enum([
25749
+ var EstimateMarketStudyInput = z101.object({
25750
+ kind: z101.enum([
25678
25751
  "video",
25679
25752
  "product_task"
25680
25753
  ]).describe('"video" para generate_video_creative; "product_task" para create_product_task.'),
25681
- videoAngleCount: z100.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
25682
- durationSeconds: z100.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
25754
+ videoAngleCount: z101.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
25755
+ durationSeconds: z101.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
25683
25756
  videoStructure: VideoStructureEnum.default("single_take"),
25684
25757
  videoQuality: VideoQualityEnum.default("economy"),
25685
25758
  videoResolution: VideoResolutionEnum.default("480p"),
25686
- productImageCount: z100.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
25759
+ productImageCount: z101.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
25687
25760
  outputs: ProductTaskOutputEnum.array().min(1).max(3).optional().describe('Solo para kind="product_task": los mismos outputs de create_product_task. Default: todos.'),
25688
- generateAiMusic: z100.boolean().optional(),
25689
- replicateWinnerWhenFound: z100.boolean().optional().describe("La misma preferencia que enviar\xE1s al crear. false excluye la reserva de r\xE9plica del ganador de la cotizaci\xF3n con estudio.")
25761
+ generateAiMusic: z101.boolean().optional(),
25762
+ replicateWinnerWhenFound: z101.boolean().optional().describe("La misma preferencia que enviar\xE1s al crear. false excluye la reserva de r\xE9plica del ganador de la cotizaci\xF3n con estudio.")
25690
25763
  }).strict();
25691
25764
  function buildMarketStudyEstimateRequests(input) {
25692
25765
  const quotesVideo = input.kind === "video" || (input.outputs ?? [