@productmaker/mcp 11.3.2 → 11.3.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
@@ -21600,8 +21600,33 @@ var ServicePageGenerateRequestSchema = z100.object({
21600
21600
  instruction: ServicePageEditInstructionSchema.optional(),
21601
21601
  attachmentRefs: ServicePageAttachmentRefsSchema.optional()
21602
21602
  }).strict();
21603
+ var SERVICE_PAGE_CREATION_MAX_ATTEMPTS = 3;
21604
+ var ServicePageCreationMarkerSchema = z100.object({
21605
+ rootOperationId: z100.string().uuid().optional(),
21606
+ attempt: z100.number().int().min(1).max(SERVICE_PAGE_CREATION_MAX_ATTEMPTS)
21607
+ }).strict();
21608
+ var ServicePageCreationEstimateRequestSchema = z100.object({
21609
+ textCharacters: z100.number().int().min(0).max(1e6),
21610
+ documentBytes: z100.number().int().min(0).max(1e8),
21611
+ imageCount: z100.number().int().min(0).max(50),
21612
+ instagram: z100.boolean()
21613
+ }).strict();
21614
+ var ServicePageCreationEstimateResponseSchema = z100.object({
21615
+ estimatedMinCostCredits: z100.number().int().nonnegative(),
21616
+ estimatedMaxCostCredits: z100.number().int().nonnegative()
21617
+ }).strict();
21618
+ var ServicePageCreationStatusSchema = z100.object({
21619
+ status: z100.enum([
21620
+ "idle",
21621
+ "running",
21622
+ "failed"
21623
+ ]),
21624
+ errorCode: z100.string().max(64).optional()
21625
+ }).strict();
21603
21626
  var ServicePageFactExtractionRequestSchema = ServicePageGenerateRequestSchema.omit({
21604
21627
  instruction: true
21628
+ }).extend({
21629
+ continueWith: z100.literal("generation").optional()
21605
21630
  });
21606
21631
  var ServicePageOperationStatusSchema = z100.enum([
21607
21632
  "queued",
@@ -22246,6 +22271,159 @@ var WebsiteCaptureResearchSchema = z107.object({
22246
22271
  })
22247
22272
  });
22248
22273
 
22274
+ // ../../packages/types/src/demo-mode.ts
22275
+ import { z as z108 } from "zod";
22276
+ var DEMO_MODE_FLOWS = [
22277
+ "brand",
22278
+ "servicePage",
22279
+ "motion",
22280
+ "image"
22281
+ ];
22282
+ var DemoModeFlowSchema = z108.enum(DEMO_MODE_FLOWS);
22283
+ var DEMO_MODE_STEPS = [
22284
+ "running",
22285
+ "research",
22286
+ "design",
22287
+ "render_0",
22288
+ "render_33",
22289
+ "render_66",
22290
+ "render_100",
22291
+ "review",
22292
+ "final",
22293
+ "watchdog"
22294
+ ];
22295
+ var DemoModeStepSchema = z108.enum(DEMO_MODE_STEPS);
22296
+ var DEMO_MODE_WAIT_SECONDS = {
22297
+ min: 30,
22298
+ max: 450,
22299
+ default: 150
22300
+ };
22301
+ var centsSchema = z108.number().int().min(0).max(1e5);
22302
+ var emailSchema = z108.string().trim().toLowerCase().email();
22303
+ var DemoModeTemplatesSchema = z108.object({
22304
+ brandId: z108.string().uuid(),
22305
+ servicePageId: z108.string().uuid(),
22306
+ motionTaskId: z108.string().uuid(),
22307
+ imageTaskId: z108.string().uuid()
22308
+ });
22309
+ var DemoModeEditableSchema = z108.object({
22310
+ enabled: z108.boolean(),
22311
+ emails: z108.array(emailSchema).max(50).transform((list) => [
22312
+ ...new Set(list)
22313
+ ]),
22314
+ waitSeconds: z108.number().int().min(DEMO_MODE_WAIT_SECONDS.min).max(DEMO_MODE_WAIT_SECONDS.max),
22315
+ chargeCents: z108.object({
22316
+ brand: centsSchema,
22317
+ servicePage: centsSchema,
22318
+ motion: centsSchema,
22319
+ image: centsSchema
22320
+ }),
22321
+ templates: DemoModeTemplatesSchema
22322
+ });
22323
+ var nullableString = z108.string().nullable();
22324
+ var DemoModeSnapshotSchema = z108.object({
22325
+ brand: z108.object({
22326
+ /** Columnas de identidad de `Brand` listas para un `update` (sin id/userId/slug/estado/fechas). */
22327
+ identity: z108.record(z108.unknown()),
22328
+ productSamples: z108.array(z108.object({
22329
+ name: z108.string(),
22330
+ priceCents: z108.number().int().nullable(),
22331
+ currency: nullableString,
22332
+ imageKey: z108.string(),
22333
+ productUrl: nullableString,
22334
+ position: z108.number().int()
22335
+ })),
22336
+ personas: z108.array(z108.object({
22337
+ name: z108.string(),
22338
+ demographics: nullableString,
22339
+ painPoints: nullableString,
22340
+ motivations: nullableString,
22341
+ objections: nullableString,
22342
+ gender: nullableString,
22343
+ isDefault: z108.boolean()
22344
+ }))
22345
+ }),
22346
+ servicePage: z108.object({
22347
+ facts: z108.unknown(),
22348
+ review: z108.unknown(),
22349
+ artifact: z108.unknown()
22350
+ }),
22351
+ motion: z108.object({
22352
+ outputs: MotionGraphicsOutputsSchema,
22353
+ /**
22354
+ * La captura REAL de la web de la plantilla (nunca una fabricada por la
22355
+ * demo). Null cuando la plantilla no tiene ninguna: la captura demo nunca
22356
+ * va live, así que el servicio usa `DEMO_MODE_PLACEHOLDER_CAPTURE`.
22357
+ */
22358
+ capture: z108.object({
22359
+ bundleKey: z108.string(),
22360
+ sha256: z108.string(),
22361
+ uploadBytes: z108.number().int().nullable(),
22362
+ previewKey: nullableString
22363
+ }).nullable()
22364
+ }),
22365
+ image: z108.object({
22366
+ provider: z108.string(),
22367
+ model: z108.string(),
22368
+ prompt: z108.string(),
22369
+ imageUrl: z108.string(),
22370
+ width: z108.number().int(),
22371
+ height: z108.number().int(),
22372
+ adCopy: nullableString,
22373
+ rawResponse: z108.unknown()
22374
+ })
22375
+ });
22376
+ var DemoModeConfigSchema = DemoModeEditableSchema.extend({
22377
+ snapshot: DemoModeSnapshotSchema.nullable(),
22378
+ snapshotAt: z108.string().datetime().nullable()
22379
+ });
22380
+ var DemoModeAdminViewSchema = DemoModeEditableSchema.extend({
22381
+ // Sin configurar, la API devuelve ids vacíos ("" no es uuid): la vista los
22382
+ // admite; el PUT sí exige uuid (`DemoModeEditableSchema`).
22383
+ templates: z108.object({
22384
+ brandId: z108.string(),
22385
+ servicePageId: z108.string(),
22386
+ motionTaskId: z108.string(),
22387
+ imageTaskId: z108.string()
22388
+ }),
22389
+ snapshotAt: z108.string().nullable()
22390
+ });
22391
+ var DEMO_MODE_TEMPLATE_PROBLEMS = [
22392
+ "not_found",
22393
+ "brand_not_ready",
22394
+ "no_artifact",
22395
+ "artifact_invalid",
22396
+ "task_not_done",
22397
+ "no_video",
22398
+ "no_creative"
22399
+ ];
22400
+ var DemoModeTemplateVerdictSchema = z108.discriminatedUnion("ok", [
22401
+ z108.object({
22402
+ ok: z108.literal(true)
22403
+ }),
22404
+ z108.object({
22405
+ ok: z108.literal(false),
22406
+ problem: z108.enum(DEMO_MODE_TEMPLATE_PROBLEMS)
22407
+ })
22408
+ ]);
22409
+ var DemoModeValidationSchema = z108.object({
22410
+ brandId: DemoModeTemplateVerdictSchema,
22411
+ servicePageId: DemoModeTemplateVerdictSchema,
22412
+ motionTaskId: DemoModeTemplateVerdictSchema,
22413
+ imageTaskId: DemoModeTemplateVerdictSchema
22414
+ });
22415
+ var DemoModeJobSchema = z108.object({
22416
+ flow: DemoModeFlowSchema,
22417
+ step: DemoModeStepSchema,
22418
+ /** brandId | servicePageOperationId | taskId según el flujo. */
22419
+ targetId: z108.string().uuid(),
22420
+ userId: z108.string().min(1),
22421
+ /** Solo marca: la generación de extracción que el guion completa. */
22422
+ generation: z108.number().int().positive().optional(),
22423
+ /** Solo `final`/`watchdog`: la parte del snapshot de ESTE flujo, congelada al empezar. */
22424
+ result: z108.unknown().optional()
22425
+ });
22426
+
22249
22427
  // src/http.ts
22250
22428
  import express4 from "express";
22251
22429
  import rateLimit2 from "express-rate-limit";
@@ -22755,23 +22933,23 @@ import { InsufficientScopeError, InvalidTokenError } from "@modelcontextprotocol
22755
22933
  import { createRemoteJWKSet as createRemoteJWKSet2, jwtVerify as jwtVerify2 } from "jose";
22756
22934
 
22757
22935
  // src/auth/oauth-config.ts
22758
- import { z as z108 } from "zod";
22936
+ import { z as z109 } from "zod";
22759
22937
  var MCP_RESOURCE = new URL("https://mcp.productmaker.app/mcp");
22760
22938
  var MCP_SCOPE = "mcp:access";
22761
22939
  var REFRESH_SCOPE = "offline_access";
22762
22940
  var STATIC_CLIENT_ISSUER = new URL(MCP_RESOURCE.origin);
22763
- var oauthEnvSchema = z108.object({
22764
- MCP_REMOTE_AUTH_MODE: z108.literal("oauth"),
22765
- MCP_AUTH0_ISSUER: z108.string().trim().min(1),
22766
- MCP_AUTH0_AUDIENCE: z108.string().trim().refine((value) => value === MCP_RESOURCE.href, {
22941
+ var oauthEnvSchema = z109.object({
22942
+ MCP_REMOTE_AUTH_MODE: z109.literal("oauth"),
22943
+ MCP_AUTH0_ISSUER: z109.string().trim().min(1),
22944
+ MCP_AUTH0_AUDIENCE: z109.string().trim().refine((value) => value === MCP_RESOURCE.href, {
22767
22945
  message: `must equal ${MCP_RESOURCE.href}`
22768
22946
  }),
22769
- MCP_AUTH0_CLIENT_ID: z108.string().trim().min(1),
22770
- MCP_AUTH0_CLIENT_SECRET: z108.string().trim().min(1),
22771
- PM_API_AUDIENCE: z108.string().trim().min(1),
22772
- AUTH0_AUDIENCE: z108.string().trim().min(1),
22773
- MCP_STATIC_CLIENT_ID: z108.string().trim().min(1).optional(),
22774
- MCP_STATIC_CLIENT_SECRET: z108.string().trim().min(1).optional()
22947
+ MCP_AUTH0_CLIENT_ID: z109.string().trim().min(1),
22948
+ MCP_AUTH0_CLIENT_SECRET: z109.string().trim().min(1),
22949
+ PM_API_AUDIENCE: z109.string().trim().min(1),
22950
+ AUTH0_AUDIENCE: z109.string().trim().min(1),
22951
+ MCP_STATIC_CLIENT_ID: z109.string().trim().min(1).optional(),
22952
+ MCP_STATIC_CLIENT_SECRET: z109.string().trim().min(1).optional()
22775
22953
  });
22776
22954
  function formatZodIssues(error) {
22777
22955
  return error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
@@ -23927,7 +24105,7 @@ var ApiClient = class {
23927
24105
  };
23928
24106
 
23929
24107
  // src/index.ts
23930
- var MCP_VERSION = "11.3.2";
24108
+ var MCP_VERSION = "11.3.3";
23931
24109
 
23932
24110
  // src/meta-upload-app.ts
23933
24111
  import { readFileSync } from "fs";
@@ -23999,7 +24177,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
23999
24177
  __name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
24000
24178
 
24001
24179
  // src/tools/tasks.ts
24002
- import { z as z113 } from "zod";
24180
+ import { z as z114 } from "zod";
24003
24181
 
24004
24182
  // src/resolve-image.ts
24005
24183
  import { lookup as dnsLookup } from "dns/promises";
@@ -24560,9 +24738,9 @@ async function resolveMediaRef(ref, opts) {
24560
24738
  __name(resolveMediaRef, "resolveMediaRef");
24561
24739
 
24562
24740
  // src/tools/shared.ts
24563
- import { z as z109 } from "zod";
24564
- var Lang = z109.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);
24565
- var Country = z109.string().min(2).max(3);
24741
+ import { z as z110 } from "zod";
24742
+ var Lang = z110.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);
24743
+ var Country = z110.string().min(2).max(3);
24566
24744
  var LandingStrategyEnum = LandingStrategySchema;
24567
24745
  var LandingImageFormatEnum = LandingImageFormatSchema;
24568
24746
  var VideoPresetEnum = VideoPreset.extract([
@@ -24666,7 +24844,7 @@ function animationStyleApplies(videoPreset, angleNarratives) {
24666
24844
  return ANIMATED_VIDEO_PRESETS.has(videoPreset ?? "") || (angleNarratives ?? []).some((n) => ANIMATED_NARRATIVE_STYLES.has(n));
24667
24845
  }
24668
24846
  __name(animationStyleApplies, "animationStyleApplies");
24669
- var VideoTierEnum = z109.enum([
24847
+ var VideoTierEnum = z110.enum([
24670
24848
  "basic"
24671
24849
  ]);
24672
24850
  function resolveVideoTier(_tier) {
@@ -24724,10 +24902,10 @@ var ImageCreativeStyleEnum = ImageCreativeStyle;
24724
24902
  var ImageCreativeArchetypeEnum = ImageCreativeArchetype;
24725
24903
  var ImageCreativeVisualTreatmentEnum = ImageCreativeVisualTreatment;
24726
24904
  var ImageCreativeAspectRatioEnum = ImageCreativeAspectRatio;
24727
- var ImageRefSchema = z109.object({
24728
- url: z109.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.'),
24729
- path: z109.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`.'),
24730
- assetId: z109.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.")
24905
+ var ImageRefSchema = z110.object({
24906
+ url: z110.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.'),
24907
+ path: z110.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`.'),
24908
+ assetId: z110.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.")
24731
24909
  }).refine((v) => [
24732
24910
  v.url,
24733
24911
  v.path,
@@ -24735,11 +24913,11 @@ var ImageRefSchema = z109.object({
24735
24913
  ].filter(Boolean).length === 1, {
24736
24914
  message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
24737
24915
  });
24738
- var ImagesInput = z109.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
24916
+ var ImagesInput = z110.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
24739
24917
  const assetCount = images.filter((image) => Boolean(image.assetId)).length;
24740
24918
  if (assetCount > 0 && assetCount !== images.length) {
24741
24919
  ctx.addIssue({
24742
- code: z109.ZodIssueCode.custom,
24920
+ code: z110.ZodIssueCode.custom,
24743
24921
  message: "all image entries must use assetId, or all must use URL/path sources"
24744
24922
  });
24745
24923
  }
@@ -24789,16 +24967,24 @@ async function submitCreative(api, opts) {
24789
24967
  ...img,
24790
24968
  filename: `image-${i}.png`
24791
24969
  }));
24792
- const r = await api.postMultipart(opts.path, {
24793
- images: parts
24794
- }, flatten({
24795
- ...rest,
24796
- ...assetIds ? {
24797
- assetIds
24798
- } : {}
24799
- }), opts.idempotencyKey ? {
24800
- idempotencyKey: opts.idempotencyKey
24801
- } : void 0);
24970
+ const r = await api.postMultipart(
24971
+ opts.path,
24972
+ {
24973
+ images: parts
24974
+ },
24975
+ // assetIds stays an array so postMultipart appends one `assetIds` field per
24976
+ // id: `flatten` would comma-join them into a single non-UUID value and the
24977
+ // API rejects every multi-photo upload with "assetId must be a valid UUID".
24978
+ {
24979
+ ...flatten(rest),
24980
+ ...assetIds ? {
24981
+ assetIds
24982
+ } : {}
24983
+ },
24984
+ opts.idempotencyKey ? {
24985
+ idempotencyKey: opts.idempotencyKey
24986
+ } : void 0
24987
+ );
24802
24988
  const taskId = r.taskId ?? r.jobId;
24803
24989
  return asText({
24804
24990
  taskId,
@@ -24812,14 +24998,14 @@ async function submitCreative(api, opts) {
24812
24998
  });
24813
24999
  }
24814
25000
  __name(submitCreative, "submitCreative");
24815
- var ResearchTargetCountryEnum = z109.enum([
25001
+ var ResearchTargetCountryEnum = z110.enum([
24816
25002
  "CO",
24817
25003
  "MX",
24818
25004
  "PE",
24819
25005
  "EC",
24820
25006
  "CL"
24821
25007
  ]);
24822
- var ResearchCategoryEnum = z109.enum([
25008
+ var ResearchCategoryEnum = z110.enum([
24823
25009
  "auto",
24824
25010
  "automotive",
24825
25011
  "kitchen",
@@ -26131,29 +26317,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
26131
26317
  __name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
26132
26318
 
26133
26319
  // src/tools/media-presentation.ts
26134
- import { z as z110 } from "zod";
26135
- var HttpsPresentationUrlSchema = z110.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
26320
+ import { z as z111 } from "zod";
26321
+ var HttpsPresentationUrlSchema = z111.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
26136
26322
  var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
26137
26323
  const hostname = new URL(value).hostname.toLowerCase();
26138
26324
  return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
26139
26325
  }, "preview URL must be owned by ProductMaker");
26140
- var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z110.number().int().positive().max(maximum), "positiveIntAtMost");
26141
- var PresentationImageSchema = z110.object({
26142
- kind: z110.literal("image"),
26326
+ var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z111.number().int().positive().max(maximum), "positiveIntAtMost");
26327
+ var PresentationImageSchema = z111.object({
26328
+ kind: z111.literal("image"),
26143
26329
  url: HttpsPresentationUrlSchema,
26144
- mimeType: z110.enum([
26330
+ mimeType: z111.enum([
26145
26331
  "image/jpeg",
26146
26332
  "image/png"
26147
26333
  ]),
26148
26334
  byteSize: positiveIntAtMost(5 * 1024 * 1024),
26149
26335
  width: positiveIntAtMost(16384),
26150
26336
  height: positiveIntAtMost(16384),
26151
- alt: z110.string().trim().min(1).max(240)
26337
+ alt: z111.string().trim().min(1).max(240)
26152
26338
  }).strict();
26153
26339
  var McpMediaPresentationSchema = PresentationImageSchema;
26154
- var GalleryImageSchema = z110.object({
26340
+ var GalleryImageSchema = z111.object({
26155
26341
  url: ProductMakerPreviewUrlSchema,
26156
- alt: z110.string().trim().min(1).max(240)
26342
+ alt: z111.string().trim().min(1).max(240)
26157
26343
  });
26158
26344
  var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
26159
26345
  async function imageBlocks(image, transport) {
@@ -26210,12 +26396,12 @@ async function buildMcpMediaPresentationContent(rawPresentation, transport = "ht
26210
26396
  ];
26211
26397
  }
26212
26398
  __name(buildMcpMediaPresentationContent, "buildMcpMediaPresentationContent");
26213
- var OwnedImagePreviewSchema = z110.object({
26399
+ var OwnedImagePreviewSchema = z111.object({
26214
26400
  url: HttpsPresentationUrlSchema.refine((value) => {
26215
26401
  const url = new URL(value);
26216
26402
  return !url.username && !url.password && !isPrivateHost(url.hostname);
26217
26403
  }, "Preview URL must be public HTTPS without credentials"),
26218
- alt: z110.string().trim().min(1).max(240)
26404
+ alt: z111.string().trim().min(1).max(240)
26219
26405
  });
26220
26406
  async function buildMcpImagePreviewContent(rawPreview, transport = "http") {
26221
26407
  const preview2 = OwnedImagePreviewSchema.safeParse(rawPreview);
@@ -26298,7 +26484,7 @@ async function buildMcpImageGalleryContent(rawItems, transport = "http") {
26298
26484
  __name(buildMcpImageGalleryContent, "buildMcpImageGalleryContent");
26299
26485
 
26300
26486
  // src/tools/animated-video.ts
26301
- import { z as z111 } from "zod";
26487
+ import { z as z112 } from "zod";
26302
26488
 
26303
26489
  // src/tools/paid-confirmation.ts
26304
26490
  function describeMarketStudyChoice(enabled) {
@@ -26548,27 +26734,27 @@ function hookVariantsLabel(count) {
26548
26734
  return count === 1 ? "1 versi\xF3n del gancho" : `${count} versiones del gancho`;
26549
26735
  }
26550
26736
  __name(hookVariantsLabel, "hookVariantsLabel");
26551
- var DurationInput = z111.union(MOTION_GRAPHICS_DURATIONS.map((d) => z111.literal(d)));
26552
- var CreateAnimatedVideoInput = z111.object({
26553
- action: z111.enum([
26737
+ var DurationInput = z112.union(MOTION_GRAPHICS_DURATIONS.map((d) => z112.literal(d)));
26738
+ var CreateAnimatedVideoInput = z112.object({
26739
+ action: z112.enum([
26554
26740
  "prepare",
26555
26741
  "status",
26556
26742
  "cancel",
26557
26743
  "generate"
26558
26744
  ]).default("prepare").describe("prepare inicia una captura gratuita; status consulta websiteCaptureId; cancel la cancela; generate requiere captura ready y confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrar vista previa y precio."),
26559
- websiteCaptureId: z111.string().uuid().optional().describe("ID de la captura preparada. Obligatorio para status/cancel/generate; no inventarlo."),
26560
- generationRequestId: z111.string().uuid().optional().describe("Identidad opcional de una generaci\xF3n confirmada. Repite el mismo UUID al recuperar una respuesta perdida; usa otro \xFAnicamente cuando el usuario pida y confirme otro video, nunca por un error de transporte."),
26561
- confirmed: z111.boolean().optional().describe("Solo true despu\xE9s de que el usuario confirme esta captura, formato, duraci\xF3n, idioma y precio. Obligatorio para generate; preparar no genera ni cobra."),
26745
+ websiteCaptureId: z112.string().uuid().optional().describe("ID de la captura preparada. Obligatorio para status/cancel/generate; no inventarlo."),
26746
+ generationRequestId: z112.string().uuid().optional().describe("Identidad opcional de una generaci\xF3n confirmada. Repite el mismo UUID al recuperar una respuesta perdida; usa otro \xFAnicamente cuando el usuario pida y confirme otro video, nunca por un error de transporte."),
26747
+ confirmed: z112.boolean().optional().describe("Solo true despu\xE9s de que el usuario confirme esta captura, formato, duraci\xF3n, idioma y precio. Obligatorio para generate; preparar no genera ni cobra."),
26562
26748
  // Plain text, not `.url()`: users type «cal.com», and the web accepts it.
26563
26749
  // normalizeWebAddress (shared with the web) adds https:// and refuses
26564
26750
  // anything that is not a public http(s) address.
26565
- landingUrl: z111.string().trim().min(1).optional().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."),
26751
+ landingUrl: z112.string().trim().min(1).optional().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."),
26566
26752
  format: MotionGraphicsFormatSchema.optional().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.'),
26567
26753
  durationSec: DurationInput.optional().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.`),
26568
26754
  language: MotionGraphicsLanguageSchema.optional().describe('Idioma de los textos del video: "es", "en" o "pt".'),
26569
- notes: z111.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)."),
26755
+ notes: z112.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)."),
26570
26756
  hookVariants: MotionGraphicsHookVariantsSchema.optional().describe(`Opcional. Versiones del gancho: el mismo video con distintas aperturas para probar cu\xE1l funciona mejor, de 1 a ${MOTION_GRAPHICS_HOOK_VARIANTS_MAX} (por defecto 1). Cada versi\xF3n extra tiene precio (ver la descripci\xF3n de la herramienta); \xFAsalo solo si el usuario lo pide.`),
26571
- music: z111.boolean().optional().describe("Opcional. M\xFAsica de fondo (por defecto true). false hace el video sin m\xFAsica, m\xE1s crudo, estilo UGC: quedan la voz y los efectos de sonido. Mismo precio. \xDAsalo solo si el usuario lo pide.")
26757
+ music: z112.boolean().optional().describe("Opcional. M\xFAsica de fondo (por defecto true). false hace el video sin m\xFAsica, m\xE1s crudo, estilo UGC: quedan la voz y los efectos de sonido. Mismo precio. \xDAsalo solo si el usuario lo pide.")
26572
26758
  }).strict();
26573
26759
  function captureNextAction(capture) {
26574
26760
  if (capture.status === "ready") return "Muestra la vista previa al usuario y confirma formato, duraci\xF3n, idioma y precio. Solo despu\xE9s llama create_animated_video con action=generate, este websiteCaptureId y confirmed=true.";
@@ -26601,43 +26787,43 @@ var FORMAT_LABELS = {
26601
26787
  square: "cuadrado 1:1",
26602
26788
  horizontal: "horizontal 16:9"
26603
26789
  };
26604
- var AnimatedVideoResultSchema = z111.object({
26605
- status: z111.enum([
26790
+ var AnimatedVideoResultSchema = z112.object({
26791
+ status: z112.enum([
26606
26792
  "pending",
26607
26793
  "done",
26608
26794
  "error"
26609
26795
  ]),
26610
- serviceMode: z111.literal("motion_graphics"),
26611
- finalMp4Url: z111.string().optional(),
26612
- error: z111.string().optional(),
26613
- motionGraphics: z111.object({
26796
+ serviceMode: z112.literal("motion_graphics"),
26797
+ finalMp4Url: z112.string().optional(),
26798
+ error: z112.string().optional(),
26799
+ motionGraphics: z112.object({
26614
26800
  stage: MotionGraphicsStageSchema,
26615
26801
  format: MotionGraphicsFormatSchema,
26616
- durationSec: z111.number(),
26617
- width: z111.number().optional(),
26618
- height: z111.number().optional(),
26802
+ durationSec: z112.number(),
26803
+ width: z112.number().optional(),
26804
+ height: z112.number().optional(),
26619
26805
  language: MotionGraphicsLanguageSchema.optional(),
26620
- queuedAt: z111.string().optional(),
26621
- jobsAhead: z111.number().int().nonnegative().optional(),
26622
- stageStartedAt: z111.string().optional(),
26623
- renderProgress: z111.number().optional(),
26806
+ queuedAt: z112.string().optional(),
26807
+ jobsAhead: z112.number().int().nonnegative().optional(),
26808
+ stageStartedAt: z112.string().optional(),
26809
+ renderProgress: z112.number().optional(),
26624
26810
  // AI clip fields (absent on a video paid before clips, or from an API
26625
26811
  // that predates them). Lenient: an unreadable value is dropped
26626
26812
  // instead of hiding the status.
26627
- clipCount: z111.number().int().nonnegative().optional().catch(void 0),
26628
- clipsUsed: z111.number().int().nonnegative().optional().catch(void 0),
26629
- clipPriceCents: z111.number().finite().nonnegative().optional().catch(void 0),
26630
- clipsRefunded: z111.number().int().nonnegative().optional().catch(void 0),
26813
+ clipCount: z112.number().int().nonnegative().optional().catch(void 0),
26814
+ clipsUsed: z112.number().int().nonnegative().optional().catch(void 0),
26815
+ clipPriceCents: z112.number().finite().nonnegative().optional().catch(void 0),
26816
+ clipsRefunded: z112.number().int().nonnegative().optional().catch(void 0),
26631
26817
  // Hook versions (absent from an API or a video before them): the
26632
26818
  // count ordered and, once done, the signed URLs of the EXTRA versions
26633
26819
  // (hook 2, hook 3); `finalMp4Url` is hook 1.
26634
- hookVariants: z111.number().int().min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).optional().catch(void 0),
26635
- variantUrls: z111.array(z111.string().min(1)).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
26820
+ hookVariants: z112.number().int().min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).optional().catch(void 0),
26821
+ variantUrls: z112.array(z112.string().min(1)).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
26636
26822
  // Extra hook versions given back, as the task recorded it once the
26637
26823
  // refunds landed (absent until then, and from an API before it).
26638
- variantsRefunded: z111.number().int().nonnegative().optional().catch(void 0),
26639
- activity: z111.array(MotionGraphicsActivitySchema).optional().catch(void 0),
26640
- previewUrl: z111.string().optional()
26824
+ variantsRefunded: z112.number().int().nonnegative().optional().catch(void 0),
26825
+ activity: z112.array(MotionGraphicsActivitySchema).optional().catch(void 0),
26826
+ previewUrl: z112.string().optional()
26641
26827
  }).passthrough()
26642
26828
  }).passthrough();
26643
26829
  function parseAnimatedVideoResult(value) {
@@ -26893,10 +27079,10 @@ function registerAnimatedVideoTools(server, api) {
26893
27079
  __name(registerAnimatedVideoTools, "registerAnimatedVideoTools");
26894
27080
 
26895
27081
  // src/tools/winning-product-image.ts
26896
- import { z as z112 } from "zod";
26897
- var WinnerReferenceInput = z112.object({
26898
- runId: z112.string().uuid(),
26899
- candidateSourceId: z112.string().trim().min(1).max(160)
27082
+ import { z as z113 } from "zod";
27083
+ var WinnerReferenceInput = z113.object({
27084
+ runId: z113.string().uuid(),
27085
+ candidateSourceId: z113.string().trim().min(1).max(160)
26900
27086
  }).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
26901
27087
  async function resolveWinnerImages(api, winnerReference, images) {
26902
27088
  if (!winnerReference) return images;
@@ -26933,62 +27119,62 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
26933
27119
  var CREATE_SERVICE_VIDEO_ON_MCP = PRODUCTMAKER_MCP_CAPABILITY_NAMES.includes("create_service_video");
26934
27120
  var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
26935
27121
  var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
26936
- var CreateProductTaskInput = z113.object({
27122
+ var CreateProductTaskInput = z114.object({
26937
27123
  images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
26938
27124
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
26939
- projectId: z113.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
26940
- productUrl: z113.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."),
27125
+ projectId: z114.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
27126
+ productUrl: z114.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."),
26941
27127
  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.'),
26942
27128
  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.'),
26943
- price: z113.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.'),
26944
- compareAtPrice: z113.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".'),
26945
- offer: z113.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.'),
26946
- paymentMethods: z113.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.'),
26947
- productContext: z113.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."),
26948
- productLabel: z113.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.'),
27129
+ price: z114.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.'),
27130
+ compareAtPrice: z114.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".'),
27131
+ offer: z114.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.'),
27132
+ paymentMethods: z114.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.'),
27133
+ productContext: z114.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."),
27134
+ productLabel: z114.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.'),
26949
27135
  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.'),
26950
27136
  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.'),
26951
- durationSeconds: z113.union([
26952
- z113.literal(15),
26953
- z113.literal(30)
27137
+ durationSeconds: z114.union([
27138
+ z114.literal(15),
27139
+ z114.literal(30)
26954
27140
  ]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
26955
- pauseForAngleReview: z113.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."),
26956
- aiDecidesAll: z113.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."),
27141
+ pauseForAngleReview: z114.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."),
27142
+ aiDecidesAll: z114.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."),
26957
27143
  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.'),
26958
27144
  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.'),
26959
27145
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
26960
27146
  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).'),
26961
- videoAngleCount: z113.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."),
27147
+ videoAngleCount: z114.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."),
26962
27148
  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.'),
26963
- outputs: z113.array(z113.enum([
27149
+ outputs: z114.array(z114.enum([
26964
27150
  "landing",
26965
27151
  "video",
26966
27152
  "image"
26967
27153
  ])).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}`),
26968
- includeInitialLandingGif: z113.boolean().optional().describe("Opcional. En nuevas landings cl\xE1sicas habilitadas, omitirlo incluye el primer GIF del producto y su coste en el total. Env\xEDa false si el usuario lo excluye: no se genera ni se reserva su coste. Conserva la elecci\xF3n al confirmar y al reintentar."),
26969
- competitorScanEnabled: z113.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."),
27154
+ includeInitialLandingGif: z114.boolean().optional().describe("Opcional. En nuevas landings cl\xE1sicas habilitadas, omitirlo incluye el primer GIF del producto y su coste en el total. Env\xEDa false si el usuario lo excluye: no se genera ni se reserva su coste. Conserva la elecci\xF3n al confirmar y al reintentar."),
27155
+ competitorScanEnabled: z114.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."),
26970
27156
  generateAiEdit: AiEditRequestSchema.optional().describe('Opcional. Pide la Edici\xF3n con IA: una pasada que a\xF1ade texto, efectos y m\xFAsica sobre cada video entregado (variante with_ai_edit; se cobra al entregar, por video). Nivel: "economy" (Econ\xF3mica, Sonnet 5.5, m\xE1s barata) o "pro" (Opus 5.5, mejor calidad, ~10 min). true equivale a "pro"; false/omitido = sin edici\xF3n.'),
26971
- replicateWinnerWhenFound: z113.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."),
26972
- brandId: z113.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."),
26973
- actorId: z113.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."),
27157
+ replicateWinnerWhenFound: z114.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."),
27158
+ brandId: z114.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."),
27159
+ actorId: z114.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."),
26974
27160
  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.'),
26975
- creativeDirection: z113.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.'),
26976
- headline: z113.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."),
26977
- subheadline: z113.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."),
27161
+ creativeDirection: z114.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.'),
27162
+ headline: z114.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."),
27163
+ subheadline: z114.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."),
26978
27164
  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".'),
26979
27165
  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".')
26980
27166
  }).strict();
26981
- var CreateServiceVideoInput = z113.object({
26982
- landingUrl: z113.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
26983
- additionalContext: z113.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
27167
+ var CreateServiceVideoInput = z114.object({
27168
+ landingUrl: z114.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
27169
+ additionalContext: z114.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
26984
27170
  language: Lang.describe("Idioma del video: es, en o pt."),
26985
- voiceId: z113.string().trim().min(1).pipe(VoiceId).optional().describe('Opcional. Voz para toda la narraci\xF3n. Usa "auto" para que la IA la alinee con el presentador. Las voces del banco compartido fueron retiradas.'),
26986
- brandId: z113.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
26987
- reviewMode: z113.enum([
27171
+ voiceId: z114.string().trim().min(1).pipe(VoiceId).optional().describe('Opcional. Voz para toda la narraci\xF3n. Usa "auto" para que la IA la alinee con el presentador. Las voces del banco compartido fueron retiradas.'),
27172
+ brandId: z114.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
27173
+ reviewMode: z114.enum([
26988
27174
  "automatic",
26989
27175
  "guided"
26990
27176
  ]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
26991
- videoPreset: z113.enum([
27177
+ videoPreset: z114.enum([
26992
27178
  "auto",
26993
27179
  "ugc_dynamic",
26994
27180
  "ugc_how_to",
@@ -26998,128 +27184,128 @@ var CreateServiceVideoInput = z113.object({
26998
27184
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
26999
27185
  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.')
27000
27186
  }).strict();
27001
- var GetTaskStatusInput = z113.object({
27002
- taskId: z113.string().min(1),
27003
- waitSeconds: z113.number().int().min(0).max(120).optional()
27187
+ var GetTaskStatusInput = z114.object({
27188
+ taskId: z114.string().min(1),
27189
+ waitSeconds: z114.number().int().min(0).max(120).optional()
27004
27190
  });
27005
- var ListTasksInput = z113.object({
27006
- limit: z113.number().int().min(1).max(50).optional(),
27007
- offset: z113.number().int().min(0).optional(),
27008
- search: z113.string().optional()
27191
+ var ListTasksInput = z114.object({
27192
+ limit: z114.number().int().min(1).max(50).optional(),
27193
+ offset: z114.number().int().min(0).optional(),
27194
+ search: z114.string().optional()
27009
27195
  });
27010
27196
  var MCP_REVIEW_LIST_FIELD_MAX = IMAGE_WIZARD_LIST_FIELD_MAX;
27011
27197
  var MCP_REVIEW_FEATURE_ITEM_MAX = IMAGE_FEATURE_ITEM_MAX;
27012
- var EditTaskDraftInput = z113.object({
27013
- taskId: z113.string().min(1),
27014
- angleIndex: z113.number().int().min(0),
27015
- angle: z113.object({
27016
- angle: z113.string().min(1).max(480),
27017
- buyerPersona: z113.string().min(1).max(360),
27018
- actor: z113.string().min(1).max(360).optional(),
27019
- actorId: z113.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."),
27020
- gender: z113.enum([
27198
+ var EditTaskDraftInput = z114.object({
27199
+ taskId: z114.string().min(1),
27200
+ angleIndex: z114.number().int().min(0),
27201
+ angle: z114.object({
27202
+ angle: z114.string().min(1).max(480),
27203
+ buyerPersona: z114.string().min(1).max(360),
27204
+ actor: z114.string().min(1).max(360).optional(),
27205
+ actorId: z114.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."),
27206
+ gender: z114.enum([
27021
27207
  "female",
27022
27208
  "male"
27023
27209
  ]).optional(),
27024
- scriptNotes: z113.string().max(2e3).optional()
27210
+ scriptNotes: z114.string().max(2e3).optional()
27025
27211
  })
27026
27212
  });
27027
- var PendingActionPayload = z113.discriminatedUnion("kind", [
27028
- z113.object({
27029
- kind: z113.literal("product_reference_set_approval"),
27213
+ var PendingActionPayload = z114.discriminatedUnion("kind", [
27214
+ z114.object({
27215
+ kind: z114.literal("product_reference_set_approval"),
27030
27216
  scope: ProductReferenceScopeEnum.optional(),
27031
- scopeKey: z113.string().min(1).max(120).optional(),
27032
- scopeSnapshotId: z113.string().uuid().optional(),
27033
- expectedScopeHash: z113.string().min(1).max(128).optional(),
27217
+ scopeKey: z114.string().min(1).max(120).optional(),
27218
+ scopeSnapshotId: z114.string().uuid().optional(),
27219
+ expectedScopeHash: z114.string().min(1).max(128).optional(),
27034
27220
  decision: ProductReferenceResolutionDecisionEnum,
27035
27221
  reason: ProductReferenceRejectionReasonEnum.optional(),
27036
- affectedRefKeys: z113.array(z113.string().min(1).max(200)).min(1).optional(),
27037
- affectedPhotoNumbers: z113.array(z113.number().int().positive()).min(1).optional(),
27038
- recoveryAction: z113.enum([
27222
+ affectedRefKeys: z114.array(z114.string().min(1).max(200)).min(1).optional(),
27223
+ affectedPhotoNumbers: z114.array(z114.number().int().positive()).min(1).optional(),
27224
+ recoveryAction: z114.enum([
27039
27225
  "remove",
27040
27226
  "replace",
27041
27227
  "upload",
27042
27228
  "return_to_selection"
27043
27229
  ]).optional()
27044
27230
  }),
27045
- z113.object({
27046
- kind: z113.literal("product_reference_confirmation"),
27047
- selectedPhotoNumbers: z113.array(z113.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."),
27231
+ z114.object({
27232
+ kind: z114.literal("product_reference_confirmation"),
27233
+ selectedPhotoNumbers: z114.array(z114.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."),
27048
27234
  userChoice: ProductReferenceUserChoiceEnum.optional(),
27049
- confirmedProductNames: z113.array(z113.string().min(1).max(120)).min(2).max(8).optional(),
27235
+ confirmedProductNames: z114.array(z114.string().min(1).max(120)).min(2).max(8).optional(),
27050
27236
  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."),
27051
27237
  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."),
27052
- useMultiSceneShowcase: z113.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
27238
+ useMultiSceneShowcase: z114.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
27053
27239
  }),
27054
- z113.object({
27055
- kind: z113.literal("angle_review_approval"),
27240
+ z114.object({
27241
+ kind: z114.literal("angle_review_approval"),
27056
27242
  // All edits are optional — empty action body just approves the
27057
27243
  // backend-generated draft as-is. Field shapes mirror the angle-review
27058
27244
  // request contracts in @packages/types/wizard.ts; the handler routes to
27059
27245
  // the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
27060
- customAngle: z113.string().min(1).max(480).optional(),
27246
+ customAngle: z114.string().min(1).max(480).optional(),
27061
27247
  // Keep the shared MCP action within the strictest downstream contract:
27062
27248
  // autopilot/image resume endpoints cap these fields at 1500 characters.
27063
- painPoints: z113.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
27064
- benefits: z113.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
27249
+ painPoints: z114.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
27250
+ benefits: z114.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
27065
27251
  // Same policy as the two fields above: the strictest downstream contract
27066
27252
  // wins. The image endpoint caps each feature at 240 while landing/video
27067
27253
  // accept 300, and this single action routes to whichever the task is — so
27068
27254
  // accepting 300 here turns a 250-character feature on an image task into
27069
27255
  // an opaque HTTP 400 after the model already believed it had been saved.
27070
- features: z113.array(z113.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
27071
- buyerPersona: z113.string().min(1).max(360).optional(),
27256
+ features: z114.array(z114.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
27257
+ buyerPersona: z114.string().min(1).max(360).optional(),
27072
27258
  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.'),
27073
- actor: z113.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."),
27074
- actorId: z113.string().max(120).nullable().optional(),
27075
- creativeDirection: z113.string().max(2e3).optional(),
27076
- selectedAngleNumbers: z113.array(z113.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."),
27077
- angleEdits: z113.array(z113.object({
27078
- angleNumber: z113.number().int().positive(),
27079
- narrativeSelection: z113.enum([
27259
+ actor: z114.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."),
27260
+ actorId: z114.string().max(120).nullable().optional(),
27261
+ creativeDirection: z114.string().max(2e3).optional(),
27262
+ selectedAngleNumbers: z114.array(z114.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."),
27263
+ angleEdits: z114.array(z114.object({
27264
+ angleNumber: z114.number().int().positive(),
27265
+ narrativeSelection: z114.enum([
27080
27266
  "market",
27081
27267
  "guided"
27082
27268
  ]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
27083
- angle: z113.string().min(1).max(480).optional(),
27084
- buyerPersona: z113.string().min(1).max(360).optional(),
27269
+ angle: z114.string().min(1).max(480).optional(),
27270
+ buyerPersona: z114.string().min(1).max(360).optional(),
27085
27271
  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.'),
27086
- actor: z113.string().min(1).max(360).optional(),
27087
- actorId: z113.string().max(120).nullable().optional(),
27088
- creativeDirection: z113.string().max(2e3).optional()
27272
+ actor: z114.string().min(1).max(360).optional(),
27273
+ actorId: z114.string().max(120).nullable().optional(),
27274
+ creativeDirection: z114.string().max(2e3).optional()
27089
27275
  }).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)."),
27090
- gapDurationSeconds: z113.union([
27091
- z113.literal(15),
27092
- z113.literal(30)
27276
+ gapDurationSeconds: z114.union([
27277
+ z114.literal(15),
27278
+ z114.literal(30)
27093
27279
  ]).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.")
27094
27280
  }),
27095
- z113.object({
27096
- kind: z113.literal("service_angle_approval"),
27097
- angleId: z113.string().uuid().optional(),
27098
- angleNumber: z113.number().int().positive().optional(),
27099
- content: z113.string().min(1).max(480).optional(),
27100
- creativeDirection: z113.string().min(1).max(1500).optional(),
27101
- actor: z113.string().min(1).max(360).optional()
27281
+ z114.object({
27282
+ kind: z114.literal("service_angle_approval"),
27283
+ angleId: z114.string().uuid().optional(),
27284
+ angleNumber: z114.number().int().positive().optional(),
27285
+ content: z114.string().min(1).max(480).optional(),
27286
+ creativeDirection: z114.string().min(1).max(1500).optional(),
27287
+ actor: z114.string().min(1).max(360).optional()
27102
27288
  }),
27103
- z113.object({
27104
- kind: z113.literal("service_script_approval"),
27105
- voiceovers: z113.record(z113.string(), z113.string().min(1).max(600)).optional(),
27106
- visualDirections: z113.record(z113.string(), z113.string().min(1).max(1200)).optional(),
27107
- voiceoversByScene: z113.record(z113.string(), z113.string().min(1).max(600)).optional(),
27108
- visualDirectionsByScene: z113.record(z113.string(), z113.string().min(1).max(1200)).optional()
27289
+ z114.object({
27290
+ kind: z114.literal("service_script_approval"),
27291
+ voiceovers: z114.record(z114.string(), z114.string().min(1).max(600)).optional(),
27292
+ visualDirections: z114.record(z114.string(), z114.string().min(1).max(1200)).optional(),
27293
+ voiceoversByScene: z114.record(z114.string(), z114.string().min(1).max(600)).optional(),
27294
+ visualDirectionsByScene: z114.record(z114.string(), z114.string().min(1).max(1200)).optional()
27109
27295
  })
27110
27296
  ]);
27111
- var ResolvePendingActionInput = z113.object({
27112
- taskId: z113.string().min(1),
27297
+ var ResolvePendingActionInput = z114.object({
27298
+ taskId: z114.string().min(1),
27113
27299
  action: PendingActionPayload
27114
27300
  }).strict();
27115
27301
  function resolveVariantConfirmVideoTier(action) {
27116
27302
  return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
27117
27303
  }
27118
27304
  __name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
27119
- var StatusForResolveSchema = z113.object({
27305
+ var StatusForResolveSchema = z114.object({
27120
27306
  // Metadata used to select the backend resume contract. Older API responses
27121
27307
  // may omit these fields, so the resolver keeps the generic fallback.
27122
- kind: z113.enum([
27308
+ kind: z114.enum([
27123
27309
  "autopilot",
27124
27310
  "video",
27125
27311
  "image",
@@ -27127,18 +27313,18 @@ var StatusForResolveSchema = z113.object({
27127
27313
  "mix",
27128
27314
  "service"
27129
27315
  ]).optional(),
27130
- selectedOutputs: z113.array(z113.enum([
27316
+ selectedOutputs: z114.array(z114.enum([
27131
27317
  "landing",
27132
27318
  "video",
27133
27319
  "image"
27134
27320
  ])).optional(),
27135
- videoAngleCount: z113.number().int().min(1).max(3).optional(),
27136
- ugcFormat: z113.enum([
27321
+ videoAngleCount: z114.number().int().min(1).max(3).optional(),
27322
+ ugcFormat: z114.enum([
27137
27323
  "single_8s",
27138
27324
  "single_15s",
27139
27325
  "double_30s"
27140
27326
  ]).optional(),
27141
- videoStyle: z113.enum([
27327
+ videoStyle: z114.enum([
27142
27328
  "ugc",
27143
27329
  "cartoon_3d",
27144
27330
  "product_only",
@@ -27148,13 +27334,13 @@ var StatusForResolveSchema = z113.object({
27148
27334
  videoQuality: VideoQualityEnum.optional(),
27149
27335
  videoRouteId: VideoRouteIdEnum.optional(),
27150
27336
  videoModel: TaskVideoModelEnum.optional(),
27151
- videoTier: z113.enum([
27337
+ videoTier: z114.enum([
27152
27338
  "legacy",
27153
27339
  "standard",
27154
27340
  "pro",
27155
27341
  "single_call"
27156
27342
  ]).optional(),
27157
- videoResolution: z113.enum([
27343
+ videoResolution: z114.enum([
27158
27344
  "480p",
27159
27345
  "720p"
27160
27346
  ]).optional(),
@@ -27162,60 +27348,60 @@ var StatusForResolveSchema = z113.object({
27162
27348
  // A task created before a narrative was blocked/hidden must still parse,
27163
27349
  // or resolve_pending_action could never approve it.
27164
27350
  narrativeStyle: NarrativeStyle.optional(),
27165
- pauseForVideoScriptReview: z113.boolean().optional(),
27166
- pendingUserAction: z113.object({
27167
- kind: z113.string(),
27168
- candidateGrouping: z113.string().optional(),
27169
- selectedImageUrls: z113.array(z113.string()).optional(),
27170
- proposedProductNames: z113.array(z113.string()).optional(),
27351
+ pauseForVideoScriptReview: z114.boolean().optional(),
27352
+ pendingUserAction: z114.object({
27353
+ kind: z114.string(),
27354
+ candidateGrouping: z114.string().optional(),
27355
+ selectedImageUrls: z114.array(z114.string()).optional(),
27356
+ proposedProductNames: z114.array(z114.string()).optional(),
27171
27357
  // Adaptive reference questions are server-owned. Echo only the evidence
27172
27358
  // identity and the choices shown by the current snapshot; never accept a
27173
27359
  // client-supplied reference set as authorization.
27174
- options: z113.array(ProductReferenceUserChoiceEnum).max(4).optional(),
27175
- mode: z113.enum([
27360
+ options: z114.array(ProductReferenceUserChoiceEnum).max(4).optional(),
27361
+ mode: z114.enum([
27176
27362
  "question",
27177
27363
  "visual_recovery"
27178
27364
  ]).optional(),
27179
27365
  /** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
27180
- canKeepSelection: z113.boolean().optional(),
27181
- decisionKey: z113.string().optional(),
27182
- questionOrdinal: z113.number().int().min(1).max(5).optional(),
27183
- questionCeiling: z113.union([
27184
- z113.literal(3),
27185
- z113.literal(5)
27366
+ canKeepSelection: z114.boolean().optional(),
27367
+ decisionKey: z114.string().optional(),
27368
+ questionOrdinal: z114.number().int().min(1).max(5).optional(),
27369
+ questionCeiling: z114.union([
27370
+ z114.literal(3),
27371
+ z114.literal(5)
27186
27372
  ]).optional(),
27187
- referenceEvidenceVersion: z113.number().int().positive().optional(),
27188
- expectedEvidenceHash: z113.string().optional(),
27189
- question: z113.object({
27190
- prompt: z113.string().min(1).max(240),
27191
- helpText: z113.string().min(1).max(300).optional(),
27192
- options: z113.array(z113.object({
27373
+ referenceEvidenceVersion: z114.number().int().positive().optional(),
27374
+ expectedEvidenceHash: z114.string().optional(),
27375
+ question: z114.object({
27376
+ prompt: z114.string().min(1).max(240),
27377
+ helpText: z114.string().min(1).max(300).optional(),
27378
+ options: z114.array(z114.object({
27193
27379
  value: ProductReferenceUserChoiceEnum,
27194
- label: z113.string().min(1).max(120),
27195
- description: z113.string().min(1).max(240).optional()
27380
+ label: z114.string().min(1).max(120),
27381
+ description: z114.string().min(1).max(240).optional()
27196
27382
  })).min(2).max(4)
27197
27383
  }).optional(),
27198
27384
  scope: ProductReferenceScopeEnum.optional(),
27199
- scopeKey: z113.string().optional(),
27200
- scopeSnapshotId: z113.string().uuid().optional(),
27201
- scopeHash: z113.string().optional(),
27202
- baseReferenceSetHash: z113.string().optional(),
27203
- phase: z113.enum([
27385
+ scopeKey: z114.string().optional(),
27386
+ scopeSnapshotId: z114.string().uuid().optional(),
27387
+ scopeHash: z114.string().optional(),
27388
+ baseReferenceSetHash: z114.string().optional(),
27389
+ phase: z114.enum([
27204
27390
  "preparation",
27205
27391
  "final"
27206
27392
  ]).optional(),
27207
- selectedRefKeys: z113.array(z113.string().min(1).max(200)).optional(),
27208
- allowedDecisions: z113.array(ProductReferenceResolutionDecisionEnum).optional(),
27209
- previews: z113.array(z113.object({
27210
- refKey: z113.string().min(1).max(200)
27393
+ selectedRefKeys: z114.array(z114.string().min(1).max(200)).optional(),
27394
+ allowedDecisions: z114.array(ProductReferenceResolutionDecisionEnum).optional(),
27395
+ previews: z114.array(z114.object({
27396
+ refKey: z114.string().min(1).max(200)
27211
27397
  }).passthrough()).optional(),
27212
- customAngleDraft: z113.string().optional(),
27213
- painPointsDraft: z113.string().optional(),
27214
- benefitsDraft: z113.string().optional(),
27215
- featuresDraft: z113.array(z113.string()).optional(),
27216
- angleOptions: z113.array(z113.object({
27217
- index: z113.number().int().nonnegative(),
27218
- angle: z113.string().min(1)
27398
+ customAngleDraft: z114.string().optional(),
27399
+ painPointsDraft: z114.string().optional(),
27400
+ benefitsDraft: z114.string().optional(),
27401
+ featuresDraft: z114.array(z114.string()).optional(),
27402
+ angleOptions: z114.array(z114.object({
27403
+ index: z114.number().int().nonnegative(),
27404
+ angle: z114.string().min(1)
27219
27405
  }).passthrough()).min(1).max(5).optional(),
27220
27406
  // Recommendation consumed only when the caller explicitly sends
27221
27407
  // gapDurationSeconds: 30 in the angle approval action.
@@ -27225,17 +27411,17 @@ var StatusForResolveSchema = z113.object({
27225
27411
  // keys. `actorId` (the saved custom actor the picker stored) was silently
27226
27412
  // dropped here, so the approval handler below could not echo it back on the
27227
27413
  // PATCH — the selection looked accepted and reached no render.
27228
- angles: z113.array(z113.object({
27229
- id: z113.string().uuid(),
27230
- content: z113.string(),
27231
- creativeDirection: z113.string(),
27232
- actor: z113.string(),
27233
- actorId: z113.string().nullable().optional()
27414
+ angles: z114.array(z114.object({
27415
+ id: z114.string().uuid(),
27416
+ content: z114.string(),
27417
+ creativeDirection: z114.string(),
27418
+ actor: z114.string(),
27419
+ actorId: z114.string().nullable().optional()
27234
27420
  }).passthrough()).optional(),
27235
- panels: z113.array(z113.object({
27236
- beatId: z113.string(),
27237
- voiceover: z113.string(),
27238
- visualDirection: z113.string()
27421
+ panels: z114.array(z114.object({
27422
+ beatId: z114.string(),
27423
+ voiceover: z114.string(),
27424
+ visualDirection: z114.string()
27239
27425
  }).passthrough()).optional()
27240
27426
  }).optional()
27241
27427
  }).passthrough();
@@ -27587,8 +27773,8 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
27587
27773
  server.registerTool("verify_landing_commerce", {
27588
27774
  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.",
27589
27775
  inputSchema: {
27590
- taskId: z113.string().uuid(),
27591
- editId: z113.string().uuid()
27776
+ taskId: z114.string().uuid(),
27777
+ editId: z114.string().uuid()
27592
27778
  },
27593
27779
  annotations: OVERWRITES_EXTERNAL
27594
27780
  }, async (input) => {
@@ -28234,25 +28420,25 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
28234
28420
  __name(registerTaskTools, "registerTaskTools");
28235
28421
 
28236
28422
  // src/tools/brands.ts
28237
- import { z as z114 } from "zod";
28423
+ import { z as z115 } from "zod";
28238
28424
  var guidance2 = getProductMakerCapabilityModelGuidance("create_brand");
28239
28425
  var BRAND_START_REPLAY_WINDOW_MS = 15 * 60 * 1e3;
28240
28426
  var BRAND_NOTES_MAX_CHARS = 2e4;
28241
- var CreateBrandInput = z114.object({
28242
- action: z114.enum([
28427
+ var CreateBrandInput = z115.object({
28428
+ action: z115.enum([
28243
28429
  "start",
28244
28430
  "status",
28245
28431
  "list"
28246
28432
  ]).default("start").describe("start cotiza (sin confirmed) o inicia (confirmed=true) el an\xE1lisis; status consulta brandId hasta ready o failed; list muestra las marcas que el usuario ya tiene."),
28247
- sourceUrl: z114.string().trim().min(1).max(500).optional().describe("Instagram, Facebook, TikTok o web p\xFAblica del negocio, como la dio el usuario (\xAB@sanlucasbarberia\xBB, \xABinstagram.com/sanlucasbarberia\xBB, \xABmibarberia.com\xBB). Obligatorio para start."),
28248
- businessNotes: z114.string().trim().max(BRAND_NOTES_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cuente de su negocio en el chat (servicios y precios, WhatsApp, ciudad o zona, horarios). Se guarda como documento del negocio y llega tal cual a la marca y a su landing. Copia sus palabras; no inventes datos."),
28249
- language: z114.enum([
28433
+ sourceUrl: z115.string().trim().min(1).max(500).optional().describe("Instagram, Facebook, TikTok o web p\xFAblica del negocio, como la dio el usuario (\xAB@sanlucasbarberia\xBB, \xABinstagram.com/sanlucasbarberia\xBB, \xABmibarberia.com\xBB). Obligatorio para start."),
28434
+ businessNotes: z115.string().trim().max(BRAND_NOTES_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cuente de su negocio en el chat (servicios y precios, WhatsApp, ciudad o zona, horarios). Se guarda como documento del negocio y llega tal cual a la marca y a su landing. Copia sus palabras; no inventes datos."),
28435
+ language: z115.enum([
28250
28436
  "es",
28251
28437
  "en",
28252
28438
  "pt"
28253
28439
  ]).optional().describe("Idioma de la conversaci\xF3n. Solo se usa si la p\xE1gina del negocio no deja claro su idioma."),
28254
- confirmed: z114.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, start solo cotiza y no cobra."),
28255
- brandId: z114.string().uuid().optional().describe("ID de la marca. Obligatorio para status; no lo inventes.")
28440
+ confirmed: z115.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, start solo cotiza y no cobra."),
28441
+ brandId: z115.string().uuid().optional().describe("ID de la marca. Obligatorio para status; no lo inventes.")
28256
28442
  }).strict();
28257
28443
  function normalizeBrandSourceUrl(raw) {
28258
28444
  const value = raw.trim();
@@ -28492,24 +28678,24 @@ __name(registerBrandTools, "registerBrandTools");
28492
28678
 
28493
28679
  // src/tools/service-landing.ts
28494
28680
  import { createHash as createHash4 } from "crypto";
28495
- import { z as z115 } from "zod";
28681
+ import { z as z116 } from "zod";
28496
28682
  var guidance3 = getProductMakerCapabilityModelGuidance("create_service_landing");
28497
28683
  var SERVICE_LANDING_KEY_NAMESPACE = "6f1d8c2a-3b4e-5f60-8a7b-9c0d1e2f3a4b";
28498
28684
  var SERVICE_LANDING_INFO_MAX_CHARS = 2e4;
28499
- var CreateServiceLandingInput = z115.object({
28500
- action: z115.enum([
28685
+ var CreateServiceLandingInput = z116.object({
28686
+ action: z116.enum([
28501
28687
  "prepare",
28502
28688
  "build",
28503
28689
  "status",
28504
28690
  "publish"
28505
28691
  ]).default("prepare").describe("prepare (gratis) crea o retoma la landing de la marca y da el precio; build (pagado, confirmed=true) lee los datos del negocio y luego crea la p\xE1gina; status sigue el avance; publish la publica y devuelve su enlace."),
28506
- brandId: z115.string().uuid().optional().describe("ID de la marca (de create_brand). Obligatorio para prepare. Nunca un taskId de producto."),
28507
- servicePageId: z115.string().uuid().optional().describe("ID de la landing que devolvi\xF3 prepare. Obligatorio para build, status y publish."),
28508
- businessInfo: z115.string().trim().max(SERVICE_LANDING_INFO_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cont\xF3 del negocio y no estaba en su marca: servicios y precios, WhatsApp o tel\xE9fono, ciudad o zona, horarios. Copia sus palabras; no inventes datos."),
28509
- confirmed: z115.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio total y que el usuario acepte. Obligatorio para build."),
28510
- maxCredits: z115.number().int().positive().optional().describe("El total en cr\xE9ditos que el usuario acept\xF3 (el que devolvi\xF3 prepare). Obligatorio para build: ninguna etapa se inicia si su precio supera este total."),
28511
- operationId: z115.string().uuid().optional().describe("Opcional en status: la operaci\xF3n que devolvi\xF3 build."),
28512
- slug: z115.string().trim().toLowerCase().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).max(64).optional().describe("Opcional en publish: la direcci\xF3n corta de la p\xE1gina (ej. sanlucas-barberia). Si falta se usa la sugerida desde el nombre del negocio.")
28692
+ brandId: z116.string().uuid().optional().describe("ID de la marca (de create_brand). Obligatorio para prepare. Nunca un taskId de producto."),
28693
+ servicePageId: z116.string().uuid().optional().describe("ID de la landing que devolvi\xF3 prepare. Obligatorio para build, status y publish."),
28694
+ businessInfo: z116.string().trim().max(SERVICE_LANDING_INFO_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cont\xF3 del negocio y no estaba en su marca: servicios y precios, WhatsApp o tel\xE9fono, ciudad o zona, horarios. Copia sus palabras; no inventes datos."),
28695
+ confirmed: z116.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio total y que el usuario acepte. Obligatorio para build."),
28696
+ maxCredits: z116.number().int().positive().optional().describe("El total en cr\xE9ditos que el usuario acept\xF3 (el que devolvi\xF3 prepare). Obligatorio para build: ninguna etapa se inicia si su precio supera este total."),
28697
+ operationId: z116.string().uuid().optional().describe("Opcional en status: la operaci\xF3n que devolvi\xF3 build."),
28698
+ slug: z116.string().trim().toLowerCase().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).max(64).optional().describe("Opcional en publish: la direcci\xF3n corta de la p\xE1gina (ej. sanlucas-barberia). Si falta se usa la sugerida desde el nombre del negocio.")
28513
28699
  }).strict();
28514
28700
  var SERVICE_LANDING_MAX_BUILD_ATTEMPTS = 10;
28515
28701
  function serviceKey(...parts) {
@@ -28731,9 +28917,6 @@ function registerServiceLandingTools(server, api) {
28731
28917
  let operation2 = null;
28732
28918
  if (input.operationId) {
28733
28919
  operation2 = await api.getJson(`/v1/service-pages/operations/${encodeURIComponent(input.operationId)}`);
28734
- if (operation2.recoverable && (operation2.status === "failed" || operation2.status === "requires_reconciliation")) {
28735
- operation2 = await api.postJson(`${pagePath(input.servicePageId)}/operations/${encodeURIComponent(operation2.opId)}/recover`, {});
28736
- }
28737
28920
  if (operation2.status === "queued" || operation2.status === "running") {
28738
28921
  return asText({
28739
28922
  servicePageId: input.servicePageId,
@@ -28750,7 +28933,7 @@ function registerServiceLandingTools(server, api) {
28750
28933
  status: "in_review",
28751
28934
  // Unknown on purpose: the charge is exactly what is being
28752
28935
  // confirmed. Settlement only charges a completed step.
28753
- nextAction: "Esta etapa qued\xF3 en revisi\xF3n por un problema temporal: estamos confirmando si se complet\xF3. Si no se complet\xF3, no se cobra. Dile al usuario que sus datos est\xE1n guardados; vuelve a llamar action=status con el mismo operationId en unos minutos (si no se complet\xF3, pasa a fallida y la reintentas con build). No inicies otra etapa mientras tanto."
28936
+ nextAction: "Esta etapa qued\xF3 en revisi\xF3n por un problema temporal: el servidor est\xE1 confirmando si se complet\xF3 y la resuelve solo. Si no se completa, se devuelve lo cobrado. Dile al usuario que sus datos est\xE1n guardados; vuelve a llamar action=status con el mismo operationId en unos minutos (si no se complet\xF3, pasa a fallida y la reintentas con build). No inicies otra etapa mientras tanto."
28754
28937
  });
28755
28938
  }
28756
28939
  if (operation2.status !== "succeeded") {
@@ -28845,7 +29028,7 @@ function registerServiceLandingTools(server, api) {
28845
29028
  __name(registerServiceLandingTools, "registerServiceLandingTools");
28846
29029
 
28847
29030
  // src/tools/service-images.ts
28848
- import { z as z116 } from "zod";
29031
+ import { z as z117 } from "zod";
28849
29032
  var guidance4 = getProductMakerCapabilityModelGuidance("create_service_images");
28850
29033
  var SERVICE_IMAGE_FORMATS = [
28851
29034
  "4:5",
@@ -28858,23 +29041,23 @@ var LANGUAGE_TAGS = {
28858
29041
  en: "en-US",
28859
29042
  pt: "pt-BR"
28860
29043
  };
28861
- var CreateServiceImagesInput = z116.object({
28862
- brandId: z116.string().uuid().optional().describe("ID de la marca (de create_brand). Recomendado: da nombre, colores, tono y servicios. Nunca un taskId de producto."),
28863
- instruction: z116.string().trim().max(4e3).optional().describe("Qu\xE9 servicio o promoci\xF3n mostrar, con las palabras del usuario (ej. \xABcorte + barba a $35.000 los martes\xBB). Si el usuario deja que la IA decida, om\xEDtelo y usa delegateToAi=true."),
28864
- delegateToAi: z116.boolean().optional().describe("true si el usuario prefiere que la IA elija qu\xE9 mostrar a partir de su marca."),
28865
- format: z116.enum(SERVICE_IMAGE_FORMATS).optional().describe('Formato: "4:5" (feed, por defecto), "9:16" (historias/reels) o "1:1" (cuadrado).'),
28866
- count: z116.number().int().min(1).max(SERVICE_IMAGE_MAX_COUNT).optional().describe("Cu\xE1ntas im\xE1genes, de 1 a 3 (por defecto 1)."),
28867
- quality: z116.enum([
29044
+ var CreateServiceImagesInput = z117.object({
29045
+ brandId: z117.string().uuid().optional().describe("ID de la marca (de create_brand). Recomendado: da nombre, colores, tono y servicios. Nunca un taskId de producto."),
29046
+ instruction: z117.string().trim().max(4e3).optional().describe("Qu\xE9 servicio o promoci\xF3n mostrar, con las palabras del usuario (ej. \xABcorte + barba a $35.000 los martes\xBB). Si el usuario deja que la IA decida, om\xEDtelo y usa delegateToAi=true."),
29047
+ delegateToAi: z117.boolean().optional().describe("true si el usuario prefiere que la IA elija qu\xE9 mostrar a partir de su marca."),
29048
+ format: z117.enum(SERVICE_IMAGE_FORMATS).optional().describe('Formato: "4:5" (feed, por defecto), "9:16" (historias/reels) o "1:1" (cuadrado).'),
29049
+ count: z117.number().int().min(1).max(SERVICE_IMAGE_MAX_COUNT).optional().describe("Cu\xE1ntas im\xE1genes, de 1 a 3 (por defecto 1)."),
29050
+ quality: z117.enum([
28868
29051
  "standard",
28869
29052
  "high"
28870
29053
  ]).optional().describe('Calidad: "standard" (por defecto) o "high" (m\xE1s cara; no disponible en 4:5).'),
28871
- language: z116.enum([
29054
+ language: z117.enum([
28872
29055
  "es",
28873
29056
  "en",
28874
29057
  "pt"
28875
29058
  ]).optional().describe("Idioma de los textos de la imagen (por defecto es)."),
28876
- adCopy: z116.boolean().optional().describe("Opcional. true agrega textos para el anuncio (titular y descripci\xF3n). Por defecto false."),
28877
- confirmed: z116.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, solo cotiza y no cobra.")
29059
+ adCopy: z117.boolean().optional().describe("Opcional. true agrega textos para el anuncio (titular y descripci\xF3n). Por defecto false."),
29060
+ confirmed: z117.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, solo cotiza y no cobra.")
28878
29061
  }).strict();
28879
29062
  function serviceImageModel(quality) {
28880
29063
  return quality === "high" ? AD_CREATIVE_MODELS.PREMIUM : AD_CREATIVE_MODELS.STANDARD;
@@ -28985,7 +29168,7 @@ function registerServiceImageTools(server, api, options = {}) {
28985
29168
  nextAction: "Dile al usuario que est\xE1s creando sus im\xE1genes. Llama get_task_status con este taskId (waitSeconds=45) hasta done (trae las im\xE1genes) o error."
28986
29169
  });
28987
29170
  } catch (error) {
28988
- if (error instanceof z116.ZodError) throw invalidInputFromZod(error);
29171
+ if (error instanceof z117.ZodError) throw invalidInputFromZod(error);
28989
29172
  throw translateError(error);
28990
29173
  }
28991
29174
  });
@@ -28993,7 +29176,7 @@ function registerServiceImageTools(server, api, options = {}) {
28993
29176
  __name(registerServiceImageTools, "registerServiceImageTools");
28994
29177
 
28995
29178
  // src/tools/creatives.ts
28996
- import { z as z117 } from "zod";
29179
+ import { z as z118 } from "zod";
28997
29180
  var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
28998
29181
  var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
28999
29182
  var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
@@ -29004,72 +29187,72 @@ var CreativeRefs = {
29004
29187
  images: ImagesInput,
29005
29188
  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.'),
29006
29189
  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.'),
29007
- price: z117.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.'),
29008
- offer: z117.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.'),
29009
- compareAtPrice: z117.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
29010
- productContext: z117.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."),
29011
- productLabel: z117.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.'),
29012
- buyerPersona: z117.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.'),
29013
- isCombo: z117.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
29014
- competitorScanEnabled: z117.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."),
29015
- brandId: z117.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.")
29190
+ price: z118.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.'),
29191
+ offer: z118.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.'),
29192
+ compareAtPrice: z118.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
29193
+ productContext: z118.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."),
29194
+ productLabel: z118.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.'),
29195
+ buyerPersona: z118.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.'),
29196
+ isCombo: z118.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
29197
+ competitorScanEnabled: z118.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."),
29198
+ brandId: z118.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.")
29016
29199
  };
29017
- var VideoPresenter = z117.discriminatedUnion("mode", [
29018
- z117.object({
29019
- mode: z117.literal("none")
29200
+ var VideoPresenter = z118.discriminatedUnion("mode", [
29201
+ z118.object({
29202
+ mode: z118.literal("none")
29020
29203
  }).strict(),
29021
- z117.object({
29022
- mode: z117.literal("saved_actor"),
29023
- actorId: z117.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
29204
+ z118.object({
29205
+ mode: z118.literal("saved_actor"),
29206
+ actorId: z118.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
29024
29207
  }).strict(),
29025
- z117.object({
29026
- mode: z117.literal("described"),
29027
- description: z117.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
29208
+ z118.object({
29209
+ mode: z118.literal("described"),
29210
+ description: z118.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
29028
29211
  }).strict()
29029
29212
  ]);
29030
- var VideoCreativeSetup = z117.discriminatedUnion("mode", [
29031
- z117.object({
29032
- mode: z117.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
29213
+ var VideoCreativeSetup = z118.discriminatedUnion("mode", [
29214
+ z118.object({
29215
+ mode: z118.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
29033
29216
  }).strict(),
29034
- z117.object({
29035
- mode: z117.literal("guided"),
29217
+ z118.object({
29218
+ mode: z118.literal("guided"),
29036
29219
  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.'),
29037
- buyerPersona: z117.string().trim().min(1).max(360),
29220
+ buyerPersona: z118.string().trim().min(1).max(360),
29038
29221
  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.'),
29039
29222
  presenter: VideoPresenter,
29040
- creativeDirection: z117.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
29223
+ creativeDirection: z118.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
29041
29224
  }).strict()
29042
29225
  ]);
29043
- var VideoInput = z117.object({
29226
+ var VideoInput = z118.object({
29044
29227
  images: CreativeRefs.images.optional(),
29045
29228
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
29046
- title: z117.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
29047
- primaryAngle: z117.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".'),
29229
+ title: z118.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
29230
+ primaryAngle: z118.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".'),
29048
29231
  language: CreativeRefs.language,
29049
29232
  country: CreativeRefs.country,
29050
- aspectRatio: z117.enum([
29233
+ aspectRatio: z118.enum([
29051
29234
  "9:16",
29052
29235
  "16:9",
29053
29236
  "Auto"
29054
29237
  ]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
29055
29238
  generateAiEdit: AiEditRequestSchema.optional().describe('Opcional. Pide la Edici\xF3n con IA: una pasada que a\xF1ade texto, efectos y m\xFAsica sobre cada video entregado (variante with_ai_edit; se cobra al entregar, por video). Nivel: "economy" (Econ\xF3mica, Sonnet 5.5, m\xE1s barata) o "pro" (Opus 5.5, mejor calidad, ~10 min). true equivale a "pro"; false/omitido = sin edici\xF3n.'),
29056
- durationSeconds: z117.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."),
29057
- videoAngleCount: z117.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."),
29239
+ durationSeconds: z118.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."),
29240
+ videoAngleCount: z118.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."),
29058
29241
  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.'),
29059
29242
  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."),
29060
29243
  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.'),
29061
29244
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
29062
29245
  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.'),
29063
- features: z117.array(z117.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
29246
+ features: z118.array(z118.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
29064
29247
  price: CreativeRefs.price,
29065
29248
  offer: CreativeRefs.offer,
29066
29249
  productContext: CreativeRefs.productContext,
29067
29250
  productLabel: CreativeRefs.productLabel,
29068
- cta: z117.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.'),
29069
- scriptNotes: z117.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.'),
29251
+ cta: z118.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.'),
29252
+ scriptNotes: z118.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.'),
29070
29253
  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.'),
29071
29254
  competitorScanEnabled: CreativeRefs.competitorScanEnabled,
29072
- replicateWinnerWhenFound: z117.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."),
29255
+ replicateWinnerWhenFound: z118.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."),
29073
29256
  brandId: CreativeRefs.brandId
29074
29257
  }).strict();
29075
29258
  var FreeVideoQualityEnum = VideoQualityEnum;
@@ -29087,7 +29270,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
29087
29270
  length: 29
29088
29271
  }, (_, index) => index + 2)
29089
29272
  };
29090
- var FreeVideoModelIdEnum = z117.enum([
29273
+ var FreeVideoModelIdEnum = z118.enum([
29091
29274
  "grok-imagine-video-1-5-preview",
29092
29275
  "minimax-h3/reference-to-video",
29093
29276
  "wan/3-0-video",
@@ -29098,66 +29281,66 @@ var FREE_SELECTABLE_MODEL_IDS = [
29098
29281
  "minimax-h3/reference-to-video",
29099
29282
  "wan/3-0-video"
29100
29283
  ];
29101
- var FreeVideoInput = z117.object({
29284
+ var FreeVideoInput = z118.object({
29102
29285
  images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
29103
- rawPrompt: z117.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."),
29286
+ rawPrompt: z118.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."),
29104
29287
  language: CreativeRefs.language,
29105
29288
  quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
29106
29289
  // Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
29107
29290
  // parsed ONLY so the handler can reject it with a message naming its
29108
29291
  // replacement — dropping it silently would turn a caller's explicit
29109
29292
  // Pro++ pick into a quiet fallback to Wan.
29110
- freeProModel: z117.enum([
29293
+ freeProModel: z118.enum([
29111
29294
  "wan",
29112
29295
  "seedance"
29113
29296
  ]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
29114
29297
  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.'),
29115
- durationSeconds: z117.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."),
29298
+ durationSeconds: z118.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."),
29116
29299
  videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
29117
- generateAiMusic: z117.boolean().default(false).describe('Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false. Equivale a generateAiEdit (nivel "pro"): la Edici\xF3n con IA trae su propia m\xFAsica.'),
29300
+ generateAiMusic: z118.boolean().default(false).describe('Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false. Equivale a generateAiEdit (nivel "pro"): la Edici\xF3n con IA trae su propia m\xFAsica.'),
29118
29301
  generateAiEdit: AiEditRequestSchema.optional().describe('Opcional. Pide la Edici\xF3n con IA: una pasada que a\xF1ade texto, gr\xE1ficos y m\xFAsica sobre el video ya entregado (variante with_ai_edit; se cobra al entregar). Nivel: "economy" (Econ\xF3mica, Sonnet 5.5, m\xE1s barata) o "pro" (Opus 5.5, mejor calidad, ~10 min). true equivale a "pro". Default sin edici\xF3n.'),
29119
- addSubtitles: z117.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
29120
- idempotencyKey: z117.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.")
29302
+ addSubtitles: z118.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
29303
+ idempotencyKey: z118.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.")
29121
29304
  }).strict();
29122
29305
  var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
29123
- var ImageCreativeSetup = z117.discriminatedUnion("mode", [
29124
- z117.object({
29125
- mode: z117.literal("automatic")
29306
+ var ImageCreativeSetup = z118.discriminatedUnion("mode", [
29307
+ z118.object({
29308
+ mode: z118.literal("automatic")
29126
29309
  }).strict(),
29127
- z117.object({
29128
- mode: z117.literal("guided"),
29129
- creativeArchetype: z117.union([
29310
+ z118.object({
29311
+ mode: z118.literal("guided"),
29312
+ creativeArchetype: z118.union([
29130
29313
  ImageCreativeArchetypeEnum,
29131
- z117.literal("ai_decides")
29314
+ z118.literal("ai_decides")
29132
29315
  ]),
29133
- visualTreatment: z117.union([
29316
+ visualTreatment: z118.union([
29134
29317
  ImageCreativeVisualTreatmentEnum,
29135
- z117.literal("ai_decides")
29318
+ z118.literal("ai_decides")
29136
29319
  ]),
29137
29320
  aspectRatio: ImageCreativeAspectRatioEnum,
29138
- nVariants: z117.union([
29139
- z117.literal(1),
29140
- z117.literal(2),
29141
- z117.literal(3),
29142
- z117.literal(4),
29143
- z117.literal(6)
29321
+ nVariants: z118.union([
29322
+ z118.literal(1),
29323
+ z118.literal(2),
29324
+ z118.literal(3),
29325
+ z118.literal(4),
29326
+ z118.literal(6)
29144
29327
  ]),
29145
- imageModel: z117.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.'),
29146
- styleMix: z117.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
29147
- generateAdCopy: z117.boolean(),
29148
- competitorScanEnabled: z117.boolean(),
29149
- productContext: z117.string().trim().min(1).max(3e3).nullable(),
29150
- creativeDirection: z117.string().trim().min(1).max(500).nullable(),
29151
- brandColors: z117.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.'),
29152
- headline: z117.string().trim().min(1).max(120).nullable(),
29153
- subheadline: z117.string().trim().min(1).max(160).nullable()
29328
+ imageModel: z118.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.'),
29329
+ styleMix: z118.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
29330
+ generateAdCopy: z118.boolean(),
29331
+ competitorScanEnabled: z118.boolean(),
29332
+ productContext: z118.string().trim().min(1).max(3e3).nullable(),
29333
+ creativeDirection: z118.string().trim().min(1).max(500).nullable(),
29334
+ brandColors: z118.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.'),
29335
+ headline: z118.string().trim().min(1).max(120).nullable(),
29336
+ subheadline: z118.string().trim().min(1).max(160).nullable()
29154
29337
  }).strict()
29155
29338
  ]).superRefine((setup, context) => {
29156
29339
  if (setup.mode !== "guided") return;
29157
29340
  const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
29158
29341
  if (needsStyleMix && setup.styleMix === null) {
29159
29342
  context.addIssue({
29160
- code: z117.ZodIssueCode.custom,
29343
+ code: z118.ZodIssueCode.custom,
29161
29344
  path: [
29162
29345
  "styleMix"
29163
29346
  ],
@@ -29166,7 +29349,7 @@ var ImageCreativeSetup = z117.discriminatedUnion("mode", [
29166
29349
  }
29167
29350
  if (!needsStyleMix && setup.styleMix !== null) {
29168
29351
  context.addIssue({
29169
- code: z117.ZodIssueCode.custom,
29352
+ code: z118.ZodIssueCode.custom,
29170
29353
  path: [
29171
29354
  "styleMix"
29172
29355
  ],
@@ -29175,7 +29358,7 @@ var ImageCreativeSetup = z117.discriminatedUnion("mode", [
29175
29358
  }
29176
29359
  if (imageResolutionOf(setup.imageModel) === "2k" && setup.aspectRatio === "4:5") {
29177
29360
  context.addIssue({
29178
- code: z117.ZodIssueCode.custom,
29361
+ code: z118.ZodIssueCode.custom,
29179
29362
  path: [
29180
29363
  "aspectRatio"
29181
29364
  ],
@@ -29183,55 +29366,55 @@ var ImageCreativeSetup = z117.discriminatedUnion("mode", [
29183
29366
  });
29184
29367
  }
29185
29368
  });
29186
- var LandingCreativeSetup = z117.discriminatedUnion("mode", [
29187
- z117.object({
29188
- mode: z117.literal("automatic")
29369
+ var LandingCreativeSetup = z118.discriminatedUnion("mode", [
29370
+ z118.object({
29371
+ mode: z118.literal("automatic")
29189
29372
  }).strict(),
29190
- z117.object({
29191
- mode: z117.literal("guided"),
29373
+ z118.object({
29374
+ mode: z118.literal("guided"),
29192
29375
  landingStrategy: LandingStrategyEnum,
29193
29376
  landingImageFormat: LandingImageFormatEnum,
29194
- competitorScanEnabled: z117.boolean(),
29195
- paymentMethods: z117.string().trim().min(1).max(240).nullable(),
29196
- productContext: z117.string().trim().min(1).max(3e3).nullable(),
29197
- creativeDirection: z117.string().trim().min(1).max(500).nullable(),
29198
- headline: z117.string().trim().min(1).max(120).nullable(),
29199
- subheadline: z117.string().trim().min(1).max(160).nullable()
29377
+ competitorScanEnabled: z118.boolean(),
29378
+ paymentMethods: z118.string().trim().min(1).max(240).nullable(),
29379
+ productContext: z118.string().trim().min(1).max(3e3).nullable(),
29380
+ creativeDirection: z118.string().trim().min(1).max(500).nullable(),
29381
+ headline: z118.string().trim().min(1).max(120).nullable(),
29382
+ subheadline: z118.string().trim().min(1).max(160).nullable()
29200
29383
  }).strict()
29201
29384
  ]);
29202
- var ImageInput = z117.object({
29385
+ var ImageInput = z118.object({
29203
29386
  images: CreativeRefs.images.optional(),
29204
29387
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
29205
- productTitle: z117.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
29206
- primaryAngle: z117.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.'),
29388
+ productTitle: z118.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
29389
+ primaryAngle: z118.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.'),
29207
29390
  buyerPersona: CreativeRefs.buyerPersona,
29208
29391
  language: CreativeRefs.language,
29209
29392
  country: CreativeRefs.country,
29210
29393
  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."),
29211
29394
  imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
29212
- features: z117.array(z117.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
29395
+ features: z118.array(z118.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
29213
29396
  price: CreativeRefs.price,
29214
- omitPrice: z117.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."),
29397
+ omitPrice: z118.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."),
29215
29398
  compareAtPrice: CreativeRefs.compareAtPrice,
29216
29399
  offer: CreativeRefs.offer,
29217
29400
  productLabel: CreativeRefs.productLabel,
29218
29401
  isCombo: CreativeRefs.isCombo,
29219
29402
  brandId: CreativeRefs.brandId
29220
29403
  });
29221
- var EditImageCreativeInput = z117.object({
29222
- taskId: z117.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
29223
- variantIndex: z117.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
29224
- clientRequestId: z117.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."),
29225
- instruction: z117.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".')
29404
+ var EditImageCreativeInput = z118.object({
29405
+ taskId: z118.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
29406
+ variantIndex: z118.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
29407
+ clientRequestId: z118.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."),
29408
+ instruction: z118.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".')
29226
29409
  });
29227
- var LandingInput = z117.object({
29228
- includeInitialLandingGif: z117.boolean().optional().describe("Opcional. En nuevas landings cl\xE1sicas habilitadas, omitirlo incluye el primer GIF del producto y su coste en el total. Env\xEDa false si el usuario lo excluye: no se genera ni se reserva su coste. Conserva la elecci\xF3n al confirmar y al reintentar."),
29410
+ var LandingInput = z118.object({
29411
+ includeInitialLandingGif: z118.boolean().optional().describe("Opcional. En nuevas landings cl\xE1sicas habilitadas, omitirlo incluye el primer GIF del producto y su coste en el total. Env\xEDa false si el usuario lo excluye: no se genera ni se reserva su coste. Conserva la elecci\xF3n al confirmar y al reintentar."),
29229
29412
  images: CreativeRefs.images.optional(),
29230
29413
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
29231
29414
  language: CreativeRefs.language,
29232
29415
  country: CreativeRefs.country,
29233
29416
  creativeSetup: LandingCreativeSetup.describe("Configuraci\xF3n obligatoria de landing cl\xE1sica equivalente al wizard web. No expone landing editable/code mientras siga siendo admin-only."),
29234
- salesAngle: z117.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.'),
29417
+ salesAngle: z118.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.'),
29235
29418
  buyerPersona: CreativeRefs.buyerPersona,
29236
29419
  price: CreativeRefs.price,
29237
29420
  compareAtPrice: CreativeRefs.compareAtPrice,
@@ -29513,8 +29696,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
29513
29696
  server.registerTool("get_image_edit_status", {
29514
29697
  description: imageEditStatusGuidance.summary,
29515
29698
  inputSchema: {
29516
- taskId: z117.string().uuid(),
29517
- operationId: z117.string().uuid()
29699
+ taskId: z118.string().uuid(),
29700
+ operationId: z118.string().uuid()
29518
29701
  },
29519
29702
  annotations: READS_INTERNAL
29520
29703
  }, async (input) => {
@@ -29571,10 +29754,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
29571
29754
  __name(registerCreativeTools, "registerCreativeTools");
29572
29755
 
29573
29756
  // src/tools/creative-variants.ts
29574
- import { z as z118 } from "zod";
29757
+ import { z as z119 } from "zod";
29575
29758
  var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
29576
29759
  var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
29577
- var LandingSectionKeyEnum = z118.enum([
29760
+ var LandingSectionKeyEnum = z119.enum([
29578
29761
  "problem_hook",
29579
29762
  "problem_cost",
29580
29763
  "solution_mechanism",
@@ -29614,24 +29797,24 @@ var LandingSectionKeyEnum = z118.enum([
29614
29797
  "lifestyle_fit",
29615
29798
  "join_lifestyle"
29616
29799
  ]);
29617
- var CreativeVariantKindEnum = z118.enum([
29800
+ var CreativeVariantKindEnum = z119.enum([
29618
29801
  "video",
29619
29802
  "image",
29620
29803
  "landing"
29621
29804
  ]);
29622
- var EstimateCreativeVariantInputBase = z118.object({
29623
- sourceTaskId: z118.string().uuid().describe("ID de la tarea original completada."),
29805
+ var EstimateCreativeVariantInputBase = z119.object({
29806
+ sourceTaskId: z119.string().uuid().describe("ID de la tarea original completada."),
29624
29807
  kind: CreativeVariantKindEnum,
29625
29808
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
29626
29809
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
29627
- nVariants: z118.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
29810
+ nVariants: z119.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
29628
29811
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
29629
- instructions: z118.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.")
29812
+ instructions: z119.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.")
29630
29813
  }).strict();
29631
29814
  var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
29632
29815
  if (input.kind === "video" && input.nVariants !== void 0) {
29633
29816
  ctx.addIssue({
29634
- code: z118.ZodIssueCode.custom,
29817
+ code: z119.ZodIssueCode.custom,
29635
29818
  path: [
29636
29819
  "nVariants"
29637
29820
  ],
@@ -29641,7 +29824,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
29641
29824
  if (input.kind !== "video") {
29642
29825
  if (input.videoPreset !== void 0) {
29643
29826
  ctx.addIssue({
29644
- code: z118.ZodIssueCode.custom,
29827
+ code: z119.ZodIssueCode.custom,
29645
29828
  path: [
29646
29829
  "videoPreset"
29647
29830
  ],
@@ -29650,7 +29833,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
29650
29833
  }
29651
29834
  if (input.videoResolution !== void 0) {
29652
29835
  ctx.addIssue({
29653
- code: z118.ZodIssueCode.custom,
29836
+ code: z119.ZodIssueCode.custom,
29654
29837
  path: [
29655
29838
  "videoResolution"
29656
29839
  ],
@@ -29660,7 +29843,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
29660
29843
  }
29661
29844
  if (input.kind !== "image" && input.nVariants !== void 0) {
29662
29845
  ctx.addIssue({
29663
- code: z118.ZodIssueCode.custom,
29846
+ code: z119.ZodIssueCode.custom,
29664
29847
  path: [
29665
29848
  "nVariants"
29666
29849
  ],
@@ -29670,7 +29853,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
29670
29853
  if (input.kind !== "landing") {
29671
29854
  if (input.sectionKey !== void 0) {
29672
29855
  ctx.addIssue({
29673
- code: z118.ZodIssueCode.custom,
29856
+ code: z119.ZodIssueCode.custom,
29674
29857
  path: [
29675
29858
  "sectionKey"
29676
29859
  ],
@@ -29679,7 +29862,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
29679
29862
  }
29680
29863
  if (input.instructions !== void 0) {
29681
29864
  ctx.addIssue({
29682
- code: z118.ZodIssueCode.custom,
29865
+ code: z119.ZodIssueCode.custom,
29683
29866
  path: [
29684
29867
  "instructions"
29685
29868
  ],
@@ -29688,31 +29871,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
29688
29871
  }
29689
29872
  }
29690
29873
  });
29691
- var CreateCreativeVariantInputBase = z118.object({
29692
- sourceTaskId: z118.string().uuid().describe("ID de la tarea original completada."),
29874
+ var CreateCreativeVariantInputBase = z119.object({
29875
+ sourceTaskId: z119.string().uuid().describe("ID de la tarea original completada."),
29693
29876
  kind: CreativeVariantKindEnum,
29694
- confirm: z118.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
29695
- clientRequestId: z118.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."),
29696
- angle: z118.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
29697
- buyerPersona: z118.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
29698
- scriptNotes: z118.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
29699
- creativeDirection: z118.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
29877
+ confirm: z119.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
29878
+ clientRequestId: z119.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."),
29879
+ angle: z119.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
29880
+ buyerPersona: z119.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
29881
+ scriptNotes: z119.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
29882
+ creativeDirection: z119.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
29700
29883
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
29701
29884
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
29702
- generateAiMusic: z118.boolean().optional().describe("Opcional para video."),
29703
- nVariants: z118.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
29885
+ generateAiMusic: z119.boolean().optional().describe("Opcional para video."),
29886
+ nVariants: z119.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
29704
29887
  imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
29705
29888
  creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
29706
29889
  visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
29707
29890
  aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
29708
- styleMix: z118.boolean().optional().describe("Opcional para imagen."),
29891
+ styleMix: z119.boolean().optional().describe("Opcional para imagen."),
29709
29892
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
29710
- instructions: z118.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.")
29893
+ instructions: z119.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.")
29711
29894
  }).strict();
29712
29895
  var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
29713
29896
  if ((input.kind === "video" || input.kind === "image") && !input.angle) {
29714
29897
  ctx.addIssue({
29715
- code: z118.ZodIssueCode.custom,
29898
+ code: z119.ZodIssueCode.custom,
29716
29899
  path: [
29717
29900
  "angle"
29718
29901
  ],
@@ -29721,7 +29904,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
29721
29904
  }
29722
29905
  if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
29723
29906
  ctx.addIssue({
29724
- code: z118.ZodIssueCode.custom,
29907
+ code: z119.ZodIssueCode.custom,
29725
29908
  path: [
29726
29909
  "instructions"
29727
29910
  ],
@@ -29767,7 +29950,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
29767
29950
  for (const field of fieldsByKind[input.kind]) {
29768
29951
  if (input[field] !== void 0) {
29769
29952
  ctx.addIssue({
29770
- code: z118.ZodIssueCode.custom,
29953
+ code: z119.ZodIssueCode.custom,
29771
29954
  path: [
29772
29955
  field
29773
29956
  ],
@@ -29900,13 +30083,13 @@ function registerCreativeVariantTools(server, api) {
29900
30083
  __name(registerCreativeVariantTools, "registerCreativeVariantTools");
29901
30084
 
29902
30085
  // src/tools/script-review.ts
29903
- import { z as z119 } from "zod";
30086
+ import { z as z120 } from "zod";
29904
30087
  var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
29905
30088
  var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
29906
30089
  var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
29907
- var GetVideoScriptInput = z119.object({
29908
- taskId: z119.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
29909
- angleKey: z119.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.')
30090
+ var GetVideoScriptInput = z120.object({
30091
+ taskId: z120.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
30092
+ angleKey: z120.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.')
29910
30093
  }).strict();
29911
30094
  var ApproveVideoScriptInput = ApproveVideoScriptCapabilityRequest;
29912
30095
  var RegenerateVideoScriptInput = RegenerateVideoScriptCapabilityRequest.extend({
@@ -29989,7 +30172,7 @@ function registerScriptReviewTools(server, api) {
29989
30172
  __name(registerScriptReviewTools, "registerScriptReviewTools");
29990
30173
 
29991
30174
  // src/tools/connections.ts
29992
- import { z as z120 } from "zod";
30175
+ import { z as z121 } from "zod";
29993
30176
  var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
29994
30177
  var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
29995
30178
  var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
@@ -29998,7 +30181,7 @@ var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list
29998
30181
  function registerConnectionTools(server, api) {
29999
30182
  server.registerTool("list_shopify_shops", {
30000
30183
  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.",
30001
- inputSchema: z120.object({}).shape,
30184
+ inputSchema: z121.object({}).shape,
30002
30185
  annotations: READS_INTERNAL
30003
30186
  }, async () => {
30004
30187
  try {
@@ -30010,10 +30193,10 @@ function registerConnectionTools(server, api) {
30010
30193
  });
30011
30194
  server.registerTool("list_shopify_products", {
30012
30195
  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.',
30013
- inputSchema: z120.object({
30014
- shopDomain: z120.string().min(3).max(120),
30015
- query: z120.string().trim().max(120).optional(),
30016
- taskId: z120.string().uuid().optional()
30196
+ inputSchema: z121.object({
30197
+ shopDomain: z121.string().min(3).max(120),
30198
+ query: z121.string().trim().max(120).optional(),
30199
+ taskId: z121.string().uuid().optional()
30017
30200
  }).shape,
30018
30201
  annotations: READS_EXTERNAL
30019
30202
  }, async ({ shopDomain, query, taskId }) => {
@@ -30031,7 +30214,7 @@ function registerConnectionTools(server, api) {
30031
30214
  });
30032
30215
  server.registerTool("list_meta_ad_accounts", {
30033
30216
  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.",
30034
- inputSchema: z120.object({}).shape,
30217
+ inputSchema: z121.object({}).shape,
30035
30218
  annotations: READS_EXTERNAL
30036
30219
  }, async () => {
30037
30220
  try {
@@ -30043,7 +30226,7 @@ function registerConnectionTools(server, api) {
30043
30226
  });
30044
30227
  server.registerTool("list_meta_destinations", {
30045
30228
  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.",
30046
- inputSchema: z120.object({}).shape,
30229
+ inputSchema: z121.object({}).shape,
30047
30230
  annotations: READS_EXTERNAL,
30048
30231
  _meta: {
30049
30232
  "openai/widgetAccessible": true
@@ -30058,7 +30241,7 @@ function registerConnectionTools(server, api) {
30058
30241
  });
30059
30242
  server.registerTool("list_tiktok_advertisers", {
30060
30243
  description: listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.",
30061
- inputSchema: z120.object({}).shape,
30244
+ inputSchema: z121.object({}).shape,
30062
30245
  annotations: READS_EXTERNAL
30063
30246
  }, async () => {
30064
30247
  try {
@@ -30072,7 +30255,7 @@ function registerConnectionTools(server, api) {
30072
30255
  __name(registerConnectionTools, "registerConnectionTools");
30073
30256
 
30074
30257
  // src/tools/actors.ts
30075
- import { z as z121 } from "zod";
30258
+ import { z as z122 } from "zod";
30076
30259
  var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
30077
30260
  var actorVoiceGuidance = {
30078
30261
  capabilities: getProductMakerCapabilityModelGuidance("get_actor_voice_capabilities"),
@@ -30112,7 +30295,7 @@ function sanitizeVoiceResult(value) {
30112
30295
  __name(sanitizeVoiceResult, "sanitizeVoiceResult");
30113
30296
  function registerActorTools(server, api) {
30114
30297
  const actor = {
30115
- actorId: z121.string().min(1).max(64)
30298
+ actorId: z122.string().min(1).max(64)
30116
30299
  };
30117
30300
  const safe = /* @__PURE__ */ __name(async (request) => {
30118
30301
  try {
@@ -30141,8 +30324,8 @@ function registerActorTools(server, api) {
30141
30324
  inputSchema: {
30142
30325
  ...actor,
30143
30326
  draft: ActorVoiceDraftSchema,
30144
- requestKey: z121.string().trim().min(1).max(128),
30145
- acceptedQuoteId: z121.string().trim().min(1).max(128)
30327
+ requestKey: z122.string().trim().min(1).max(128),
30328
+ acceptedQuoteId: z122.string().trim().min(1).max(128)
30146
30329
  },
30147
30330
  annotations: CREATES_PAID
30148
30331
  }, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/previews`, body)));
@@ -30150,7 +30333,7 @@ function registerActorTools(server, api) {
30150
30333
  description: actorVoiceGuidance.get.summary,
30151
30334
  inputSchema: {
30152
30335
  ...actor,
30153
- candidateId: z121.string().min(1).max(64)
30336
+ candidateId: z122.string().min(1).max(64)
30154
30337
  },
30155
30338
  // Polling can resume the first paid submission of an accepted quote.
30156
30339
  // The immutable candidate/operation key keeps recovery idempotent.
@@ -30163,16 +30346,16 @@ function registerActorTools(server, api) {
30163
30346
  description: actorVoiceGuidance.approve.summary,
30164
30347
  inputSchema: {
30165
30348
  ...actor,
30166
- candidateId: z121.string().min(1).max(64),
30167
- expectedRevision: z121.number().int().positive(),
30168
- expectedApprovedRevision: z121.number().int().positive().nullable().optional()
30349
+ candidateId: z122.string().min(1).max(64),
30350
+ expectedRevision: z122.number().int().positive(),
30351
+ expectedApprovedRevision: z122.number().int().positive().nullable().optional()
30169
30352
  },
30170
30353
  // Replaces the selected voice and withdraws the old catalog grants.
30171
30354
  annotations: OVERWRITES_INTERNAL
30172
30355
  }, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/approve`, body)));
30173
30356
  server.registerTool("list_actors", {
30174
30357
  description: listActorsGuidance.summary + " Devuelve id, nombre, descripci\xF3n, g\xE9nero y voz privada del personaje. Cuando el personaje tiene una voz personalizada, `voice.identityId` y `voice.revision` identifican la versi\xF3n aprobada \u2014 conserva la revisi\xF3n al llamar `approve_actor_voice` (expectedApprovedRevision) para reemplazarla. Los IDs de proveedor nunca se exponen por MCP. 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.",
30175
- inputSchema: z121.object({}).shape,
30358
+ inputSchema: z122.object({}).shape,
30176
30359
  annotations: READS_INTERNAL
30177
30360
  }, async () => {
30178
30361
  try {
@@ -30205,7 +30388,7 @@ function registerActorTools(server, api) {
30205
30388
  __name(registerActorTools, "registerActorTools");
30206
30389
 
30207
30390
  // src/tools/publish.ts
30208
- import { z as z122 } from "zod";
30391
+ import { z as z123 } from "zod";
30209
30392
 
30210
30393
  // src/tools/meta-publish-attempt-id.ts
30211
30394
  var META_PUBLISH_NAMESPACE = "7b19c9ac-b4eb-4db1-970e-c2f24ce30b98";
@@ -30244,40 +30427,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
30244
30427
  var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
30245
30428
  var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
30246
30429
  var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
30247
- var ShopifyInput = z122.object({
30248
- taskId: z122.string().min(1),
30249
- shopDomain: z122.string().min(1),
30430
+ var ShopifyInput = z123.object({
30431
+ taskId: z123.string().min(1),
30432
+ shopDomain: z123.string().min(1),
30250
30433
  /** Override: number of landing images to include. Default = ALL images the
30251
30434
  * task generated (the MCP fetches /v1/results first to count). Bounded
30252
30435
  * generously here; the backend validates each index against
30253
30436
  * landing.images.length and rejects out-of-range. */
30254
- numLandingImages: z122.number().int().min(1).max(20).optional(),
30255
- variantIndex: z122.number().int().min(0).optional(),
30437
+ numLandingImages: z123.number().int().min(1).max(20).optional(),
30438
+ variantIndex: z123.number().int().min(0).optional(),
30256
30439
  /** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
30257
30440
  * When true, the landing renders variant-picker pills; when false, it ships
30258
30441
  * a single-option product page. Defaults to false. */
30259
- showVariantPicker: z122.boolean().optional(),
30442
+ showVariantPicker: z123.boolean().optional(),
30260
30443
  /** Default `auto` updates the product previously published for this task and
30261
30444
  * shop. Use `existing` with targetProductId to choose another product, or
30262
30445
  * `new` only when the user explicitly wants a duplicate/new listing. */
30263
- publicationMode: z122.enum([
30446
+ publicationMode: z123.enum([
30264
30447
  "auto",
30265
30448
  "existing",
30266
30449
  "new"
30267
30450
  ]).optional(),
30268
30451
  /** Shopify product GID, numeric id, or admin product URL. Required when
30269
30452
  * publicationMode is `existing`. */
30270
- targetProductId: z122.string().trim().min(1).max(300).optional(),
30453
+ targetProductId: z123.string().trim().min(1).max(300).optional(),
30271
30454
  /** Add an announcement bar text above add-to-cart (optional). */
30272
- announcementBarEnabled: z122.boolean().optional(),
30273
- announcementBarText: z122.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
30455
+ announcementBarEnabled: z123.boolean().optional(),
30456
+ announcementBarText: z123.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
30274
30457
  commerceCorrection: PublishCommerceCorrectionSchema.optional().describe("Complete seller-confirmed commerce values, with the revision and fingerprint returned in recovery. Never invent missing prices or convert currency."),
30275
- confirmed: z122.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
30458
+ confirmed: z123.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
30276
30459
  });
30277
30460
  var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
30278
30461
  if (value.commerceCorrection && value.confirmed !== true) {
30279
30462
  ctx.addIssue({
30280
- code: z122.ZodIssueCode.custom,
30463
+ code: z123.ZodIssueCode.custom,
30281
30464
  path: [
30282
30465
  "confirmed"
30283
30466
  ],
@@ -30286,7 +30469,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
30286
30469
  }
30287
30470
  if (value.announcementBarEnabled && !value.announcementBarText) {
30288
30471
  ctx.addIssue({
30289
- code: z122.ZodIssueCode.custom,
30472
+ code: z123.ZodIssueCode.custom,
30290
30473
  path: [
30291
30474
  "announcementBarText"
30292
30475
  ],
@@ -30295,7 +30478,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
30295
30478
  }
30296
30479
  if (!value.announcementBarEnabled && value.announcementBarText) {
30297
30480
  ctx.addIssue({
30298
- code: z122.ZodIssueCode.custom,
30481
+ code: z123.ZodIssueCode.custom,
30299
30482
  path: [
30300
30483
  "announcementBarText"
30301
30484
  ],
@@ -30309,91 +30492,91 @@ function parseShopifyInput(rawInput) {
30309
30492
  return parsed.data;
30310
30493
  }
30311
30494
  __name(parseShopifyInput, "parseShopifyInput");
30312
- var McpCampaignConfig = z122.object({
30495
+ var McpCampaignConfig = z123.object({
30313
30496
  /** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
30314
30497
  * converts to the account currency server-side. Do NOT pre-convert: on a COP
30315
30498
  * account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
30316
- dailyBudgetUsd: z122.number().positive().optional(),
30499
+ dailyBudgetUsd: z123.number().positive().optional(),
30317
30500
  /** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
30318
30501
  * normalizes at validation). Meta accepts max 1 (single-country ad set).
30319
30502
  * TikTok takes only the first entry. */
30320
- targetCountries: z122.array(CountryIso2Schema).max(1).optional(),
30321
- campaignName: z122.string().trim().min(1).max(100).optional()
30503
+ targetCountries: z123.array(CountryIso2Schema).max(1).optional(),
30504
+ campaignName: z123.string().trim().min(1).max(100).optional()
30322
30505
  });
30323
30506
  var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
30324
- var MetaInput = z122.object({
30325
- taskId: z122.string().min(1),
30507
+ var MetaInput = z123.object({
30508
+ taskId: z123.string().min(1),
30326
30509
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
30327
- portfolioId: z122.string().trim().min(1),
30510
+ portfolioId: z123.string().trim().min(1),
30328
30511
  /** Exact Facebook Page selected from `list_meta_destinations`. */
30329
- pageId: z122.string().trim().min(1),
30512
+ pageId: z123.string().trim().min(1),
30330
30513
  adAccountId: McpAdAccountId,
30331
- pixelId: z122.string().min(1).optional(),
30332
- landingUrl: z122.string().url().optional(),
30514
+ pixelId: z123.string().min(1).optional(),
30515
+ landingUrl: z123.string().url().optional(),
30333
30516
  /** Select which angles to publish by 0-based index. Omit to publish all
30334
30517
  * successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
30335
- angleIndexes: z122.array(z122.number().int().nonnegative()).optional(),
30518
+ angleIndexes: z123.array(z123.number().int().nonnegative()).optional(),
30336
30519
  campaignConfig: McpCampaignConfig.optional(),
30337
30520
  /** Override the ad's primary text (body copy). If omitted, ProductMaker
30338
30521
  * uses the auto-generated copy attached to the task. Capped at 500 chars
30339
30522
  * (Meta's primary-text limit). */
30340
- primaryText: z122.string().trim().min(1).max(500).optional(),
30523
+ primaryText: z123.string().trim().min(1).max(500).optional(),
30341
30524
  /** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
30342
30525
  * (wa.me) instead of a landing page. */
30343
- phoneNumber: z122.string().min(8).max(32).optional()
30526
+ phoneNumber: z123.string().min(8).max(32).optional()
30344
30527
  });
30345
- var GroupedTaskSource = z122.object({
30346
- type: z122.literal("task"),
30347
- taskId: z122.string().min(1),
30348
- angleIndex: z122.number().int().min(0).optional(),
30349
- videoVariant: z122.enum([
30528
+ var GroupedTaskSource = z123.object({
30529
+ type: z123.literal("task"),
30530
+ taskId: z123.string().min(1),
30531
+ angleIndex: z123.number().int().min(0).optional(),
30532
+ videoVariant: z123.enum([
30350
30533
  "with_subtitles",
30351
30534
  "without_subtitles"
30352
30535
  ]).optional(),
30353
- imageVariantIndex: z122.number().int().min(0).optional()
30354
- });
30355
- var GroupedMediaSource = z122.object({
30356
- type: z122.literal("media"),
30357
- url: z122.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
30358
- path: z122.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".'),
30359
- thumbnailUrl: z122.string().url().optional(),
30360
- thumbnailPath: z122.string().min(1).optional()
30536
+ imageVariantIndex: z123.number().int().min(0).optional()
30537
+ });
30538
+ var GroupedMediaSource = z123.object({
30539
+ type: z123.literal("media"),
30540
+ url: z123.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
30541
+ path: z123.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".'),
30542
+ thumbnailUrl: z123.string().url().optional(),
30543
+ thumbnailPath: z123.string().min(1).optional()
30361
30544
  }).refine((value) => Boolean(value.url) !== Boolean(value.path), {
30362
30545
  message: "media source needs exactly one of `url` or `path`"
30363
30546
  }).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
30364
30547
  message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
30365
30548
  });
30366
- var GroupedUploadedAssetSource = z122.object({
30367
- type: z122.literal("asset"),
30549
+ var GroupedUploadedAssetSource = z123.object({
30550
+ type: z123.literal("asset"),
30368
30551
  /** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
30369
- assetId: z122.string().uuid(),
30370
- thumbnailAssetId: z122.string().uuid().optional()
30552
+ assetId: z123.string().uuid(),
30553
+ thumbnailAssetId: z123.string().uuid().optional()
30371
30554
  });
30372
- var GroupedCreative = z122.object({
30373
- type: z122.enum([
30555
+ var GroupedCreative = z123.object({
30556
+ type: z123.enum([
30374
30557
  "image",
30375
30558
  "video"
30376
30559
  ]),
30377
- source: z122.union([
30560
+ source: z123.union([
30378
30561
  GroupedTaskSource,
30379
30562
  GroupedMediaSource,
30380
30563
  GroupedUploadedAssetSource
30381
30564
  ]),
30382
- title: z122.string().max(120).optional(),
30383
- description: z122.string().max(500).optional(),
30565
+ title: z123.string().max(120).optional(),
30566
+ description: z123.string().max(500).optional(),
30384
30567
  cta: MetaCtaType.optional(),
30385
- creativeId: z122.string().min(1).optional()
30568
+ creativeId: z123.string().min(1).optional()
30386
30569
  });
30387
- var GroupedCampaignConfigBase = z122.object({
30570
+ var GroupedCampaignConfigBase = z123.object({
30388
30571
  campaignType: MetaCampaignType.default("sales"),
30389
30572
  optimizationMode: MetaOptimizationMode.default("advantage_plus"),
30390
30573
  budgetMode: MetaBudgetMode.optional(),
30391
- campaignDailyBudget: z122.number().int().positive().optional(),
30392
- adSets: z122.array(z122.object({
30393
- tempId: z122.string().min(1).max(80),
30394
- name: z122.string().min(1).max(100),
30395
- dailyBudget: z122.number().int().positive().optional(),
30396
- creativeIds: z122.array(z122.string().min(1)).min(1)
30574
+ campaignDailyBudget: z123.number().int().positive().optional(),
30575
+ adSets: z123.array(z123.object({
30576
+ tempId: z123.string().min(1).max(80),
30577
+ name: z123.string().min(1).max(100),
30578
+ dailyBudget: z123.number().int().positive().optional(),
30579
+ creativeIds: z123.array(z123.string().min(1)).min(1)
30397
30580
  })).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
30398
30581
  /**
30399
30582
  * Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
@@ -30401,17 +30584,17 @@ var GroupedCampaignConfigBase = z122.object({
30401
30584
  * opaque `invalid_literal` and made the WhatsApp destination — supported by
30402
30585
  * the API since #849 — unreachable from this tool.
30403
30586
  */
30404
- destination: z122.discriminatedUnion("type", [
30405
- z122.object({
30406
- type: z122.literal("landing"),
30407
- landingUrl: z122.string().url()
30587
+ destination: z123.discriminatedUnion("type", [
30588
+ z123.object({
30589
+ type: z123.literal("landing"),
30590
+ landingUrl: z123.string().url()
30408
30591
  }),
30409
- z122.object({
30410
- type: z122.literal("whatsapp"),
30411
- phoneNumber: z122.string().min(8).max(32)
30592
+ z123.object({
30593
+ type: z123.literal("whatsapp"),
30594
+ phoneNumber: z123.string().min(8).max(32)
30412
30595
  })
30413
30596
  ]),
30414
- saveAsDefault: z122.boolean().default(false),
30597
+ saveAsDefault: z123.boolean().default(false),
30415
30598
  budgetPolicy: MetaBudgetPolicy.optional()
30416
30599
  });
30417
30600
  function resolveBudgetMode(value) {
@@ -30425,7 +30608,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
30425
30608
  const budgetMode = resolveBudgetMode(value);
30426
30609
  if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
30427
30610
  ctx.addIssue({
30428
- code: z122.ZodIssueCode.custom,
30611
+ code: z123.ZodIssueCode.custom,
30429
30612
  path: [
30430
30613
  "campaignDailyBudget"
30431
30614
  ],
@@ -30436,7 +30619,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
30436
30619
  value.adSets.forEach((adSet, index) => {
30437
30620
  if (adSet.dailyBudget === void 0) {
30438
30621
  ctx.addIssue({
30439
- code: z122.ZodIssueCode.custom,
30622
+ code: z123.ZodIssueCode.custom,
30440
30623
  path: [
30441
30624
  "adSets",
30442
30625
  index,
@@ -30451,28 +30634,28 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
30451
30634
  ...value,
30452
30635
  budgetMode: resolveBudgetMode(value)
30453
30636
  }));
30454
- var PublishCreativesToMetaInputBase = z122.object({
30455
- creatives: z122.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
30637
+ var PublishCreativesToMetaInputBase = z123.object({
30638
+ creatives: z123.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
30456
30639
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
30457
- portfolioId: z122.string().trim().min(1),
30640
+ portfolioId: z123.string().trim().min(1),
30458
30641
  /** Exact Facebook Page selected from `list_meta_destinations`. */
30459
- pageId: z122.string().trim().min(1),
30642
+ pageId: z123.string().trim().min(1),
30460
30643
  adAccountId: McpAdAccountId,
30461
- pixelId: z122.string().min(1).optional(),
30644
+ pixelId: z123.string().min(1).optional(),
30462
30645
  /** Required unless `campaignConfig.destination` is whatsapp — see the
30463
30646
  * superRefine below. Mirrors the API's `FacebookCreateCampaignFromTasksBodySchema`. */
30464
- landingUrl: z122.string().url().optional(),
30647
+ landingUrl: z123.string().url().optional(),
30465
30648
  /** ISO-2 code or resolvable country name — mirrors the API contract
30466
30649
  * (CountryIso2Schema), which normalizes names to alpha-2 at validation. */
30467
30650
  targetCountry: CountryIso2Schema,
30468
- campaignName: z122.string().trim().min(1).max(100),
30651
+ campaignName: z123.string().trim().min(1).max(100),
30469
30652
  campaignConfig: GroupedCampaignConfig.optional()
30470
30653
  });
30471
30654
  var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
30472
30655
  const destination = value.campaignConfig?.destination;
30473
30656
  if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
30474
30657
  ctx.addIssue({
30475
- code: z122.ZodIssueCode.custom,
30658
+ code: z123.ZodIssueCode.custom,
30476
30659
  path: [
30477
30660
  "landingUrl"
30478
30661
  ],
@@ -30481,7 +30664,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
30481
30664
  }
30482
30665
  if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
30483
30666
  ctx.addIssue({
30484
- code: z122.ZodIssueCode.custom,
30667
+ code: z123.ZodIssueCode.custom,
30485
30668
  path: [
30486
30669
  "campaignConfig",
30487
30670
  "destination",
@@ -30500,16 +30683,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
30500
30683
  }
30501
30684
  return value;
30502
30685
  });
30503
- var PresignUploadResponseSchema = z122.object({
30504
- uploadUrl: z122.string().url().refine((value) => {
30686
+ var PresignUploadResponseSchema = z123.object({
30687
+ uploadUrl: z123.string().url().refine((value) => {
30505
30688
  const url = new URL(value);
30506
30689
  return !url.username && !url.password && url.protocol === "https:";
30507
30690
  }, "presigned upload URL must be HTTPS without embedded credentials"),
30508
- publicUrl: z122.string().url().refine((value) => {
30691
+ publicUrl: z123.string().url().refine((value) => {
30509
30692
  const url = new URL(value);
30510
30693
  return !url.username && !url.password;
30511
30694
  }, "public media URL must not contain embedded credentials"),
30512
- stagingAssetId: z122.string().uuid()
30695
+ stagingAssetId: z123.string().uuid()
30513
30696
  });
30514
30697
  async function uploadResolvedMedia(api, media, assetRole) {
30515
30698
  if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
@@ -30534,16 +30717,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
30534
30717
  return uploadResolvedMedia(api, media, assetRole);
30535
30718
  }
30536
30719
  __name(resolveAndUploadMedia, "resolveAndUploadMedia");
30537
- var TikTokInput = z122.object({
30538
- taskId: z122.string().min(1),
30539
- advertiserId: z122.string().min(1),
30540
- pixelId: z122.string().min(1).optional(),
30541
- landingUrl: z122.string().url().optional(),
30542
- angleIndexes: z122.array(z122.number().int().nonnegative()).optional(),
30720
+ var TikTokInput = z123.object({
30721
+ taskId: z123.string().min(1),
30722
+ advertiserId: z123.string().min(1),
30723
+ pixelId: z123.string().min(1).optional(),
30724
+ landingUrl: z123.string().url().optional(),
30725
+ angleIndexes: z123.array(z123.number().int().nonnegative()).optional(),
30543
30726
  campaignConfig: McpCampaignConfig.optional(),
30544
30727
  /** Override the ad's description (TikTok's body copy). If omitted,
30545
30728
  * ProductMaker uses the auto-generated copy attached to the task. */
30546
- primaryText: z122.string().trim().min(1).max(500).optional()
30729
+ primaryText: z123.string().trim().min(1).max(500).optional()
30547
30730
  });
30548
30731
  function registerPublishTools(server, api, opts = {}) {
30549
30732
  const transport = opts.transport ?? "http";
@@ -30895,39 +31078,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
30895
31078
 
30896
31079
  // src/tools/meta-upload.ts
30897
31080
  import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
30898
- import { z as z123 } from "zod";
31081
+ import { z as z124 } from "zod";
30899
31082
  var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
30900
- var UploadSessionInputBase = z123.object({
30901
- mediaKind: z123.enum([
31083
+ var UploadSessionInputBase = z124.object({
31084
+ mediaKind: z124.enum([
30902
31085
  "image",
30903
31086
  "video",
30904
31087
  "mixed"
30905
31088
  ]).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."),
30906
- assetRole: z123.enum([
31089
+ assetRole: z124.enum([
30907
31090
  "media",
30908
31091
  "thumbnail"
30909
31092
  ]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
30910
- uploadPurpose: z123.enum([
31093
+ uploadPurpose: z124.enum([
30911
31094
  "product_reference",
30912
31095
  "creative",
30913
31096
  "generic"
30914
31097
  ]).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."),
30915
- maxFiles: z123.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
31098
+ maxFiles: z124.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
30916
31099
  });
30917
- var OpenAiFileReference = z123.object({
30918
- download_url: z123.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."),
30919
- file_id: z123.string().min(1),
30920
- mime_type: z123.string().min(1).optional(),
30921
- file_name: z123.string().min(1).optional()
31100
+ var OpenAiFileReference = z124.object({
31101
+ download_url: z124.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."),
31102
+ file_id: z124.string().min(1),
31103
+ mime_type: z124.string().min(1).optional(),
31104
+ file_name: z124.string().min(1).optional()
30922
31105
  });
30923
31106
  var UploadSessionToolInputShape = {
30924
31107
  ...UploadSessionInputBase.shape,
30925
- files: z123.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.")
31108
+ files: z124.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.")
30926
31109
  };
30927
- var UploadSessionToolInput = z123.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
31110
+ var UploadSessionToolInput = z124.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
30928
31111
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
30929
31112
  ctx.addIssue({
30930
- code: z123.ZodIssueCode.custom,
31113
+ code: z124.ZodIssueCode.custom,
30931
31114
  path: [
30932
31115
  "mediaKind"
30933
31116
  ],
@@ -30936,7 +31119,7 @@ var UploadSessionToolInput = z123.object(UploadSessionToolInputShape).superRefin
30936
31119
  }
30937
31120
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
30938
31121
  ctx.addIssue({
30939
- code: z123.ZodIssueCode.custom,
31122
+ code: z124.ZodIssueCode.custom,
30940
31123
  path: [
30941
31124
  "maxFiles"
30942
31125
  ],
@@ -30945,7 +31128,7 @@ var UploadSessionToolInput = z123.object(UploadSessionToolInputShape).superRefin
30945
31128
  }
30946
31129
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
30947
31130
  ctx.addIssue({
30948
- code: z123.ZodIssueCode.custom,
31131
+ code: z124.ZodIssueCode.custom,
30949
31132
  path: [
30950
31133
  "maxFiles"
30951
31134
  ],
@@ -30953,38 +31136,38 @@ var UploadSessionToolInput = z123.object(UploadSessionToolInputShape).superRefin
30953
31136
  });
30954
31137
  }
30955
31138
  });
30956
- var UploadSessionResponse = z123.object({
30957
- sessionId: z123.string().uuid(),
30958
- uploadPageUrl: z123.string().url(),
30959
- mediaKind: z123.enum([
31139
+ var UploadSessionResponse = z124.object({
31140
+ sessionId: z124.string().uuid(),
31141
+ uploadPageUrl: z124.string().url(),
31142
+ mediaKind: z124.enum([
30960
31143
  "image",
30961
31144
  "video",
30962
31145
  "mixed"
30963
31146
  ]),
30964
- assetRole: z123.enum([
31147
+ assetRole: z124.enum([
30965
31148
  "media",
30966
31149
  "thumbnail"
30967
31150
  ]),
30968
- maxFiles: z123.number().int().positive(),
30969
- expiresAt: z123.string().datetime()
31151
+ maxFiles: z124.number().int().positive(),
31152
+ expiresAt: z124.string().datetime()
30970
31153
  });
30971
- var UploadStatusInput = z123.object({
30972
- sessionId: z123.string().uuid().describe("The sessionId returned by request_media_upload.")
31154
+ var UploadStatusInput = z124.object({
31155
+ sessionId: z124.string().uuid().describe("The sessionId returned by request_media_upload.")
30973
31156
  });
30974
- var UniversalUploadStatusResponse = z123.discriminatedUnion("status", [
30975
- z123.object({
30976
- status: z123.literal("pending"),
30977
- assets: z123.array(z123.never()).length(0)
31157
+ var UniversalUploadStatusResponse = z124.discriminatedUnion("status", [
31158
+ z124.object({
31159
+ status: z124.literal("pending"),
31160
+ assets: z124.array(z124.never()).length(0)
30978
31161
  }),
30979
- z123.object({
30980
- status: z123.literal("uploaded"),
30981
- assets: z123.array(z123.object({
30982
- assetId: z123.string().uuid(),
30983
- mediaKind: z123.enum([
31162
+ z124.object({
31163
+ status: z124.literal("uploaded"),
31164
+ assets: z124.array(z124.object({
31165
+ assetId: z124.string().uuid(),
31166
+ mediaKind: z124.enum([
30984
31167
  "image",
30985
31168
  "video"
30986
31169
  ]),
30987
- assetRole: z123.enum([
31170
+ assetRole: z124.enum([
30988
31171
  "media",
30989
31172
  "thumbnail"
30990
31173
  ])
@@ -30992,13 +31175,13 @@ var UniversalUploadStatusResponse = z123.discriminatedUnion("status", [
30992
31175
  })
30993
31176
  ]);
30994
31177
  var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
30995
- uploadPurpose: z123.enum([
31178
+ uploadPurpose: z124.enum([
30996
31179
  "product_reference",
30997
31180
  "creative",
30998
31181
  "generic"
30999
31182
  ]),
31000
- checkToolName: z123.literal("check_media_upload"),
31001
- resolveEndpoint: z123.string().url()
31183
+ checkToolName: z124.literal("check_media_upload"),
31184
+ resolveEndpoint: z124.string().url()
31002
31185
  });
31003
31186
  function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
31004
31187
  const url = new URL(uploadPageUrl);
@@ -31089,15 +31272,15 @@ function registerMediaUploadTools(server, api) {
31089
31272
  __name(registerMediaUploadTools, "registerMediaUploadTools");
31090
31273
 
31091
31274
  // src/tools/campaigns.ts
31092
- import { z as z124 } from "zod";
31275
+ import { z as z125 } from "zod";
31093
31276
  var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
31094
31277
  var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
31095
- var MetaStatusInput = z124.object({
31096
- campaignId: z124.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
31278
+ var MetaStatusInput = z125.object({
31279
+ campaignId: z125.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
31097
31280
  });
31098
- var TikTokStatusInput = z124.object({
31099
- campaignId: z124.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
31100
- advertiserId: z124.string().min(1).describe("The same advertiserId used to publish the campaign.")
31281
+ var TikTokStatusInput = z125.object({
31282
+ campaignId: z125.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
31283
+ advertiserId: z125.string().min(1).describe("The same advertiserId used to publish the campaign.")
31101
31284
  });
31102
31285
  function registerCampaignTools(server, api) {
31103
31286
  server.registerTool("get_meta_campaign_status", {
@@ -31202,10 +31385,10 @@ function renderTikTokStatusMarkdown(r) {
31202
31385
  __name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
31203
31386
 
31204
31387
  // ../../packages/product-economics/src/product-costing.ts
31205
- import { z as z126 } from "zod";
31388
+ import { z as z127 } from "zod";
31206
31389
 
31207
31390
  // ../../packages/product-economics/src/product-costing-countries.ts
31208
- import { z as z125 } from "zod";
31391
+ import { z as z126 } from "zod";
31209
31392
 
31210
31393
  // ../../packages/product-economics/src/product-costing-shipping-references.json
31211
31394
  var product_costing_shipping_references_default = {
@@ -31269,21 +31452,21 @@ var product_costing_shipping_references_default = {
31269
31452
  };
31270
31453
 
31271
31454
  // ../../packages/product-economics/src/product-costing-countries.ts
31272
- var ShippingReferenceSchema = z125.object({
31273
- reference: z125.number().positive(),
31274
- min: z125.number().nonnegative(),
31275
- max: z125.number().positive(),
31276
- updatedAt: z125.string().date(),
31277
- confidence: z125.enum([
31455
+ var ShippingReferenceSchema = z126.object({
31456
+ reference: z126.number().positive(),
31457
+ min: z126.number().nonnegative(),
31458
+ max: z126.number().positive(),
31459
+ updatedAt: z126.string().date(),
31460
+ confidence: z126.enum([
31278
31461
  "high",
31279
31462
  "medium",
31280
31463
  "medium-low"
31281
31464
  ]),
31282
- sources: z125.array(z125.string().url().startsWith("https://")).min(1).max(3)
31465
+ sources: z126.array(z126.string().url().startsWith("https://")).min(1).max(3)
31283
31466
  }).superRefine(({ reference, min, max }, context) => {
31284
31467
  if (min > reference || reference > max) {
31285
31468
  context.addIssue({
31286
- code: z125.ZodIssueCode.custom,
31469
+ code: z126.ZodIssueCode.custom,
31287
31470
  message: "shipping_reference_outside_range",
31288
31471
  path: [
31289
31472
  "reference"
@@ -31291,7 +31474,7 @@ var ShippingReferenceSchema = z125.object({
31291
31474
  });
31292
31475
  }
31293
31476
  });
31294
- var SHIPPING_REFERENCES = z125.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
31477
+ var SHIPPING_REFERENCES = z126.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
31295
31478
  var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
31296
31479
  var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
31297
31480
  "MX",
@@ -31473,18 +31656,18 @@ function getProductCostingCountryName(country) {
31473
31656
  __name(getProductCostingCountryName, "getProductCostingCountryName");
31474
31657
 
31475
31658
  // ../../packages/product-economics/src/product-costing.ts
31476
- var ProductCostingInputSchema = z126.object({
31477
- country: z126.string().refine(isProductCostingCountryCode, "unsupported_country"),
31478
- supplierCost: z126.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
31479
- shippingCost: z126.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
31480
- returnRate: z126.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
31481
- cancellationRate: z126.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
31482
- adsManagerCpa: z126.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
31483
- desiredMargin: z126.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
31659
+ var ProductCostingInputSchema = z127.object({
31660
+ country: z127.string().refine(isProductCostingCountryCode, "unsupported_country"),
31661
+ supplierCost: z127.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
31662
+ shippingCost: z127.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
31663
+ returnRate: z127.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
31664
+ cancellationRate: z127.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
31665
+ adsManagerCpa: z127.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
31666
+ desiredMargin: z127.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
31484
31667
  }).superRefine(({ returnRate, cancellationRate }, context) => {
31485
31668
  if (returnRate + cancellationRate >= 1) {
31486
31669
  context.addIssue({
31487
- code: z126.ZodIssueCode.custom,
31670
+ code: z127.ZodIssueCode.custom,
31488
31671
  message: "delivery_rate_positive",
31489
31672
  path: [
31490
31673
  "cancellationRate"
@@ -31581,15 +31764,15 @@ function calculateProductCosting(rawInput) {
31581
31764
  __name(calculateProductCosting, "calculateProductCosting");
31582
31765
 
31583
31766
  // src/tools/product-costing.ts
31584
- import { z as z127 } from "zod";
31767
+ import { z as z128 } from "zod";
31585
31768
  var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
31586
- var optionalAmount = /* @__PURE__ */ __name((description) => z127.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
31587
- var optionalPercent = /* @__PURE__ */ __name((description) => z127.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
31588
- var ProductCostingToolInput = z127.object({
31589
- country: z127.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
31769
+ var optionalAmount = /* @__PURE__ */ __name((description) => z128.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
31770
+ var optionalPercent = /* @__PURE__ */ __name((description) => z128.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
31771
+ var ProductCostingToolInput = z128.object({
31772
+ country: z128.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
31590
31773
  message: "Pa\xEDs no soportado por ProductMaker."
31591
31774
  }).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
31592
- supplierCost: z127.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."),
31775
+ supplierCost: z128.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."),
31593
31776
  supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
31594
31777
  shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
31595
31778
  shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
@@ -31752,7 +31935,7 @@ function formatPercent(value) {
31752
31935
  __name(formatPercent, "formatPercent");
31753
31936
 
31754
31937
  // src/tools/product-research.ts
31755
- import { z as z128 } from "zod";
31938
+ import { z as z129 } from "zod";
31756
31939
 
31757
31940
  // src/tools/product-research-idempotency.ts
31758
31941
  var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
@@ -32123,17 +32306,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
32123
32306
  ]);
32124
32307
  var POLL_INTERVAL_MS = 5e3;
32125
32308
  var MAX_WAIT_SECONDS = 120;
32126
- var FindInput = z128.object({
32309
+ var FindInput = z129.object({
32127
32310
  targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
32128
32311
  categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
32129
- confirmed: z128.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
32130
- waitSeconds: z128.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
32312
+ confirmed: z129.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
32313
+ waitSeconds: z129.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
32131
32314
  });
32132
- var GetInput = z128.object({
32133
- runId: z128.string().uuid().describe("ID del run devuelto por find_winning_products.")
32315
+ var GetInput = z129.object({
32316
+ runId: z129.string().uuid().describe("ID del run devuelto por find_winning_products.")
32134
32317
  });
32135
- var ListInput = z128.object({
32136
- limit: z128.number().int().min(1).max(20).default(10)
32318
+ var ListInput = z129.object({
32319
+ limit: z129.number().int().min(1).max(20).default(10)
32137
32320
  });
32138
32321
  function textResult(text2) {
32139
32322
  return {
@@ -32272,17 +32455,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
32272
32455
  __name(registerProductResearchTools, "registerProductResearchTools");
32273
32456
 
32274
32457
  // src/tools/dropshipping-projects.ts
32275
- import { z as z129 } from "zod";
32458
+ import { z as z130 } from "zod";
32276
32459
  var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
32277
32460
  var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
32278
32461
  var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
32279
- var ProjectId = z129.string().uuid();
32280
- var DropshippingProjectStatus = z129.enum([
32462
+ var ProjectId = z130.string().uuid();
32463
+ var DropshippingProjectStatus = z130.enum([
32281
32464
  "active",
32282
32465
  "completed",
32283
32466
  "archived"
32284
32467
  ]);
32285
- var DropshippingProjectPhase = z129.enum([
32468
+ var DropshippingProjectPhase = z130.enum([
32286
32469
  "research",
32287
32470
  "costing",
32288
32471
  "media",
@@ -32291,21 +32474,21 @@ var DropshippingProjectPhase = z129.enum([
32291
32474
  "advertising",
32292
32475
  "complete"
32293
32476
  ]);
32294
- var DropshippingRewardMilestone = z129.enum([
32477
+ var DropshippingRewardMilestone = z130.enum([
32295
32478
  "product_selected",
32296
32479
  "costing_saved",
32297
32480
  "product_media_ready",
32298
32481
  "creatives_completed",
32299
32482
  "campaign_created"
32300
32483
  ]);
32301
- var TargetCountry = z129.enum([
32484
+ var TargetCountry = z130.enum([
32302
32485
  "CO",
32303
32486
  "MX",
32304
32487
  "PE",
32305
32488
  "EC",
32306
32489
  "CL"
32307
32490
  ]);
32308
- var ResearchCategory = z129.enum([
32491
+ var ResearchCategory = z130.enum([
32309
32492
  "auto",
32310
32493
  "automotive",
32311
32494
  "kitchen",
@@ -32320,7 +32503,7 @@ var ResearchCategory = z129.enum([
32320
32503
  "garden",
32321
32504
  "cleaning"
32322
32505
  ]);
32323
- var HttpUrl3 = z129.string().url().max(2e3).refine((value) => {
32506
+ var HttpUrl3 = z130.string().url().max(2e3).refine((value) => {
32324
32507
  try {
32325
32508
  return [
32326
32509
  "http:",
@@ -32330,45 +32513,45 @@ var HttpUrl3 = z129.string().url().max(2e3).refine((value) => {
32330
32513
  return false;
32331
32514
  }
32332
32515
  }, "URL must use HTTP(S)");
32333
- var ResearchCandidateOrigin = z129.object({
32334
- type: z129.literal("research_candidate"),
32516
+ var ResearchCandidateOrigin = z130.object({
32517
+ type: z130.literal("research_candidate"),
32335
32518
  runId: ProjectId,
32336
- candidateSourceId: z129.string().min(1).max(160)
32519
+ candidateSourceId: z130.string().min(1).max(160)
32337
32520
  });
32338
- var TaskOrigin = z129.object({
32339
- type: z129.literal("task"),
32521
+ var TaskOrigin = z130.object({
32522
+ type: z130.literal("task"),
32340
32523
  taskId: ProjectId
32341
32524
  });
32342
- var ManualOrigin = z129.object({
32343
- type: z129.literal("manual"),
32525
+ var ManualOrigin = z130.object({
32526
+ type: z130.literal("manual"),
32344
32527
  clientRequestId: ProjectId,
32345
- country: z129.string().min(2).max(3).optional()
32528
+ country: z130.string().min(2).max(3).optional()
32346
32529
  });
32347
- var StartProjectInput = z129.object({
32348
- origin: z129.discriminatedUnion("type", [
32530
+ var StartProjectInput = z130.object({
32531
+ origin: z130.discriminatedUnion("type", [
32349
32532
  ResearchCandidateOrigin,
32350
32533
  TaskOrigin,
32351
32534
  ManualOrigin
32352
32535
  ]),
32353
- productName: z129.string().trim().min(1).max(240).optional(),
32536
+ productName: z130.string().trim().min(1).max(240).optional(),
32354
32537
  productUrl: HttpUrl3.optional(),
32355
- country: z129.string().min(2).max(3).optional(),
32356
- languageCode: z129.string().min(2).max(16).optional()
32538
+ country: z130.string().min(2).max(3).optional(),
32539
+ languageCode: z130.string().min(2).max(16).optional()
32357
32540
  }).strict();
32358
- var CostProjectInput = z129.object({
32541
+ var CostProjectInput = z130.object({
32359
32542
  projectId: ProjectId,
32360
- version: z129.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
32361
- country: z129.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
32543
+ version: z130.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
32544
+ country: z130.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
32362
32545
  message: "Pa\xEDs no soportado por ProductMaker."
32363
32546
  }).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
32364
- supplierCost: z129.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."),
32365
- shippingCost: z129.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
32366
- returnRate: z129.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."),
32367
- cancellationRate: z129.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."),
32368
- adsManagerCpa: z129.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
32369
- desiredMargin: z129.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
32370
- });
32371
- var GuideInput = z129.object({
32547
+ supplierCost: z130.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."),
32548
+ shippingCost: z130.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
32549
+ returnRate: z130.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."),
32550
+ cancellationRate: z130.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."),
32551
+ adsManagerCpa: z130.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
32552
+ desiredMargin: z130.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
32553
+ });
32554
+ var GuideInput = z130.object({
32372
32555
  projectId: ProjectId.optional()
32373
32556
  }).strict();
32374
32557
  var NEXT_ACTION_KINDS = [
@@ -32386,29 +32569,29 @@ var NEXT_ACTION_KINDS = [
32386
32569
  "repair_meta_campaign",
32387
32570
  "review_paused_campaign"
32388
32571
  ];
32389
- var DropshippingProjectNextAction = z129.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z129.object({
32390
- kind: z129.literal(kind),
32391
- href: z129.string().min(1)
32572
+ var DropshippingProjectNextAction = z130.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z130.object({
32573
+ kind: z130.literal(kind),
32574
+ href: z130.string().min(1)
32392
32575
  })));
32393
- var CostingInputSchema = z129.object({
32394
- country: z129.string().min(2).max(3),
32395
- supplierCost: z129.number().finite().positive(),
32396
- shippingCost: z129.number().finite().nonnegative(),
32397
- returnRate: z129.number().finite().min(0).lt(1),
32398
- cancellationRate: z129.number().finite().min(0).lt(1),
32399
- adsManagerCpa: z129.number().finite().nonnegative(),
32400
- desiredMargin: z129.number().finite().min(0).lt(1)
32576
+ var CostingInputSchema = z130.object({
32577
+ country: z130.string().min(2).max(3),
32578
+ supplierCost: z130.number().finite().positive(),
32579
+ shippingCost: z130.number().finite().nonnegative(),
32580
+ returnRate: z130.number().finite().min(0).lt(1),
32581
+ cancellationRate: z130.number().finite().min(0).lt(1),
32582
+ adsManagerCpa: z130.number().finite().nonnegative(),
32583
+ desiredMargin: z130.number().finite().min(0).lt(1)
32401
32584
  }).superRefine(({ returnRate, cancellationRate }, context) => {
32402
32585
  if (returnRate + cancellationRate >= 1) context.addIssue({
32403
- code: z129.ZodIssueCode.custom,
32586
+ code: z130.ZodIssueCode.custom,
32404
32587
  path: [
32405
32588
  "cancellationRate"
32406
32589
  ]
32407
32590
  });
32408
32591
  });
32409
- var FiniteCostingNumber = z129.number().finite();
32410
- var CostingResultSchema = z129.object({
32411
- country: z129.string().min(2).max(3),
32592
+ var FiniteCostingNumber = z130.number().finite();
32593
+ var CostingResultSchema = z130.object({
32594
+ country: z130.string().min(2).max(3),
32412
32595
  deliveryRate: FiniteCostingNumber,
32413
32596
  adjustedShippingCost: FiniteCostingNumber,
32414
32597
  adjustedCpa: FiniteCostingNumber,
@@ -32421,45 +32604,45 @@ var CostingResultSchema = z129.object({
32421
32604
  estimatedProfit: FiniteCostingNumber,
32422
32605
  actualMargin: FiniteCostingNumber,
32423
32606
  breakEvenAdsManagerCpa: FiniteCostingNumber,
32424
- wasPriceAutoAdjusted: z129.boolean(),
32425
- profitabilityStatus: z129.literal("healthy")
32426
- });
32427
- var RewardProgressSchema = z129.object({
32428
- campaignKey: z129.literal("dropshipping-launch-v1"),
32429
- totalCredits: z129.number().int().positive(),
32430
- earnedCredits: z129.number().int().nonnegative(),
32431
- milestones: z129.array(z129.object({
32607
+ wasPriceAutoAdjusted: z130.boolean(),
32608
+ profitabilityStatus: z130.literal("healthy")
32609
+ });
32610
+ var RewardProgressSchema = z130.object({
32611
+ campaignKey: z130.literal("dropshipping-launch-v1"),
32612
+ totalCredits: z130.number().int().positive(),
32613
+ earnedCredits: z130.number().int().nonnegative(),
32614
+ milestones: z130.array(z130.object({
32432
32615
  milestone: DropshippingRewardMilestone,
32433
- credits: z129.number().int().positive(),
32434
- available: z129.boolean().optional(),
32435
- earned: z129.boolean(),
32616
+ credits: z130.number().int().positive(),
32617
+ available: z130.boolean().optional(),
32618
+ earned: z130.boolean(),
32436
32619
  grantId: ProjectId.nullable(),
32437
- grantedAt: z129.string().datetime().nullable()
32620
+ grantedAt: z130.string().datetime().nullable()
32438
32621
  })).length(DropshippingRewardMilestone.options.length)
32439
32622
  });
32440
- var ProjectResponseSchema = z129.object({
32623
+ var ProjectResponseSchema = z130.object({
32441
32624
  id: ProjectId,
32442
32625
  taskId: ProjectId.nullable(),
32443
32626
  status: DropshippingProjectStatus,
32444
- originKey: z129.string().min(1),
32627
+ originKey: z130.string().min(1),
32445
32628
  researchRunId: ProjectId.nullable(),
32446
- candidateSourceId: z129.string().nullable(),
32447
- productName: z129.string().nullable(),
32629
+ candidateSourceId: z130.string().nullable(),
32630
+ productName: z130.string().nullable(),
32448
32631
  productUrl: HttpUrl3.nullable(),
32449
32632
  referenceImageUrl: HttpUrl3.nullable(),
32450
- targetCountry: z129.string().nullable(),
32451
- languageCode: z129.string().nullable(),
32452
- hasReferenceImage: z129.boolean(),
32453
- hasWinnerReferenceImage: z129.boolean(),
32633
+ targetCountry: z130.string().nullable(),
32634
+ languageCode: z130.string().nullable(),
32635
+ hasReferenceImage: z130.boolean(),
32636
+ hasWinnerReferenceImage: z130.boolean(),
32454
32637
  costingInput: CostingInputSchema.nullable(),
32455
32638
  costingResult: CostingResultSchema.nullable(),
32456
- costingVersion: z129.number().int().positive().nullable(),
32457
- version: z129.number().int().positive(),
32639
+ costingVersion: z130.number().int().positive().nullable(),
32640
+ version: z130.number().int().positive(),
32458
32641
  phase: DropshippingProjectPhase,
32459
32642
  nextAction: DropshippingProjectNextAction.nullable(),
32460
32643
  rewards: RewardProgressSchema,
32461
- createdAt: z129.string().datetime(),
32462
- updatedAt: z129.string().datetime()
32644
+ createdAt: z130.string().datetime(),
32645
+ updatedAt: z130.string().datetime()
32463
32646
  }).passthrough();
32464
32647
  var NEXT_ACTION_GUIDANCE = {
32465
32648
  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.",
@@ -32579,58 +32762,58 @@ function registerDropshippingProjectTools(server, api) {
32579
32762
  __name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
32580
32763
 
32581
32764
  // src/tools/daily-control.ts
32582
- import { z as z130 } from "zod";
32765
+ import { z as z131 } from "zod";
32583
32766
  var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
32584
32767
  var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
32585
32768
  var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
32586
- var ProviderCampaignIdentifier = z130.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
32587
- var DateOnly = z130.string().regex(/^\d{4}-\d{2}-\d{2}$/);
32588
- var DailyControlInput = z130.object({
32769
+ var ProviderCampaignIdentifier = z131.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
32770
+ var DateOnly = z131.string().regex(/^\d{4}-\d{2}-\d{2}$/);
32771
+ var DailyControlInput = z131.object({
32589
32772
  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."),
32590
- days: z130.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
32591
- projectId: z130.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
32773
+ days: z131.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
32774
+ projectId: z131.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
32592
32775
  }).strict();
32593
- var LinkCampaignInput = z130.object({
32594
- projectId: z130.string().uuid(),
32595
- provider: z130.enum([
32776
+ var LinkCampaignInput = z131.object({
32777
+ projectId: z131.string().uuid(),
32778
+ provider: z131.enum([
32596
32779
  "meta",
32597
32780
  "tiktok"
32598
32781
  ]),
32599
32782
  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."),
32600
32783
  campaignId: ProviderCampaignIdentifier
32601
32784
  }).strict();
32602
- var ReportReturnsInput = z130.object({
32603
- projectId: z130.string().uuid(),
32785
+ var ReportReturnsInput = z131.object({
32786
+ projectId: z131.string().uuid(),
32604
32787
  date: DateOnly,
32605
- returnedOrders: z130.number().int().min(0).max(1e5),
32606
- note: z130.string().trim().max(280).optional()
32788
+ returnedOrders: z131.number().int().min(0).max(1e5),
32789
+ note: z131.string().trim().max(280).optional()
32607
32790
  }).strict();
32608
- var DailyControlStatusMirror = DailyControlStatusEnum.or(z130.string());
32609
- var DailyControlLightMirror = DailyControlLightEnum.or(z130.string());
32610
- var DailyControlSourceMirror = DailyControlSourceEnum.or(z130.string());
32611
- var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z130.string());
32612
- var DailyControlDayMirror = z130.object({
32613
- date: z130.string(),
32614
- returnedOrders: z130.number(),
32791
+ var DailyControlStatusMirror = DailyControlStatusEnum.or(z131.string());
32792
+ var DailyControlLightMirror = DailyControlLightEnum.or(z131.string());
32793
+ var DailyControlSourceMirror = DailyControlSourceEnum.or(z131.string());
32794
+ var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z131.string());
32795
+ var DailyControlDayMirror = z131.object({
32796
+ date: z131.string(),
32797
+ returnedOrders: z131.number(),
32615
32798
  returnedSource: DailyControlSourceMirror,
32616
32799
  cancelledSource: DailyControlSourceMirror,
32617
- hasEstimates: z130.boolean(),
32800
+ hasEstimates: z131.boolean(),
32618
32801
  light: DailyControlLightMirror
32619
32802
  }).passthrough();
32620
- var DailyControlProductMirror = z130.object({
32621
- projectId: z130.string().uuid(),
32622
- productName: z130.string().nullable(),
32803
+ var DailyControlProductMirror = z131.object({
32804
+ projectId: z131.string().uuid(),
32805
+ productName: z131.string().nullable(),
32623
32806
  status: DailyControlStatusMirror,
32624
- statusMessage: z130.string().nullable(),
32625
- days: z130.array(DailyControlDayMirror),
32807
+ statusMessage: z131.string().nullable(),
32808
+ days: z131.array(DailyControlDayMirror),
32626
32809
  verdict: DailyControlVerdictMirror.nullable(),
32627
- rationale: z130.string().nullable()
32810
+ rationale: z131.string().nullable()
32628
32811
  }).passthrough();
32629
- var DailyControlResponseMirror = z130.object({
32630
- since: z130.string(),
32631
- until: z130.string(),
32632
- products: z130.array(DailyControlProductMirror),
32633
- archivedProjectSpend: z130.array(z130.unknown())
32812
+ var DailyControlResponseMirror = z131.object({
32813
+ since: z131.string(),
32814
+ until: z131.string(),
32815
+ products: z131.array(DailyControlProductMirror),
32816
+ archivedProjectSpend: z131.array(z131.unknown())
32634
32817
  }).passthrough();
32635
32818
  var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
32636
32819
  function withWarnings(response) {
@@ -32705,7 +32888,7 @@ __name(registerDailyControlTools, "registerDailyControlTools");
32705
32888
  // src/tools/product-control.ts
32706
32889
  import { readFile, stat } from "fs/promises";
32707
32890
  import { basename as basename2, isAbsolute, resolve as resolve3 } from "path";
32708
- import { z as z131 } from "zod";
32891
+ import { z as z132 } from "zod";
32709
32892
  var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
32710
32893
  var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
32711
32894
  var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
@@ -32718,36 +32901,36 @@ var createOperationGuidance = getProductMakerCapabilityModelGuidance("create_ope
32718
32901
  var mergeProductsGuidance = getProductMakerCapabilityModelGuidance("merge_products");
32719
32902
  var syncShopifyOrdersGuidance = getProductMakerCapabilityModelGuidance("sync_shopify_orders");
32720
32903
  var importOrdersFileGuidance = getProductMakerCapabilityModelGuidance("import_orders_file");
32721
- var DateOnly2 = z131.string().regex(/^\d{4}-\d{2}-\d{2}$/);
32904
+ var DateOnly2 = z132.string().regex(/^\d{4}-\d{2}-\d{2}$/);
32722
32905
  var IMPORT_BATCH_MAX2 = 50;
32723
- var ProductControlListInput = z131.object({
32724
- days: z131.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
32906
+ var ProductControlListInput = z132.object({
32907
+ days: z132.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
32725
32908
  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."),
32726
- shopDomain: z131.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
32909
+ shopDomain: z132.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
32727
32910
  }).strict();
32728
- var ImportableProductsInput = z131.object({
32729
- q: z131.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
32730
- after: z131.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
32731
- shopDomain: z131.string().min(1).optional()
32911
+ var ImportableProductsInput = z132.object({
32912
+ q: z132.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
32913
+ after: z132.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
32914
+ shopDomain: z132.string().min(1).optional()
32732
32915
  }).strict();
32733
- var ImportProductControlsInput = z131.object({
32734
- shopifyProductIds: z131.array(z131.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."),
32916
+ var ImportProductControlsInput = z132.object({
32917
+ shopifyProductIds: z132.array(z132.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."),
32735
32918
  // Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
32736
32919
  // sin decir a cuál archivaría el producto bajo la tienda equivocada.
32737
- shopDomain: z131.string().min(1)
32920
+ shopDomain: z132.string().min(1)
32738
32921
  }).strict();
32739
- var SetProductCostingInput = z131.object({
32740
- shopDomain: z131.string().min(1),
32741
- shopifyProductId: z131.string().min(1).max(64),
32742
- targetCountry: z131.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
32743
- supplierCost: z131.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
32744
- shippingCost: z131.number().finite().nonnegative(),
32745
- returnRate: z131.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
32746
- cancellationRate: z131.number().finite().min(0).lt(1)
32922
+ var SetProductCostingInput = z132.object({
32923
+ shopDomain: z132.string().min(1),
32924
+ shopifyProductId: z132.string().min(1).max(64),
32925
+ targetCountry: z132.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
32926
+ supplierCost: z132.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
32927
+ shippingCost: z132.number().finite().nonnegative(),
32928
+ returnRate: z132.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
32929
+ cancellationRate: z132.number().finite().min(0).lt(1)
32747
32930
  }).strict();
32748
- var Count = z131.number().int().min(0).max(1e5).nullable().optional();
32749
- var ReportProductCountsInput = z131.object({
32750
- productControlId: z131.string().uuid().describe("El identificador que devuelve get_product_control."),
32931
+ var Count = z132.number().int().min(0).max(1e5).nullable().optional();
32932
+ var ReportProductCountsInput = z132.object({
32933
+ productControlId: z132.string().uuid().describe("El identificador que devuelve get_product_control."),
32751
32934
  date: DateOnly2,
32752
32935
  orders: Count.describe("Pedidos que entraron ese d\xEDa."),
32753
32936
  cancelledOrders: Count,
@@ -32757,36 +32940,36 @@ var ReportProductCountsInput = z131.object({
32757
32940
  }).strict();
32758
32941
  var MAX_ORDERS_FILE_BYTES = 8 * 1024 * 1024;
32759
32942
  var SyncShopifyOrdersInput = SyncShopifyOrdersSchema;
32760
- var ImportOrdersFileInput = z131.object({
32943
+ var ImportOrdersFileInput = z132.object({
32761
32944
  /** Ruta ABSOLUTA en la máquina de quien usa el MCP. */
32762
- path: z131.string().min(1),
32763
- operationId: z131.string().uuid().optional(),
32945
+ path: z132.string().min(1),
32946
+ operationId: z132.string().uuid().optional(),
32764
32947
  /** Solo mirar: devuelve el resumen y no escribe nada. */
32765
- dryRun: z131.boolean().optional()
32948
+ dryRun: z132.boolean().optional()
32766
32949
  }).strict();
32767
- var CreateOperationInput = z131.object({
32768
- countryCode: z131.string().length(2),
32769
- label: z131.string().trim().min(1).max(60).optional()
32950
+ var CreateOperationInput = z132.object({
32951
+ countryCode: z132.string().length(2),
32952
+ label: z132.string().trim().min(1).max(60).optional()
32770
32953
  }).strict();
32771
- var MergeProductsInput = z131.object({
32772
- sourceId: z131.string().uuid(),
32773
- targetId: z131.string().uuid()
32954
+ var MergeProductsInput = z132.object({
32955
+ sourceId: z132.string().uuid(),
32956
+ targetId: z132.string().uuid()
32774
32957
  }).strict();
32775
- var SetMonthlyExpenseInput = z131.object({
32776
- month: z131.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
32958
+ var SetMonthlyExpenseInput = z132.object({
32959
+ month: z132.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
32777
32960
  label: SaveMonthlyExpenseSchema.shape.label,
32778
- amount: z131.number().finite().min(0),
32779
- operationId: z131.string().uuid().optional()
32961
+ amount: z132.number().finite().min(0),
32962
+ operationId: z132.string().uuid().optional()
32780
32963
  }).strict();
32781
- var SetAdSpendInput = z131.object({
32782
- month: z131.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
32783
- operationId: z131.string().uuid().optional(),
32964
+ var SetAdSpendInput = z132.object({
32965
+ month: z132.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
32966
+ operationId: z132.string().uuid().optional(),
32784
32967
  /** null RETIRA la corrección; cero afirma que no pautó. */
32785
- amount: z131.number().finite().min(0).nullable()
32968
+ amount: z132.number().finite().min(0).nullable()
32786
32969
  }).strict();
32787
- var GetFinancesInput = z131.object({
32788
- month: z131.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."),
32789
- operationId: z131.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
32970
+ var GetFinancesInput = z132.object({
32971
+ month: z132.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."),
32972
+ operationId: z132.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
32790
32973
  }).strict();
32791
32974
  function registerProductControlTools(server, api, { transport = "http" } = {}) {
32792
32975
  server.registerTool("get_product_control", {
@@ -32978,28 +33161,28 @@ function registerProductControlTools(server, api, { transport = "http" } = {}) {
32978
33161
  __name(registerProductControlTools, "registerProductControlTools");
32979
33162
 
32980
33163
  // src/tools/market-study-estimate.ts
32981
- import { z as z132 } from "zod";
33164
+ import { z as z133 } from "zod";
32982
33165
  var estimateMarketStudyGuidance = getProductMakerCapabilityModelGuidance("estimate_market_study_cost");
32983
- var ProductTaskOutputEnum = z132.enum([
33166
+ var ProductTaskOutputEnum = z133.enum([
32984
33167
  "landing",
32985
33168
  "video",
32986
33169
  "image"
32987
33170
  ]);
32988
- var EstimateMarketStudyInput = z132.object({
32989
- kind: z132.enum([
33171
+ var EstimateMarketStudyInput = z133.object({
33172
+ kind: z133.enum([
32990
33173
  "video",
32991
33174
  "product_task"
32992
33175
  ]).describe('"video" para generate_video_creative; "product_task" para create_product_task.'),
32993
- videoAngleCount: z132.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
32994
- durationSeconds: z132.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
33176
+ videoAngleCount: z133.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
33177
+ durationSeconds: z133.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
32995
33178
  videoStructure: VideoStructureEnum.default("single_take"),
32996
33179
  videoQuality: VideoQualityEnum.default("economy"),
32997
33180
  videoResolution: VideoResolutionEnum.default("480p"),
32998
- productImageCount: z132.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
33181
+ productImageCount: z133.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
32999
33182
  outputs: ProductTaskOutputEnum.array().min(1).max(3).optional().describe('Solo para kind="product_task": los mismos outputs de create_product_task. Default: todos.'),
33000
- generateAiMusic: z132.boolean().optional(),
33183
+ generateAiMusic: z133.boolean().optional(),
33001
33184
  generateAiEdit: AiEditRequestSchema.optional(),
33002
- replicateWinnerWhenFound: z132.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.")
33185
+ replicateWinnerWhenFound: z133.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.")
33003
33186
  }).strict();
33004
33187
  function buildMarketStudyEstimateRequests(input) {
33005
33188
  const quotesVideo = input.kind === "video" || (input.outputs ?? [