@productmaker/mcp 8.11.1 → 8.11.3

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