@productmaker/mcp 8.11.2 → 8.11.4

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/http.js CHANGED
@@ -151,6 +151,14 @@ var FrankensteinSourceUploadPresignResponseSchema = z2.object({
151
151
 
152
152
  // ../../packages/types/src/product-context-limits.ts
153
153
  var PRODUCT_CONTEXT_MAX_CHARS = 3e3;
154
+ function canonicalizeLineBreaks(value) {
155
+ return value.replace(/\r\n?/g, "\n");
156
+ }
157
+ __name(canonicalizeLineBreaks, "canonicalizeLineBreaks");
158
+ function canonicalizeProductContext(value) {
159
+ return canonicalizeLineBreaks(value).trim();
160
+ }
161
+ __name(canonicalizeProductContext, "canonicalizeProductContext");
154
162
 
155
163
  // ../../packages/types/src/video-creation.ts
156
164
  var VideoCreationAspectRatio = z3.enum([
@@ -182,7 +190,7 @@ var FrankensteinVideoRequestBaseSchema = z3.object({
182
190
  generateAiMusic: z3.boolean().default(false),
183
191
  title: z3.string().trim().min(1).max(300).optional(),
184
192
  primaryAngle: z3.string().trim().max(500).optional(),
185
- productContext: z3.string().trim().max(PRODUCT_CONTEXT_MAX_CHARS).optional(),
193
+ productContext: z3.string().transform(canonicalizeProductContext).pipe(z3.string().max(PRODUCT_CONTEXT_MAX_CHARS)).optional(),
186
194
  productLabel: z3.string().trim().max(120).optional(),
187
195
  buyerPersona: z3.string().trim().max(500).optional(),
188
196
  cta: z3.string().trim().max(300).optional(),
@@ -4252,7 +4260,7 @@ var IngestOptions = z22.object({
4252
4260
  * per task. Length only, never `.uuid()` — Actor.id is a CUID. */
4253
4261
  actorId: z22.string().min(1).max(120).optional(),
4254
4262
  isCombo: z22.boolean().default(false),
4255
- productContext: z22.string().transform((value) => value.trim()).pipe(z22.string().max(PRODUCT_CONTEXT_MAX_CHARS)).optional(),
4263
+ productContext: z22.string().transform(canonicalizeProductContext).pipe(z22.string().max(PRODUCT_CONTEXT_MAX_CHARS)).optional(),
4256
4264
  creativeDirection: z22.string().transform((value) => value.trim()).pipe(z22.string().max(500)).optional(),
4257
4265
  /** Exact copy the user pinned. Rendered VERBATIM on the image creatives this task
4258
4266
  * produces and on the landing hero — never on video, which steers via scriptNotes.
@@ -5813,7 +5821,12 @@ var ShopifyPublishErrorResponse = z29.discriminatedUnion("code", [
5813
5821
  * variants, another app rewrote the product, landing too large).
5814
5822
  * `message` carries the seller's next step; never a 500.
5815
5823
  */
5816
- "SHOPIFY_PUBLISH_VERIFICATION_FAILED"
5824
+ "SHOPIFY_PUBLISH_VERIFICATION_FAILED",
5825
+ /**
5826
+ * The seller's store is frozen/paused/closed on Shopify's side (402/423
5827
+ * "Unavailable Shop"). 409; `message` says to reactivate it in Shopify.
5828
+ */
5829
+ "SHOPIFY_SHOP_UNAVAILABLE"
5817
5830
  ]),
5818
5831
  message: z29.string().optional(),
5819
5832
  authUrl: z29.string().url().optional(),
@@ -12084,7 +12097,11 @@ var VideoRegenerationEngineSchema = z58.enum([
12084
12097
  "free_text",
12085
12098
  "free_image",
12086
12099
  "single_call",
12087
- "multi_shot"
12100
+ "multi_shot",
12101
+ // Voice-only script edit: TTS of the new script in the video's own voice,
12102
+ // muxed over the delivered video. Only for voiceover-only renders (no shot
12103
+ // with on-camera lipsync), so no frame is regenerated.
12104
+ "voiceover"
12088
12105
  ]);
12089
12106
  var VideoRegenerationRouteFingerprintSchema = z58.string().trim().min(1).max(128);
12090
12107
  var RegenerateEditRequestSchema = z58.object({
@@ -14282,6 +14299,8 @@ var ProductControlDailyCountsSchema = z69.object({
14282
14299
  var ProductControlRowSchema = z69.object({
14283
14300
  /** `null` hasta que la vendedora toca el producto por primera vez. */
14284
14301
  productControlId: z69.string().nullable(),
14302
+ /** La operación a la que pertenece; opcional para payloads anteriores. */
14303
+ operationId: z69.string().nullable().optional(),
14285
14304
  shopId: z69.string(),
14286
14305
  shopDomain: z69.string(),
14287
14306
  /** Nulo cuando el producto NO vive en Shopify: importado del archivo de un
@@ -14478,9 +14497,7 @@ var SaveProductCatalogSchema = z69.object({
14478
14497
  "tiktok"
14479
14498
  ]).nullable().optional()
14480
14499
  }).strict();
14481
- var LinkProductControlCampaignSchema = z69.object({
14482
- shopDomain: z69.string().min(1),
14483
- shopifyProductId: z69.string().min(1),
14500
+ var ProductControlCampaignFieldsSchema = z69.object({
14484
14501
  provider: z69.enum([
14485
14502
  "meta",
14486
14503
  "tiktok"
@@ -14488,6 +14505,15 @@ var LinkProductControlCampaignSchema = z69.object({
14488
14505
  accountId: z69.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/),
14489
14506
  campaignId: z69.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/)
14490
14507
  }).strict();
14508
+ var LinkProductControlCampaignSchema = z69.union([
14509
+ ProductControlCampaignFieldsSchema.extend({
14510
+ productControlId: z69.string().uuid()
14511
+ }).strict(),
14512
+ ProductControlCampaignFieldsSchema.extend({
14513
+ shopDomain: z69.string().min(1),
14514
+ shopifyProductId: z69.string().min(1)
14515
+ }).strict()
14516
+ ]);
14491
14517
  var ReportProductControlReturnsSchema = z69.object({
14492
14518
  returnedOrders: z69.number().int().min(0).max(1e5),
14493
14519
  note: z69.string().trim().max(280).optional()
@@ -17784,6 +17810,53 @@ var RegenerateVideoScriptCapabilityRequest = z79.object({
17784
17810
  ]).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.")
17785
17811
  }).strict();
17786
17812
 
17813
+ // ../../packages/types/src/dropi-financial.ts
17814
+ import { z as z80 } from "zod";
17815
+ var ConnectDropiFinancialSchema = z80.object({
17816
+ integrationKey: z80.string().trim().min(1).max(4096).regex(/^[\x21-\x7e]+$/)
17817
+ }).strict();
17818
+ var SyncDropiFinancialSchema = z80.object({
17819
+ operationId: z80.string().uuid().optional(),
17820
+ since: z80.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
17821
+ until: z80.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional()
17822
+ }).strict();
17823
+ var DropiFinancialStatusSchema = z80.object({
17824
+ enabled: z80.boolean(),
17825
+ connected: z80.boolean(),
17826
+ countryCode: z80.literal("CO"),
17827
+ environment: z80.enum([
17828
+ "sandbox",
17829
+ "production"
17830
+ ]),
17831
+ lastSyncAt: z80.string().nullable(),
17832
+ lastError: z80.string().nullable(),
17833
+ historyNext: z80.string().nullable(),
17834
+ historyUntil: z80.string().nullable(),
17835
+ changesThrough: z80.string().nullable(),
17836
+ manualNext: z80.string().nullable(),
17837
+ manual: z80.object({
17838
+ since: z80.string(),
17839
+ until: z80.string(),
17840
+ next: z80.string().nullable()
17841
+ }).nullable(),
17842
+ retentionSince: z80.string()
17843
+ });
17844
+ var DropiFinancialSyncResultSchema = z80.object({
17845
+ orders: z80.number().int().nonnegative(),
17846
+ written: z80.number().int().nonnegative(),
17847
+ updated: z80.number().int().nonnegative(),
17848
+ pending: z80.boolean(),
17849
+ next: z80.string().nullable(),
17850
+ historyNext: z80.string().nullable(),
17851
+ changesThrough: z80.string().nullable(),
17852
+ since: z80.string(),
17853
+ until: z80.string(),
17854
+ unmatched: z80.array(z80.object({
17855
+ externalProductId: z80.string(),
17856
+ orders: z80.number().int().nonnegative()
17857
+ }))
17858
+ });
17859
+
17787
17860
  // src/http.ts
17788
17861
  import express4 from "express";
17789
17862
  import rateLimit2 from "express-rate-limit";
@@ -18293,23 +18366,23 @@ import { InsufficientScopeError, InvalidTokenError } from "@modelcontextprotocol
18293
18366
  import { createRemoteJWKSet as createRemoteJWKSet2, jwtVerify as jwtVerify2 } from "jose";
18294
18367
 
18295
18368
  // src/auth/oauth-config.ts
18296
- import { z as z80 } from "zod";
18369
+ import { z as z81 } from "zod";
18297
18370
  var MCP_RESOURCE = new URL("https://mcp.productmaker.app/mcp");
18298
18371
  var MCP_SCOPE = "mcp:access";
18299
18372
  var REFRESH_SCOPE = "offline_access";
18300
18373
  var STATIC_CLIENT_ISSUER = new URL(MCP_RESOURCE.origin);
18301
- var oauthEnvSchema = z80.object({
18302
- MCP_REMOTE_AUTH_MODE: z80.literal("oauth"),
18303
- MCP_AUTH0_ISSUER: z80.string().trim().min(1),
18304
- MCP_AUTH0_AUDIENCE: z80.string().trim().refine((value) => value === MCP_RESOURCE.href, {
18374
+ var oauthEnvSchema = z81.object({
18375
+ MCP_REMOTE_AUTH_MODE: z81.literal("oauth"),
18376
+ MCP_AUTH0_ISSUER: z81.string().trim().min(1),
18377
+ MCP_AUTH0_AUDIENCE: z81.string().trim().refine((value) => value === MCP_RESOURCE.href, {
18305
18378
  message: `must equal ${MCP_RESOURCE.href}`
18306
18379
  }),
18307
- MCP_AUTH0_CLIENT_ID: z80.string().trim().min(1),
18308
- MCP_AUTH0_CLIENT_SECRET: z80.string().trim().min(1),
18309
- PM_API_AUDIENCE: z80.string().trim().min(1),
18310
- AUTH0_AUDIENCE: z80.string().trim().min(1),
18311
- MCP_STATIC_CLIENT_ID: z80.string().trim().min(1).optional(),
18312
- MCP_STATIC_CLIENT_SECRET: z80.string().trim().min(1).optional()
18380
+ MCP_AUTH0_CLIENT_ID: z81.string().trim().min(1),
18381
+ MCP_AUTH0_CLIENT_SECRET: z81.string().trim().min(1),
18382
+ PM_API_AUDIENCE: z81.string().trim().min(1),
18383
+ AUTH0_AUDIENCE: z81.string().trim().min(1),
18384
+ MCP_STATIC_CLIENT_ID: z81.string().trim().min(1).optional(),
18385
+ MCP_STATIC_CLIENT_SECRET: z81.string().trim().min(1).optional()
18313
18386
  });
18314
18387
  function formatZodIssues(error) {
18315
18388
  return error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
@@ -19462,7 +19535,7 @@ var ApiClient = class {
19462
19535
  };
19463
19536
 
19464
19537
  // src/index.ts
19465
- var MCP_VERSION = "8.11.2";
19538
+ var MCP_VERSION = "8.11.4";
19466
19539
 
19467
19540
  // src/meta-upload-app.ts
19468
19541
  import { readFileSync } from "fs";
@@ -19534,7 +19607,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
19534
19607
  __name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
19535
19608
 
19536
19609
  // src/tools/tasks.ts
19537
- import { z as z85 } from "zod";
19610
+ import { z as z86 } from "zod";
19538
19611
 
19539
19612
  // src/resolve-image.ts
19540
19613
  import { lookup as dnsLookup } from "dns/promises";
@@ -20095,9 +20168,9 @@ async function resolveMediaRef(ref, opts) {
20095
20168
  __name(resolveMediaRef, "resolveMediaRef");
20096
20169
 
20097
20170
  // src/tools/shared.ts
20098
- import { z as z81 } from "zod";
20099
- 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);
20100
- var Country = z81.string().min(2).max(3);
20171
+ import { z as z82 } from "zod";
20172
+ var Lang = z82.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);
20173
+ var Country = z82.string().min(2).max(3);
20101
20174
  var LandingStrategyEnum = LandingStrategySchema;
20102
20175
  var LandingImageFormatEnum = LandingImageFormatSchema;
20103
20176
  var VideoPresetEnum = VideoPreset.extract([
@@ -20201,7 +20274,7 @@ function animationStyleApplies(videoPreset, angleNarratives) {
20201
20274
  return ANIMATED_VIDEO_PRESETS.has(videoPreset ?? "") || (angleNarratives ?? []).some((n) => ANIMATED_NARRATIVE_STYLES.has(n));
20202
20275
  }
20203
20276
  __name(animationStyleApplies, "animationStyleApplies");
20204
- var VideoTierEnum = z81.enum([
20277
+ var VideoTierEnum = z82.enum([
20205
20278
  "basic"
20206
20279
  ]);
20207
20280
  function resolveVideoTier(_tier) {
@@ -20259,10 +20332,10 @@ var ImageCreativeStyleEnum = ImageCreativeStyle;
20259
20332
  var ImageCreativeArchetypeEnum = ImageCreativeArchetype;
20260
20333
  var ImageCreativeVisualTreatmentEnum = ImageCreativeVisualTreatment;
20261
20334
  var ImageCreativeAspectRatioEnum = ImageCreativeAspectRatio;
20262
- var ImageRefSchema = z81.object({
20263
- 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.'),
20264
- 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`.'),
20265
- 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.")
20335
+ var ImageRefSchema = z82.object({
20336
+ url: z82.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.'),
20337
+ path: z82.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`.'),
20338
+ assetId: z82.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.")
20266
20339
  }).refine((v) => [
20267
20340
  v.url,
20268
20341
  v.path,
@@ -20270,11 +20343,11 @@ var ImageRefSchema = z81.object({
20270
20343
  ].filter(Boolean).length === 1, {
20271
20344
  message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
20272
20345
  });
20273
- var ImagesInput = z81.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
20346
+ var ImagesInput = z82.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
20274
20347
  const assetCount = images.filter((image) => Boolean(image.assetId)).length;
20275
20348
  if (assetCount > 0 && assetCount !== images.length) {
20276
20349
  ctx.addIssue({
20277
- code: z81.ZodIssueCode.custom,
20350
+ code: z82.ZodIssueCode.custom,
20278
20351
  message: "all image entries must use assetId, or all must use URL/path sources"
20279
20352
  });
20280
20353
  }
@@ -20347,14 +20420,14 @@ async function submitCreative(api, opts) {
20347
20420
  });
20348
20421
  }
20349
20422
  __name(submitCreative, "submitCreative");
20350
- var ResearchTargetCountryEnum = z81.enum([
20423
+ var ResearchTargetCountryEnum = z82.enum([
20351
20424
  "CO",
20352
20425
  "MX",
20353
20426
  "PE",
20354
20427
  "EC",
20355
20428
  "CL"
20356
20429
  ]);
20357
- var ResearchCategoryEnum = z81.enum([
20430
+ var ResearchCategoryEnum = z82.enum([
20358
20431
  "auto",
20359
20432
  "automotive",
20360
20433
  "kitchen",
@@ -20491,6 +20564,7 @@ var McpErrorCode = {
20491
20564
  SHOPIFY_SCOPE_UPGRADE_REQUIRED: "SHOPIFY_SCOPE_UPGRADE_REQUIRED",
20492
20565
  SHOPIFY_PUBLISH_FAILED: "SHOPIFY_PUBLISH_FAILED",
20493
20566
  SHOPIFY_NO_PUBLISHED_THEME: "SHOPIFY_NO_PUBLISHED_THEME",
20567
+ SHOPIFY_SHOP_UNAVAILABLE: "SHOPIFY_SHOP_UNAVAILABLE",
20494
20568
  SHOPIFY_THEME_STRUCTURE_UNSUPPORTED: "SHOPIFY_THEME_STRUCTURE_UNSUPPORTED",
20495
20569
  SHOPIFY_PUBLISH_INPUT_REQUIRED: "SHOPIFY_PUBLISH_INPUT_REQUIRED",
20496
20570
  SHOPIFY_PUBLISH_CONTEXT_CHANGED: "SHOPIFY_PUBLISH_CONTEXT_CHANGED",
@@ -20573,6 +20647,7 @@ var CODE_MESSAGES = {
20573
20647
  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).",
20574
20648
  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.",
20575
20649
  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.",
20650
+ 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.",
20576
20651
  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.",
20577
20652
  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.",
20578
20653
  // Meta — high-frequency
@@ -20764,6 +20839,7 @@ var INVALID_PARAM_CODES = /* @__PURE__ */ new Set([
20764
20839
  McpErrorCode.SHOPIFY_SCOPE_UPGRADE_REQUIRED,
20765
20840
  McpErrorCode.SHOPIFY_NOT_CONNECTED,
20766
20841
  McpErrorCode.SHOPIFY_NO_PUBLISHED_THEME,
20842
+ McpErrorCode.SHOPIFY_SHOP_UNAVAILABLE,
20767
20843
  McpErrorCode.SHOPIFY_THEME_STRUCTURE_UNSUPPORTED,
20768
20844
  McpErrorCode.SHOPIFY_PUBLISH_INPUT_REQUIRED,
20769
20845
  McpErrorCode.SHOPIFY_PUBLISH_CONTEXT_CHANGED,
@@ -20806,6 +20882,7 @@ var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
20806
20882
  McpErrorCode.SHOPIFY_SCOPE_UPGRADE_REQUIRED,
20807
20883
  McpErrorCode.SHOPIFY_PUBLISH_FAILED,
20808
20884
  McpErrorCode.SHOPIFY_NO_PUBLISHED_THEME,
20885
+ McpErrorCode.SHOPIFY_SHOP_UNAVAILABLE,
20809
20886
  McpErrorCode.SHOPIFY_THEME_STRUCTURE_UNSUPPORTED,
20810
20887
  // Meta
20811
20888
  McpErrorCode.META_NO_FB_PAGE,
@@ -21520,29 +21597,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
21520
21597
  __name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
21521
21598
 
21522
21599
  // src/tools/media-presentation.ts
21523
- import { z as z82 } from "zod";
21524
- var HttpsPresentationUrlSchema = z82.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
21600
+ import { z as z83 } from "zod";
21601
+ var HttpsPresentationUrlSchema = z83.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
21525
21602
  var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
21526
21603
  const hostname = new URL(value).hostname.toLowerCase();
21527
21604
  return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
21528
21605
  }, "preview URL must be owned by ProductMaker");
21529
- var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z82.number().int().positive().max(maximum), "positiveIntAtMost");
21530
- var PresentationImageSchema = z82.object({
21531
- kind: z82.literal("image"),
21606
+ var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z83.number().int().positive().max(maximum), "positiveIntAtMost");
21607
+ var PresentationImageSchema = z83.object({
21608
+ kind: z83.literal("image"),
21532
21609
  url: HttpsPresentationUrlSchema,
21533
- mimeType: z82.enum([
21610
+ mimeType: z83.enum([
21534
21611
  "image/jpeg",
21535
21612
  "image/png"
21536
21613
  ]),
21537
21614
  byteSize: positiveIntAtMost(5 * 1024 * 1024),
21538
21615
  width: positiveIntAtMost(16384),
21539
21616
  height: positiveIntAtMost(16384),
21540
- alt: z82.string().trim().min(1).max(240)
21617
+ alt: z83.string().trim().min(1).max(240)
21541
21618
  }).strict();
21542
21619
  var McpMediaPresentationSchema = PresentationImageSchema;
21543
- var GalleryImageSchema = z82.object({
21620
+ var GalleryImageSchema = z83.object({
21544
21621
  url: ProductMakerPreviewUrlSchema,
21545
- alt: z82.string().trim().min(1).max(240)
21622
+ alt: z83.string().trim().min(1).max(240)
21546
21623
  });
21547
21624
  var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
21548
21625
  async function imageBlocks(image, transport) {
@@ -21663,7 +21740,7 @@ async function buildMcpImageGalleryContent(rawItems, transport = "http") {
21663
21740
  __name(buildMcpImageGalleryContent, "buildMcpImageGalleryContent");
21664
21741
 
21665
21742
  // src/tools/animated-video.ts
21666
- import { z as z83 } from "zod";
21743
+ import { z as z84 } from "zod";
21667
21744
 
21668
21745
  // src/tools/paid-confirmation.ts
21669
21746
  function describeMarketStudyChoice(enabled) {
@@ -21876,44 +21953,44 @@ function describeAnimatedVideoPrices() {
21876
21953
  return MOTION_GRAPHICS_DURATIONS.map((d) => `${d} s = ${creditsFor(d)} cr\xE9ditos (US$${usdFor(d)})`).join(", ");
21877
21954
  }
21878
21955
  __name(describeAnimatedVideoPrices, "describeAnimatedVideoPrices");
21879
- var DurationInput = z83.union(MOTION_GRAPHICS_DURATIONS.map((d) => z83.literal(d)));
21880
- var CreateAnimatedVideoInput = z83.object({
21956
+ var DurationInput = z84.union(MOTION_GRAPHICS_DURATIONS.map((d) => z84.literal(d)));
21957
+ var CreateAnimatedVideoInput = z84.object({
21881
21958
  // Plain text, not `.url()`: users type «cal.com», and the web accepts it.
21882
21959
  // normalizeWebAddress (shared with the web) adds https:// and refuses
21883
21960
  // anything that is not a public http(s) address.
21884
- 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."),
21961
+ landingUrl: z84.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."),
21885
21962
  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.'),
21886
21963
  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.`),
21887
21964
  language: MotionGraphicsLanguageSchema.describe('Idioma de los textos del video: "es", "en" o "pt".'),
21888
- 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).")
21965
+ notes: z84.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).")
21889
21966
  }).strict();
21890
21967
  var FORMAT_LABELS = {
21891
21968
  vertical: "vertical 9:16",
21892
21969
  square: "cuadrado 1:1",
21893
21970
  horizontal: "horizontal 16:9"
21894
21971
  };
21895
- var AnimatedVideoResultSchema = z83.object({
21896
- status: z83.enum([
21972
+ var AnimatedVideoResultSchema = z84.object({
21973
+ status: z84.enum([
21897
21974
  "pending",
21898
21975
  "done",
21899
21976
  "error"
21900
21977
  ]),
21901
- serviceMode: z83.literal("motion_graphics"),
21902
- finalMp4Url: z83.string().optional(),
21903
- error: z83.string().optional(),
21904
- motionGraphics: z83.object({
21978
+ serviceMode: z84.literal("motion_graphics"),
21979
+ finalMp4Url: z84.string().optional(),
21980
+ error: z84.string().optional(),
21981
+ motionGraphics: z84.object({
21905
21982
  stage: MotionGraphicsStageSchema,
21906
21983
  format: MotionGraphicsFormatSchema,
21907
- durationSec: z83.number(),
21908
- width: z83.number().optional(),
21909
- height: z83.number().optional(),
21984
+ durationSec: z84.number(),
21985
+ width: z84.number().optional(),
21986
+ height: z84.number().optional(),
21910
21987
  language: MotionGraphicsLanguageSchema.optional(),
21911
- queuedAt: z83.string().optional(),
21912
- jobsAhead: z83.number().int().nonnegative().optional(),
21913
- stageStartedAt: z83.string().optional(),
21914
- renderProgress: z83.number().optional(),
21915
- activity: z83.array(MotionGraphicsActivitySchema).optional().catch(void 0),
21916
- previewUrl: z83.string().optional()
21988
+ queuedAt: z84.string().optional(),
21989
+ jobsAhead: z84.number().int().nonnegative().optional(),
21990
+ stageStartedAt: z84.string().optional(),
21991
+ renderProgress: z84.number().optional(),
21992
+ activity: z84.array(MotionGraphicsActivitySchema).optional().catch(void 0),
21993
+ previewUrl: z84.string().optional()
21917
21994
  }).passthrough()
21918
21995
  }).passthrough();
21919
21996
  function parseAnimatedVideoResult(value) {
@@ -22075,10 +22152,10 @@ function registerAnimatedVideoTools(server, api) {
22075
22152
  __name(registerAnimatedVideoTools, "registerAnimatedVideoTools");
22076
22153
 
22077
22154
  // src/tools/winning-product-image.ts
22078
- import { z as z84 } from "zod";
22079
- var WinnerReferenceInput = z84.object({
22080
- runId: z84.string().uuid(),
22081
- candidateSourceId: z84.string().trim().min(1).max(160)
22155
+ import { z as z85 } from "zod";
22156
+ var WinnerReferenceInput = z85.object({
22157
+ runId: z85.string().uuid(),
22158
+ candidateSourceId: z85.string().trim().min(1).max(160)
22082
22159
  }).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
22083
22160
  async function resolveWinnerImages(api, winnerReference, images) {
22084
22161
  if (!winnerReference) return images;
@@ -22115,60 +22192,60 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
22115
22192
  var createServiceVideoGuidance = getProductMakerCapabilityModelGuidance("create_service_video");
22116
22193
  var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
22117
22194
  var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
22118
- var CreateProductTaskInput = z85.object({
22195
+ var CreateProductTaskInput = z86.object({
22119
22196
  images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
22120
22197
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
22121
- 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."),
22122
- 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."),
22198
+ projectId: z86.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
22199
+ productUrl: z86.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."),
22123
22200
  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.'),
22124
22201
  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.'),
22125
- 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.'),
22126
- 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".'),
22127
- 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.'),
22128
- 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.'),
22129
- 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."),
22130
- 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.'),
22202
+ price: z86.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.'),
22203
+ compareAtPrice: z86.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".'),
22204
+ offer: z86.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.'),
22205
+ paymentMethods: z86.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.'),
22206
+ productContext: z86.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."),
22207
+ productLabel: z86.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.'),
22131
22208
  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.'),
22132
22209
  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.'),
22133
- durationSeconds: z85.union([
22134
- z85.literal(15),
22135
- z85.literal(30)
22210
+ durationSeconds: z86.union([
22211
+ z86.literal(15),
22212
+ z86.literal(30)
22136
22213
  ]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
22137
- 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."),
22138
- 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."),
22214
+ pauseForAngleReview: z86.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."),
22215
+ aiDecidesAll: z86.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."),
22139
22216
  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.'),
22140
22217
  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.'),
22141
22218
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
22142
22219
  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).'),
22143
- 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."),
22220
+ videoAngleCount: z86.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."),
22144
22221
  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.'),
22145
- outputs: z85.array(z85.enum([
22222
+ outputs: z86.array(z86.enum([
22146
22223
  "landing",
22147
22224
  "video",
22148
22225
  "image"
22149
22226
  ])).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}`),
22150
- 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."),
22151
- 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."),
22152
- 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."),
22153
- 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."),
22227
+ competitorScanEnabled: z86.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."),
22228
+ replicateWinnerWhenFound: z86.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."),
22229
+ 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 los outputs generados."),
22230
+ actorId: z86.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."),
22154
22231
  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.'),
22155
- 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.'),
22156
- 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."),
22157
- 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."),
22232
+ creativeDirection: z86.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.'),
22233
+ headline: z86.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."),
22234
+ subheadline: z86.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."),
22158
22235
  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".'),
22159
22236
  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".')
22160
22237
  }).strict();
22161
- var CreateServiceVideoInput = z85.object({
22162
- 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."),
22163
- 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.'),
22238
+ var CreateServiceVideoInput = z86.object({
22239
+ landingUrl: z86.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
22240
+ additionalContext: z86.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
22164
22241
  language: Lang.describe("Idioma del video: es, en o pt."),
22165
- 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.'),
22166
- brandId: z85.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
22167
- reviewMode: z85.enum([
22242
+ voiceId: z86.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.'),
22243
+ brandId: z86.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
22244
+ reviewMode: z86.enum([
22168
22245
  "automatic",
22169
22246
  "guided"
22170
22247
  ]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
22171
- videoPreset: z85.enum([
22248
+ videoPreset: z86.enum([
22172
22249
  "auto",
22173
22250
  "ugc_dynamic",
22174
22251
  "ugc_how_to",
@@ -22178,128 +22255,128 @@ var CreateServiceVideoInput = z85.object({
22178
22255
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
22179
22256
  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.')
22180
22257
  }).strict();
22181
- var GetTaskStatusInput = z85.object({
22182
- taskId: z85.string().min(1),
22183
- waitSeconds: z85.number().int().min(0).max(120).optional()
22258
+ var GetTaskStatusInput = z86.object({
22259
+ taskId: z86.string().min(1),
22260
+ waitSeconds: z86.number().int().min(0).max(120).optional()
22184
22261
  });
22185
- var ListTasksInput = z85.object({
22186
- limit: z85.number().int().min(1).max(50).optional(),
22187
- offset: z85.number().int().min(0).optional(),
22188
- search: z85.string().optional()
22262
+ var ListTasksInput = z86.object({
22263
+ limit: z86.number().int().min(1).max(50).optional(),
22264
+ offset: z86.number().int().min(0).optional(),
22265
+ search: z86.string().optional()
22189
22266
  });
22190
22267
  var MCP_REVIEW_LIST_FIELD_MAX = IMAGE_WIZARD_LIST_FIELD_MAX;
22191
22268
  var MCP_REVIEW_FEATURE_ITEM_MAX = IMAGE_FEATURE_ITEM_MAX;
22192
- var EditTaskDraftInput = z85.object({
22193
- taskId: z85.string().min(1),
22194
- angleIndex: z85.number().int().min(0),
22195
- angle: z85.object({
22196
- angle: z85.string().min(1).max(480),
22197
- buyerPersona: z85.string().min(1).max(360),
22198
- actor: z85.string().min(1).max(360).optional(),
22199
- 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."),
22200
- gender: z85.enum([
22269
+ var EditTaskDraftInput = z86.object({
22270
+ taskId: z86.string().min(1),
22271
+ angleIndex: z86.number().int().min(0),
22272
+ angle: z86.object({
22273
+ angle: z86.string().min(1).max(480),
22274
+ buyerPersona: z86.string().min(1).max(360),
22275
+ actor: z86.string().min(1).max(360).optional(),
22276
+ actorId: z86.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."),
22277
+ gender: z86.enum([
22201
22278
  "female",
22202
22279
  "male"
22203
22280
  ]).optional(),
22204
- scriptNotes: z85.string().max(2e3).optional()
22281
+ scriptNotes: z86.string().max(2e3).optional()
22205
22282
  })
22206
22283
  });
22207
- var PendingActionPayload = z85.discriminatedUnion("kind", [
22208
- z85.object({
22209
- kind: z85.literal("product_reference_set_approval"),
22284
+ var PendingActionPayload = z86.discriminatedUnion("kind", [
22285
+ z86.object({
22286
+ kind: z86.literal("product_reference_set_approval"),
22210
22287
  scope: ProductReferenceScopeEnum.optional(),
22211
- scopeKey: z85.string().min(1).max(120).optional(),
22212
- scopeSnapshotId: z85.string().uuid().optional(),
22213
- expectedScopeHash: z85.string().min(1).max(128).optional(),
22288
+ scopeKey: z86.string().min(1).max(120).optional(),
22289
+ scopeSnapshotId: z86.string().uuid().optional(),
22290
+ expectedScopeHash: z86.string().min(1).max(128).optional(),
22214
22291
  decision: ProductReferenceResolutionDecisionEnum,
22215
22292
  reason: ProductReferenceRejectionReasonEnum.optional(),
22216
- affectedRefKeys: z85.array(z85.string().min(1).max(200)).min(1).optional(),
22217
- affectedPhotoNumbers: z85.array(z85.number().int().positive()).min(1).optional(),
22218
- recoveryAction: z85.enum([
22293
+ affectedRefKeys: z86.array(z86.string().min(1).max(200)).min(1).optional(),
22294
+ affectedPhotoNumbers: z86.array(z86.number().int().positive()).min(1).optional(),
22295
+ recoveryAction: z86.enum([
22219
22296
  "remove",
22220
22297
  "replace",
22221
22298
  "upload",
22222
22299
  "return_to_selection"
22223
22300
  ]).optional()
22224
22301
  }),
22225
- z85.object({
22226
- kind: z85.literal("product_reference_confirmation"),
22227
- 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."),
22302
+ z86.object({
22303
+ kind: z86.literal("product_reference_confirmation"),
22304
+ selectedPhotoNumbers: z86.array(z86.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."),
22228
22305
  userChoice: ProductReferenceUserChoiceEnum.optional(),
22229
- confirmedProductNames: z85.array(z85.string().min(1).max(120)).min(2).max(8).optional(),
22306
+ confirmedProductNames: z86.array(z86.string().min(1).max(120)).min(2).max(8).optional(),
22230
22307
  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."),
22231
22308
  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."),
22232
- useMultiSceneShowcase: z85.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
22309
+ useMultiSceneShowcase: z86.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
22233
22310
  }),
22234
- z85.object({
22235
- kind: z85.literal("angle_review_approval"),
22311
+ z86.object({
22312
+ kind: z86.literal("angle_review_approval"),
22236
22313
  // All edits are optional — empty action body just approves the
22237
22314
  // backend-generated draft as-is. Field shapes mirror the angle-review
22238
22315
  // request contracts in @packages/types/wizard.ts; the handler routes to
22239
22316
  // the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
22240
- customAngle: z85.string().min(1).max(480).optional(),
22317
+ customAngle: z86.string().min(1).max(480).optional(),
22241
22318
  // Keep the shared MCP action within the strictest downstream contract:
22242
22319
  // autopilot/image resume endpoints cap these fields at 1500 characters.
22243
- painPoints: z85.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
22244
- benefits: z85.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
22320
+ painPoints: z86.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
22321
+ benefits: z86.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
22245
22322
  // Same policy as the two fields above: the strictest downstream contract
22246
22323
  // wins. The image endpoint caps each feature at 240 while landing/video
22247
22324
  // accept 300, and this single action routes to whichever the task is — so
22248
22325
  // accepting 300 here turns a 250-character feature on an image task into
22249
22326
  // an opaque HTTP 400 after the model already believed it had been saved.
22250
- features: z85.array(z85.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
22251
- buyerPersona: z85.string().min(1).max(360).optional(),
22327
+ features: z86.array(z86.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
22328
+ buyerPersona: z86.string().min(1).max(360).optional(),
22252
22329
  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.'),
22253
- 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."),
22254
- actorId: z85.string().max(120).nullable().optional(),
22255
- creativeDirection: z85.string().max(2e3).optional(),
22256
- 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."),
22257
- angleEdits: z85.array(z85.object({
22258
- angleNumber: z85.number().int().positive(),
22259
- narrativeSelection: z85.enum([
22330
+ actor: z86.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."),
22331
+ actorId: z86.string().max(120).nullable().optional(),
22332
+ creativeDirection: z86.string().max(2e3).optional(),
22333
+ selectedAngleNumbers: z86.array(z86.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."),
22334
+ angleEdits: z86.array(z86.object({
22335
+ angleNumber: z86.number().int().positive(),
22336
+ narrativeSelection: z86.enum([
22260
22337
  "market",
22261
22338
  "guided"
22262
22339
  ]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
22263
- angle: z85.string().min(1).max(480).optional(),
22264
- buyerPersona: z85.string().min(1).max(360).optional(),
22340
+ angle: z86.string().min(1).max(480).optional(),
22341
+ buyerPersona: z86.string().min(1).max(360).optional(),
22265
22342
  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.'),
22266
- actor: z85.string().min(1).max(360).optional(),
22267
- actorId: z85.string().max(120).nullable().optional(),
22268
- creativeDirection: z85.string().max(2e3).optional()
22343
+ actor: z86.string().min(1).max(360).optional(),
22344
+ actorId: z86.string().max(120).nullable().optional(),
22345
+ creativeDirection: z86.string().max(2e3).optional()
22269
22346
  }).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)."),
22270
- gapDurationSeconds: z85.union([
22271
- z85.literal(15),
22272
- z85.literal(30)
22347
+ gapDurationSeconds: z86.union([
22348
+ z86.literal(15),
22349
+ z86.literal(30)
22273
22350
  ]).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.")
22274
22351
  }),
22275
- z85.object({
22276
- kind: z85.literal("service_angle_approval"),
22277
- angleId: z85.string().uuid().optional(),
22278
- angleNumber: z85.number().int().positive().optional(),
22279
- content: z85.string().min(1).max(480).optional(),
22280
- creativeDirection: z85.string().min(1).max(1500).optional(),
22281
- actor: z85.string().min(1).max(360).optional()
22352
+ z86.object({
22353
+ kind: z86.literal("service_angle_approval"),
22354
+ angleId: z86.string().uuid().optional(),
22355
+ angleNumber: z86.number().int().positive().optional(),
22356
+ content: z86.string().min(1).max(480).optional(),
22357
+ creativeDirection: z86.string().min(1).max(1500).optional(),
22358
+ actor: z86.string().min(1).max(360).optional()
22282
22359
  }),
22283
- z85.object({
22284
- kind: z85.literal("service_script_approval"),
22285
- voiceovers: z85.record(z85.string(), z85.string().min(1).max(600)).optional(),
22286
- visualDirections: z85.record(z85.string(), z85.string().min(1).max(1200)).optional(),
22287
- voiceoversByScene: z85.record(z85.string(), z85.string().min(1).max(600)).optional(),
22288
- visualDirectionsByScene: z85.record(z85.string(), z85.string().min(1).max(1200)).optional()
22360
+ z86.object({
22361
+ kind: z86.literal("service_script_approval"),
22362
+ voiceovers: z86.record(z86.string(), z86.string().min(1).max(600)).optional(),
22363
+ visualDirections: z86.record(z86.string(), z86.string().min(1).max(1200)).optional(),
22364
+ voiceoversByScene: z86.record(z86.string(), z86.string().min(1).max(600)).optional(),
22365
+ visualDirectionsByScene: z86.record(z86.string(), z86.string().min(1).max(1200)).optional()
22289
22366
  })
22290
22367
  ]);
22291
- var ResolvePendingActionInput = z85.object({
22292
- taskId: z85.string().min(1),
22368
+ var ResolvePendingActionInput = z86.object({
22369
+ taskId: z86.string().min(1),
22293
22370
  action: PendingActionPayload
22294
22371
  }).strict();
22295
22372
  function resolveVariantConfirmVideoTier(action) {
22296
22373
  return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
22297
22374
  }
22298
22375
  __name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
22299
- var StatusForResolveSchema = z85.object({
22376
+ var StatusForResolveSchema = z86.object({
22300
22377
  // Metadata used to select the backend resume contract. Older API responses
22301
22378
  // may omit these fields, so the resolver keeps the generic fallback.
22302
- kind: z85.enum([
22379
+ kind: z86.enum([
22303
22380
  "autopilot",
22304
22381
  "video",
22305
22382
  "image",
@@ -22307,18 +22384,18 @@ var StatusForResolveSchema = z85.object({
22307
22384
  "mix",
22308
22385
  "service"
22309
22386
  ]).optional(),
22310
- selectedOutputs: z85.array(z85.enum([
22387
+ selectedOutputs: z86.array(z86.enum([
22311
22388
  "landing",
22312
22389
  "video",
22313
22390
  "image"
22314
22391
  ])).optional(),
22315
- videoAngleCount: z85.number().int().min(1).max(3).optional(),
22316
- ugcFormat: z85.enum([
22392
+ videoAngleCount: z86.number().int().min(1).max(3).optional(),
22393
+ ugcFormat: z86.enum([
22317
22394
  "single_8s",
22318
22395
  "single_15s",
22319
22396
  "double_30s"
22320
22397
  ]).optional(),
22321
- videoStyle: z85.enum([
22398
+ videoStyle: z86.enum([
22322
22399
  "ugc",
22323
22400
  "cartoon_3d",
22324
22401
  "product_only",
@@ -22328,13 +22405,13 @@ var StatusForResolveSchema = z85.object({
22328
22405
  videoQuality: VideoQualityEnum.optional(),
22329
22406
  videoRouteId: VideoRouteIdEnum.optional(),
22330
22407
  videoModel: TaskVideoModelEnum.optional(),
22331
- videoTier: z85.enum([
22408
+ videoTier: z86.enum([
22332
22409
  "legacy",
22333
22410
  "standard",
22334
22411
  "pro",
22335
22412
  "single_call"
22336
22413
  ]).optional(),
22337
- videoResolution: z85.enum([
22414
+ videoResolution: z86.enum([
22338
22415
  "480p",
22339
22416
  "720p"
22340
22417
  ]).optional(),
@@ -22342,60 +22419,60 @@ var StatusForResolveSchema = z85.object({
22342
22419
  // A task created before a narrative was blocked/hidden must still parse,
22343
22420
  // or resolve_pending_action could never approve it.
22344
22421
  narrativeStyle: NarrativeStyle.optional(),
22345
- pauseForVideoScriptReview: z85.boolean().optional(),
22346
- pendingUserAction: z85.object({
22347
- kind: z85.string(),
22348
- candidateGrouping: z85.string().optional(),
22349
- selectedImageUrls: z85.array(z85.string()).optional(),
22350
- proposedProductNames: z85.array(z85.string()).optional(),
22422
+ pauseForVideoScriptReview: z86.boolean().optional(),
22423
+ pendingUserAction: z86.object({
22424
+ kind: z86.string(),
22425
+ candidateGrouping: z86.string().optional(),
22426
+ selectedImageUrls: z86.array(z86.string()).optional(),
22427
+ proposedProductNames: z86.array(z86.string()).optional(),
22351
22428
  // Adaptive reference questions are server-owned. Echo only the evidence
22352
22429
  // identity and the choices shown by the current snapshot; never accept a
22353
22430
  // client-supplied reference set as authorization.
22354
- options: z85.array(ProductReferenceUserChoiceEnum).max(4).optional(),
22355
- mode: z85.enum([
22431
+ options: z86.array(ProductReferenceUserChoiceEnum).max(4).optional(),
22432
+ mode: z86.enum([
22356
22433
  "question",
22357
22434
  "visual_recovery"
22358
22435
  ]).optional(),
22359
22436
  /** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
22360
- canKeepSelection: z85.boolean().optional(),
22361
- decisionKey: z85.string().optional(),
22362
- questionOrdinal: z85.number().int().min(1).max(5).optional(),
22363
- questionCeiling: z85.union([
22364
- z85.literal(3),
22365
- z85.literal(5)
22437
+ canKeepSelection: z86.boolean().optional(),
22438
+ decisionKey: z86.string().optional(),
22439
+ questionOrdinal: z86.number().int().min(1).max(5).optional(),
22440
+ questionCeiling: z86.union([
22441
+ z86.literal(3),
22442
+ z86.literal(5)
22366
22443
  ]).optional(),
22367
- referenceEvidenceVersion: z85.number().int().positive().optional(),
22368
- expectedEvidenceHash: z85.string().optional(),
22369
- question: z85.object({
22370
- prompt: z85.string().min(1).max(240),
22371
- helpText: z85.string().min(1).max(300).optional(),
22372
- options: z85.array(z85.object({
22444
+ referenceEvidenceVersion: z86.number().int().positive().optional(),
22445
+ expectedEvidenceHash: z86.string().optional(),
22446
+ question: z86.object({
22447
+ prompt: z86.string().min(1).max(240),
22448
+ helpText: z86.string().min(1).max(300).optional(),
22449
+ options: z86.array(z86.object({
22373
22450
  value: ProductReferenceUserChoiceEnum,
22374
- label: z85.string().min(1).max(120),
22375
- description: z85.string().min(1).max(240).optional()
22451
+ label: z86.string().min(1).max(120),
22452
+ description: z86.string().min(1).max(240).optional()
22376
22453
  })).min(2).max(4)
22377
22454
  }).optional(),
22378
22455
  scope: ProductReferenceScopeEnum.optional(),
22379
- scopeKey: z85.string().optional(),
22380
- scopeSnapshotId: z85.string().uuid().optional(),
22381
- scopeHash: z85.string().optional(),
22382
- baseReferenceSetHash: z85.string().optional(),
22383
- phase: z85.enum([
22456
+ scopeKey: z86.string().optional(),
22457
+ scopeSnapshotId: z86.string().uuid().optional(),
22458
+ scopeHash: z86.string().optional(),
22459
+ baseReferenceSetHash: z86.string().optional(),
22460
+ phase: z86.enum([
22384
22461
  "preparation",
22385
22462
  "final"
22386
22463
  ]).optional(),
22387
- selectedRefKeys: z85.array(z85.string().min(1).max(200)).optional(),
22388
- allowedDecisions: z85.array(ProductReferenceResolutionDecisionEnum).optional(),
22389
- previews: z85.array(z85.object({
22390
- refKey: z85.string().min(1).max(200)
22464
+ selectedRefKeys: z86.array(z86.string().min(1).max(200)).optional(),
22465
+ allowedDecisions: z86.array(ProductReferenceResolutionDecisionEnum).optional(),
22466
+ previews: z86.array(z86.object({
22467
+ refKey: z86.string().min(1).max(200)
22391
22468
  }).passthrough()).optional(),
22392
- customAngleDraft: z85.string().optional(),
22393
- painPointsDraft: z85.string().optional(),
22394
- benefitsDraft: z85.string().optional(),
22395
- featuresDraft: z85.array(z85.string()).optional(),
22396
- angleOptions: z85.array(z85.object({
22397
- index: z85.number().int().nonnegative(),
22398
- angle: z85.string().min(1)
22469
+ customAngleDraft: z86.string().optional(),
22470
+ painPointsDraft: z86.string().optional(),
22471
+ benefitsDraft: z86.string().optional(),
22472
+ featuresDraft: z86.array(z86.string()).optional(),
22473
+ angleOptions: z86.array(z86.object({
22474
+ index: z86.number().int().nonnegative(),
22475
+ angle: z86.string().min(1)
22399
22476
  }).passthrough()).min(1).max(5).optional(),
22400
22477
  // Recommendation consumed only when the caller explicitly sends
22401
22478
  // gapDurationSeconds: 30 in the angle approval action.
@@ -22405,17 +22482,17 @@ var StatusForResolveSchema = z85.object({
22405
22482
  // keys. `actorId` (the saved custom actor the picker stored) was silently
22406
22483
  // dropped here, so the approval handler below could not echo it back on the
22407
22484
  // PATCH — the selection looked accepted and reached no render.
22408
- angles: z85.array(z85.object({
22409
- id: z85.string().uuid(),
22410
- content: z85.string(),
22411
- creativeDirection: z85.string(),
22412
- actor: z85.string(),
22413
- actorId: z85.string().nullable().optional()
22485
+ angles: z86.array(z86.object({
22486
+ id: z86.string().uuid(),
22487
+ content: z86.string(),
22488
+ creativeDirection: z86.string(),
22489
+ actor: z86.string(),
22490
+ actorId: z86.string().nullable().optional()
22414
22491
  }).passthrough()).optional(),
22415
- panels: z85.array(z85.object({
22416
- beatId: z85.string(),
22417
- voiceover: z85.string(),
22418
- visualDirection: z85.string()
22492
+ panels: z86.array(z86.object({
22493
+ beatId: z86.string(),
22494
+ voiceover: z86.string(),
22495
+ visualDirection: z86.string()
22419
22496
  }).passthrough()).optional()
22420
22497
  }).optional()
22421
22498
  }).passthrough();
@@ -22762,8 +22839,8 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
22762
22839
  server.registerTool("verify_landing_commerce", {
22763
22840
  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.",
22764
22841
  inputSchema: {
22765
- taskId: z85.string().uuid(),
22766
- editId: z85.string().uuid()
22842
+ taskId: z86.string().uuid(),
22843
+ editId: z86.string().uuid()
22767
22844
  },
22768
22845
  annotations: OVERWRITES_EXTERNAL
22769
22846
  }, async (input) => {
@@ -23402,7 +23479,7 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
23402
23479
  __name(registerTaskTools, "registerTaskTools");
23403
23480
 
23404
23481
  // src/tools/creatives.ts
23405
- import { z as z86 } from "zod";
23482
+ import { z as z87 } from "zod";
23406
23483
  var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
23407
23484
  var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
23408
23485
  var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
@@ -23413,71 +23490,71 @@ var CreativeRefs = {
23413
23490
  images: ImagesInput,
23414
23491
  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.'),
23415
23492
  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.'),
23416
- 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.'),
23417
- 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.'),
23418
- 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".'),
23419
- 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."),
23420
- 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.'),
23421
- 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.'),
23422
- isCombo: z86.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
23423
- 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."),
23424
- 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.")
23493
+ price: z87.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.'),
23494
+ offer: z87.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.'),
23495
+ compareAtPrice: z87.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
23496
+ productContext: z87.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."),
23497
+ productLabel: z87.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.'),
23498
+ buyerPersona: z87.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.'),
23499
+ isCombo: z87.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
23500
+ competitorScanEnabled: z87.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."),
23501
+ brandId: z87.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.")
23425
23502
  };
23426
- var VideoPresenter = z86.discriminatedUnion("mode", [
23427
- z86.object({
23428
- mode: z86.literal("none")
23503
+ var VideoPresenter = z87.discriminatedUnion("mode", [
23504
+ z87.object({
23505
+ mode: z87.literal("none")
23429
23506
  }).strict(),
23430
- z86.object({
23431
- mode: z86.literal("saved_actor"),
23432
- actorId: z86.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
23507
+ z87.object({
23508
+ mode: z87.literal("saved_actor"),
23509
+ actorId: z87.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
23433
23510
  }).strict(),
23434
- z86.object({
23435
- mode: z86.literal("described"),
23436
- description: z86.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
23511
+ z87.object({
23512
+ mode: z87.literal("described"),
23513
+ description: z87.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
23437
23514
  }).strict()
23438
23515
  ]);
23439
- var VideoCreativeSetup = z86.discriminatedUnion("mode", [
23440
- z86.object({
23441
- mode: z86.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
23516
+ var VideoCreativeSetup = z87.discriminatedUnion("mode", [
23517
+ z87.object({
23518
+ mode: z87.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
23442
23519
  }).strict(),
23443
- z86.object({
23444
- mode: z86.literal("guided"),
23520
+ z87.object({
23521
+ mode: z87.literal("guided"),
23445
23522
  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.'),
23446
- buyerPersona: z86.string().trim().min(1).max(360),
23523
+ buyerPersona: z87.string().trim().min(1).max(360),
23447
23524
  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.'),
23448
23525
  presenter: VideoPresenter,
23449
- 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.")
23526
+ creativeDirection: z87.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
23450
23527
  }).strict()
23451
23528
  ]);
23452
- var VideoInput = z86.object({
23529
+ var VideoInput = z87.object({
23453
23530
  images: CreativeRefs.images.optional(),
23454
23531
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
23455
- title: z86.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
23456
- 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".'),
23532
+ title: z87.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
23533
+ primaryAngle: z87.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".'),
23457
23534
  language: CreativeRefs.language,
23458
23535
  country: CreativeRefs.country,
23459
- aspectRatio: z86.enum([
23536
+ aspectRatio: z87.enum([
23460
23537
  "9:16",
23461
23538
  "16:9",
23462
23539
  "Auto"
23463
23540
  ]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
23464
- 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."),
23465
- 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."),
23541
+ durationSeconds: z87.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."),
23542
+ videoAngleCount: z87.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."),
23466
23543
  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.'),
23467
23544
  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."),
23468
23545
  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.'),
23469
23546
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
23470
23547
  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.'),
23471
- 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"].'),
23548
+ features: z87.array(z87.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
23472
23549
  price: CreativeRefs.price,
23473
23550
  offer: CreativeRefs.offer,
23474
23551
  productContext: CreativeRefs.productContext,
23475
23552
  productLabel: CreativeRefs.productLabel,
23476
- 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.'),
23477
- 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.'),
23553
+ cta: z87.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.'),
23554
+ scriptNotes: z87.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.'),
23478
23555
  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.'),
23479
23556
  competitorScanEnabled: CreativeRefs.competitorScanEnabled,
23480
- 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."),
23557
+ replicateWinnerWhenFound: z87.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."),
23481
23558
  brandId: CreativeRefs.brandId
23482
23559
  }).strict();
23483
23560
  var FreeVideoQualityEnum = VideoQualityEnum;
@@ -23495,7 +23572,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
23495
23572
  length: 29
23496
23573
  }, (_, index) => index + 2)
23497
23574
  };
23498
- var FreeVideoModelIdEnum = z86.enum([
23575
+ var FreeVideoModelIdEnum = z87.enum([
23499
23576
  "grok-imagine-video-1-5-preview",
23500
23577
  "minimax-h3/reference-to-video",
23501
23578
  "wan/3-0-video",
@@ -23506,65 +23583,65 @@ var FREE_SELECTABLE_MODEL_IDS = [
23506
23583
  "minimax-h3/reference-to-video",
23507
23584
  "wan/3-0-video"
23508
23585
  ];
23509
- var FreeVideoInput = z86.object({
23586
+ var FreeVideoInput = z87.object({
23510
23587
  images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
23511
- 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."),
23588
+ rawPrompt: z87.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."),
23512
23589
  language: CreativeRefs.language,
23513
23590
  quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
23514
23591
  // Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
23515
23592
  // parsed ONLY so the handler can reject it with a message naming its
23516
23593
  // replacement — dropping it silently would turn a caller's explicit
23517
23594
  // Pro++ pick into a quiet fallback to Wan.
23518
- freeProModel: z86.enum([
23595
+ freeProModel: z87.enum([
23519
23596
  "wan",
23520
23597
  "seedance"
23521
23598
  ]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
23522
23599
  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.'),
23523
- 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."),
23600
+ durationSeconds: z87.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."),
23524
23601
  videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
23525
- generateAiMusic: z86.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
23526
- addSubtitles: z86.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
23527
- 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.")
23602
+ generateAiMusic: z87.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
23603
+ addSubtitles: z87.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
23604
+ idempotencyKey: z87.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.")
23528
23605
  }).strict();
23529
23606
  var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
23530
- var ImageCreativeSetup = z86.discriminatedUnion("mode", [
23531
- z86.object({
23532
- mode: z86.literal("automatic")
23607
+ var ImageCreativeSetup = z87.discriminatedUnion("mode", [
23608
+ z87.object({
23609
+ mode: z87.literal("automatic")
23533
23610
  }).strict(),
23534
- z86.object({
23535
- mode: z86.literal("guided"),
23536
- creativeArchetype: z86.union([
23611
+ z87.object({
23612
+ mode: z87.literal("guided"),
23613
+ creativeArchetype: z87.union([
23537
23614
  ImageCreativeArchetypeEnum,
23538
- z86.literal("ai_decides")
23615
+ z87.literal("ai_decides")
23539
23616
  ]),
23540
- visualTreatment: z86.union([
23617
+ visualTreatment: z87.union([
23541
23618
  ImageCreativeVisualTreatmentEnum,
23542
- z86.literal("ai_decides")
23619
+ z87.literal("ai_decides")
23543
23620
  ]),
23544
23621
  aspectRatio: ImageCreativeAspectRatioEnum,
23545
- nVariants: z86.union([
23546
- z86.literal(1),
23547
- z86.literal(2),
23548
- z86.literal(3),
23549
- z86.literal(4),
23550
- z86.literal(6)
23622
+ nVariants: z87.union([
23623
+ z87.literal(1),
23624
+ z87.literal(2),
23625
+ z87.literal(3),
23626
+ z87.literal(4),
23627
+ z87.literal(6)
23551
23628
  ]),
23552
- 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.'),
23553
- 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."),
23554
- generateAdCopy: z86.boolean(),
23555
- competitorScanEnabled: z86.boolean(),
23556
- productContext: z86.string().trim().min(1).max(3e3).nullable(),
23557
- creativeDirection: z86.string().trim().min(1).max(500).nullable(),
23558
- 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.'),
23559
- headline: z86.string().trim().min(1).max(120).nullable(),
23560
- subheadline: z86.string().trim().min(1).max(160).nullable()
23629
+ imageModel: z87.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.'),
23630
+ styleMix: z87.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
23631
+ generateAdCopy: z87.boolean(),
23632
+ competitorScanEnabled: z87.boolean(),
23633
+ productContext: z87.string().trim().min(1).max(3e3).nullable(),
23634
+ creativeDirection: z87.string().trim().min(1).max(500).nullable(),
23635
+ brandColors: z87.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.'),
23636
+ headline: z87.string().trim().min(1).max(120).nullable(),
23637
+ subheadline: z87.string().trim().min(1).max(160).nullable()
23561
23638
  }).strict()
23562
23639
  ]).superRefine((setup, context) => {
23563
23640
  if (setup.mode !== "guided") return;
23564
23641
  const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
23565
23642
  if (needsStyleMix && setup.styleMix === null) {
23566
23643
  context.addIssue({
23567
- code: z86.ZodIssueCode.custom,
23644
+ code: z87.ZodIssueCode.custom,
23568
23645
  path: [
23569
23646
  "styleMix"
23570
23647
  ],
@@ -23573,7 +23650,7 @@ var ImageCreativeSetup = z86.discriminatedUnion("mode", [
23573
23650
  }
23574
23651
  if (!needsStyleMix && setup.styleMix !== null) {
23575
23652
  context.addIssue({
23576
- code: z86.ZodIssueCode.custom,
23653
+ code: z87.ZodIssueCode.custom,
23577
23654
  path: [
23578
23655
  "styleMix"
23579
23656
  ],
@@ -23582,7 +23659,7 @@ var ImageCreativeSetup = z86.discriminatedUnion("mode", [
23582
23659
  }
23583
23660
  if (imageResolutionOf(setup.imageModel) === "2k" && setup.aspectRatio === "4:5") {
23584
23661
  context.addIssue({
23585
- code: z86.ZodIssueCode.custom,
23662
+ code: z87.ZodIssueCode.custom,
23586
23663
  path: [
23587
23664
  "aspectRatio"
23588
23665
  ],
@@ -23590,54 +23667,54 @@ var ImageCreativeSetup = z86.discriminatedUnion("mode", [
23590
23667
  });
23591
23668
  }
23592
23669
  });
23593
- var LandingCreativeSetup = z86.discriminatedUnion("mode", [
23594
- z86.object({
23595
- mode: z86.literal("automatic")
23670
+ var LandingCreativeSetup = z87.discriminatedUnion("mode", [
23671
+ z87.object({
23672
+ mode: z87.literal("automatic")
23596
23673
  }).strict(),
23597
- z86.object({
23598
- mode: z86.literal("guided"),
23674
+ z87.object({
23675
+ mode: z87.literal("guided"),
23599
23676
  landingStrategy: LandingStrategyEnum,
23600
23677
  landingImageFormat: LandingImageFormatEnum,
23601
- competitorScanEnabled: z86.boolean(),
23602
- paymentMethods: z86.string().trim().min(1).max(240).nullable(),
23603
- productContext: z86.string().trim().min(1).max(3e3).nullable(),
23604
- creativeDirection: z86.string().trim().min(1).max(500).nullable(),
23605
- headline: z86.string().trim().min(1).max(120).nullable(),
23606
- subheadline: z86.string().trim().min(1).max(160).nullable()
23678
+ competitorScanEnabled: z87.boolean(),
23679
+ paymentMethods: z87.string().trim().min(1).max(240).nullable(),
23680
+ productContext: z87.string().trim().min(1).max(3e3).nullable(),
23681
+ creativeDirection: z87.string().trim().min(1).max(500).nullable(),
23682
+ headline: z87.string().trim().min(1).max(120).nullable(),
23683
+ subheadline: z87.string().trim().min(1).max(160).nullable()
23607
23684
  }).strict()
23608
23685
  ]);
23609
- var ImageInput = z86.object({
23686
+ var ImageInput = z87.object({
23610
23687
  images: CreativeRefs.images.optional(),
23611
23688
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
23612
- productTitle: z86.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
23613
- 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.'),
23689
+ productTitle: z87.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
23690
+ primaryAngle: z87.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.'),
23614
23691
  buyerPersona: CreativeRefs.buyerPersona,
23615
23692
  language: CreativeRefs.language,
23616
23693
  country: CreativeRefs.country,
23617
23694
  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."),
23618
23695
  imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
23619
- features: z86.array(z86.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
23696
+ features: z87.array(z87.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
23620
23697
  price: CreativeRefs.price,
23621
- 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."),
23698
+ omitPrice: z87.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."),
23622
23699
  compareAtPrice: CreativeRefs.compareAtPrice,
23623
23700
  offer: CreativeRefs.offer,
23624
23701
  productLabel: CreativeRefs.productLabel,
23625
23702
  isCombo: CreativeRefs.isCombo,
23626
23703
  brandId: CreativeRefs.brandId
23627
23704
  });
23628
- var EditImageCreativeInput = z86.object({
23629
- taskId: z86.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
23630
- variantIndex: z86.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
23631
- 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."),
23632
- 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".')
23705
+ var EditImageCreativeInput = z87.object({
23706
+ taskId: z87.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
23707
+ variantIndex: z87.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
23708
+ clientRequestId: z87.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."),
23709
+ instruction: z87.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".')
23633
23710
  });
23634
- var LandingInput = z86.object({
23711
+ var LandingInput = z87.object({
23635
23712
  images: CreativeRefs.images.optional(),
23636
23713
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
23637
23714
  language: CreativeRefs.language,
23638
23715
  country: CreativeRefs.country,
23639
23716
  creativeSetup: LandingCreativeSetup.describe("Configuraci\xF3n obligatoria de landing cl\xE1sica equivalente al wizard web. No expone landing editable/code mientras siga siendo admin-only."),
23640
- 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.'),
23717
+ salesAngle: z87.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.'),
23641
23718
  buyerPersona: CreativeRefs.buyerPersona,
23642
23719
  price: CreativeRefs.price,
23643
23720
  compareAtPrice: CreativeRefs.compareAtPrice,
@@ -23916,8 +23993,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
23916
23993
  server.registerTool("get_image_edit_status", {
23917
23994
  description: imageEditStatusGuidance.summary,
23918
23995
  inputSchema: {
23919
- taskId: z86.string().uuid(),
23920
- operationId: z86.string().uuid()
23996
+ taskId: z87.string().uuid(),
23997
+ operationId: z87.string().uuid()
23921
23998
  },
23922
23999
  annotations: READS_INTERNAL
23923
24000
  }, async (input) => {
@@ -23974,10 +24051,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
23974
24051
  __name(registerCreativeTools, "registerCreativeTools");
23975
24052
 
23976
24053
  // src/tools/creative-variants.ts
23977
- import { z as z87 } from "zod";
24054
+ import { z as z88 } from "zod";
23978
24055
  var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
23979
24056
  var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
23980
- var LandingSectionKeyEnum = z87.enum([
24057
+ var LandingSectionKeyEnum = z88.enum([
23981
24058
  "problem_hook",
23982
24059
  "problem_cost",
23983
24060
  "solution_mechanism",
@@ -24017,24 +24094,24 @@ var LandingSectionKeyEnum = z87.enum([
24017
24094
  "lifestyle_fit",
24018
24095
  "join_lifestyle"
24019
24096
  ]);
24020
- var CreativeVariantKindEnum = z87.enum([
24097
+ var CreativeVariantKindEnum = z88.enum([
24021
24098
  "video",
24022
24099
  "image",
24023
24100
  "landing"
24024
24101
  ]);
24025
- var EstimateCreativeVariantInputBase = z87.object({
24026
- sourceTaskId: z87.string().uuid().describe("ID de la tarea original completada."),
24102
+ var EstimateCreativeVariantInputBase = z88.object({
24103
+ sourceTaskId: z88.string().uuid().describe("ID de la tarea original completada."),
24027
24104
  kind: CreativeVariantKindEnum,
24028
24105
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
24029
24106
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
24030
- nVariants: z87.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
24107
+ nVariants: z88.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
24031
24108
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
24032
- 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.")
24109
+ instructions: z88.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.")
24033
24110
  }).strict();
24034
24111
  var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
24035
24112
  if (input.kind === "video" && input.nVariants !== void 0) {
24036
24113
  ctx.addIssue({
24037
- code: z87.ZodIssueCode.custom,
24114
+ code: z88.ZodIssueCode.custom,
24038
24115
  path: [
24039
24116
  "nVariants"
24040
24117
  ],
@@ -24044,7 +24121,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
24044
24121
  if (input.kind !== "video") {
24045
24122
  if (input.videoPreset !== void 0) {
24046
24123
  ctx.addIssue({
24047
- code: z87.ZodIssueCode.custom,
24124
+ code: z88.ZodIssueCode.custom,
24048
24125
  path: [
24049
24126
  "videoPreset"
24050
24127
  ],
@@ -24053,7 +24130,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
24053
24130
  }
24054
24131
  if (input.videoResolution !== void 0) {
24055
24132
  ctx.addIssue({
24056
- code: z87.ZodIssueCode.custom,
24133
+ code: z88.ZodIssueCode.custom,
24057
24134
  path: [
24058
24135
  "videoResolution"
24059
24136
  ],
@@ -24063,7 +24140,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
24063
24140
  }
24064
24141
  if (input.kind !== "image" && input.nVariants !== void 0) {
24065
24142
  ctx.addIssue({
24066
- code: z87.ZodIssueCode.custom,
24143
+ code: z88.ZodIssueCode.custom,
24067
24144
  path: [
24068
24145
  "nVariants"
24069
24146
  ],
@@ -24073,7 +24150,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
24073
24150
  if (input.kind !== "landing") {
24074
24151
  if (input.sectionKey !== void 0) {
24075
24152
  ctx.addIssue({
24076
- code: z87.ZodIssueCode.custom,
24153
+ code: z88.ZodIssueCode.custom,
24077
24154
  path: [
24078
24155
  "sectionKey"
24079
24156
  ],
@@ -24082,7 +24159,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
24082
24159
  }
24083
24160
  if (input.instructions !== void 0) {
24084
24161
  ctx.addIssue({
24085
- code: z87.ZodIssueCode.custom,
24162
+ code: z88.ZodIssueCode.custom,
24086
24163
  path: [
24087
24164
  "instructions"
24088
24165
  ],
@@ -24091,31 +24168,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
24091
24168
  }
24092
24169
  }
24093
24170
  });
24094
- var CreateCreativeVariantInputBase = z87.object({
24095
- sourceTaskId: z87.string().uuid().describe("ID de la tarea original completada."),
24171
+ var CreateCreativeVariantInputBase = z88.object({
24172
+ sourceTaskId: z88.string().uuid().describe("ID de la tarea original completada."),
24096
24173
  kind: CreativeVariantKindEnum,
24097
- confirm: z87.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
24098
- 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."),
24099
- angle: z87.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
24100
- buyerPersona: z87.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
24101
- scriptNotes: z87.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
24102
- creativeDirection: z87.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
24174
+ confirm: z88.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
24175
+ clientRequestId: z88.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."),
24176
+ angle: z88.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
24177
+ buyerPersona: z88.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
24178
+ scriptNotes: z88.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
24179
+ creativeDirection: z88.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
24103
24180
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
24104
24181
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
24105
- generateAiMusic: z87.boolean().optional().describe("Opcional para video."),
24106
- nVariants: z87.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
24182
+ generateAiMusic: z88.boolean().optional().describe("Opcional para video."),
24183
+ nVariants: z88.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
24107
24184
  imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
24108
24185
  creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
24109
24186
  visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
24110
24187
  aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
24111
- styleMix: z87.boolean().optional().describe("Opcional para imagen."),
24188
+ styleMix: z88.boolean().optional().describe("Opcional para imagen."),
24112
24189
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
24113
- 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.")
24190
+ instructions: z88.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.")
24114
24191
  }).strict();
24115
24192
  var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
24116
24193
  if ((input.kind === "video" || input.kind === "image") && !input.angle) {
24117
24194
  ctx.addIssue({
24118
- code: z87.ZodIssueCode.custom,
24195
+ code: z88.ZodIssueCode.custom,
24119
24196
  path: [
24120
24197
  "angle"
24121
24198
  ],
@@ -24124,7 +24201,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
24124
24201
  }
24125
24202
  if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
24126
24203
  ctx.addIssue({
24127
- code: z87.ZodIssueCode.custom,
24204
+ code: z88.ZodIssueCode.custom,
24128
24205
  path: [
24129
24206
  "instructions"
24130
24207
  ],
@@ -24170,7 +24247,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
24170
24247
  for (const field of fieldsByKind[input.kind]) {
24171
24248
  if (input[field] !== void 0) {
24172
24249
  ctx.addIssue({
24173
- code: z87.ZodIssueCode.custom,
24250
+ code: z88.ZodIssueCode.custom,
24174
24251
  path: [
24175
24252
  field
24176
24253
  ],
@@ -24303,13 +24380,13 @@ function registerCreativeVariantTools(server, api) {
24303
24380
  __name(registerCreativeVariantTools, "registerCreativeVariantTools");
24304
24381
 
24305
24382
  // src/tools/script-review.ts
24306
- import { z as z88 } from "zod";
24383
+ import { z as z89 } from "zod";
24307
24384
  var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
24308
24385
  var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
24309
24386
  var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
24310
- var GetVideoScriptInput = z88.object({
24311
- taskId: z88.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
24312
- 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.')
24387
+ var GetVideoScriptInput = z89.object({
24388
+ taskId: z89.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
24389
+ angleKey: z89.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.')
24313
24390
  }).strict();
24314
24391
  var ApproveVideoScriptInput = ApproveVideoScriptCapabilityRequest;
24315
24392
  var RegenerateVideoScriptInput = RegenerateVideoScriptCapabilityRequest.extend({
@@ -24392,7 +24469,7 @@ function registerScriptReviewTools(server, api) {
24392
24469
  __name(registerScriptReviewTools, "registerScriptReviewTools");
24393
24470
 
24394
24471
  // src/tools/connections.ts
24395
- import { z as z89 } from "zod";
24472
+ import { z as z90 } from "zod";
24396
24473
  var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
24397
24474
  var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
24398
24475
  var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
@@ -24401,7 +24478,7 @@ var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list
24401
24478
  function registerConnectionTools(server, api) {
24402
24479
  server.registerTool("list_shopify_shops", {
24403
24480
  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.",
24404
- inputSchema: z89.object({}).shape,
24481
+ inputSchema: z90.object({}).shape,
24405
24482
  annotations: READS_INTERNAL
24406
24483
  }, async () => {
24407
24484
  try {
@@ -24413,10 +24490,10 @@ function registerConnectionTools(server, api) {
24413
24490
  });
24414
24491
  server.registerTool("list_shopify_products", {
24415
24492
  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.',
24416
- inputSchema: z89.object({
24417
- shopDomain: z89.string().min(3).max(120),
24418
- query: z89.string().trim().max(120).optional(),
24419
- taskId: z89.string().uuid().optional()
24493
+ inputSchema: z90.object({
24494
+ shopDomain: z90.string().min(3).max(120),
24495
+ query: z90.string().trim().max(120).optional(),
24496
+ taskId: z90.string().uuid().optional()
24420
24497
  }).shape,
24421
24498
  annotations: READS_EXTERNAL
24422
24499
  }, async ({ shopDomain, query, taskId }) => {
@@ -24434,7 +24511,7 @@ function registerConnectionTools(server, api) {
24434
24511
  });
24435
24512
  server.registerTool("list_meta_ad_accounts", {
24436
24513
  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.",
24437
- inputSchema: z89.object({}).shape,
24514
+ inputSchema: z90.object({}).shape,
24438
24515
  annotations: READS_EXTERNAL
24439
24516
  }, async () => {
24440
24517
  try {
@@ -24446,7 +24523,7 @@ function registerConnectionTools(server, api) {
24446
24523
  });
24447
24524
  server.registerTool("list_meta_destinations", {
24448
24525
  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.",
24449
- inputSchema: z89.object({}).shape,
24526
+ inputSchema: z90.object({}).shape,
24450
24527
  annotations: READS_EXTERNAL,
24451
24528
  _meta: {
24452
24529
  "openai/widgetAccessible": true
@@ -24461,7 +24538,7 @@ function registerConnectionTools(server, api) {
24461
24538
  });
24462
24539
  server.registerTool("list_tiktok_advertisers", {
24463
24540
  description: listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.",
24464
- inputSchema: z89.object({}).shape,
24541
+ inputSchema: z90.object({}).shape,
24465
24542
  annotations: READS_EXTERNAL
24466
24543
  }, async () => {
24467
24544
  try {
@@ -24475,12 +24552,12 @@ function registerConnectionTools(server, api) {
24475
24552
  __name(registerConnectionTools, "registerConnectionTools");
24476
24553
 
24477
24554
  // src/tools/actors.ts
24478
- import { z as z90 } from "zod";
24555
+ import { z as z91 } from "zod";
24479
24556
  var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
24480
24557
  function registerActorTools(server, api) {
24481
24558
  server.registerTool("list_actors", {
24482
24559
  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.",
24483
- inputSchema: z90.object({}).shape,
24560
+ inputSchema: z91.object({}).shape,
24484
24561
  annotations: READS_INTERNAL
24485
24562
  }, async () => {
24486
24563
  try {
@@ -24503,7 +24580,7 @@ function registerActorTools(server, api) {
24503
24580
  __name(registerActorTools, "registerActorTools");
24504
24581
 
24505
24582
  // src/tools/publish.ts
24506
- import { z as z91 } from "zod";
24583
+ import { z as z92 } from "zod";
24507
24584
 
24508
24585
  // src/tools/meta-publish-attempt-id.ts
24509
24586
  var META_PUBLISH_NAMESPACE = "7b19c9ac-b4eb-4db1-970e-c2f24ce30b98";
@@ -24542,40 +24619,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
24542
24619
  var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
24543
24620
  var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
24544
24621
  var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
24545
- var ShopifyInput = z91.object({
24546
- taskId: z91.string().min(1),
24547
- shopDomain: z91.string().min(1),
24622
+ var ShopifyInput = z92.object({
24623
+ taskId: z92.string().min(1),
24624
+ shopDomain: z92.string().min(1),
24548
24625
  /** Override: number of landing images to include. Default = ALL images the
24549
24626
  * task generated (the MCP fetches /v1/results first to count). Bounded
24550
24627
  * generously here; the backend validates each index against
24551
24628
  * landing.images.length and rejects out-of-range. */
24552
- numLandingImages: z91.number().int().min(1).max(20).optional(),
24553
- variantIndex: z91.number().int().min(0).optional(),
24629
+ numLandingImages: z92.number().int().min(1).max(20).optional(),
24630
+ variantIndex: z92.number().int().min(0).optional(),
24554
24631
  /** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
24555
24632
  * When true, the landing renders variant-picker pills; when false, it ships
24556
24633
  * a single-option product page. Defaults to false. */
24557
- showVariantPicker: z91.boolean().optional(),
24634
+ showVariantPicker: z92.boolean().optional(),
24558
24635
  /** Default `auto` updates the product previously published for this task and
24559
24636
  * shop. Use `existing` with targetProductId to choose another product, or
24560
24637
  * `new` only when the user explicitly wants a duplicate/new listing. */
24561
- publicationMode: z91.enum([
24638
+ publicationMode: z92.enum([
24562
24639
  "auto",
24563
24640
  "existing",
24564
24641
  "new"
24565
24642
  ]).optional(),
24566
24643
  /** Shopify product GID, numeric id, or admin product URL. Required when
24567
24644
  * publicationMode is `existing`. */
24568
- targetProductId: z91.string().trim().min(1).max(300).optional(),
24645
+ targetProductId: z92.string().trim().min(1).max(300).optional(),
24569
24646
  /** Add an announcement bar text above add-to-cart (optional). */
24570
- announcementBarEnabled: z91.boolean().optional(),
24571
- announcementBarText: z91.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
24647
+ announcementBarEnabled: z92.boolean().optional(),
24648
+ announcementBarText: z92.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
24572
24649
  commerceCorrection: PublishCommerceCorrectionSchema.optional().describe("Complete seller-confirmed commerce values, with the revision and fingerprint returned in recovery. Never invent missing prices or convert currency."),
24573
- confirmed: z91.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
24650
+ confirmed: z92.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
24574
24651
  });
24575
24652
  var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
24576
24653
  if (value.commerceCorrection && value.confirmed !== true) {
24577
24654
  ctx.addIssue({
24578
- code: z91.ZodIssueCode.custom,
24655
+ code: z92.ZodIssueCode.custom,
24579
24656
  path: [
24580
24657
  "confirmed"
24581
24658
  ],
@@ -24584,7 +24661,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
24584
24661
  }
24585
24662
  if (value.announcementBarEnabled && !value.announcementBarText) {
24586
24663
  ctx.addIssue({
24587
- code: z91.ZodIssueCode.custom,
24664
+ code: z92.ZodIssueCode.custom,
24588
24665
  path: [
24589
24666
  "announcementBarText"
24590
24667
  ],
@@ -24593,7 +24670,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
24593
24670
  }
24594
24671
  if (!value.announcementBarEnabled && value.announcementBarText) {
24595
24672
  ctx.addIssue({
24596
- code: z91.ZodIssueCode.custom,
24673
+ code: z92.ZodIssueCode.custom,
24597
24674
  path: [
24598
24675
  "announcementBarText"
24599
24676
  ],
@@ -24607,91 +24684,91 @@ function parseShopifyInput(rawInput) {
24607
24684
  return parsed.data;
24608
24685
  }
24609
24686
  __name(parseShopifyInput, "parseShopifyInput");
24610
- var McpCampaignConfig = z91.object({
24687
+ var McpCampaignConfig = z92.object({
24611
24688
  /** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
24612
24689
  * converts to the account currency server-side. Do NOT pre-convert: on a COP
24613
24690
  * account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
24614
- dailyBudgetUsd: z91.number().positive().optional(),
24691
+ dailyBudgetUsd: z92.number().positive().optional(),
24615
24692
  /** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
24616
24693
  * normalizes at validation). Meta accepts max 1 (single-country ad set).
24617
24694
  * TikTok takes only the first entry. */
24618
- targetCountries: z91.array(CountryIso2Schema).max(1).optional(),
24619
- campaignName: z91.string().trim().min(1).max(100).optional()
24695
+ targetCountries: z92.array(CountryIso2Schema).max(1).optional(),
24696
+ campaignName: z92.string().trim().min(1).max(100).optional()
24620
24697
  });
24621
24698
  var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
24622
- var MetaInput = z91.object({
24623
- taskId: z91.string().min(1),
24699
+ var MetaInput = z92.object({
24700
+ taskId: z92.string().min(1),
24624
24701
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
24625
- portfolioId: z91.string().trim().min(1),
24702
+ portfolioId: z92.string().trim().min(1),
24626
24703
  /** Exact Facebook Page selected from `list_meta_destinations`. */
24627
- pageId: z91.string().trim().min(1),
24704
+ pageId: z92.string().trim().min(1),
24628
24705
  adAccountId: McpAdAccountId,
24629
- pixelId: z91.string().min(1).optional(),
24630
- landingUrl: z91.string().url().optional(),
24706
+ pixelId: z92.string().min(1).optional(),
24707
+ landingUrl: z92.string().url().optional(),
24631
24708
  /** Select which angles to publish by 0-based index. Omit to publish all
24632
24709
  * successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
24633
- angleIndexes: z91.array(z91.number().int().nonnegative()).optional(),
24710
+ angleIndexes: z92.array(z92.number().int().nonnegative()).optional(),
24634
24711
  campaignConfig: McpCampaignConfig.optional(),
24635
24712
  /** Override the ad's primary text (body copy). If omitted, ProductMaker
24636
24713
  * uses the auto-generated copy attached to the task. Capped at 500 chars
24637
24714
  * (Meta's primary-text limit). */
24638
- primaryText: z91.string().trim().min(1).max(500).optional(),
24715
+ primaryText: z92.string().trim().min(1).max(500).optional(),
24639
24716
  /** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
24640
24717
  * (wa.me) instead of a landing page. */
24641
- phoneNumber: z91.string().min(8).max(32).optional()
24718
+ phoneNumber: z92.string().min(8).max(32).optional()
24642
24719
  });
24643
- var GroupedTaskSource = z91.object({
24644
- type: z91.literal("task"),
24645
- taskId: z91.string().min(1),
24646
- angleIndex: z91.number().int().min(0).optional(),
24647
- videoVariant: z91.enum([
24720
+ var GroupedTaskSource = z92.object({
24721
+ type: z92.literal("task"),
24722
+ taskId: z92.string().min(1),
24723
+ angleIndex: z92.number().int().min(0).optional(),
24724
+ videoVariant: z92.enum([
24648
24725
  "with_subtitles",
24649
24726
  "without_subtitles"
24650
24727
  ]).optional(),
24651
- imageVariantIndex: z91.number().int().min(0).optional()
24652
- });
24653
- var GroupedMediaSource = z91.object({
24654
- type: z91.literal("media"),
24655
- 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."),
24656
- 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".'),
24657
- thumbnailUrl: z91.string().url().optional(),
24658
- thumbnailPath: z91.string().min(1).optional()
24728
+ imageVariantIndex: z92.number().int().min(0).optional()
24729
+ });
24730
+ var GroupedMediaSource = z92.object({
24731
+ type: z92.literal("media"),
24732
+ url: z92.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
24733
+ path: z92.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".'),
24734
+ thumbnailUrl: z92.string().url().optional(),
24735
+ thumbnailPath: z92.string().min(1).optional()
24659
24736
  }).refine((value) => Boolean(value.url) !== Boolean(value.path), {
24660
24737
  message: "media source needs exactly one of `url` or `path`"
24661
24738
  }).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
24662
24739
  message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
24663
24740
  });
24664
- var GroupedUploadedAssetSource = z91.object({
24665
- type: z91.literal("asset"),
24741
+ var GroupedUploadedAssetSource = z92.object({
24742
+ type: z92.literal("asset"),
24666
24743
  /** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
24667
- assetId: z91.string().uuid(),
24668
- thumbnailAssetId: z91.string().uuid().optional()
24744
+ assetId: z92.string().uuid(),
24745
+ thumbnailAssetId: z92.string().uuid().optional()
24669
24746
  });
24670
- var GroupedCreative = z91.object({
24671
- type: z91.enum([
24747
+ var GroupedCreative = z92.object({
24748
+ type: z92.enum([
24672
24749
  "image",
24673
24750
  "video"
24674
24751
  ]),
24675
- source: z91.union([
24752
+ source: z92.union([
24676
24753
  GroupedTaskSource,
24677
24754
  GroupedMediaSource,
24678
24755
  GroupedUploadedAssetSource
24679
24756
  ]),
24680
- title: z91.string().max(120).optional(),
24681
- description: z91.string().max(500).optional(),
24757
+ title: z92.string().max(120).optional(),
24758
+ description: z92.string().max(500).optional(),
24682
24759
  cta: MetaCtaType.optional(),
24683
- creativeId: z91.string().min(1).optional()
24760
+ creativeId: z92.string().min(1).optional()
24684
24761
  });
24685
- var GroupedCampaignConfigBase = z91.object({
24762
+ var GroupedCampaignConfigBase = z92.object({
24686
24763
  campaignType: MetaCampaignType.default("sales"),
24687
24764
  optimizationMode: MetaOptimizationMode.default("advantage_plus"),
24688
24765
  budgetMode: MetaBudgetMode.optional(),
24689
- campaignDailyBudget: z91.number().int().positive().optional(),
24690
- adSets: z91.array(z91.object({
24691
- tempId: z91.string().min(1).max(80),
24692
- name: z91.string().min(1).max(100),
24693
- dailyBudget: z91.number().int().positive().optional(),
24694
- creativeIds: z91.array(z91.string().min(1)).min(1)
24766
+ campaignDailyBudget: z92.number().int().positive().optional(),
24767
+ adSets: z92.array(z92.object({
24768
+ tempId: z92.string().min(1).max(80),
24769
+ name: z92.string().min(1).max(100),
24770
+ dailyBudget: z92.number().int().positive().optional(),
24771
+ creativeIds: z92.array(z92.string().min(1)).min(1)
24695
24772
  })).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
24696
24773
  /**
24697
24774
  * Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
@@ -24699,17 +24776,17 @@ var GroupedCampaignConfigBase = z91.object({
24699
24776
  * opaque `invalid_literal` and made the WhatsApp destination — supported by
24700
24777
  * the API since #849 — unreachable from this tool.
24701
24778
  */
24702
- destination: z91.discriminatedUnion("type", [
24703
- z91.object({
24704
- type: z91.literal("landing"),
24705
- landingUrl: z91.string().url()
24779
+ destination: z92.discriminatedUnion("type", [
24780
+ z92.object({
24781
+ type: z92.literal("landing"),
24782
+ landingUrl: z92.string().url()
24706
24783
  }),
24707
- z91.object({
24708
- type: z91.literal("whatsapp"),
24709
- phoneNumber: z91.string().min(8).max(32)
24784
+ z92.object({
24785
+ type: z92.literal("whatsapp"),
24786
+ phoneNumber: z92.string().min(8).max(32)
24710
24787
  })
24711
24788
  ]),
24712
- saveAsDefault: z91.boolean().default(false),
24789
+ saveAsDefault: z92.boolean().default(false),
24713
24790
  budgetPolicy: MetaBudgetPolicy.optional()
24714
24791
  });
24715
24792
  function resolveBudgetMode(value) {
@@ -24723,7 +24800,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
24723
24800
  const budgetMode = resolveBudgetMode(value);
24724
24801
  if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
24725
24802
  ctx.addIssue({
24726
- code: z91.ZodIssueCode.custom,
24803
+ code: z92.ZodIssueCode.custom,
24727
24804
  path: [
24728
24805
  "campaignDailyBudget"
24729
24806
  ],
@@ -24734,7 +24811,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
24734
24811
  value.adSets.forEach((adSet, index) => {
24735
24812
  if (adSet.dailyBudget === void 0) {
24736
24813
  ctx.addIssue({
24737
- code: z91.ZodIssueCode.custom,
24814
+ code: z92.ZodIssueCode.custom,
24738
24815
  path: [
24739
24816
  "adSets",
24740
24817
  index,
@@ -24749,28 +24826,28 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
24749
24826
  ...value,
24750
24827
  budgetMode: resolveBudgetMode(value)
24751
24828
  }));
24752
- var PublishCreativesToMetaInputBase = z91.object({
24753
- creatives: z91.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
24829
+ var PublishCreativesToMetaInputBase = z92.object({
24830
+ creatives: z92.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
24754
24831
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
24755
- portfolioId: z91.string().trim().min(1),
24832
+ portfolioId: z92.string().trim().min(1),
24756
24833
  /** Exact Facebook Page selected from `list_meta_destinations`. */
24757
- pageId: z91.string().trim().min(1),
24834
+ pageId: z92.string().trim().min(1),
24758
24835
  adAccountId: McpAdAccountId,
24759
- pixelId: z91.string().min(1).optional(),
24836
+ pixelId: z92.string().min(1).optional(),
24760
24837
  /** Required unless `campaignConfig.destination` is whatsapp — see the
24761
24838
  * superRefine below. Mirrors the API's `FacebookCreateCampaignFromTasksBodySchema`. */
24762
- landingUrl: z91.string().url().optional(),
24839
+ landingUrl: z92.string().url().optional(),
24763
24840
  /** ISO-2 code or resolvable country name — mirrors the API contract
24764
24841
  * (CountryIso2Schema), which normalizes names to alpha-2 at validation. */
24765
24842
  targetCountry: CountryIso2Schema,
24766
- campaignName: z91.string().trim().min(1).max(100),
24843
+ campaignName: z92.string().trim().min(1).max(100),
24767
24844
  campaignConfig: GroupedCampaignConfig.optional()
24768
24845
  });
24769
24846
  var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
24770
24847
  const destination = value.campaignConfig?.destination;
24771
24848
  if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
24772
24849
  ctx.addIssue({
24773
- code: z91.ZodIssueCode.custom,
24850
+ code: z92.ZodIssueCode.custom,
24774
24851
  path: [
24775
24852
  "landingUrl"
24776
24853
  ],
@@ -24779,7 +24856,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
24779
24856
  }
24780
24857
  if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
24781
24858
  ctx.addIssue({
24782
- code: z91.ZodIssueCode.custom,
24859
+ code: z92.ZodIssueCode.custom,
24783
24860
  path: [
24784
24861
  "campaignConfig",
24785
24862
  "destination",
@@ -24798,16 +24875,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
24798
24875
  }
24799
24876
  return value;
24800
24877
  });
24801
- var PresignUploadResponseSchema = z91.object({
24802
- uploadUrl: z91.string().url().refine((value) => {
24878
+ var PresignUploadResponseSchema = z92.object({
24879
+ uploadUrl: z92.string().url().refine((value) => {
24803
24880
  const url = new URL(value);
24804
24881
  return !url.username && !url.password && url.protocol === "https:";
24805
24882
  }, "presigned upload URL must be HTTPS without embedded credentials"),
24806
- publicUrl: z91.string().url().refine((value) => {
24883
+ publicUrl: z92.string().url().refine((value) => {
24807
24884
  const url = new URL(value);
24808
24885
  return !url.username && !url.password;
24809
24886
  }, "public media URL must not contain embedded credentials"),
24810
- stagingAssetId: z91.string().uuid()
24887
+ stagingAssetId: z92.string().uuid()
24811
24888
  });
24812
24889
  async function uploadResolvedMedia(api, media, assetRole) {
24813
24890
  if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
@@ -24832,16 +24909,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
24832
24909
  return uploadResolvedMedia(api, media, assetRole);
24833
24910
  }
24834
24911
  __name(resolveAndUploadMedia, "resolveAndUploadMedia");
24835
- var TikTokInput = z91.object({
24836
- taskId: z91.string().min(1),
24837
- advertiserId: z91.string().min(1),
24838
- pixelId: z91.string().min(1).optional(),
24839
- landingUrl: z91.string().url().optional(),
24840
- angleIndexes: z91.array(z91.number().int().nonnegative()).optional(),
24912
+ var TikTokInput = z92.object({
24913
+ taskId: z92.string().min(1),
24914
+ advertiserId: z92.string().min(1),
24915
+ pixelId: z92.string().min(1).optional(),
24916
+ landingUrl: z92.string().url().optional(),
24917
+ angleIndexes: z92.array(z92.number().int().nonnegative()).optional(),
24841
24918
  campaignConfig: McpCampaignConfig.optional(),
24842
24919
  /** Override the ad's description (TikTok's body copy). If omitted,
24843
24920
  * ProductMaker uses the auto-generated copy attached to the task. */
24844
- primaryText: z91.string().trim().min(1).max(500).optional()
24921
+ primaryText: z92.string().trim().min(1).max(500).optional()
24845
24922
  });
24846
24923
  function registerPublishTools(server, api, opts = {}) {
24847
24924
  const transport = opts.transport ?? "http";
@@ -25193,39 +25270,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
25193
25270
 
25194
25271
  // src/tools/meta-upload.ts
25195
25272
  import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
25196
- import { z as z92 } from "zod";
25273
+ import { z as z93 } from "zod";
25197
25274
  var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
25198
- var UploadSessionInputBase = z92.object({
25199
- mediaKind: z92.enum([
25275
+ var UploadSessionInputBase = z93.object({
25276
+ mediaKind: z93.enum([
25200
25277
  "image",
25201
25278
  "video",
25202
25279
  "mixed"
25203
25280
  ]).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."),
25204
- assetRole: z92.enum([
25281
+ assetRole: z93.enum([
25205
25282
  "media",
25206
25283
  "thumbnail"
25207
25284
  ]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
25208
- uploadPurpose: z92.enum([
25285
+ uploadPurpose: z93.enum([
25209
25286
  "product_reference",
25210
25287
  "creative",
25211
25288
  "generic"
25212
25289
  ]).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."),
25213
- maxFiles: z92.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
25290
+ maxFiles: z93.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
25214
25291
  });
25215
- var OpenAiFileReference = z92.object({
25216
- 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."),
25217
- file_id: z92.string().min(1),
25218
- mime_type: z92.string().min(1).optional(),
25219
- file_name: z92.string().min(1).optional()
25292
+ var OpenAiFileReference = z93.object({
25293
+ download_url: z93.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."),
25294
+ file_id: z93.string().min(1),
25295
+ mime_type: z93.string().min(1).optional(),
25296
+ file_name: z93.string().min(1).optional()
25220
25297
  });
25221
25298
  var UploadSessionToolInputShape = {
25222
25299
  ...UploadSessionInputBase.shape,
25223
- 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.")
25300
+ files: z93.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.")
25224
25301
  };
25225
- var UploadSessionToolInput = z92.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
25302
+ var UploadSessionToolInput = z93.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
25226
25303
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
25227
25304
  ctx.addIssue({
25228
- code: z92.ZodIssueCode.custom,
25305
+ code: z93.ZodIssueCode.custom,
25229
25306
  path: [
25230
25307
  "mediaKind"
25231
25308
  ],
@@ -25234,7 +25311,7 @@ var UploadSessionToolInput = z92.object(UploadSessionToolInputShape).superRefine
25234
25311
  }
25235
25312
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
25236
25313
  ctx.addIssue({
25237
- code: z92.ZodIssueCode.custom,
25314
+ code: z93.ZodIssueCode.custom,
25238
25315
  path: [
25239
25316
  "maxFiles"
25240
25317
  ],
@@ -25243,7 +25320,7 @@ var UploadSessionToolInput = z92.object(UploadSessionToolInputShape).superRefine
25243
25320
  }
25244
25321
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
25245
25322
  ctx.addIssue({
25246
- code: z92.ZodIssueCode.custom,
25323
+ code: z93.ZodIssueCode.custom,
25247
25324
  path: [
25248
25325
  "maxFiles"
25249
25326
  ],
@@ -25251,38 +25328,38 @@ var UploadSessionToolInput = z92.object(UploadSessionToolInputShape).superRefine
25251
25328
  });
25252
25329
  }
25253
25330
  });
25254
- var UploadSessionResponse = z92.object({
25255
- sessionId: z92.string().uuid(),
25256
- uploadPageUrl: z92.string().url(),
25257
- mediaKind: z92.enum([
25331
+ var UploadSessionResponse = z93.object({
25332
+ sessionId: z93.string().uuid(),
25333
+ uploadPageUrl: z93.string().url(),
25334
+ mediaKind: z93.enum([
25258
25335
  "image",
25259
25336
  "video",
25260
25337
  "mixed"
25261
25338
  ]),
25262
- assetRole: z92.enum([
25339
+ assetRole: z93.enum([
25263
25340
  "media",
25264
25341
  "thumbnail"
25265
25342
  ]),
25266
- maxFiles: z92.number().int().positive(),
25267
- expiresAt: z92.string().datetime()
25343
+ maxFiles: z93.number().int().positive(),
25344
+ expiresAt: z93.string().datetime()
25268
25345
  });
25269
- var UploadStatusInput = z92.object({
25270
- sessionId: z92.string().uuid().describe("The sessionId returned by request_media_upload.")
25346
+ var UploadStatusInput = z93.object({
25347
+ sessionId: z93.string().uuid().describe("The sessionId returned by request_media_upload.")
25271
25348
  });
25272
- var UniversalUploadStatusResponse = z92.discriminatedUnion("status", [
25273
- z92.object({
25274
- status: z92.literal("pending"),
25275
- assets: z92.array(z92.never()).length(0)
25349
+ var UniversalUploadStatusResponse = z93.discriminatedUnion("status", [
25350
+ z93.object({
25351
+ status: z93.literal("pending"),
25352
+ assets: z93.array(z93.never()).length(0)
25276
25353
  }),
25277
- z92.object({
25278
- status: z92.literal("uploaded"),
25279
- assets: z92.array(z92.object({
25280
- assetId: z92.string().uuid(),
25281
- mediaKind: z92.enum([
25354
+ z93.object({
25355
+ status: z93.literal("uploaded"),
25356
+ assets: z93.array(z93.object({
25357
+ assetId: z93.string().uuid(),
25358
+ mediaKind: z93.enum([
25282
25359
  "image",
25283
25360
  "video"
25284
25361
  ]),
25285
- assetRole: z92.enum([
25362
+ assetRole: z93.enum([
25286
25363
  "media",
25287
25364
  "thumbnail"
25288
25365
  ])
@@ -25290,13 +25367,13 @@ var UniversalUploadStatusResponse = z92.discriminatedUnion("status", [
25290
25367
  })
25291
25368
  ]);
25292
25369
  var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
25293
- uploadPurpose: z92.enum([
25370
+ uploadPurpose: z93.enum([
25294
25371
  "product_reference",
25295
25372
  "creative",
25296
25373
  "generic"
25297
25374
  ]),
25298
- checkToolName: z92.literal("check_media_upload"),
25299
- resolveEndpoint: z92.string().url()
25375
+ checkToolName: z93.literal("check_media_upload"),
25376
+ resolveEndpoint: z93.string().url()
25300
25377
  });
25301
25378
  function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
25302
25379
  const url = new URL(uploadPageUrl);
@@ -25387,15 +25464,15 @@ function registerMediaUploadTools(server, api) {
25387
25464
  __name(registerMediaUploadTools, "registerMediaUploadTools");
25388
25465
 
25389
25466
  // src/tools/campaigns.ts
25390
- import { z as z93 } from "zod";
25467
+ import { z as z94 } from "zod";
25391
25468
  var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
25392
25469
  var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
25393
- var MetaStatusInput = z93.object({
25394
- campaignId: z93.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
25470
+ var MetaStatusInput = z94.object({
25471
+ campaignId: z94.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
25395
25472
  });
25396
- var TikTokStatusInput = z93.object({
25397
- campaignId: z93.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
25398
- advertiserId: z93.string().min(1).describe("The same advertiserId used to publish the campaign.")
25473
+ var TikTokStatusInput = z94.object({
25474
+ campaignId: z94.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
25475
+ advertiserId: z94.string().min(1).describe("The same advertiserId used to publish the campaign.")
25399
25476
  });
25400
25477
  function registerCampaignTools(server, api) {
25401
25478
  server.registerTool("get_meta_campaign_status", {
@@ -25500,10 +25577,10 @@ function renderTikTokStatusMarkdown(r) {
25500
25577
  __name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
25501
25578
 
25502
25579
  // ../../packages/product-economics/src/product-costing.ts
25503
- import { z as z95 } from "zod";
25580
+ import { z as z96 } from "zod";
25504
25581
 
25505
25582
  // ../../packages/product-economics/src/product-costing-countries.ts
25506
- import { z as z94 } from "zod";
25583
+ import { z as z95 } from "zod";
25507
25584
 
25508
25585
  // ../../packages/product-economics/src/product-costing-shipping-references.json
25509
25586
  var product_costing_shipping_references_default = {
@@ -25567,21 +25644,21 @@ var product_costing_shipping_references_default = {
25567
25644
  };
25568
25645
 
25569
25646
  // ../../packages/product-economics/src/product-costing-countries.ts
25570
- var ShippingReferenceSchema = z94.object({
25571
- reference: z94.number().positive(),
25572
- min: z94.number().nonnegative(),
25573
- max: z94.number().positive(),
25574
- updatedAt: z94.string().date(),
25575
- confidence: z94.enum([
25647
+ var ShippingReferenceSchema = z95.object({
25648
+ reference: z95.number().positive(),
25649
+ min: z95.number().nonnegative(),
25650
+ max: z95.number().positive(),
25651
+ updatedAt: z95.string().date(),
25652
+ confidence: z95.enum([
25576
25653
  "high",
25577
25654
  "medium",
25578
25655
  "medium-low"
25579
25656
  ]),
25580
- sources: z94.array(z94.string().url().startsWith("https://")).min(1).max(3)
25657
+ sources: z95.array(z95.string().url().startsWith("https://")).min(1).max(3)
25581
25658
  }).superRefine(({ reference, min, max }, context) => {
25582
25659
  if (min > reference || reference > max) {
25583
25660
  context.addIssue({
25584
- code: z94.ZodIssueCode.custom,
25661
+ code: z95.ZodIssueCode.custom,
25585
25662
  message: "shipping_reference_outside_range",
25586
25663
  path: [
25587
25664
  "reference"
@@ -25589,7 +25666,7 @@ var ShippingReferenceSchema = z94.object({
25589
25666
  });
25590
25667
  }
25591
25668
  });
25592
- var SHIPPING_REFERENCES = z94.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
25669
+ var SHIPPING_REFERENCES = z95.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
25593
25670
  var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
25594
25671
  var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
25595
25672
  "MX",
@@ -25771,18 +25848,18 @@ function getProductCostingCountryName(country) {
25771
25848
  __name(getProductCostingCountryName, "getProductCostingCountryName");
25772
25849
 
25773
25850
  // ../../packages/product-economics/src/product-costing.ts
25774
- var ProductCostingInputSchema = z95.object({
25775
- country: z95.string().refine(isProductCostingCountryCode, "unsupported_country"),
25776
- supplierCost: z95.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
25777
- shippingCost: z95.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
25778
- returnRate: z95.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
25779
- cancellationRate: z95.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
25780
- adsManagerCpa: z95.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
25781
- desiredMargin: z95.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
25851
+ var ProductCostingInputSchema = z96.object({
25852
+ country: z96.string().refine(isProductCostingCountryCode, "unsupported_country"),
25853
+ supplierCost: z96.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
25854
+ shippingCost: z96.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
25855
+ returnRate: z96.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
25856
+ cancellationRate: z96.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
25857
+ adsManagerCpa: z96.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
25858
+ desiredMargin: z96.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
25782
25859
  }).superRefine(({ returnRate, cancellationRate }, context) => {
25783
25860
  if (returnRate + cancellationRate >= 1) {
25784
25861
  context.addIssue({
25785
- code: z95.ZodIssueCode.custom,
25862
+ code: z96.ZodIssueCode.custom,
25786
25863
  message: "delivery_rate_positive",
25787
25864
  path: [
25788
25865
  "cancellationRate"
@@ -25879,15 +25956,15 @@ function calculateProductCosting(rawInput) {
25879
25956
  __name(calculateProductCosting, "calculateProductCosting");
25880
25957
 
25881
25958
  // src/tools/product-costing.ts
25882
- import { z as z96 } from "zod";
25959
+ import { z as z97 } from "zod";
25883
25960
  var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
25884
- var optionalAmount = /* @__PURE__ */ __name((description) => z96.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
25885
- var optionalPercent = /* @__PURE__ */ __name((description) => z96.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
25886
- var ProductCostingToolInput = z96.object({
25887
- country: z96.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
25961
+ var optionalAmount = /* @__PURE__ */ __name((description) => z97.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
25962
+ var optionalPercent = /* @__PURE__ */ __name((description) => z97.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
25963
+ var ProductCostingToolInput = z97.object({
25964
+ country: z97.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
25888
25965
  message: "Pa\xEDs no soportado por ProductMaker."
25889
25966
  }).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
25890
- 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."),
25967
+ supplierCost: z97.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."),
25891
25968
  supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
25892
25969
  shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
25893
25970
  shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
@@ -26050,7 +26127,7 @@ function formatPercent(value) {
26050
26127
  __name(formatPercent, "formatPercent");
26051
26128
 
26052
26129
  // src/tools/product-research.ts
26053
- import { z as z97 } from "zod";
26130
+ import { z as z98 } from "zod";
26054
26131
 
26055
26132
  // src/tools/product-research-idempotency.ts
26056
26133
  var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
@@ -26421,17 +26498,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
26421
26498
  ]);
26422
26499
  var POLL_INTERVAL_MS = 5e3;
26423
26500
  var MAX_WAIT_SECONDS = 120;
26424
- var FindInput = z97.object({
26501
+ var FindInput = z98.object({
26425
26502
  targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
26426
26503
  categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
26427
- 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.`),
26428
- 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.")
26504
+ confirmed: z98.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
26505
+ waitSeconds: z98.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
26429
26506
  });
26430
- var GetInput = z97.object({
26431
- runId: z97.string().uuid().describe("ID del run devuelto por find_winning_products.")
26507
+ var GetInput = z98.object({
26508
+ runId: z98.string().uuid().describe("ID del run devuelto por find_winning_products.")
26432
26509
  });
26433
- var ListInput = z97.object({
26434
- limit: z97.number().int().min(1).max(20).default(10)
26510
+ var ListInput = z98.object({
26511
+ limit: z98.number().int().min(1).max(20).default(10)
26435
26512
  });
26436
26513
  function textResult(text2) {
26437
26514
  return {
@@ -26570,17 +26647,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
26570
26647
  __name(registerProductResearchTools, "registerProductResearchTools");
26571
26648
 
26572
26649
  // src/tools/dropshipping-projects.ts
26573
- import { z as z98 } from "zod";
26650
+ import { z as z99 } from "zod";
26574
26651
  var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
26575
26652
  var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
26576
26653
  var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
26577
- var ProjectId = z98.string().uuid();
26578
- var DropshippingProjectStatus = z98.enum([
26654
+ var ProjectId = z99.string().uuid();
26655
+ var DropshippingProjectStatus = z99.enum([
26579
26656
  "active",
26580
26657
  "completed",
26581
26658
  "archived"
26582
26659
  ]);
26583
- var DropshippingProjectPhase = z98.enum([
26660
+ var DropshippingProjectPhase = z99.enum([
26584
26661
  "research",
26585
26662
  "costing",
26586
26663
  "media",
@@ -26589,21 +26666,21 @@ var DropshippingProjectPhase = z98.enum([
26589
26666
  "advertising",
26590
26667
  "complete"
26591
26668
  ]);
26592
- var DropshippingRewardMilestone = z98.enum([
26669
+ var DropshippingRewardMilestone = z99.enum([
26593
26670
  "product_selected",
26594
26671
  "costing_saved",
26595
26672
  "product_media_ready",
26596
26673
  "creatives_completed",
26597
26674
  "campaign_created"
26598
26675
  ]);
26599
- var TargetCountry = z98.enum([
26676
+ var TargetCountry = z99.enum([
26600
26677
  "CO",
26601
26678
  "MX",
26602
26679
  "PE",
26603
26680
  "EC",
26604
26681
  "CL"
26605
26682
  ]);
26606
- var ResearchCategory = z98.enum([
26683
+ var ResearchCategory = z99.enum([
26607
26684
  "auto",
26608
26685
  "automotive",
26609
26686
  "kitchen",
@@ -26618,7 +26695,7 @@ var ResearchCategory = z98.enum([
26618
26695
  "garden",
26619
26696
  "cleaning"
26620
26697
  ]);
26621
- var HttpUrl3 = z98.string().url().max(2e3).refine((value) => {
26698
+ var HttpUrl3 = z99.string().url().max(2e3).refine((value) => {
26622
26699
  try {
26623
26700
  return [
26624
26701
  "http:",
@@ -26628,45 +26705,45 @@ var HttpUrl3 = z98.string().url().max(2e3).refine((value) => {
26628
26705
  return false;
26629
26706
  }
26630
26707
  }, "URL must use HTTP(S)");
26631
- var ResearchCandidateOrigin = z98.object({
26632
- type: z98.literal("research_candidate"),
26708
+ var ResearchCandidateOrigin = z99.object({
26709
+ type: z99.literal("research_candidate"),
26633
26710
  runId: ProjectId,
26634
- candidateSourceId: z98.string().min(1).max(160)
26711
+ candidateSourceId: z99.string().min(1).max(160)
26635
26712
  });
26636
- var TaskOrigin = z98.object({
26637
- type: z98.literal("task"),
26713
+ var TaskOrigin = z99.object({
26714
+ type: z99.literal("task"),
26638
26715
  taskId: ProjectId
26639
26716
  });
26640
- var ManualOrigin = z98.object({
26641
- type: z98.literal("manual"),
26717
+ var ManualOrigin = z99.object({
26718
+ type: z99.literal("manual"),
26642
26719
  clientRequestId: ProjectId,
26643
- country: z98.string().min(2).max(3).optional()
26720
+ country: z99.string().min(2).max(3).optional()
26644
26721
  });
26645
- var StartProjectInput = z98.object({
26646
- origin: z98.discriminatedUnion("type", [
26722
+ var StartProjectInput = z99.object({
26723
+ origin: z99.discriminatedUnion("type", [
26647
26724
  ResearchCandidateOrigin,
26648
26725
  TaskOrigin,
26649
26726
  ManualOrigin
26650
26727
  ]),
26651
- productName: z98.string().trim().min(1).max(240).optional(),
26728
+ productName: z99.string().trim().min(1).max(240).optional(),
26652
26729
  productUrl: HttpUrl3.optional(),
26653
- country: z98.string().min(2).max(3).optional(),
26654
- languageCode: z98.string().min(2).max(16).optional()
26730
+ country: z99.string().min(2).max(3).optional(),
26731
+ languageCode: z99.string().min(2).max(16).optional()
26655
26732
  }).strict();
26656
- var CostProjectInput = z98.object({
26733
+ var CostProjectInput = z99.object({
26657
26734
  projectId: ProjectId,
26658
- version: z98.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
26659
- country: z98.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
26735
+ version: z99.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
26736
+ country: z99.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
26660
26737
  message: "Pa\xEDs no soportado por ProductMaker."
26661
26738
  }).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
26662
- 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."),
26663
- 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."),
26664
- 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."),
26665
- 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."),
26666
- adsManagerCpa: z98.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
26667
- 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.")
26668
- });
26669
- var GuideInput = z98.object({
26739
+ supplierCost: z99.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."),
26740
+ shippingCost: z99.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
26741
+ returnRate: z99.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."),
26742
+ cancellationRate: z99.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."),
26743
+ adsManagerCpa: z99.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
26744
+ desiredMargin: z99.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
26745
+ });
26746
+ var GuideInput = z99.object({
26670
26747
  projectId: ProjectId.optional()
26671
26748
  }).strict();
26672
26749
  var NEXT_ACTION_KINDS = [
@@ -26684,29 +26761,29 @@ var NEXT_ACTION_KINDS = [
26684
26761
  "repair_meta_campaign",
26685
26762
  "review_paused_campaign"
26686
26763
  ];
26687
- var DropshippingProjectNextAction = z98.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z98.object({
26688
- kind: z98.literal(kind),
26689
- href: z98.string().min(1)
26764
+ var DropshippingProjectNextAction = z99.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z99.object({
26765
+ kind: z99.literal(kind),
26766
+ href: z99.string().min(1)
26690
26767
  })));
26691
- var CostingInputSchema = z98.object({
26692
- country: z98.string().min(2).max(3),
26693
- supplierCost: z98.number().finite().positive(),
26694
- shippingCost: z98.number().finite().nonnegative(),
26695
- returnRate: z98.number().finite().min(0).lt(1),
26696
- cancellationRate: z98.number().finite().min(0).lt(1),
26697
- adsManagerCpa: z98.number().finite().nonnegative(),
26698
- desiredMargin: z98.number().finite().min(0).lt(1)
26768
+ var CostingInputSchema = z99.object({
26769
+ country: z99.string().min(2).max(3),
26770
+ supplierCost: z99.number().finite().positive(),
26771
+ shippingCost: z99.number().finite().nonnegative(),
26772
+ returnRate: z99.number().finite().min(0).lt(1),
26773
+ cancellationRate: z99.number().finite().min(0).lt(1),
26774
+ adsManagerCpa: z99.number().finite().nonnegative(),
26775
+ desiredMargin: z99.number().finite().min(0).lt(1)
26699
26776
  }).superRefine(({ returnRate, cancellationRate }, context) => {
26700
26777
  if (returnRate + cancellationRate >= 1) context.addIssue({
26701
- code: z98.ZodIssueCode.custom,
26778
+ code: z99.ZodIssueCode.custom,
26702
26779
  path: [
26703
26780
  "cancellationRate"
26704
26781
  ]
26705
26782
  });
26706
26783
  });
26707
- var FiniteCostingNumber = z98.number().finite();
26708
- var CostingResultSchema = z98.object({
26709
- country: z98.string().min(2).max(3),
26784
+ var FiniteCostingNumber = z99.number().finite();
26785
+ var CostingResultSchema = z99.object({
26786
+ country: z99.string().min(2).max(3),
26710
26787
  deliveryRate: FiniteCostingNumber,
26711
26788
  adjustedShippingCost: FiniteCostingNumber,
26712
26789
  adjustedCpa: FiniteCostingNumber,
@@ -26719,45 +26796,45 @@ var CostingResultSchema = z98.object({
26719
26796
  estimatedProfit: FiniteCostingNumber,
26720
26797
  actualMargin: FiniteCostingNumber,
26721
26798
  breakEvenAdsManagerCpa: FiniteCostingNumber,
26722
- wasPriceAutoAdjusted: z98.boolean(),
26723
- profitabilityStatus: z98.literal("healthy")
26724
- });
26725
- var RewardProgressSchema = z98.object({
26726
- campaignKey: z98.literal("dropshipping-launch-v1"),
26727
- totalCredits: z98.number().int().positive(),
26728
- earnedCredits: z98.number().int().nonnegative(),
26729
- milestones: z98.array(z98.object({
26799
+ wasPriceAutoAdjusted: z99.boolean(),
26800
+ profitabilityStatus: z99.literal("healthy")
26801
+ });
26802
+ var RewardProgressSchema = z99.object({
26803
+ campaignKey: z99.literal("dropshipping-launch-v1"),
26804
+ totalCredits: z99.number().int().positive(),
26805
+ earnedCredits: z99.number().int().nonnegative(),
26806
+ milestones: z99.array(z99.object({
26730
26807
  milestone: DropshippingRewardMilestone,
26731
- credits: z98.number().int().positive(),
26732
- available: z98.boolean().optional(),
26733
- earned: z98.boolean(),
26808
+ credits: z99.number().int().positive(),
26809
+ available: z99.boolean().optional(),
26810
+ earned: z99.boolean(),
26734
26811
  grantId: ProjectId.nullable(),
26735
- grantedAt: z98.string().datetime().nullable()
26812
+ grantedAt: z99.string().datetime().nullable()
26736
26813
  })).length(DropshippingRewardMilestone.options.length)
26737
26814
  });
26738
- var ProjectResponseSchema = z98.object({
26815
+ var ProjectResponseSchema = z99.object({
26739
26816
  id: ProjectId,
26740
26817
  taskId: ProjectId.nullable(),
26741
26818
  status: DropshippingProjectStatus,
26742
- originKey: z98.string().min(1),
26819
+ originKey: z99.string().min(1),
26743
26820
  researchRunId: ProjectId.nullable(),
26744
- candidateSourceId: z98.string().nullable(),
26745
- productName: z98.string().nullable(),
26821
+ candidateSourceId: z99.string().nullable(),
26822
+ productName: z99.string().nullable(),
26746
26823
  productUrl: HttpUrl3.nullable(),
26747
26824
  referenceImageUrl: HttpUrl3.nullable(),
26748
- targetCountry: z98.string().nullable(),
26749
- languageCode: z98.string().nullable(),
26750
- hasReferenceImage: z98.boolean(),
26751
- hasWinnerReferenceImage: z98.boolean(),
26825
+ targetCountry: z99.string().nullable(),
26826
+ languageCode: z99.string().nullable(),
26827
+ hasReferenceImage: z99.boolean(),
26828
+ hasWinnerReferenceImage: z99.boolean(),
26752
26829
  costingInput: CostingInputSchema.nullable(),
26753
26830
  costingResult: CostingResultSchema.nullable(),
26754
- costingVersion: z98.number().int().positive().nullable(),
26755
- version: z98.number().int().positive(),
26831
+ costingVersion: z99.number().int().positive().nullable(),
26832
+ version: z99.number().int().positive(),
26756
26833
  phase: DropshippingProjectPhase,
26757
26834
  nextAction: DropshippingProjectNextAction.nullable(),
26758
26835
  rewards: RewardProgressSchema,
26759
- createdAt: z98.string().datetime(),
26760
- updatedAt: z98.string().datetime()
26836
+ createdAt: z99.string().datetime(),
26837
+ updatedAt: z99.string().datetime()
26761
26838
  }).passthrough();
26762
26839
  var NEXT_ACTION_GUIDANCE = {
26763
26840
  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.",
@@ -26877,58 +26954,58 @@ function registerDropshippingProjectTools(server, api) {
26877
26954
  __name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
26878
26955
 
26879
26956
  // src/tools/daily-control.ts
26880
- import { z as z99 } from "zod";
26957
+ import { z as z100 } from "zod";
26881
26958
  var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
26882
26959
  var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
26883
26960
  var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
26884
- var ProviderCampaignIdentifier = z99.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
26885
- var DateOnly = z99.string().regex(/^\d{4}-\d{2}-\d{2}$/);
26886
- var DailyControlInput = z99.object({
26961
+ var ProviderCampaignIdentifier = z100.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
26962
+ var DateOnly = z100.string().regex(/^\d{4}-\d{2}-\d{2}$/);
26963
+ var DailyControlInput = z100.object({
26887
26964
  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."),
26888
- days: z99.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
26889
- projectId: z99.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
26965
+ days: z100.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
26966
+ projectId: z100.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
26890
26967
  }).strict();
26891
- var LinkCampaignInput = z99.object({
26892
- projectId: z99.string().uuid(),
26893
- provider: z99.enum([
26968
+ var LinkCampaignInput = z100.object({
26969
+ projectId: z100.string().uuid(),
26970
+ provider: z100.enum([
26894
26971
  "meta",
26895
26972
  "tiktok"
26896
26973
  ]),
26897
26974
  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."),
26898
26975
  campaignId: ProviderCampaignIdentifier
26899
26976
  }).strict();
26900
- var ReportReturnsInput = z99.object({
26901
- projectId: z99.string().uuid(),
26977
+ var ReportReturnsInput = z100.object({
26978
+ projectId: z100.string().uuid(),
26902
26979
  date: DateOnly,
26903
- returnedOrders: z99.number().int().min(0).max(1e5),
26904
- note: z99.string().trim().max(280).optional()
26980
+ returnedOrders: z100.number().int().min(0).max(1e5),
26981
+ note: z100.string().trim().max(280).optional()
26905
26982
  }).strict();
26906
- var DailyControlStatusMirror = DailyControlStatusEnum.or(z99.string());
26907
- var DailyControlLightMirror = DailyControlLightEnum.or(z99.string());
26908
- var DailyControlSourceMirror = DailyControlSourceEnum.or(z99.string());
26909
- var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z99.string());
26910
- var DailyControlDayMirror = z99.object({
26911
- date: z99.string(),
26912
- returnedOrders: z99.number(),
26983
+ var DailyControlStatusMirror = DailyControlStatusEnum.or(z100.string());
26984
+ var DailyControlLightMirror = DailyControlLightEnum.or(z100.string());
26985
+ var DailyControlSourceMirror = DailyControlSourceEnum.or(z100.string());
26986
+ var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z100.string());
26987
+ var DailyControlDayMirror = z100.object({
26988
+ date: z100.string(),
26989
+ returnedOrders: z100.number(),
26913
26990
  returnedSource: DailyControlSourceMirror,
26914
26991
  cancelledSource: DailyControlSourceMirror,
26915
- hasEstimates: z99.boolean(),
26992
+ hasEstimates: z100.boolean(),
26916
26993
  light: DailyControlLightMirror
26917
26994
  }).passthrough();
26918
- var DailyControlProductMirror = z99.object({
26919
- projectId: z99.string().uuid(),
26920
- productName: z99.string().nullable(),
26995
+ var DailyControlProductMirror = z100.object({
26996
+ projectId: z100.string().uuid(),
26997
+ productName: z100.string().nullable(),
26921
26998
  status: DailyControlStatusMirror,
26922
- statusMessage: z99.string().nullable(),
26923
- days: z99.array(DailyControlDayMirror),
26999
+ statusMessage: z100.string().nullable(),
27000
+ days: z100.array(DailyControlDayMirror),
26924
27001
  verdict: DailyControlVerdictMirror.nullable(),
26925
- rationale: z99.string().nullable()
27002
+ rationale: z100.string().nullable()
26926
27003
  }).passthrough();
26927
- var DailyControlResponseMirror = z99.object({
26928
- since: z99.string(),
26929
- until: z99.string(),
26930
- products: z99.array(DailyControlProductMirror),
26931
- archivedProjectSpend: z99.array(z99.unknown())
27004
+ var DailyControlResponseMirror = z100.object({
27005
+ since: z100.string(),
27006
+ until: z100.string(),
27007
+ products: z100.array(DailyControlProductMirror),
27008
+ archivedProjectSpend: z100.array(z100.unknown())
26932
27009
  }).passthrough();
26933
27010
  var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
26934
27011
  function withWarnings(response) {
@@ -27003,7 +27080,7 @@ __name(registerDailyControlTools, "registerDailyControlTools");
27003
27080
  // src/tools/product-control.ts
27004
27081
  import { readFile, stat } from "fs/promises";
27005
27082
  import { basename as basename2, isAbsolute, resolve as resolve3 } from "path";
27006
- import { z as z100 } from "zod";
27083
+ import { z as z101 } from "zod";
27007
27084
  var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
27008
27085
  var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
27009
27086
  var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
@@ -27016,36 +27093,36 @@ var createOperationGuidance = getProductMakerCapabilityModelGuidance("create_ope
27016
27093
  var mergeProductsGuidance = getProductMakerCapabilityModelGuidance("merge_products");
27017
27094
  var syncShopifyOrdersGuidance = getProductMakerCapabilityModelGuidance("sync_shopify_orders");
27018
27095
  var importOrdersFileGuidance = getProductMakerCapabilityModelGuidance("import_orders_file");
27019
- var DateOnly2 = z100.string().regex(/^\d{4}-\d{2}-\d{2}$/);
27096
+ var DateOnly2 = z101.string().regex(/^\d{4}-\d{2}-\d{2}$/);
27020
27097
  var IMPORT_BATCH_MAX2 = 50;
27021
- var ProductControlListInput = z100.object({
27022
- days: z100.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
27098
+ var ProductControlListInput = z101.object({
27099
+ days: z101.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
27023
27100
  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."),
27024
- shopDomain: z100.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
27101
+ shopDomain: z101.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
27025
27102
  }).strict();
27026
- var ImportableProductsInput = z100.object({
27027
- q: z100.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
27028
- after: z100.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
27029
- shopDomain: z100.string().min(1).optional()
27103
+ var ImportableProductsInput = z101.object({
27104
+ q: z101.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
27105
+ after: z101.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
27106
+ shopDomain: z101.string().min(1).optional()
27030
27107
  }).strict();
27031
- var ImportProductControlsInput = z100.object({
27032
- 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."),
27108
+ var ImportProductControlsInput = z101.object({
27109
+ shopifyProductIds: z101.array(z101.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."),
27033
27110
  // Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
27034
27111
  // sin decir a cuál archivaría el producto bajo la tienda equivocada.
27035
- shopDomain: z100.string().min(1)
27112
+ shopDomain: z101.string().min(1)
27036
27113
  }).strict();
27037
- var SetProductCostingInput = z100.object({
27038
- shopDomain: z100.string().min(1),
27039
- shopifyProductId: z100.string().min(1).max(64),
27040
- targetCountry: z100.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
27041
- supplierCost: z100.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
27042
- shippingCost: z100.number().finite().nonnegative(),
27043
- returnRate: z100.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
27044
- cancellationRate: z100.number().finite().min(0).lt(1)
27114
+ var SetProductCostingInput = z101.object({
27115
+ shopDomain: z101.string().min(1),
27116
+ shopifyProductId: z101.string().min(1).max(64),
27117
+ targetCountry: z101.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
27118
+ supplierCost: z101.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
27119
+ shippingCost: z101.number().finite().nonnegative(),
27120
+ returnRate: z101.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
27121
+ cancellationRate: z101.number().finite().min(0).lt(1)
27045
27122
  }).strict();
27046
- var Count = z100.number().int().min(0).max(1e5).nullable().optional();
27047
- var ReportProductCountsInput = z100.object({
27048
- productControlId: z100.string().uuid().describe("El identificador que devuelve get_product_control."),
27123
+ var Count = z101.number().int().min(0).max(1e5).nullable().optional();
27124
+ var ReportProductCountsInput = z101.object({
27125
+ productControlId: z101.string().uuid().describe("El identificador que devuelve get_product_control."),
27049
27126
  date: DateOnly2,
27050
27127
  orders: Count.describe("Pedidos que entraron ese d\xEDa."),
27051
27128
  cancelledOrders: Count,
@@ -27055,36 +27132,36 @@ var ReportProductCountsInput = z100.object({
27055
27132
  }).strict();
27056
27133
  var MAX_ORDERS_FILE_BYTES = 8 * 1024 * 1024;
27057
27134
  var SyncShopifyOrdersInput = SyncShopifyOrdersSchema;
27058
- var ImportOrdersFileInput = z100.object({
27135
+ var ImportOrdersFileInput = z101.object({
27059
27136
  /** Ruta ABSOLUTA en la máquina de quien usa el MCP. */
27060
- path: z100.string().min(1),
27061
- operationId: z100.string().uuid().optional(),
27137
+ path: z101.string().min(1),
27138
+ operationId: z101.string().uuid().optional(),
27062
27139
  /** Solo mirar: devuelve el resumen y no escribe nada. */
27063
- dryRun: z100.boolean().optional()
27140
+ dryRun: z101.boolean().optional()
27064
27141
  }).strict();
27065
- var CreateOperationInput = z100.object({
27066
- countryCode: z100.string().length(2),
27067
- label: z100.string().trim().min(1).max(60).optional()
27142
+ var CreateOperationInput = z101.object({
27143
+ countryCode: z101.string().length(2),
27144
+ label: z101.string().trim().min(1).max(60).optional()
27068
27145
  }).strict();
27069
- var MergeProductsInput = z100.object({
27070
- sourceId: z100.string().uuid(),
27071
- targetId: z100.string().uuid()
27146
+ var MergeProductsInput = z101.object({
27147
+ sourceId: z101.string().uuid(),
27148
+ targetId: z101.string().uuid()
27072
27149
  }).strict();
27073
- var SetMonthlyExpenseInput = z100.object({
27074
- month: z100.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
27150
+ var SetMonthlyExpenseInput = z101.object({
27151
+ month: z101.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
27075
27152
  label: SaveMonthlyExpenseSchema.shape.label,
27076
- amount: z100.number().finite().min(0),
27077
- operationId: z100.string().uuid().optional()
27153
+ amount: z101.number().finite().min(0),
27154
+ operationId: z101.string().uuid().optional()
27078
27155
  }).strict();
27079
- var SetAdSpendInput = z100.object({
27080
- month: z100.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
27081
- operationId: z100.string().uuid().optional(),
27156
+ var SetAdSpendInput = z101.object({
27157
+ month: z101.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
27158
+ operationId: z101.string().uuid().optional(),
27082
27159
  /** null RETIRA la corrección; cero afirma que no pautó. */
27083
- amount: z100.number().finite().min(0).nullable()
27160
+ amount: z101.number().finite().min(0).nullable()
27084
27161
  }).strict();
27085
- var GetFinancesInput = z100.object({
27086
- 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."),
27087
- operationId: z100.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
27162
+ var GetFinancesInput = z101.object({
27163
+ month: z101.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."),
27164
+ operationId: z101.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
27088
27165
  }).strict();
27089
27166
  function registerProductControlTools(server, api, { transport = "http" } = {}) {
27090
27167
  server.registerTool("get_product_control", {
@@ -27281,27 +27358,27 @@ function registerProductControlTools(server, api, { transport = "http" } = {}) {
27281
27358
  __name(registerProductControlTools, "registerProductControlTools");
27282
27359
 
27283
27360
  // src/tools/market-study-estimate.ts
27284
- import { z as z101 } from "zod";
27361
+ import { z as z102 } from "zod";
27285
27362
  var estimateMarketStudyGuidance = getProductMakerCapabilityModelGuidance("estimate_market_study_cost");
27286
- var ProductTaskOutputEnum = z101.enum([
27363
+ var ProductTaskOutputEnum = z102.enum([
27287
27364
  "landing",
27288
27365
  "video",
27289
27366
  "image"
27290
27367
  ]);
27291
- var EstimateMarketStudyInput = z101.object({
27292
- kind: z101.enum([
27368
+ var EstimateMarketStudyInput = z102.object({
27369
+ kind: z102.enum([
27293
27370
  "video",
27294
27371
  "product_task"
27295
27372
  ]).describe('"video" para generate_video_creative; "product_task" para create_product_task.'),
27296
- videoAngleCount: z101.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
27297
- durationSeconds: z101.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
27373
+ videoAngleCount: z102.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
27374
+ durationSeconds: z102.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
27298
27375
  videoStructure: VideoStructureEnum.default("single_take"),
27299
27376
  videoQuality: VideoQualityEnum.default("economy"),
27300
27377
  videoResolution: VideoResolutionEnum.default("480p"),
27301
- productImageCount: z101.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
27378
+ productImageCount: z102.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
27302
27379
  outputs: ProductTaskOutputEnum.array().min(1).max(3).optional().describe('Solo para kind="product_task": los mismos outputs de create_product_task. Default: todos.'),
27303
- generateAiMusic: z101.boolean().optional(),
27304
- 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.")
27380
+ generateAiMusic: z102.boolean().optional(),
27381
+ replicateWinnerWhenFound: z102.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.")
27305
27382
  }).strict();
27306
27383
  function buildMarketStudyEstimateRequests(input) {
27307
27384
  const quotesVideo = input.kind === "video" || (input.outputs ?? [