@productmaker/mcp 11.2.0 → 11.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/http.js +830 -789
  2. package/dist/stdio.js +819 -778
  3. package/package.json +1 -1
package/dist/http.js CHANGED
@@ -7514,6 +7514,12 @@ var ResultAngle = Angle.extend({
7514
7514
  });
7515
7515
  var MVPResult = z39.object({
7516
7516
  taskId: z39.string().uuid(),
7517
+ /** Read-only identity derived from validated persisted request context.
7518
+ * Optional for older APIs and content-only tasks; absence never implies a service. */
7519
+ subjectKind: z39.enum([
7520
+ "product",
7521
+ "service"
7522
+ ]).optional(),
7517
7523
  product: Product,
7518
7524
  // READ contract, NOT a generation cap. The generator writes exactly 3 angles
7519
7525
  // (`replaceAngles` renumbers positions 0..2), but a duplicated angles run
@@ -8314,6 +8320,10 @@ var VideoRegenerateEstimationOptions = z40.object({
8314
8320
  sceneCount: z40.number().int().positive().optional()
8315
8321
  });
8316
8322
  var ImageCreativeEstimationOptions = z40.object({
8323
+ subject: z40.enum([
8324
+ "product",
8325
+ "service"
8326
+ ]).optional(),
8317
8327
  nVariants: z40.number().int().positive().optional(),
8318
8328
  generateAdCopy: z40.boolean().optional(),
8319
8329
  /** Literal model name (e.g. 'gpt-image/1.5', 'nano-banana-2'). Defaults to the premium ad-creative model. */
@@ -9211,6 +9221,7 @@ var VideoMixQaJobSchema = z46.object({
9211
9221
  // jobId for retry uniqueness) but the worker only reads mixSceneTaskId.
9212
9222
  externalId: z46.string().min(1).optional()
9213
9223
  });
9224
+ var BrandExtractLocaleSchema = z46.string().regex(/^[A-Za-z]{2,3}(?:[-_][A-Za-z0-9]{2,8})?$/, "invalid locale");
9214
9225
  var BrandExtractJobSchema = z46.object({
9215
9226
  brandId: z46.string().uuid(),
9216
9227
  // Generation is part of the durable paid-spend identity. Default 1 keeps
@@ -9226,7 +9237,10 @@ var BrandExtractJobSchema = z46.object({
9226
9237
  "shopify_sync"
9227
9238
  ]).default("url_extract"),
9228
9239
  shopifyShopId: z46.string().optional(),
9229
- documents: z46.array(BrandExtractDocumentSchema).max(3).default([])
9240
+ documents: z46.array(BrandExtractDocumentSchema).max(3).default([]),
9241
+ // Requesting user's UI locale (BCP-47, e.g. "es", "en-US"). Fallback for the
9242
+ // brand kit's output language when the brand's own text is inconclusive.
9243
+ locale: BrandExtractLocaleSchema.optional()
9230
9244
  });
9231
9245
 
9232
9246
  // ../../packages/types/src/chat-parse.ts
@@ -21820,19 +21834,46 @@ var DropiFinancialSyncResultSchema = z103.object({
21820
21834
  }))
21821
21835
  });
21822
21836
 
21823
- // ../../packages/types/src/service-website-capture.ts
21837
+ // ../../packages/types/src/service-image.ts
21824
21838
  import { z as z104 } from "zod";
21839
+ var ServiceImageIntentSchema = z104.enum([
21840
+ "user_brief",
21841
+ "delegate_to_ai"
21842
+ ]);
21843
+ var ServiceImageInputSchema = z104.object({
21844
+ instruction: z104.string().trim().max(4e3).default(""),
21845
+ intent: ServiceImageIntentSchema.default("user_brief")
21846
+ }).strict().refine((value) => value.intent === "delegate_to_ai" || value.instruction.length > 0, {
21847
+ message: "Cu\xE9ntanos qu\xE9 servicio quieres promocionar.",
21848
+ path: [
21849
+ "instruction"
21850
+ ]
21851
+ });
21852
+ var ServiceImageContextSchema = z104.object({
21853
+ kind: z104.literal("service_image"),
21854
+ version: z104.literal(1),
21855
+ instruction: z104.string().max(4e3),
21856
+ intent: ServiceImageIntentSchema,
21857
+ businessName: z104.string().max(300),
21858
+ description: z104.string().max(2e4),
21859
+ brandCard: z104.string().max(2e4),
21860
+ palette: z104.array(z104.string()).max(20),
21861
+ referenceKeys: z104.array(z104.string()).max(10)
21862
+ }).strict();
21863
+
21864
+ // ../../packages/types/src/service-website-capture.ts
21865
+ import { z as z105 } from "zod";
21825
21866
  var WEBSITE_CAPTURE_MAX_RESEARCH_BYTES = 1024 * 1024;
21826
21867
  var WEBSITE_CAPTURE_MAX_FILES = 100;
21827
21868
  var WEBSITE_CAPTURE_MAX_FILE_BYTES = 8 * 1024 * 1024;
21828
21869
  var WEBSITE_CAPTURE_MAX_BUNDLE_BYTES = 30 * 1024 * 1024;
21829
- var WebsiteCaptureCauseSchema = z104.enum([
21870
+ var WebsiteCaptureCauseSchema = z105.enum([
21830
21871
  "site_blocked",
21831
21872
  "site_unreachable",
21832
21873
  "not_enough_content",
21833
21874
  "internal"
21834
21875
  ]);
21835
- var WebsiteCaptureStatusSchema = z104.enum([
21876
+ var WebsiteCaptureStatusSchema = z105.enum([
21836
21877
  "queued",
21837
21878
  "capturing",
21838
21879
  "ready",
@@ -21854,128 +21895,128 @@ function normalizeWebsiteCaptureUrl(value) {
21854
21895
  }
21855
21896
  }
21856
21897
  __name(normalizeWebsiteCaptureUrl, "normalizeWebsiteCaptureUrl");
21857
- var WebsiteCaptureRequestSchema = z104.object({
21858
- url: z104.string().trim().max(2048).url().refine((value) => normalizeWebsiteCaptureUrl(value) !== null, "Use an HTTP(S) URL without credentials").transform((value) => normalizeWebsiteCaptureUrl(value)),
21898
+ var WebsiteCaptureRequestSchema = z105.object({
21899
+ url: z105.string().trim().max(2048).url().refine((value) => normalizeWebsiteCaptureUrl(value) !== null, "Use an HTTP(S) URL without credentials").transform((value) => normalizeWebsiteCaptureUrl(value)),
21859
21900
  language: MotionGraphicsLanguageSchema
21860
21901
  }).strict();
21861
- var WebsiteCaptureResponseSchema = z104.object({
21862
- captureId: z104.string().uuid(),
21902
+ var WebsiteCaptureResponseSchema = z105.object({
21903
+ captureId: z105.string().uuid(),
21863
21904
  status: WebsiteCaptureStatusSchema,
21864
- expiresAt: z104.string().datetime(),
21865
- previewUrl: z104.string().url().optional(),
21905
+ expiresAt: z105.string().datetime(),
21906
+ previewUrl: z105.string().url().optional(),
21866
21907
  cause: WebsiteCaptureCauseSchema.optional()
21867
21908
  });
21868
21909
  var WebsiteCaptureJobSchema = WebsiteCaptureRequestSchema.extend({
21869
- captureId: z104.string().uuid(),
21870
- attempt: z104.number().int().positive(),
21871
- leaseUntil: z104.string().datetime()
21910
+ captureId: z105.string().uuid(),
21911
+ attempt: z105.number().int().positive(),
21912
+ leaseUntil: z105.string().datetime()
21872
21913
  });
21873
- var WebsiteCaptureClaimResponseSchema = z104.object({
21914
+ var WebsiteCaptureClaimResponseSchema = z105.object({
21874
21915
  capture: WebsiteCaptureJobSchema.nullable()
21875
21916
  });
21876
21917
  var attempt = {
21877
- attempt: z104.number().int().positive()
21918
+ attempt: z105.number().int().positive()
21878
21919
  };
21879
- var digest = z104.string().regex(/^[a-f0-9]{64}$/);
21880
- var WebsiteCaptureUploadRequestSchema = z104.object({
21920
+ var digest = z105.string().regex(/^[a-f0-9]{64}$/);
21921
+ var WebsiteCaptureUploadRequestSchema = z105.object({
21881
21922
  ...attempt,
21882
- contentLength: z104.number().int().positive().max(WEBSITE_CAPTURE_MAX_BUNDLE_BYTES),
21923
+ contentLength: z105.number().int().positive().max(WEBSITE_CAPTURE_MAX_BUNDLE_BYTES),
21883
21924
  sha256: digest
21884
21925
  }).strict();
21885
- var WebsiteCaptureDoneRequestSchema = z104.object({
21926
+ var WebsiteCaptureDoneRequestSchema = z105.object({
21886
21927
  ...attempt,
21887
21928
  sha256: digest
21888
21929
  }).strict();
21889
- var WebsiteCaptureFailedRequestSchema = z104.object({
21930
+ var WebsiteCaptureFailedRequestSchema = z105.object({
21890
21931
  ...attempt,
21891
21932
  cause: WebsiteCaptureCauseSchema
21892
21933
  }).strict();
21893
- var WebsiteCaptureBundleSchema = z104.object({
21894
- version: z104.literal(1),
21895
- files: z104.array(z104.object({
21896
- path: z104.string().max(140).regex(/^research\/(?:page\.json|(?:desktop|mobile)-[1-9]\d*\.jpg|logo\.(?:png|svg)|image-[1-9]\d*\.(?:png|jpg|jpeg|webp|svg|avif)|font-[1-9]\d*\.(?:woff2?|ttf|otf))$/),
21897
- base64: z104.string().max(Math.ceil(WEBSITE_CAPTURE_MAX_FILE_BYTES / 3) * 4).regex(/^[A-Za-z0-9+/]*={0,2}$/).refine((value) => value.length % 4 === 0),
21934
+ var WebsiteCaptureBundleSchema = z105.object({
21935
+ version: z105.literal(1),
21936
+ files: z105.array(z105.object({
21937
+ path: z105.string().max(140).regex(/^research\/(?:page\.json|(?:desktop|mobile)-[1-9]\d*\.jpg|logo\.(?:png|svg)|image-[1-9]\d*\.(?:png|jpg|jpeg|webp|svg|avif)|font-[1-9]\d*\.(?:woff2?|ttf|otf))$/),
21938
+ base64: z105.string().max(Math.ceil(WEBSITE_CAPTURE_MAX_FILE_BYTES / 3) * 4).regex(/^[A-Za-z0-9+/]*={0,2}$/).refine((value) => value.length % 4 === 0),
21898
21939
  sha256: digest
21899
21940
  }).strict()).min(1).max(WEBSITE_CAPTURE_MAX_FILES)
21900
21941
  }).strict().refine((bundle) => new Set(bundle.files.map((file) => file.path)).size === bundle.files.length, "Duplicate capture file");
21901
- var WebsiteCaptureScreenshotSchema = z104.object({
21902
- file: z104.string(),
21903
- scrollTop: z104.number()
21904
- });
21905
- var WebsiteCaptureAccessSchema = z104.object({
21906
- publicContentText: z104.string().max(8e3),
21907
- passwordGate: z104.boolean(),
21908
- challengeGate: z104.boolean(),
21909
- blockingOverlay: z104.boolean()
21910
- });
21911
- var WebsiteCaptureResearchSchema = z104.object({
21912
- requestedUrl: z104.string().url(),
21913
- capturedAt: z104.string().datetime(),
21914
- locale: z104.string(),
21915
- bodyTextTruncated: z104.boolean(),
21916
- finalUrl: z104.string().url(),
21917
- lang: z104.string().nullable(),
21918
- title: z104.string(),
21919
- description: z104.string(),
21920
- openGraph: z104.object({
21921
- title: z104.string(),
21922
- description: z104.string(),
21923
- image: z104.string(),
21924
- siteName: z104.string()
21942
+ var WebsiteCaptureScreenshotSchema = z105.object({
21943
+ file: z105.string(),
21944
+ scrollTop: z105.number()
21945
+ });
21946
+ var WebsiteCaptureAccessSchema = z105.object({
21947
+ publicContentText: z105.string().max(8e3),
21948
+ passwordGate: z105.boolean(),
21949
+ challengeGate: z105.boolean(),
21950
+ blockingOverlay: z105.boolean()
21951
+ });
21952
+ var WebsiteCaptureResearchSchema = z105.object({
21953
+ requestedUrl: z105.string().url(),
21954
+ capturedAt: z105.string().datetime(),
21955
+ locale: z105.string(),
21956
+ bodyTextTruncated: z105.boolean(),
21957
+ finalUrl: z105.string().url(),
21958
+ lang: z105.string().nullable(),
21959
+ title: z105.string(),
21960
+ description: z105.string(),
21961
+ openGraph: z105.object({
21962
+ title: z105.string(),
21963
+ description: z105.string(),
21964
+ image: z105.string(),
21965
+ siteName: z105.string()
21925
21966
  }),
21926
- themeColor: z104.string(),
21927
- headings: z104.object({
21928
- h1: z104.array(z104.string()),
21929
- h2: z104.array(z104.string()),
21930
- h3: z104.array(z104.string())
21967
+ themeColor: z105.string(),
21968
+ headings: z105.object({
21969
+ h1: z105.array(z105.string()),
21970
+ h2: z105.array(z105.string()),
21971
+ h3: z105.array(z105.string())
21931
21972
  }),
21932
- callsToAction: z104.array(z104.string()),
21933
- listItems: z104.array(z104.string()),
21934
- bodyText: z104.string(),
21973
+ callsToAction: z105.array(z105.string()),
21974
+ listItems: z105.array(z105.string()),
21975
+ bodyText: z105.string(),
21935
21976
  access: WebsiteCaptureAccessSchema.optional(),
21936
- consent: z104.object({
21937
- pressed: z104.string().nullable(),
21938
- removed: z104.number().nonnegative()
21977
+ consent: z105.object({
21978
+ pressed: z105.string().nullable(),
21979
+ removed: z105.number().nonnegative()
21939
21980
  }).optional(),
21940
- overlaysDismissed: z104.number().int().nonnegative().optional(),
21941
- style: z104.object({
21942
- bodyBackground: z104.string(),
21943
- bodyColor: z104.string(),
21944
- bodyFont: z104.string(),
21945
- headingFont: z104.string().nullable(),
21946
- headingColor: z104.string().nullable(),
21947
- actionColors: z104.array(z104.object({
21948
- color: z104.string(),
21949
- uses: z104.number()
21981
+ overlaysDismissed: z105.number().int().nonnegative().optional(),
21982
+ style: z105.object({
21983
+ bodyBackground: z105.string(),
21984
+ bodyColor: z105.string(),
21985
+ bodyFont: z105.string(),
21986
+ headingFont: z105.string().nullable(),
21987
+ headingColor: z105.string().nullable(),
21988
+ actionColors: z105.array(z105.object({
21989
+ color: z105.string(),
21990
+ uses: z105.number()
21950
21991
  }))
21951
21992
  }),
21952
- images: z104.array(z104.object({
21953
- file: z104.string(),
21954
- src: z104.string(),
21955
- alt: z104.string(),
21956
- width: z104.number().nullable(),
21957
- height: z104.number().nullable(),
21958
- isOpenGraph: z104.boolean()
21993
+ images: z105.array(z105.object({
21994
+ file: z105.string(),
21995
+ src: z105.string(),
21996
+ alt: z105.string(),
21997
+ width: z105.number().nullable(),
21998
+ height: z105.number().nullable(),
21999
+ isOpenGraph: z105.boolean()
21959
22000
  })),
21960
- logo: z104.object({
21961
- file: z104.literal("logo.png"),
21962
- svg: z104.literal("logo.svg").optional(),
21963
- width: z104.number(),
21964
- height: z104.number()
22001
+ logo: z105.object({
22002
+ file: z105.literal("logo.png"),
22003
+ svg: z105.literal("logo.svg").optional(),
22004
+ width: z105.number(),
22005
+ height: z105.number()
21965
22006
  }).nullable(),
21966
- fonts: z104.array(z104.object({
21967
- family: z104.string(),
21968
- weight: z104.string(),
21969
- style: z104.string(),
21970
- unicodeRange: z104.string().nullable(),
21971
- file: z104.string().optional()
22007
+ fonts: z105.array(z105.object({
22008
+ family: z105.string(),
22009
+ weight: z105.string(),
22010
+ style: z105.string(),
22011
+ unicodeRange: z105.string().nullable(),
22012
+ file: z105.string().optional()
21972
22013
  }).transform((font) => ({
21973
22014
  ...font,
21974
22015
  file: font.file
21975
22016
  }))),
21976
- screenshots: z104.object({
21977
- desktop: z104.array(WebsiteCaptureScreenshotSchema),
21978
- mobile: z104.array(WebsiteCaptureScreenshotSchema)
22017
+ screenshots: z105.object({
22018
+ desktop: z105.array(WebsiteCaptureScreenshotSchema),
22019
+ mobile: z105.array(WebsiteCaptureScreenshotSchema)
21979
22020
  })
21980
22021
  });
21981
22022
 
@@ -22488,23 +22529,23 @@ import { InsufficientScopeError, InvalidTokenError } from "@modelcontextprotocol
22488
22529
  import { createRemoteJWKSet as createRemoteJWKSet2, jwtVerify as jwtVerify2 } from "jose";
22489
22530
 
22490
22531
  // src/auth/oauth-config.ts
22491
- import { z as z105 } from "zod";
22532
+ import { z as z106 } from "zod";
22492
22533
  var MCP_RESOURCE = new URL("https://mcp.productmaker.app/mcp");
22493
22534
  var MCP_SCOPE = "mcp:access";
22494
22535
  var REFRESH_SCOPE = "offline_access";
22495
22536
  var STATIC_CLIENT_ISSUER = new URL(MCP_RESOURCE.origin);
22496
- var oauthEnvSchema = z105.object({
22497
- MCP_REMOTE_AUTH_MODE: z105.literal("oauth"),
22498
- MCP_AUTH0_ISSUER: z105.string().trim().min(1),
22499
- MCP_AUTH0_AUDIENCE: z105.string().trim().refine((value) => value === MCP_RESOURCE.href, {
22537
+ var oauthEnvSchema = z106.object({
22538
+ MCP_REMOTE_AUTH_MODE: z106.literal("oauth"),
22539
+ MCP_AUTH0_ISSUER: z106.string().trim().min(1),
22540
+ MCP_AUTH0_AUDIENCE: z106.string().trim().refine((value) => value === MCP_RESOURCE.href, {
22500
22541
  message: `must equal ${MCP_RESOURCE.href}`
22501
22542
  }),
22502
- MCP_AUTH0_CLIENT_ID: z105.string().trim().min(1),
22503
- MCP_AUTH0_CLIENT_SECRET: z105.string().trim().min(1),
22504
- PM_API_AUDIENCE: z105.string().trim().min(1),
22505
- AUTH0_AUDIENCE: z105.string().trim().min(1),
22506
- MCP_STATIC_CLIENT_ID: z105.string().trim().min(1).optional(),
22507
- MCP_STATIC_CLIENT_SECRET: z105.string().trim().min(1).optional()
22543
+ MCP_AUTH0_CLIENT_ID: z106.string().trim().min(1),
22544
+ MCP_AUTH0_CLIENT_SECRET: z106.string().trim().min(1),
22545
+ PM_API_AUDIENCE: z106.string().trim().min(1),
22546
+ AUTH0_AUDIENCE: z106.string().trim().min(1),
22547
+ MCP_STATIC_CLIENT_ID: z106.string().trim().min(1).optional(),
22548
+ MCP_STATIC_CLIENT_SECRET: z106.string().trim().min(1).optional()
22508
22549
  });
22509
22550
  function formatZodIssues(error) {
22510
22551
  return error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
@@ -23658,7 +23699,7 @@ var ApiClient = class {
23658
23699
  };
23659
23700
 
23660
23701
  // src/index.ts
23661
- var MCP_VERSION = "11.2.0";
23702
+ var MCP_VERSION = "11.2.1";
23662
23703
 
23663
23704
  // src/meta-upload-app.ts
23664
23705
  import { readFileSync } from "fs";
@@ -23730,7 +23771,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
23730
23771
  __name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
23731
23772
 
23732
23773
  // src/tools/tasks.ts
23733
- import { z as z110 } from "zod";
23774
+ import { z as z111 } from "zod";
23734
23775
 
23735
23776
  // src/resolve-image.ts
23736
23777
  import { lookup as dnsLookup } from "dns/promises";
@@ -24291,9 +24332,9 @@ async function resolveMediaRef(ref, opts) {
24291
24332
  __name(resolveMediaRef, "resolveMediaRef");
24292
24333
 
24293
24334
  // src/tools/shared.ts
24294
- import { z as z106 } from "zod";
24295
- var Lang = z106.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);
24296
- var Country = z106.string().min(2).max(3);
24335
+ import { z as z107 } from "zod";
24336
+ var Lang = z107.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);
24337
+ var Country = z107.string().min(2).max(3);
24297
24338
  var LandingStrategyEnum = LandingStrategySchema;
24298
24339
  var LandingImageFormatEnum = LandingImageFormatSchema;
24299
24340
  var VideoPresetEnum = VideoPreset.extract([
@@ -24397,7 +24438,7 @@ function animationStyleApplies(videoPreset, angleNarratives) {
24397
24438
  return ANIMATED_VIDEO_PRESETS.has(videoPreset ?? "") || (angleNarratives ?? []).some((n) => ANIMATED_NARRATIVE_STYLES.has(n));
24398
24439
  }
24399
24440
  __name(animationStyleApplies, "animationStyleApplies");
24400
- var VideoTierEnum = z106.enum([
24441
+ var VideoTierEnum = z107.enum([
24401
24442
  "basic"
24402
24443
  ]);
24403
24444
  function resolveVideoTier(_tier) {
@@ -24455,10 +24496,10 @@ var ImageCreativeStyleEnum = ImageCreativeStyle;
24455
24496
  var ImageCreativeArchetypeEnum = ImageCreativeArchetype;
24456
24497
  var ImageCreativeVisualTreatmentEnum = ImageCreativeVisualTreatment;
24457
24498
  var ImageCreativeAspectRatioEnum = ImageCreativeAspectRatio;
24458
- var ImageRefSchema = z106.object({
24459
- url: z106.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.'),
24460
- path: z106.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`.'),
24461
- assetId: z106.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.")
24499
+ var ImageRefSchema = z107.object({
24500
+ url: z107.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.'),
24501
+ path: z107.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`.'),
24502
+ assetId: z107.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.")
24462
24503
  }).refine((v) => [
24463
24504
  v.url,
24464
24505
  v.path,
@@ -24466,11 +24507,11 @@ var ImageRefSchema = z106.object({
24466
24507
  ].filter(Boolean).length === 1, {
24467
24508
  message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
24468
24509
  });
24469
- var ImagesInput = z106.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
24510
+ var ImagesInput = z107.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
24470
24511
  const assetCount = images.filter((image) => Boolean(image.assetId)).length;
24471
24512
  if (assetCount > 0 && assetCount !== images.length) {
24472
24513
  ctx.addIssue({
24473
- code: z106.ZodIssueCode.custom,
24514
+ code: z107.ZodIssueCode.custom,
24474
24515
  message: "all image entries must use assetId, or all must use URL/path sources"
24475
24516
  });
24476
24517
  }
@@ -24543,14 +24584,14 @@ async function submitCreative(api, opts) {
24543
24584
  });
24544
24585
  }
24545
24586
  __name(submitCreative, "submitCreative");
24546
- var ResearchTargetCountryEnum = z106.enum([
24587
+ var ResearchTargetCountryEnum = z107.enum([
24547
24588
  "CO",
24548
24589
  "MX",
24549
24590
  "PE",
24550
24591
  "EC",
24551
24592
  "CL"
24552
24593
  ]);
24553
- var ResearchCategoryEnum = z106.enum([
24594
+ var ResearchCategoryEnum = z107.enum([
24554
24595
  "auto",
24555
24596
  "automotive",
24556
24597
  "kitchen",
@@ -25862,29 +25903,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
25862
25903
  __name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
25863
25904
 
25864
25905
  // src/tools/media-presentation.ts
25865
- import { z as z107 } from "zod";
25866
- var HttpsPresentationUrlSchema = z107.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
25906
+ import { z as z108 } from "zod";
25907
+ var HttpsPresentationUrlSchema = z108.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
25867
25908
  var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
25868
25909
  const hostname = new URL(value).hostname.toLowerCase();
25869
25910
  return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
25870
25911
  }, "preview URL must be owned by ProductMaker");
25871
- var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z107.number().int().positive().max(maximum), "positiveIntAtMost");
25872
- var PresentationImageSchema = z107.object({
25873
- kind: z107.literal("image"),
25912
+ var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z108.number().int().positive().max(maximum), "positiveIntAtMost");
25913
+ var PresentationImageSchema = z108.object({
25914
+ kind: z108.literal("image"),
25874
25915
  url: HttpsPresentationUrlSchema,
25875
- mimeType: z107.enum([
25916
+ mimeType: z108.enum([
25876
25917
  "image/jpeg",
25877
25918
  "image/png"
25878
25919
  ]),
25879
25920
  byteSize: positiveIntAtMost(5 * 1024 * 1024),
25880
25921
  width: positiveIntAtMost(16384),
25881
25922
  height: positiveIntAtMost(16384),
25882
- alt: z107.string().trim().min(1).max(240)
25923
+ alt: z108.string().trim().min(1).max(240)
25883
25924
  }).strict();
25884
25925
  var McpMediaPresentationSchema = PresentationImageSchema;
25885
- var GalleryImageSchema = z107.object({
25926
+ var GalleryImageSchema = z108.object({
25886
25927
  url: ProductMakerPreviewUrlSchema,
25887
- alt: z107.string().trim().min(1).max(240)
25928
+ alt: z108.string().trim().min(1).max(240)
25888
25929
  });
25889
25930
  var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
25890
25931
  async function imageBlocks(image, transport) {
@@ -25941,12 +25982,12 @@ async function buildMcpMediaPresentationContent(rawPresentation, transport = "ht
25941
25982
  ];
25942
25983
  }
25943
25984
  __name(buildMcpMediaPresentationContent, "buildMcpMediaPresentationContent");
25944
- var OwnedImagePreviewSchema = z107.object({
25985
+ var OwnedImagePreviewSchema = z108.object({
25945
25986
  url: HttpsPresentationUrlSchema.refine((value) => {
25946
25987
  const url = new URL(value);
25947
25988
  return !url.username && !url.password && !isPrivateHost(url.hostname);
25948
25989
  }, "Preview URL must be public HTTPS without credentials"),
25949
- alt: z107.string().trim().min(1).max(240)
25990
+ alt: z108.string().trim().min(1).max(240)
25950
25991
  });
25951
25992
  async function buildMcpImagePreviewContent(rawPreview, transport = "http") {
25952
25993
  const preview2 = OwnedImagePreviewSchema.safeParse(rawPreview);
@@ -26029,7 +26070,7 @@ async function buildMcpImageGalleryContent(rawItems, transport = "http") {
26029
26070
  __name(buildMcpImageGalleryContent, "buildMcpImageGalleryContent");
26030
26071
 
26031
26072
  // src/tools/animated-video.ts
26032
- import { z as z108 } from "zod";
26073
+ import { z as z109 } from "zod";
26033
26074
 
26034
26075
  // src/tools/paid-confirmation.ts
26035
26076
  function describeMarketStudyChoice(enabled) {
@@ -26279,27 +26320,27 @@ function hookVariantsLabel(count) {
26279
26320
  return count === 1 ? "1 versi\xF3n del gancho" : `${count} versiones del gancho`;
26280
26321
  }
26281
26322
  __name(hookVariantsLabel, "hookVariantsLabel");
26282
- var DurationInput = z108.union(MOTION_GRAPHICS_DURATIONS.map((d) => z108.literal(d)));
26283
- var CreateAnimatedVideoInput = z108.object({
26284
- action: z108.enum([
26323
+ var DurationInput = z109.union(MOTION_GRAPHICS_DURATIONS.map((d) => z109.literal(d)));
26324
+ var CreateAnimatedVideoInput = z109.object({
26325
+ action: z109.enum([
26285
26326
  "prepare",
26286
26327
  "status",
26287
26328
  "cancel",
26288
26329
  "generate"
26289
26330
  ]).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."),
26290
- websiteCaptureId: z108.string().uuid().optional().describe("ID de la captura preparada. Obligatorio para status/cancel/generate; no inventarlo."),
26291
- generationRequestId: z108.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."),
26292
- confirmed: z108.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."),
26331
+ websiteCaptureId: z109.string().uuid().optional().describe("ID de la captura preparada. Obligatorio para status/cancel/generate; no inventarlo."),
26332
+ generationRequestId: z109.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."),
26333
+ confirmed: z109.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."),
26293
26334
  // Plain text, not `.url()`: users type «cal.com», and the web accepts it.
26294
26335
  // normalizeWebAddress (shared with the web) adds https:// and refuses
26295
26336
  // anything that is not a public http(s) address.
26296
- landingUrl: z108.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."),
26337
+ landingUrl: z109.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."),
26297
26338
  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.'),
26298
26339
  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.`),
26299
26340
  language: MotionGraphicsLanguageSchema.optional().describe('Idioma de los textos del video: "es", "en" o "pt".'),
26300
- notes: z108.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)."),
26341
+ notes: z109.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)."),
26301
26342
  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.`),
26302
- music: z108.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.")
26343
+ music: z109.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.")
26303
26344
  }).strict();
26304
26345
  function captureNextAction(capture) {
26305
26346
  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.";
@@ -26332,43 +26373,43 @@ var FORMAT_LABELS = {
26332
26373
  square: "cuadrado 1:1",
26333
26374
  horizontal: "horizontal 16:9"
26334
26375
  };
26335
- var AnimatedVideoResultSchema = z108.object({
26336
- status: z108.enum([
26376
+ var AnimatedVideoResultSchema = z109.object({
26377
+ status: z109.enum([
26337
26378
  "pending",
26338
26379
  "done",
26339
26380
  "error"
26340
26381
  ]),
26341
- serviceMode: z108.literal("motion_graphics"),
26342
- finalMp4Url: z108.string().optional(),
26343
- error: z108.string().optional(),
26344
- motionGraphics: z108.object({
26382
+ serviceMode: z109.literal("motion_graphics"),
26383
+ finalMp4Url: z109.string().optional(),
26384
+ error: z109.string().optional(),
26385
+ motionGraphics: z109.object({
26345
26386
  stage: MotionGraphicsStageSchema,
26346
26387
  format: MotionGraphicsFormatSchema,
26347
- durationSec: z108.number(),
26348
- width: z108.number().optional(),
26349
- height: z108.number().optional(),
26388
+ durationSec: z109.number(),
26389
+ width: z109.number().optional(),
26390
+ height: z109.number().optional(),
26350
26391
  language: MotionGraphicsLanguageSchema.optional(),
26351
- queuedAt: z108.string().optional(),
26352
- jobsAhead: z108.number().int().nonnegative().optional(),
26353
- stageStartedAt: z108.string().optional(),
26354
- renderProgress: z108.number().optional(),
26392
+ queuedAt: z109.string().optional(),
26393
+ jobsAhead: z109.number().int().nonnegative().optional(),
26394
+ stageStartedAt: z109.string().optional(),
26395
+ renderProgress: z109.number().optional(),
26355
26396
  // AI clip fields (absent on a video paid before clips, or from an API
26356
26397
  // that predates them). Lenient: an unreadable value is dropped
26357
26398
  // instead of hiding the status.
26358
- clipCount: z108.number().int().nonnegative().optional().catch(void 0),
26359
- clipsUsed: z108.number().int().nonnegative().optional().catch(void 0),
26360
- clipPriceCents: z108.number().finite().nonnegative().optional().catch(void 0),
26361
- clipsRefunded: z108.number().int().nonnegative().optional().catch(void 0),
26399
+ clipCount: z109.number().int().nonnegative().optional().catch(void 0),
26400
+ clipsUsed: z109.number().int().nonnegative().optional().catch(void 0),
26401
+ clipPriceCents: z109.number().finite().nonnegative().optional().catch(void 0),
26402
+ clipsRefunded: z109.number().int().nonnegative().optional().catch(void 0),
26362
26403
  // Hook versions (absent from an API or a video before them): the
26363
26404
  // count ordered and, once done, the signed URLs of the EXTRA versions
26364
26405
  // (hook 2, hook 3); `finalMp4Url` is hook 1.
26365
- hookVariants: z108.number().int().min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).optional().catch(void 0),
26366
- variantUrls: z108.array(z108.string().min(1)).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
26406
+ hookVariants: z109.number().int().min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).optional().catch(void 0),
26407
+ variantUrls: z109.array(z109.string().min(1)).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
26367
26408
  // Extra hook versions given back, as the task recorded it once the
26368
26409
  // refunds landed (absent until then, and from an API before it).
26369
- variantsRefunded: z108.number().int().nonnegative().optional().catch(void 0),
26370
- activity: z108.array(MotionGraphicsActivitySchema).optional().catch(void 0),
26371
- previewUrl: z108.string().optional()
26410
+ variantsRefunded: z109.number().int().nonnegative().optional().catch(void 0),
26411
+ activity: z109.array(MotionGraphicsActivitySchema).optional().catch(void 0),
26412
+ previewUrl: z109.string().optional()
26372
26413
  }).passthrough()
26373
26414
  }).passthrough();
26374
26415
  function parseAnimatedVideoResult(value) {
@@ -26624,10 +26665,10 @@ function registerAnimatedVideoTools(server, api) {
26624
26665
  __name(registerAnimatedVideoTools, "registerAnimatedVideoTools");
26625
26666
 
26626
26667
  // src/tools/winning-product-image.ts
26627
- import { z as z109 } from "zod";
26628
- var WinnerReferenceInput = z109.object({
26629
- runId: z109.string().uuid(),
26630
- candidateSourceId: z109.string().trim().min(1).max(160)
26668
+ import { z as z110 } from "zod";
26669
+ var WinnerReferenceInput = z110.object({
26670
+ runId: z110.string().uuid(),
26671
+ candidateSourceId: z110.string().trim().min(1).max(160)
26631
26672
  }).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
26632
26673
  async function resolveWinnerImages(api, winnerReference, images) {
26633
26674
  if (!winnerReference) return images;
@@ -26664,62 +26705,62 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
26664
26705
  var CREATE_SERVICE_VIDEO_ON_MCP = PRODUCTMAKER_MCP_CAPABILITY_NAMES.includes("create_service_video");
26665
26706
  var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
26666
26707
  var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
26667
- var CreateProductTaskInput = z110.object({
26708
+ var CreateProductTaskInput = z111.object({
26668
26709
  images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
26669
26710
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
26670
- projectId: z110.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
26671
- productUrl: z110.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."),
26711
+ projectId: z111.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
26712
+ productUrl: z111.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."),
26672
26713
  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.'),
26673
26714
  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.'),
26674
- price: z110.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.'),
26675
- compareAtPrice: z110.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".'),
26676
- offer: z110.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.'),
26677
- paymentMethods: z110.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.'),
26678
- productContext: z110.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."),
26679
- productLabel: z110.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.'),
26715
+ price: z111.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.'),
26716
+ compareAtPrice: z111.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".'),
26717
+ offer: z111.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.'),
26718
+ paymentMethods: z111.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.'),
26719
+ productContext: z111.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."),
26720
+ productLabel: z111.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.'),
26680
26721
  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.'),
26681
26722
  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.'),
26682
- durationSeconds: z110.union([
26683
- z110.literal(15),
26684
- z110.literal(30)
26723
+ durationSeconds: z111.union([
26724
+ z111.literal(15),
26725
+ z111.literal(30)
26685
26726
  ]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
26686
- pauseForAngleReview: z110.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."),
26687
- aiDecidesAll: z110.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."),
26727
+ pauseForAngleReview: z111.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."),
26728
+ aiDecidesAll: z111.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."),
26688
26729
  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.'),
26689
26730
  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.'),
26690
26731
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
26691
26732
  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).'),
26692
- videoAngleCount: z110.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."),
26733
+ videoAngleCount: z111.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."),
26693
26734
  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.'),
26694
- outputs: z110.array(z110.enum([
26735
+ outputs: z111.array(z111.enum([
26695
26736
  "landing",
26696
26737
  "video",
26697
26738
  "image"
26698
26739
  ])).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}`),
26699
- includeInitialLandingGif: z110.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."),
26700
- competitorScanEnabled: z110.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."),
26740
+ includeInitialLandingGif: z111.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."),
26741
+ competitorScanEnabled: z111.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."),
26701
26742
  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.'),
26702
- replicateWinnerWhenFound: z110.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."),
26703
- brandId: z110.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."),
26704
- actorId: z110.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."),
26743
+ replicateWinnerWhenFound: z111.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."),
26744
+ brandId: z111.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."),
26745
+ actorId: z111.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."),
26705
26746
  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.'),
26706
- creativeDirection: z110.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.'),
26707
- headline: z110.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."),
26708
- subheadline: z110.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."),
26747
+ creativeDirection: z111.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.'),
26748
+ headline: z111.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."),
26749
+ subheadline: z111.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."),
26709
26750
  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".'),
26710
26751
  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".')
26711
26752
  }).strict();
26712
- var CreateServiceVideoInput = z110.object({
26713
- landingUrl: z110.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
26714
- additionalContext: z110.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
26753
+ var CreateServiceVideoInput = z111.object({
26754
+ landingUrl: z111.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
26755
+ additionalContext: z111.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
26715
26756
  language: Lang.describe("Idioma del video: es, en o pt."),
26716
- voiceId: z110.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.'),
26717
- brandId: z110.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
26718
- reviewMode: z110.enum([
26757
+ voiceId: z111.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.'),
26758
+ brandId: z111.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
26759
+ reviewMode: z111.enum([
26719
26760
  "automatic",
26720
26761
  "guided"
26721
26762
  ]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
26722
- videoPreset: z110.enum([
26763
+ videoPreset: z111.enum([
26723
26764
  "auto",
26724
26765
  "ugc_dynamic",
26725
26766
  "ugc_how_to",
@@ -26729,128 +26770,128 @@ var CreateServiceVideoInput = z110.object({
26729
26770
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
26730
26771
  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.')
26731
26772
  }).strict();
26732
- var GetTaskStatusInput = z110.object({
26733
- taskId: z110.string().min(1),
26734
- waitSeconds: z110.number().int().min(0).max(120).optional()
26773
+ var GetTaskStatusInput = z111.object({
26774
+ taskId: z111.string().min(1),
26775
+ waitSeconds: z111.number().int().min(0).max(120).optional()
26735
26776
  });
26736
- var ListTasksInput = z110.object({
26737
- limit: z110.number().int().min(1).max(50).optional(),
26738
- offset: z110.number().int().min(0).optional(),
26739
- search: z110.string().optional()
26777
+ var ListTasksInput = z111.object({
26778
+ limit: z111.number().int().min(1).max(50).optional(),
26779
+ offset: z111.number().int().min(0).optional(),
26780
+ search: z111.string().optional()
26740
26781
  });
26741
26782
  var MCP_REVIEW_LIST_FIELD_MAX = IMAGE_WIZARD_LIST_FIELD_MAX;
26742
26783
  var MCP_REVIEW_FEATURE_ITEM_MAX = IMAGE_FEATURE_ITEM_MAX;
26743
- var EditTaskDraftInput = z110.object({
26744
- taskId: z110.string().min(1),
26745
- angleIndex: z110.number().int().min(0),
26746
- angle: z110.object({
26747
- angle: z110.string().min(1).max(480),
26748
- buyerPersona: z110.string().min(1).max(360),
26749
- actor: z110.string().min(1).max(360).optional(),
26750
- actorId: z110.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."),
26751
- gender: z110.enum([
26784
+ var EditTaskDraftInput = z111.object({
26785
+ taskId: z111.string().min(1),
26786
+ angleIndex: z111.number().int().min(0),
26787
+ angle: z111.object({
26788
+ angle: z111.string().min(1).max(480),
26789
+ buyerPersona: z111.string().min(1).max(360),
26790
+ actor: z111.string().min(1).max(360).optional(),
26791
+ actorId: z111.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."),
26792
+ gender: z111.enum([
26752
26793
  "female",
26753
26794
  "male"
26754
26795
  ]).optional(),
26755
- scriptNotes: z110.string().max(2e3).optional()
26796
+ scriptNotes: z111.string().max(2e3).optional()
26756
26797
  })
26757
26798
  });
26758
- var PendingActionPayload = z110.discriminatedUnion("kind", [
26759
- z110.object({
26760
- kind: z110.literal("product_reference_set_approval"),
26799
+ var PendingActionPayload = z111.discriminatedUnion("kind", [
26800
+ z111.object({
26801
+ kind: z111.literal("product_reference_set_approval"),
26761
26802
  scope: ProductReferenceScopeEnum.optional(),
26762
- scopeKey: z110.string().min(1).max(120).optional(),
26763
- scopeSnapshotId: z110.string().uuid().optional(),
26764
- expectedScopeHash: z110.string().min(1).max(128).optional(),
26803
+ scopeKey: z111.string().min(1).max(120).optional(),
26804
+ scopeSnapshotId: z111.string().uuid().optional(),
26805
+ expectedScopeHash: z111.string().min(1).max(128).optional(),
26765
26806
  decision: ProductReferenceResolutionDecisionEnum,
26766
26807
  reason: ProductReferenceRejectionReasonEnum.optional(),
26767
- affectedRefKeys: z110.array(z110.string().min(1).max(200)).min(1).optional(),
26768
- affectedPhotoNumbers: z110.array(z110.number().int().positive()).min(1).optional(),
26769
- recoveryAction: z110.enum([
26808
+ affectedRefKeys: z111.array(z111.string().min(1).max(200)).min(1).optional(),
26809
+ affectedPhotoNumbers: z111.array(z111.number().int().positive()).min(1).optional(),
26810
+ recoveryAction: z111.enum([
26770
26811
  "remove",
26771
26812
  "replace",
26772
26813
  "upload",
26773
26814
  "return_to_selection"
26774
26815
  ]).optional()
26775
26816
  }),
26776
- z110.object({
26777
- kind: z110.literal("product_reference_confirmation"),
26778
- selectedPhotoNumbers: z110.array(z110.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."),
26817
+ z111.object({
26818
+ kind: z111.literal("product_reference_confirmation"),
26819
+ selectedPhotoNumbers: z111.array(z111.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."),
26779
26820
  userChoice: ProductReferenceUserChoiceEnum.optional(),
26780
- confirmedProductNames: z110.array(z110.string().min(1).max(120)).min(2).max(8).optional(),
26821
+ confirmedProductNames: z111.array(z111.string().min(1).max(120)).min(2).max(8).optional(),
26781
26822
  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."),
26782
26823
  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."),
26783
- useMultiSceneShowcase: z110.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
26824
+ useMultiSceneShowcase: z111.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
26784
26825
  }),
26785
- z110.object({
26786
- kind: z110.literal("angle_review_approval"),
26826
+ z111.object({
26827
+ kind: z111.literal("angle_review_approval"),
26787
26828
  // All edits are optional — empty action body just approves the
26788
26829
  // backend-generated draft as-is. Field shapes mirror the angle-review
26789
26830
  // request contracts in @packages/types/wizard.ts; the handler routes to
26790
26831
  // the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
26791
- customAngle: z110.string().min(1).max(480).optional(),
26832
+ customAngle: z111.string().min(1).max(480).optional(),
26792
26833
  // Keep the shared MCP action within the strictest downstream contract:
26793
26834
  // autopilot/image resume endpoints cap these fields at 1500 characters.
26794
- painPoints: z110.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
26795
- benefits: z110.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
26835
+ painPoints: z111.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
26836
+ benefits: z111.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
26796
26837
  // Same policy as the two fields above: the strictest downstream contract
26797
26838
  // wins. The image endpoint caps each feature at 240 while landing/video
26798
26839
  // accept 300, and this single action routes to whichever the task is — so
26799
26840
  // accepting 300 here turns a 250-character feature on an image task into
26800
26841
  // an opaque HTTP 400 after the model already believed it had been saved.
26801
- features: z110.array(z110.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
26802
- buyerPersona: z110.string().min(1).max(360).optional(),
26842
+ features: z111.array(z111.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
26843
+ buyerPersona: z111.string().min(1).max(360).optional(),
26803
26844
  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.'),
26804
- actor: z110.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."),
26805
- actorId: z110.string().max(120).nullable().optional(),
26806
- creativeDirection: z110.string().max(2e3).optional(),
26807
- selectedAngleNumbers: z110.array(z110.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."),
26808
- angleEdits: z110.array(z110.object({
26809
- angleNumber: z110.number().int().positive(),
26810
- narrativeSelection: z110.enum([
26845
+ actor: z111.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."),
26846
+ actorId: z111.string().max(120).nullable().optional(),
26847
+ creativeDirection: z111.string().max(2e3).optional(),
26848
+ selectedAngleNumbers: z111.array(z111.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."),
26849
+ angleEdits: z111.array(z111.object({
26850
+ angleNumber: z111.number().int().positive(),
26851
+ narrativeSelection: z111.enum([
26811
26852
  "market",
26812
26853
  "guided"
26813
26854
  ]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
26814
- angle: z110.string().min(1).max(480).optional(),
26815
- buyerPersona: z110.string().min(1).max(360).optional(),
26855
+ angle: z111.string().min(1).max(480).optional(),
26856
+ buyerPersona: z111.string().min(1).max(360).optional(),
26816
26857
  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.'),
26817
- actor: z110.string().min(1).max(360).optional(),
26818
- actorId: z110.string().max(120).nullable().optional(),
26819
- creativeDirection: z110.string().max(2e3).optional()
26858
+ actor: z111.string().min(1).max(360).optional(),
26859
+ actorId: z111.string().max(120).nullable().optional(),
26860
+ creativeDirection: z111.string().max(2e3).optional()
26820
26861
  }).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)."),
26821
- gapDurationSeconds: z110.union([
26822
- z110.literal(15),
26823
- z110.literal(30)
26862
+ gapDurationSeconds: z111.union([
26863
+ z111.literal(15),
26864
+ z111.literal(30)
26824
26865
  ]).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.")
26825
26866
  }),
26826
- z110.object({
26827
- kind: z110.literal("service_angle_approval"),
26828
- angleId: z110.string().uuid().optional(),
26829
- angleNumber: z110.number().int().positive().optional(),
26830
- content: z110.string().min(1).max(480).optional(),
26831
- creativeDirection: z110.string().min(1).max(1500).optional(),
26832
- actor: z110.string().min(1).max(360).optional()
26867
+ z111.object({
26868
+ kind: z111.literal("service_angle_approval"),
26869
+ angleId: z111.string().uuid().optional(),
26870
+ angleNumber: z111.number().int().positive().optional(),
26871
+ content: z111.string().min(1).max(480).optional(),
26872
+ creativeDirection: z111.string().min(1).max(1500).optional(),
26873
+ actor: z111.string().min(1).max(360).optional()
26833
26874
  }),
26834
- z110.object({
26835
- kind: z110.literal("service_script_approval"),
26836
- voiceovers: z110.record(z110.string(), z110.string().min(1).max(600)).optional(),
26837
- visualDirections: z110.record(z110.string(), z110.string().min(1).max(1200)).optional(),
26838
- voiceoversByScene: z110.record(z110.string(), z110.string().min(1).max(600)).optional(),
26839
- visualDirectionsByScene: z110.record(z110.string(), z110.string().min(1).max(1200)).optional()
26875
+ z111.object({
26876
+ kind: z111.literal("service_script_approval"),
26877
+ voiceovers: z111.record(z111.string(), z111.string().min(1).max(600)).optional(),
26878
+ visualDirections: z111.record(z111.string(), z111.string().min(1).max(1200)).optional(),
26879
+ voiceoversByScene: z111.record(z111.string(), z111.string().min(1).max(600)).optional(),
26880
+ visualDirectionsByScene: z111.record(z111.string(), z111.string().min(1).max(1200)).optional()
26840
26881
  })
26841
26882
  ]);
26842
- var ResolvePendingActionInput = z110.object({
26843
- taskId: z110.string().min(1),
26883
+ var ResolvePendingActionInput = z111.object({
26884
+ taskId: z111.string().min(1),
26844
26885
  action: PendingActionPayload
26845
26886
  }).strict();
26846
26887
  function resolveVariantConfirmVideoTier(action) {
26847
26888
  return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
26848
26889
  }
26849
26890
  __name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
26850
- var StatusForResolveSchema = z110.object({
26891
+ var StatusForResolveSchema = z111.object({
26851
26892
  // Metadata used to select the backend resume contract. Older API responses
26852
26893
  // may omit these fields, so the resolver keeps the generic fallback.
26853
- kind: z110.enum([
26894
+ kind: z111.enum([
26854
26895
  "autopilot",
26855
26896
  "video",
26856
26897
  "image",
@@ -26858,18 +26899,18 @@ var StatusForResolveSchema = z110.object({
26858
26899
  "mix",
26859
26900
  "service"
26860
26901
  ]).optional(),
26861
- selectedOutputs: z110.array(z110.enum([
26902
+ selectedOutputs: z111.array(z111.enum([
26862
26903
  "landing",
26863
26904
  "video",
26864
26905
  "image"
26865
26906
  ])).optional(),
26866
- videoAngleCount: z110.number().int().min(1).max(3).optional(),
26867
- ugcFormat: z110.enum([
26907
+ videoAngleCount: z111.number().int().min(1).max(3).optional(),
26908
+ ugcFormat: z111.enum([
26868
26909
  "single_8s",
26869
26910
  "single_15s",
26870
26911
  "double_30s"
26871
26912
  ]).optional(),
26872
- videoStyle: z110.enum([
26913
+ videoStyle: z111.enum([
26873
26914
  "ugc",
26874
26915
  "cartoon_3d",
26875
26916
  "product_only",
@@ -26879,13 +26920,13 @@ var StatusForResolveSchema = z110.object({
26879
26920
  videoQuality: VideoQualityEnum.optional(),
26880
26921
  videoRouteId: VideoRouteIdEnum.optional(),
26881
26922
  videoModel: TaskVideoModelEnum.optional(),
26882
- videoTier: z110.enum([
26923
+ videoTier: z111.enum([
26883
26924
  "legacy",
26884
26925
  "standard",
26885
26926
  "pro",
26886
26927
  "single_call"
26887
26928
  ]).optional(),
26888
- videoResolution: z110.enum([
26929
+ videoResolution: z111.enum([
26889
26930
  "480p",
26890
26931
  "720p"
26891
26932
  ]).optional(),
@@ -26893,60 +26934,60 @@ var StatusForResolveSchema = z110.object({
26893
26934
  // A task created before a narrative was blocked/hidden must still parse,
26894
26935
  // or resolve_pending_action could never approve it.
26895
26936
  narrativeStyle: NarrativeStyle.optional(),
26896
- pauseForVideoScriptReview: z110.boolean().optional(),
26897
- pendingUserAction: z110.object({
26898
- kind: z110.string(),
26899
- candidateGrouping: z110.string().optional(),
26900
- selectedImageUrls: z110.array(z110.string()).optional(),
26901
- proposedProductNames: z110.array(z110.string()).optional(),
26937
+ pauseForVideoScriptReview: z111.boolean().optional(),
26938
+ pendingUserAction: z111.object({
26939
+ kind: z111.string(),
26940
+ candidateGrouping: z111.string().optional(),
26941
+ selectedImageUrls: z111.array(z111.string()).optional(),
26942
+ proposedProductNames: z111.array(z111.string()).optional(),
26902
26943
  // Adaptive reference questions are server-owned. Echo only the evidence
26903
26944
  // identity and the choices shown by the current snapshot; never accept a
26904
26945
  // client-supplied reference set as authorization.
26905
- options: z110.array(ProductReferenceUserChoiceEnum).max(4).optional(),
26906
- mode: z110.enum([
26946
+ options: z111.array(ProductReferenceUserChoiceEnum).max(4).optional(),
26947
+ mode: z111.enum([
26907
26948
  "question",
26908
26949
  "visual_recovery"
26909
26950
  ]).optional(),
26910
26951
  /** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
26911
- canKeepSelection: z110.boolean().optional(),
26912
- decisionKey: z110.string().optional(),
26913
- questionOrdinal: z110.number().int().min(1).max(5).optional(),
26914
- questionCeiling: z110.union([
26915
- z110.literal(3),
26916
- z110.literal(5)
26952
+ canKeepSelection: z111.boolean().optional(),
26953
+ decisionKey: z111.string().optional(),
26954
+ questionOrdinal: z111.number().int().min(1).max(5).optional(),
26955
+ questionCeiling: z111.union([
26956
+ z111.literal(3),
26957
+ z111.literal(5)
26917
26958
  ]).optional(),
26918
- referenceEvidenceVersion: z110.number().int().positive().optional(),
26919
- expectedEvidenceHash: z110.string().optional(),
26920
- question: z110.object({
26921
- prompt: z110.string().min(1).max(240),
26922
- helpText: z110.string().min(1).max(300).optional(),
26923
- options: z110.array(z110.object({
26959
+ referenceEvidenceVersion: z111.number().int().positive().optional(),
26960
+ expectedEvidenceHash: z111.string().optional(),
26961
+ question: z111.object({
26962
+ prompt: z111.string().min(1).max(240),
26963
+ helpText: z111.string().min(1).max(300).optional(),
26964
+ options: z111.array(z111.object({
26924
26965
  value: ProductReferenceUserChoiceEnum,
26925
- label: z110.string().min(1).max(120),
26926
- description: z110.string().min(1).max(240).optional()
26966
+ label: z111.string().min(1).max(120),
26967
+ description: z111.string().min(1).max(240).optional()
26927
26968
  })).min(2).max(4)
26928
26969
  }).optional(),
26929
26970
  scope: ProductReferenceScopeEnum.optional(),
26930
- scopeKey: z110.string().optional(),
26931
- scopeSnapshotId: z110.string().uuid().optional(),
26932
- scopeHash: z110.string().optional(),
26933
- baseReferenceSetHash: z110.string().optional(),
26934
- phase: z110.enum([
26971
+ scopeKey: z111.string().optional(),
26972
+ scopeSnapshotId: z111.string().uuid().optional(),
26973
+ scopeHash: z111.string().optional(),
26974
+ baseReferenceSetHash: z111.string().optional(),
26975
+ phase: z111.enum([
26935
26976
  "preparation",
26936
26977
  "final"
26937
26978
  ]).optional(),
26938
- selectedRefKeys: z110.array(z110.string().min(1).max(200)).optional(),
26939
- allowedDecisions: z110.array(ProductReferenceResolutionDecisionEnum).optional(),
26940
- previews: z110.array(z110.object({
26941
- refKey: z110.string().min(1).max(200)
26979
+ selectedRefKeys: z111.array(z111.string().min(1).max(200)).optional(),
26980
+ allowedDecisions: z111.array(ProductReferenceResolutionDecisionEnum).optional(),
26981
+ previews: z111.array(z111.object({
26982
+ refKey: z111.string().min(1).max(200)
26942
26983
  }).passthrough()).optional(),
26943
- customAngleDraft: z110.string().optional(),
26944
- painPointsDraft: z110.string().optional(),
26945
- benefitsDraft: z110.string().optional(),
26946
- featuresDraft: z110.array(z110.string()).optional(),
26947
- angleOptions: z110.array(z110.object({
26948
- index: z110.number().int().nonnegative(),
26949
- angle: z110.string().min(1)
26984
+ customAngleDraft: z111.string().optional(),
26985
+ painPointsDraft: z111.string().optional(),
26986
+ benefitsDraft: z111.string().optional(),
26987
+ featuresDraft: z111.array(z111.string()).optional(),
26988
+ angleOptions: z111.array(z111.object({
26989
+ index: z111.number().int().nonnegative(),
26990
+ angle: z111.string().min(1)
26950
26991
  }).passthrough()).min(1).max(5).optional(),
26951
26992
  // Recommendation consumed only when the caller explicitly sends
26952
26993
  // gapDurationSeconds: 30 in the angle approval action.
@@ -26956,17 +26997,17 @@ var StatusForResolveSchema = z110.object({
26956
26997
  // keys. `actorId` (the saved custom actor the picker stored) was silently
26957
26998
  // dropped here, so the approval handler below could not echo it back on the
26958
26999
  // PATCH — the selection looked accepted and reached no render.
26959
- angles: z110.array(z110.object({
26960
- id: z110.string().uuid(),
26961
- content: z110.string(),
26962
- creativeDirection: z110.string(),
26963
- actor: z110.string(),
26964
- actorId: z110.string().nullable().optional()
27000
+ angles: z111.array(z111.object({
27001
+ id: z111.string().uuid(),
27002
+ content: z111.string(),
27003
+ creativeDirection: z111.string(),
27004
+ actor: z111.string(),
27005
+ actorId: z111.string().nullable().optional()
26965
27006
  }).passthrough()).optional(),
26966
- panels: z110.array(z110.object({
26967
- beatId: z110.string(),
26968
- voiceover: z110.string(),
26969
- visualDirection: z110.string()
27007
+ panels: z111.array(z111.object({
27008
+ beatId: z111.string(),
27009
+ voiceover: z111.string(),
27010
+ visualDirection: z111.string()
26970
27011
  }).passthrough()).optional()
26971
27012
  }).optional()
26972
27013
  }).passthrough();
@@ -27318,8 +27359,8 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
27318
27359
  server.registerTool("verify_landing_commerce", {
27319
27360
  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.",
27320
27361
  inputSchema: {
27321
- taskId: z110.string().uuid(),
27322
- editId: z110.string().uuid()
27362
+ taskId: z111.string().uuid(),
27363
+ editId: z111.string().uuid()
27323
27364
  },
27324
27365
  annotations: OVERWRITES_EXTERNAL
27325
27366
  }, async (input) => {
@@ -27959,7 +28000,7 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
27959
28000
  __name(registerTaskTools, "registerTaskTools");
27960
28001
 
27961
28002
  // src/tools/creatives.ts
27962
- import { z as z111 } from "zod";
28003
+ import { z as z112 } from "zod";
27963
28004
  var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
27964
28005
  var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
27965
28006
  var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
@@ -27970,72 +28011,72 @@ var CreativeRefs = {
27970
28011
  images: ImagesInput,
27971
28012
  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.'),
27972
28013
  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.'),
27973
- price: z111.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.'),
27974
- offer: z111.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.'),
27975
- compareAtPrice: z111.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
27976
- productContext: z111.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."),
27977
- productLabel: z111.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.'),
27978
- buyerPersona: z111.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.'),
27979
- isCombo: z111.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
27980
- competitorScanEnabled: z111.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."),
27981
- brandId: z111.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.")
28014
+ price: z112.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.'),
28015
+ offer: z112.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.'),
28016
+ compareAtPrice: z112.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
28017
+ productContext: z112.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."),
28018
+ productLabel: z112.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.'),
28019
+ buyerPersona: z112.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.'),
28020
+ isCombo: z112.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
28021
+ competitorScanEnabled: z112.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."),
28022
+ brandId: z112.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.")
27982
28023
  };
27983
- var VideoPresenter = z111.discriminatedUnion("mode", [
27984
- z111.object({
27985
- mode: z111.literal("none")
28024
+ var VideoPresenter = z112.discriminatedUnion("mode", [
28025
+ z112.object({
28026
+ mode: z112.literal("none")
27986
28027
  }).strict(),
27987
- z111.object({
27988
- mode: z111.literal("saved_actor"),
27989
- actorId: z111.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
28028
+ z112.object({
28029
+ mode: z112.literal("saved_actor"),
28030
+ actorId: z112.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
27990
28031
  }).strict(),
27991
- z111.object({
27992
- mode: z111.literal("described"),
27993
- description: z111.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
28032
+ z112.object({
28033
+ mode: z112.literal("described"),
28034
+ description: z112.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
27994
28035
  }).strict()
27995
28036
  ]);
27996
- var VideoCreativeSetup = z111.discriminatedUnion("mode", [
27997
- z111.object({
27998
- mode: z111.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
28037
+ var VideoCreativeSetup = z112.discriminatedUnion("mode", [
28038
+ z112.object({
28039
+ mode: z112.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
27999
28040
  }).strict(),
28000
- z111.object({
28001
- mode: z111.literal("guided"),
28041
+ z112.object({
28042
+ mode: z112.literal("guided"),
28002
28043
  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.'),
28003
- buyerPersona: z111.string().trim().min(1).max(360),
28044
+ buyerPersona: z112.string().trim().min(1).max(360),
28004
28045
  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.'),
28005
28046
  presenter: VideoPresenter,
28006
- creativeDirection: z111.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
28047
+ creativeDirection: z112.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
28007
28048
  }).strict()
28008
28049
  ]);
28009
- var VideoInput = z111.object({
28050
+ var VideoInput = z112.object({
28010
28051
  images: CreativeRefs.images.optional(),
28011
28052
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
28012
- title: z111.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
28013
- primaryAngle: z111.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".'),
28053
+ title: z112.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
28054
+ primaryAngle: z112.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".'),
28014
28055
  language: CreativeRefs.language,
28015
28056
  country: CreativeRefs.country,
28016
- aspectRatio: z111.enum([
28057
+ aspectRatio: z112.enum([
28017
28058
  "9:16",
28018
28059
  "16:9",
28019
28060
  "Auto"
28020
28061
  ]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
28021
28062
  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.'),
28022
- durationSeconds: z111.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."),
28023
- videoAngleCount: z111.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."),
28063
+ durationSeconds: z112.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."),
28064
+ videoAngleCount: z112.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."),
28024
28065
  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.'),
28025
28066
  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."),
28026
28067
  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.'),
28027
28068
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
28028
28069
  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.'),
28029
- features: z111.array(z111.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
28070
+ features: z112.array(z112.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
28030
28071
  price: CreativeRefs.price,
28031
28072
  offer: CreativeRefs.offer,
28032
28073
  productContext: CreativeRefs.productContext,
28033
28074
  productLabel: CreativeRefs.productLabel,
28034
- cta: z111.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.'),
28035
- scriptNotes: z111.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.'),
28075
+ cta: z112.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.'),
28076
+ scriptNotes: z112.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.'),
28036
28077
  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.'),
28037
28078
  competitorScanEnabled: CreativeRefs.competitorScanEnabled,
28038
- replicateWinnerWhenFound: z111.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."),
28079
+ replicateWinnerWhenFound: z112.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."),
28039
28080
  brandId: CreativeRefs.brandId
28040
28081
  }).strict();
28041
28082
  var FreeVideoQualityEnum = VideoQualityEnum;
@@ -28053,7 +28094,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
28053
28094
  length: 29
28054
28095
  }, (_, index) => index + 2)
28055
28096
  };
28056
- var FreeVideoModelIdEnum = z111.enum([
28097
+ var FreeVideoModelIdEnum = z112.enum([
28057
28098
  "grok-imagine-video-1-5-preview",
28058
28099
  "minimax-h3/reference-to-video",
28059
28100
  "wan/3-0-video",
@@ -28064,66 +28105,66 @@ var FREE_SELECTABLE_MODEL_IDS = [
28064
28105
  "minimax-h3/reference-to-video",
28065
28106
  "wan/3-0-video"
28066
28107
  ];
28067
- var FreeVideoInput = z111.object({
28108
+ var FreeVideoInput = z112.object({
28068
28109
  images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
28069
- rawPrompt: z111.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."),
28110
+ rawPrompt: z112.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."),
28070
28111
  language: CreativeRefs.language,
28071
28112
  quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
28072
28113
  // Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
28073
28114
  // parsed ONLY so the handler can reject it with a message naming its
28074
28115
  // replacement — dropping it silently would turn a caller's explicit
28075
28116
  // Pro++ pick into a quiet fallback to Wan.
28076
- freeProModel: z111.enum([
28117
+ freeProModel: z112.enum([
28077
28118
  "wan",
28078
28119
  "seedance"
28079
28120
  ]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
28080
28121
  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.'),
28081
- durationSeconds: z111.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."),
28122
+ durationSeconds: z112.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."),
28082
28123
  videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
28083
- generateAiMusic: z111.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.'),
28124
+ generateAiMusic: z112.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.'),
28084
28125
  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.'),
28085
- addSubtitles: z111.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
28086
- idempotencyKey: z111.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.")
28126
+ addSubtitles: z112.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
28127
+ idempotencyKey: z112.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.")
28087
28128
  }).strict();
28088
28129
  var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
28089
- var ImageCreativeSetup = z111.discriminatedUnion("mode", [
28090
- z111.object({
28091
- mode: z111.literal("automatic")
28130
+ var ImageCreativeSetup = z112.discriminatedUnion("mode", [
28131
+ z112.object({
28132
+ mode: z112.literal("automatic")
28092
28133
  }).strict(),
28093
- z111.object({
28094
- mode: z111.literal("guided"),
28095
- creativeArchetype: z111.union([
28134
+ z112.object({
28135
+ mode: z112.literal("guided"),
28136
+ creativeArchetype: z112.union([
28096
28137
  ImageCreativeArchetypeEnum,
28097
- z111.literal("ai_decides")
28138
+ z112.literal("ai_decides")
28098
28139
  ]),
28099
- visualTreatment: z111.union([
28140
+ visualTreatment: z112.union([
28100
28141
  ImageCreativeVisualTreatmentEnum,
28101
- z111.literal("ai_decides")
28142
+ z112.literal("ai_decides")
28102
28143
  ]),
28103
28144
  aspectRatio: ImageCreativeAspectRatioEnum,
28104
- nVariants: z111.union([
28105
- z111.literal(1),
28106
- z111.literal(2),
28107
- z111.literal(3),
28108
- z111.literal(4),
28109
- z111.literal(6)
28145
+ nVariants: z112.union([
28146
+ z112.literal(1),
28147
+ z112.literal(2),
28148
+ z112.literal(3),
28149
+ z112.literal(4),
28150
+ z112.literal(6)
28110
28151
  ]),
28111
- imageModel: z111.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.'),
28112
- styleMix: z111.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
28113
- generateAdCopy: z111.boolean(),
28114
- competitorScanEnabled: z111.boolean(),
28115
- productContext: z111.string().trim().min(1).max(3e3).nullable(),
28116
- creativeDirection: z111.string().trim().min(1).max(500).nullable(),
28117
- brandColors: z111.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.'),
28118
- headline: z111.string().trim().min(1).max(120).nullable(),
28119
- subheadline: z111.string().trim().min(1).max(160).nullable()
28152
+ imageModel: z112.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.'),
28153
+ styleMix: z112.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
28154
+ generateAdCopy: z112.boolean(),
28155
+ competitorScanEnabled: z112.boolean(),
28156
+ productContext: z112.string().trim().min(1).max(3e3).nullable(),
28157
+ creativeDirection: z112.string().trim().min(1).max(500).nullable(),
28158
+ brandColors: z112.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.'),
28159
+ headline: z112.string().trim().min(1).max(120).nullable(),
28160
+ subheadline: z112.string().trim().min(1).max(160).nullable()
28120
28161
  }).strict()
28121
28162
  ]).superRefine((setup, context) => {
28122
28163
  if (setup.mode !== "guided") return;
28123
28164
  const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
28124
28165
  if (needsStyleMix && setup.styleMix === null) {
28125
28166
  context.addIssue({
28126
- code: z111.ZodIssueCode.custom,
28167
+ code: z112.ZodIssueCode.custom,
28127
28168
  path: [
28128
28169
  "styleMix"
28129
28170
  ],
@@ -28132,7 +28173,7 @@ var ImageCreativeSetup = z111.discriminatedUnion("mode", [
28132
28173
  }
28133
28174
  if (!needsStyleMix && setup.styleMix !== null) {
28134
28175
  context.addIssue({
28135
- code: z111.ZodIssueCode.custom,
28176
+ code: z112.ZodIssueCode.custom,
28136
28177
  path: [
28137
28178
  "styleMix"
28138
28179
  ],
@@ -28141,7 +28182,7 @@ var ImageCreativeSetup = z111.discriminatedUnion("mode", [
28141
28182
  }
28142
28183
  if (imageResolutionOf(setup.imageModel) === "2k" && setup.aspectRatio === "4:5") {
28143
28184
  context.addIssue({
28144
- code: z111.ZodIssueCode.custom,
28185
+ code: z112.ZodIssueCode.custom,
28145
28186
  path: [
28146
28187
  "aspectRatio"
28147
28188
  ],
@@ -28149,55 +28190,55 @@ var ImageCreativeSetup = z111.discriminatedUnion("mode", [
28149
28190
  });
28150
28191
  }
28151
28192
  });
28152
- var LandingCreativeSetup = z111.discriminatedUnion("mode", [
28153
- z111.object({
28154
- mode: z111.literal("automatic")
28193
+ var LandingCreativeSetup = z112.discriminatedUnion("mode", [
28194
+ z112.object({
28195
+ mode: z112.literal("automatic")
28155
28196
  }).strict(),
28156
- z111.object({
28157
- mode: z111.literal("guided"),
28197
+ z112.object({
28198
+ mode: z112.literal("guided"),
28158
28199
  landingStrategy: LandingStrategyEnum,
28159
28200
  landingImageFormat: LandingImageFormatEnum,
28160
- competitorScanEnabled: z111.boolean(),
28161
- paymentMethods: z111.string().trim().min(1).max(240).nullable(),
28162
- productContext: z111.string().trim().min(1).max(3e3).nullable(),
28163
- creativeDirection: z111.string().trim().min(1).max(500).nullable(),
28164
- headline: z111.string().trim().min(1).max(120).nullable(),
28165
- subheadline: z111.string().trim().min(1).max(160).nullable()
28201
+ competitorScanEnabled: z112.boolean(),
28202
+ paymentMethods: z112.string().trim().min(1).max(240).nullable(),
28203
+ productContext: z112.string().trim().min(1).max(3e3).nullable(),
28204
+ creativeDirection: z112.string().trim().min(1).max(500).nullable(),
28205
+ headline: z112.string().trim().min(1).max(120).nullable(),
28206
+ subheadline: z112.string().trim().min(1).max(160).nullable()
28166
28207
  }).strict()
28167
28208
  ]);
28168
- var ImageInput = z111.object({
28209
+ var ImageInput = z112.object({
28169
28210
  images: CreativeRefs.images.optional(),
28170
28211
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
28171
- productTitle: z111.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
28172
- primaryAngle: z111.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.'),
28212
+ productTitle: z112.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
28213
+ primaryAngle: z112.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.'),
28173
28214
  buyerPersona: CreativeRefs.buyerPersona,
28174
28215
  language: CreativeRefs.language,
28175
28216
  country: CreativeRefs.country,
28176
28217
  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."),
28177
28218
  imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
28178
- features: z111.array(z111.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
28219
+ features: z112.array(z112.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
28179
28220
  price: CreativeRefs.price,
28180
- omitPrice: z111.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."),
28221
+ omitPrice: z112.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."),
28181
28222
  compareAtPrice: CreativeRefs.compareAtPrice,
28182
28223
  offer: CreativeRefs.offer,
28183
28224
  productLabel: CreativeRefs.productLabel,
28184
28225
  isCombo: CreativeRefs.isCombo,
28185
28226
  brandId: CreativeRefs.brandId
28186
28227
  });
28187
- var EditImageCreativeInput = z111.object({
28188
- taskId: z111.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
28189
- variantIndex: z111.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
28190
- clientRequestId: z111.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."),
28191
- instruction: z111.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".')
28228
+ var EditImageCreativeInput = z112.object({
28229
+ taskId: z112.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
28230
+ variantIndex: z112.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
28231
+ clientRequestId: z112.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."),
28232
+ instruction: z112.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".')
28192
28233
  });
28193
- var LandingInput = z111.object({
28194
- includeInitialLandingGif: z111.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."),
28234
+ var LandingInput = z112.object({
28235
+ includeInitialLandingGif: z112.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."),
28195
28236
  images: CreativeRefs.images.optional(),
28196
28237
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
28197
28238
  language: CreativeRefs.language,
28198
28239
  country: CreativeRefs.country,
28199
28240
  creativeSetup: LandingCreativeSetup.describe("Configuraci\xF3n obligatoria de landing cl\xE1sica equivalente al wizard web. No expone landing editable/code mientras siga siendo admin-only."),
28200
- salesAngle: z111.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.'),
28241
+ salesAngle: z112.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.'),
28201
28242
  buyerPersona: CreativeRefs.buyerPersona,
28202
28243
  price: CreativeRefs.price,
28203
28244
  compareAtPrice: CreativeRefs.compareAtPrice,
@@ -28479,8 +28520,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
28479
28520
  server.registerTool("get_image_edit_status", {
28480
28521
  description: imageEditStatusGuidance.summary,
28481
28522
  inputSchema: {
28482
- taskId: z111.string().uuid(),
28483
- operationId: z111.string().uuid()
28523
+ taskId: z112.string().uuid(),
28524
+ operationId: z112.string().uuid()
28484
28525
  },
28485
28526
  annotations: READS_INTERNAL
28486
28527
  }, async (input) => {
@@ -28537,10 +28578,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
28537
28578
  __name(registerCreativeTools, "registerCreativeTools");
28538
28579
 
28539
28580
  // src/tools/creative-variants.ts
28540
- import { z as z112 } from "zod";
28581
+ import { z as z113 } from "zod";
28541
28582
  var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
28542
28583
  var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
28543
- var LandingSectionKeyEnum = z112.enum([
28584
+ var LandingSectionKeyEnum = z113.enum([
28544
28585
  "problem_hook",
28545
28586
  "problem_cost",
28546
28587
  "solution_mechanism",
@@ -28580,24 +28621,24 @@ var LandingSectionKeyEnum = z112.enum([
28580
28621
  "lifestyle_fit",
28581
28622
  "join_lifestyle"
28582
28623
  ]);
28583
- var CreativeVariantKindEnum = z112.enum([
28624
+ var CreativeVariantKindEnum = z113.enum([
28584
28625
  "video",
28585
28626
  "image",
28586
28627
  "landing"
28587
28628
  ]);
28588
- var EstimateCreativeVariantInputBase = z112.object({
28589
- sourceTaskId: z112.string().uuid().describe("ID de la tarea original completada."),
28629
+ var EstimateCreativeVariantInputBase = z113.object({
28630
+ sourceTaskId: z113.string().uuid().describe("ID de la tarea original completada."),
28590
28631
  kind: CreativeVariantKindEnum,
28591
28632
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
28592
28633
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
28593
- nVariants: z112.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
28634
+ nVariants: z113.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
28594
28635
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
28595
- instructions: z112.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.")
28636
+ instructions: z113.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.")
28596
28637
  }).strict();
28597
28638
  var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
28598
28639
  if (input.kind === "video" && input.nVariants !== void 0) {
28599
28640
  ctx.addIssue({
28600
- code: z112.ZodIssueCode.custom,
28641
+ code: z113.ZodIssueCode.custom,
28601
28642
  path: [
28602
28643
  "nVariants"
28603
28644
  ],
@@ -28607,7 +28648,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
28607
28648
  if (input.kind !== "video") {
28608
28649
  if (input.videoPreset !== void 0) {
28609
28650
  ctx.addIssue({
28610
- code: z112.ZodIssueCode.custom,
28651
+ code: z113.ZodIssueCode.custom,
28611
28652
  path: [
28612
28653
  "videoPreset"
28613
28654
  ],
@@ -28616,7 +28657,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
28616
28657
  }
28617
28658
  if (input.videoResolution !== void 0) {
28618
28659
  ctx.addIssue({
28619
- code: z112.ZodIssueCode.custom,
28660
+ code: z113.ZodIssueCode.custom,
28620
28661
  path: [
28621
28662
  "videoResolution"
28622
28663
  ],
@@ -28626,7 +28667,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
28626
28667
  }
28627
28668
  if (input.kind !== "image" && input.nVariants !== void 0) {
28628
28669
  ctx.addIssue({
28629
- code: z112.ZodIssueCode.custom,
28670
+ code: z113.ZodIssueCode.custom,
28630
28671
  path: [
28631
28672
  "nVariants"
28632
28673
  ],
@@ -28636,7 +28677,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
28636
28677
  if (input.kind !== "landing") {
28637
28678
  if (input.sectionKey !== void 0) {
28638
28679
  ctx.addIssue({
28639
- code: z112.ZodIssueCode.custom,
28680
+ code: z113.ZodIssueCode.custom,
28640
28681
  path: [
28641
28682
  "sectionKey"
28642
28683
  ],
@@ -28645,7 +28686,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
28645
28686
  }
28646
28687
  if (input.instructions !== void 0) {
28647
28688
  ctx.addIssue({
28648
- code: z112.ZodIssueCode.custom,
28689
+ code: z113.ZodIssueCode.custom,
28649
28690
  path: [
28650
28691
  "instructions"
28651
28692
  ],
@@ -28654,31 +28695,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
28654
28695
  }
28655
28696
  }
28656
28697
  });
28657
- var CreateCreativeVariantInputBase = z112.object({
28658
- sourceTaskId: z112.string().uuid().describe("ID de la tarea original completada."),
28698
+ var CreateCreativeVariantInputBase = z113.object({
28699
+ sourceTaskId: z113.string().uuid().describe("ID de la tarea original completada."),
28659
28700
  kind: CreativeVariantKindEnum,
28660
- confirm: z112.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
28661
- clientRequestId: z112.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."),
28662
- angle: z112.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
28663
- buyerPersona: z112.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
28664
- scriptNotes: z112.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
28665
- creativeDirection: z112.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
28701
+ confirm: z113.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
28702
+ clientRequestId: z113.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."),
28703
+ angle: z113.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
28704
+ buyerPersona: z113.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
28705
+ scriptNotes: z113.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
28706
+ creativeDirection: z113.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
28666
28707
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
28667
28708
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
28668
- generateAiMusic: z112.boolean().optional().describe("Opcional para video."),
28669
- nVariants: z112.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
28709
+ generateAiMusic: z113.boolean().optional().describe("Opcional para video."),
28710
+ nVariants: z113.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
28670
28711
  imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
28671
28712
  creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
28672
28713
  visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
28673
28714
  aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
28674
- styleMix: z112.boolean().optional().describe("Opcional para imagen."),
28715
+ styleMix: z113.boolean().optional().describe("Opcional para imagen."),
28675
28716
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
28676
- instructions: z112.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.")
28717
+ instructions: z113.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.")
28677
28718
  }).strict();
28678
28719
  var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
28679
28720
  if ((input.kind === "video" || input.kind === "image") && !input.angle) {
28680
28721
  ctx.addIssue({
28681
- code: z112.ZodIssueCode.custom,
28722
+ code: z113.ZodIssueCode.custom,
28682
28723
  path: [
28683
28724
  "angle"
28684
28725
  ],
@@ -28687,7 +28728,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
28687
28728
  }
28688
28729
  if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
28689
28730
  ctx.addIssue({
28690
- code: z112.ZodIssueCode.custom,
28731
+ code: z113.ZodIssueCode.custom,
28691
28732
  path: [
28692
28733
  "instructions"
28693
28734
  ],
@@ -28733,7 +28774,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
28733
28774
  for (const field of fieldsByKind[input.kind]) {
28734
28775
  if (input[field] !== void 0) {
28735
28776
  ctx.addIssue({
28736
- code: z112.ZodIssueCode.custom,
28777
+ code: z113.ZodIssueCode.custom,
28737
28778
  path: [
28738
28779
  field
28739
28780
  ],
@@ -28866,13 +28907,13 @@ function registerCreativeVariantTools(server, api) {
28866
28907
  __name(registerCreativeVariantTools, "registerCreativeVariantTools");
28867
28908
 
28868
28909
  // src/tools/script-review.ts
28869
- import { z as z113 } from "zod";
28910
+ import { z as z114 } from "zod";
28870
28911
  var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
28871
28912
  var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
28872
28913
  var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
28873
- var GetVideoScriptInput = z113.object({
28874
- taskId: z113.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
28875
- angleKey: z113.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.')
28914
+ var GetVideoScriptInput = z114.object({
28915
+ taskId: z114.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
28916
+ angleKey: z114.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.')
28876
28917
  }).strict();
28877
28918
  var ApproveVideoScriptInput = ApproveVideoScriptCapabilityRequest;
28878
28919
  var RegenerateVideoScriptInput = RegenerateVideoScriptCapabilityRequest.extend({
@@ -28955,7 +28996,7 @@ function registerScriptReviewTools(server, api) {
28955
28996
  __name(registerScriptReviewTools, "registerScriptReviewTools");
28956
28997
 
28957
28998
  // src/tools/connections.ts
28958
- import { z as z114 } from "zod";
28999
+ import { z as z115 } from "zod";
28959
29000
  var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
28960
29001
  var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
28961
29002
  var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
@@ -28964,7 +29005,7 @@ var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list
28964
29005
  function registerConnectionTools(server, api) {
28965
29006
  server.registerTool("list_shopify_shops", {
28966
29007
  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.",
28967
- inputSchema: z114.object({}).shape,
29008
+ inputSchema: z115.object({}).shape,
28968
29009
  annotations: READS_INTERNAL
28969
29010
  }, async () => {
28970
29011
  try {
@@ -28976,10 +29017,10 @@ function registerConnectionTools(server, api) {
28976
29017
  });
28977
29018
  server.registerTool("list_shopify_products", {
28978
29019
  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.',
28979
- inputSchema: z114.object({
28980
- shopDomain: z114.string().min(3).max(120),
28981
- query: z114.string().trim().max(120).optional(),
28982
- taskId: z114.string().uuid().optional()
29020
+ inputSchema: z115.object({
29021
+ shopDomain: z115.string().min(3).max(120),
29022
+ query: z115.string().trim().max(120).optional(),
29023
+ taskId: z115.string().uuid().optional()
28983
29024
  }).shape,
28984
29025
  annotations: READS_EXTERNAL
28985
29026
  }, async ({ shopDomain, query, taskId }) => {
@@ -28997,7 +29038,7 @@ function registerConnectionTools(server, api) {
28997
29038
  });
28998
29039
  server.registerTool("list_meta_ad_accounts", {
28999
29040
  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.",
29000
- inputSchema: z114.object({}).shape,
29041
+ inputSchema: z115.object({}).shape,
29001
29042
  annotations: READS_EXTERNAL
29002
29043
  }, async () => {
29003
29044
  try {
@@ -29009,7 +29050,7 @@ function registerConnectionTools(server, api) {
29009
29050
  });
29010
29051
  server.registerTool("list_meta_destinations", {
29011
29052
  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.",
29012
- inputSchema: z114.object({}).shape,
29053
+ inputSchema: z115.object({}).shape,
29013
29054
  annotations: READS_EXTERNAL,
29014
29055
  _meta: {
29015
29056
  "openai/widgetAccessible": true
@@ -29024,7 +29065,7 @@ function registerConnectionTools(server, api) {
29024
29065
  });
29025
29066
  server.registerTool("list_tiktok_advertisers", {
29026
29067
  description: listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.",
29027
- inputSchema: z114.object({}).shape,
29068
+ inputSchema: z115.object({}).shape,
29028
29069
  annotations: READS_EXTERNAL
29029
29070
  }, async () => {
29030
29071
  try {
@@ -29038,7 +29079,7 @@ function registerConnectionTools(server, api) {
29038
29079
  __name(registerConnectionTools, "registerConnectionTools");
29039
29080
 
29040
29081
  // src/tools/actors.ts
29041
- import { z as z115 } from "zod";
29082
+ import { z as z116 } from "zod";
29042
29083
  var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
29043
29084
  var actorVoiceGuidance = {
29044
29085
  capabilities: getProductMakerCapabilityModelGuidance("get_actor_voice_capabilities"),
@@ -29078,7 +29119,7 @@ function sanitizeVoiceResult(value) {
29078
29119
  __name(sanitizeVoiceResult, "sanitizeVoiceResult");
29079
29120
  function registerActorTools(server, api) {
29080
29121
  const actor = {
29081
- actorId: z115.string().min(1).max(64)
29122
+ actorId: z116.string().min(1).max(64)
29082
29123
  };
29083
29124
  const safe = /* @__PURE__ */ __name(async (request) => {
29084
29125
  try {
@@ -29107,8 +29148,8 @@ function registerActorTools(server, api) {
29107
29148
  inputSchema: {
29108
29149
  ...actor,
29109
29150
  draft: ActorVoiceDraftSchema,
29110
- requestKey: z115.string().trim().min(1).max(128),
29111
- acceptedQuoteId: z115.string().trim().min(1).max(128)
29151
+ requestKey: z116.string().trim().min(1).max(128),
29152
+ acceptedQuoteId: z116.string().trim().min(1).max(128)
29112
29153
  },
29113
29154
  annotations: CREATES_PAID
29114
29155
  }, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/previews`, body)));
@@ -29116,7 +29157,7 @@ function registerActorTools(server, api) {
29116
29157
  description: actorVoiceGuidance.get.summary,
29117
29158
  inputSchema: {
29118
29159
  ...actor,
29119
- candidateId: z115.string().min(1).max(64)
29160
+ candidateId: z116.string().min(1).max(64)
29120
29161
  },
29121
29162
  annotations: READS_INTERNAL
29122
29163
  }, async ({ actorId, candidateId }) => safe(api.getJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/previews/${encodeURIComponent(candidateId)}`)));
@@ -29124,15 +29165,15 @@ function registerActorTools(server, api) {
29124
29165
  description: actorVoiceGuidance.approve.summary,
29125
29166
  inputSchema: {
29126
29167
  ...actor,
29127
- candidateId: z115.string().min(1).max(64),
29128
- expectedRevision: z115.number().int().positive(),
29129
- expectedApprovedRevision: z115.number().int().positive().nullable().optional()
29168
+ candidateId: z116.string().min(1).max(64),
29169
+ expectedRevision: z116.number().int().positive(),
29170
+ expectedApprovedRevision: z116.number().int().positive().nullable().optional()
29130
29171
  },
29131
29172
  annotations: CREATES_INTERNAL
29132
29173
  }, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/approve`, body)));
29133
29174
  server.registerTool("list_actors", {
29134
29175
  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.",
29135
- inputSchema: z115.object({}).shape,
29176
+ inputSchema: z116.object({}).shape,
29136
29177
  annotations: READS_INTERNAL
29137
29178
  }, async () => {
29138
29179
  try {
@@ -29165,7 +29206,7 @@ function registerActorTools(server, api) {
29165
29206
  __name(registerActorTools, "registerActorTools");
29166
29207
 
29167
29208
  // src/tools/publish.ts
29168
- import { z as z116 } from "zod";
29209
+ import { z as z117 } from "zod";
29169
29210
 
29170
29211
  // src/tools/meta-publish-attempt-id.ts
29171
29212
  var META_PUBLISH_NAMESPACE = "7b19c9ac-b4eb-4db1-970e-c2f24ce30b98";
@@ -29204,40 +29245,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
29204
29245
  var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
29205
29246
  var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
29206
29247
  var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
29207
- var ShopifyInput = z116.object({
29208
- taskId: z116.string().min(1),
29209
- shopDomain: z116.string().min(1),
29248
+ var ShopifyInput = z117.object({
29249
+ taskId: z117.string().min(1),
29250
+ shopDomain: z117.string().min(1),
29210
29251
  /** Override: number of landing images to include. Default = ALL images the
29211
29252
  * task generated (the MCP fetches /v1/results first to count). Bounded
29212
29253
  * generously here; the backend validates each index against
29213
29254
  * landing.images.length and rejects out-of-range. */
29214
- numLandingImages: z116.number().int().min(1).max(20).optional(),
29215
- variantIndex: z116.number().int().min(0).optional(),
29255
+ numLandingImages: z117.number().int().min(1).max(20).optional(),
29256
+ variantIndex: z117.number().int().min(0).optional(),
29216
29257
  /** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
29217
29258
  * When true, the landing renders variant-picker pills; when false, it ships
29218
29259
  * a single-option product page. Defaults to false. */
29219
- showVariantPicker: z116.boolean().optional(),
29260
+ showVariantPicker: z117.boolean().optional(),
29220
29261
  /** Default `auto` updates the product previously published for this task and
29221
29262
  * shop. Use `existing` with targetProductId to choose another product, or
29222
29263
  * `new` only when the user explicitly wants a duplicate/new listing. */
29223
- publicationMode: z116.enum([
29264
+ publicationMode: z117.enum([
29224
29265
  "auto",
29225
29266
  "existing",
29226
29267
  "new"
29227
29268
  ]).optional(),
29228
29269
  /** Shopify product GID, numeric id, or admin product URL. Required when
29229
29270
  * publicationMode is `existing`. */
29230
- targetProductId: z116.string().trim().min(1).max(300).optional(),
29271
+ targetProductId: z117.string().trim().min(1).max(300).optional(),
29231
29272
  /** Add an announcement bar text above add-to-cart (optional). */
29232
- announcementBarEnabled: z116.boolean().optional(),
29233
- announcementBarText: z116.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
29273
+ announcementBarEnabled: z117.boolean().optional(),
29274
+ announcementBarText: z117.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
29234
29275
  commerceCorrection: PublishCommerceCorrectionSchema.optional().describe("Complete seller-confirmed commerce values, with the revision and fingerprint returned in recovery. Never invent missing prices or convert currency."),
29235
- confirmed: z116.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
29276
+ confirmed: z117.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
29236
29277
  });
29237
29278
  var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
29238
29279
  if (value.commerceCorrection && value.confirmed !== true) {
29239
29280
  ctx.addIssue({
29240
- code: z116.ZodIssueCode.custom,
29281
+ code: z117.ZodIssueCode.custom,
29241
29282
  path: [
29242
29283
  "confirmed"
29243
29284
  ],
@@ -29246,7 +29287,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
29246
29287
  }
29247
29288
  if (value.announcementBarEnabled && !value.announcementBarText) {
29248
29289
  ctx.addIssue({
29249
- code: z116.ZodIssueCode.custom,
29290
+ code: z117.ZodIssueCode.custom,
29250
29291
  path: [
29251
29292
  "announcementBarText"
29252
29293
  ],
@@ -29255,7 +29296,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
29255
29296
  }
29256
29297
  if (!value.announcementBarEnabled && value.announcementBarText) {
29257
29298
  ctx.addIssue({
29258
- code: z116.ZodIssueCode.custom,
29299
+ code: z117.ZodIssueCode.custom,
29259
29300
  path: [
29260
29301
  "announcementBarText"
29261
29302
  ],
@@ -29269,91 +29310,91 @@ function parseShopifyInput(rawInput) {
29269
29310
  return parsed.data;
29270
29311
  }
29271
29312
  __name(parseShopifyInput, "parseShopifyInput");
29272
- var McpCampaignConfig = z116.object({
29313
+ var McpCampaignConfig = z117.object({
29273
29314
  /** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
29274
29315
  * converts to the account currency server-side. Do NOT pre-convert: on a COP
29275
29316
  * account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
29276
- dailyBudgetUsd: z116.number().positive().optional(),
29317
+ dailyBudgetUsd: z117.number().positive().optional(),
29277
29318
  /** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
29278
29319
  * normalizes at validation). Meta accepts max 1 (single-country ad set).
29279
29320
  * TikTok takes only the first entry. */
29280
- targetCountries: z116.array(CountryIso2Schema).max(1).optional(),
29281
- campaignName: z116.string().trim().min(1).max(100).optional()
29321
+ targetCountries: z117.array(CountryIso2Schema).max(1).optional(),
29322
+ campaignName: z117.string().trim().min(1).max(100).optional()
29282
29323
  });
29283
29324
  var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
29284
- var MetaInput = z116.object({
29285
- taskId: z116.string().min(1),
29325
+ var MetaInput = z117.object({
29326
+ taskId: z117.string().min(1),
29286
29327
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
29287
- portfolioId: z116.string().trim().min(1),
29328
+ portfolioId: z117.string().trim().min(1),
29288
29329
  /** Exact Facebook Page selected from `list_meta_destinations`. */
29289
- pageId: z116.string().trim().min(1),
29330
+ pageId: z117.string().trim().min(1),
29290
29331
  adAccountId: McpAdAccountId,
29291
- pixelId: z116.string().min(1).optional(),
29292
- landingUrl: z116.string().url().optional(),
29332
+ pixelId: z117.string().min(1).optional(),
29333
+ landingUrl: z117.string().url().optional(),
29293
29334
  /** Select which angles to publish by 0-based index. Omit to publish all
29294
29335
  * successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
29295
- angleIndexes: z116.array(z116.number().int().nonnegative()).optional(),
29336
+ angleIndexes: z117.array(z117.number().int().nonnegative()).optional(),
29296
29337
  campaignConfig: McpCampaignConfig.optional(),
29297
29338
  /** Override the ad's primary text (body copy). If omitted, ProductMaker
29298
29339
  * uses the auto-generated copy attached to the task. Capped at 500 chars
29299
29340
  * (Meta's primary-text limit). */
29300
- primaryText: z116.string().trim().min(1).max(500).optional(),
29341
+ primaryText: z117.string().trim().min(1).max(500).optional(),
29301
29342
  /** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
29302
29343
  * (wa.me) instead of a landing page. */
29303
- phoneNumber: z116.string().min(8).max(32).optional()
29344
+ phoneNumber: z117.string().min(8).max(32).optional()
29304
29345
  });
29305
- var GroupedTaskSource = z116.object({
29306
- type: z116.literal("task"),
29307
- taskId: z116.string().min(1),
29308
- angleIndex: z116.number().int().min(0).optional(),
29309
- videoVariant: z116.enum([
29346
+ var GroupedTaskSource = z117.object({
29347
+ type: z117.literal("task"),
29348
+ taskId: z117.string().min(1),
29349
+ angleIndex: z117.number().int().min(0).optional(),
29350
+ videoVariant: z117.enum([
29310
29351
  "with_subtitles",
29311
29352
  "without_subtitles"
29312
29353
  ]).optional(),
29313
- imageVariantIndex: z116.number().int().min(0).optional()
29314
- });
29315
- var GroupedMediaSource = z116.object({
29316
- type: z116.literal("media"),
29317
- url: z116.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
29318
- path: z116.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".'),
29319
- thumbnailUrl: z116.string().url().optional(),
29320
- thumbnailPath: z116.string().min(1).optional()
29354
+ imageVariantIndex: z117.number().int().min(0).optional()
29355
+ });
29356
+ var GroupedMediaSource = z117.object({
29357
+ type: z117.literal("media"),
29358
+ url: z117.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
29359
+ path: z117.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".'),
29360
+ thumbnailUrl: z117.string().url().optional(),
29361
+ thumbnailPath: z117.string().min(1).optional()
29321
29362
  }).refine((value) => Boolean(value.url) !== Boolean(value.path), {
29322
29363
  message: "media source needs exactly one of `url` or `path`"
29323
29364
  }).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
29324
29365
  message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
29325
29366
  });
29326
- var GroupedUploadedAssetSource = z116.object({
29327
- type: z116.literal("asset"),
29367
+ var GroupedUploadedAssetSource = z117.object({
29368
+ type: z117.literal("asset"),
29328
29369
  /** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
29329
- assetId: z116.string().uuid(),
29330
- thumbnailAssetId: z116.string().uuid().optional()
29370
+ assetId: z117.string().uuid(),
29371
+ thumbnailAssetId: z117.string().uuid().optional()
29331
29372
  });
29332
- var GroupedCreative = z116.object({
29333
- type: z116.enum([
29373
+ var GroupedCreative = z117.object({
29374
+ type: z117.enum([
29334
29375
  "image",
29335
29376
  "video"
29336
29377
  ]),
29337
- source: z116.union([
29378
+ source: z117.union([
29338
29379
  GroupedTaskSource,
29339
29380
  GroupedMediaSource,
29340
29381
  GroupedUploadedAssetSource
29341
29382
  ]),
29342
- title: z116.string().max(120).optional(),
29343
- description: z116.string().max(500).optional(),
29383
+ title: z117.string().max(120).optional(),
29384
+ description: z117.string().max(500).optional(),
29344
29385
  cta: MetaCtaType.optional(),
29345
- creativeId: z116.string().min(1).optional()
29386
+ creativeId: z117.string().min(1).optional()
29346
29387
  });
29347
- var GroupedCampaignConfigBase = z116.object({
29388
+ var GroupedCampaignConfigBase = z117.object({
29348
29389
  campaignType: MetaCampaignType.default("sales"),
29349
29390
  optimizationMode: MetaOptimizationMode.default("advantage_plus"),
29350
29391
  budgetMode: MetaBudgetMode.optional(),
29351
- campaignDailyBudget: z116.number().int().positive().optional(),
29352
- adSets: z116.array(z116.object({
29353
- tempId: z116.string().min(1).max(80),
29354
- name: z116.string().min(1).max(100),
29355
- dailyBudget: z116.number().int().positive().optional(),
29356
- creativeIds: z116.array(z116.string().min(1)).min(1)
29392
+ campaignDailyBudget: z117.number().int().positive().optional(),
29393
+ adSets: z117.array(z117.object({
29394
+ tempId: z117.string().min(1).max(80),
29395
+ name: z117.string().min(1).max(100),
29396
+ dailyBudget: z117.number().int().positive().optional(),
29397
+ creativeIds: z117.array(z117.string().min(1)).min(1)
29357
29398
  })).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
29358
29399
  /**
29359
29400
  * Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
@@ -29361,17 +29402,17 @@ var GroupedCampaignConfigBase = z116.object({
29361
29402
  * opaque `invalid_literal` and made the WhatsApp destination — supported by
29362
29403
  * the API since #849 — unreachable from this tool.
29363
29404
  */
29364
- destination: z116.discriminatedUnion("type", [
29365
- z116.object({
29366
- type: z116.literal("landing"),
29367
- landingUrl: z116.string().url()
29405
+ destination: z117.discriminatedUnion("type", [
29406
+ z117.object({
29407
+ type: z117.literal("landing"),
29408
+ landingUrl: z117.string().url()
29368
29409
  }),
29369
- z116.object({
29370
- type: z116.literal("whatsapp"),
29371
- phoneNumber: z116.string().min(8).max(32)
29410
+ z117.object({
29411
+ type: z117.literal("whatsapp"),
29412
+ phoneNumber: z117.string().min(8).max(32)
29372
29413
  })
29373
29414
  ]),
29374
- saveAsDefault: z116.boolean().default(false),
29415
+ saveAsDefault: z117.boolean().default(false),
29375
29416
  budgetPolicy: MetaBudgetPolicy.optional()
29376
29417
  });
29377
29418
  function resolveBudgetMode(value) {
@@ -29385,7 +29426,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
29385
29426
  const budgetMode = resolveBudgetMode(value);
29386
29427
  if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
29387
29428
  ctx.addIssue({
29388
- code: z116.ZodIssueCode.custom,
29429
+ code: z117.ZodIssueCode.custom,
29389
29430
  path: [
29390
29431
  "campaignDailyBudget"
29391
29432
  ],
@@ -29396,7 +29437,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
29396
29437
  value.adSets.forEach((adSet, index) => {
29397
29438
  if (adSet.dailyBudget === void 0) {
29398
29439
  ctx.addIssue({
29399
- code: z116.ZodIssueCode.custom,
29440
+ code: z117.ZodIssueCode.custom,
29400
29441
  path: [
29401
29442
  "adSets",
29402
29443
  index,
@@ -29411,28 +29452,28 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
29411
29452
  ...value,
29412
29453
  budgetMode: resolveBudgetMode(value)
29413
29454
  }));
29414
- var PublishCreativesToMetaInputBase = z116.object({
29415
- creatives: z116.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
29455
+ var PublishCreativesToMetaInputBase = z117.object({
29456
+ creatives: z117.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
29416
29457
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
29417
- portfolioId: z116.string().trim().min(1),
29458
+ portfolioId: z117.string().trim().min(1),
29418
29459
  /** Exact Facebook Page selected from `list_meta_destinations`. */
29419
- pageId: z116.string().trim().min(1),
29460
+ pageId: z117.string().trim().min(1),
29420
29461
  adAccountId: McpAdAccountId,
29421
- pixelId: z116.string().min(1).optional(),
29462
+ pixelId: z117.string().min(1).optional(),
29422
29463
  /** Required unless `campaignConfig.destination` is whatsapp — see the
29423
29464
  * superRefine below. Mirrors the API's `FacebookCreateCampaignFromTasksBodySchema`. */
29424
- landingUrl: z116.string().url().optional(),
29465
+ landingUrl: z117.string().url().optional(),
29425
29466
  /** ISO-2 code or resolvable country name — mirrors the API contract
29426
29467
  * (CountryIso2Schema), which normalizes names to alpha-2 at validation. */
29427
29468
  targetCountry: CountryIso2Schema,
29428
- campaignName: z116.string().trim().min(1).max(100),
29469
+ campaignName: z117.string().trim().min(1).max(100),
29429
29470
  campaignConfig: GroupedCampaignConfig.optional()
29430
29471
  });
29431
29472
  var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
29432
29473
  const destination = value.campaignConfig?.destination;
29433
29474
  if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
29434
29475
  ctx.addIssue({
29435
- code: z116.ZodIssueCode.custom,
29476
+ code: z117.ZodIssueCode.custom,
29436
29477
  path: [
29437
29478
  "landingUrl"
29438
29479
  ],
@@ -29441,7 +29482,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
29441
29482
  }
29442
29483
  if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
29443
29484
  ctx.addIssue({
29444
- code: z116.ZodIssueCode.custom,
29485
+ code: z117.ZodIssueCode.custom,
29445
29486
  path: [
29446
29487
  "campaignConfig",
29447
29488
  "destination",
@@ -29460,16 +29501,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
29460
29501
  }
29461
29502
  return value;
29462
29503
  });
29463
- var PresignUploadResponseSchema = z116.object({
29464
- uploadUrl: z116.string().url().refine((value) => {
29504
+ var PresignUploadResponseSchema = z117.object({
29505
+ uploadUrl: z117.string().url().refine((value) => {
29465
29506
  const url = new URL(value);
29466
29507
  return !url.username && !url.password && url.protocol === "https:";
29467
29508
  }, "presigned upload URL must be HTTPS without embedded credentials"),
29468
- publicUrl: z116.string().url().refine((value) => {
29509
+ publicUrl: z117.string().url().refine((value) => {
29469
29510
  const url = new URL(value);
29470
29511
  return !url.username && !url.password;
29471
29512
  }, "public media URL must not contain embedded credentials"),
29472
- stagingAssetId: z116.string().uuid()
29513
+ stagingAssetId: z117.string().uuid()
29473
29514
  });
29474
29515
  async function uploadResolvedMedia(api, media, assetRole) {
29475
29516
  if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
@@ -29494,16 +29535,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
29494
29535
  return uploadResolvedMedia(api, media, assetRole);
29495
29536
  }
29496
29537
  __name(resolveAndUploadMedia, "resolveAndUploadMedia");
29497
- var TikTokInput = z116.object({
29498
- taskId: z116.string().min(1),
29499
- advertiserId: z116.string().min(1),
29500
- pixelId: z116.string().min(1).optional(),
29501
- landingUrl: z116.string().url().optional(),
29502
- angleIndexes: z116.array(z116.number().int().nonnegative()).optional(),
29538
+ var TikTokInput = z117.object({
29539
+ taskId: z117.string().min(1),
29540
+ advertiserId: z117.string().min(1),
29541
+ pixelId: z117.string().min(1).optional(),
29542
+ landingUrl: z117.string().url().optional(),
29543
+ angleIndexes: z117.array(z117.number().int().nonnegative()).optional(),
29503
29544
  campaignConfig: McpCampaignConfig.optional(),
29504
29545
  /** Override the ad's description (TikTok's body copy). If omitted,
29505
29546
  * ProductMaker uses the auto-generated copy attached to the task. */
29506
- primaryText: z116.string().trim().min(1).max(500).optional()
29547
+ primaryText: z117.string().trim().min(1).max(500).optional()
29507
29548
  });
29508
29549
  function registerPublishTools(server, api, opts = {}) {
29509
29550
  const transport = opts.transport ?? "http";
@@ -29855,39 +29896,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
29855
29896
 
29856
29897
  // src/tools/meta-upload.ts
29857
29898
  import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
29858
- import { z as z117 } from "zod";
29899
+ import { z as z118 } from "zod";
29859
29900
  var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
29860
- var UploadSessionInputBase = z117.object({
29861
- mediaKind: z117.enum([
29901
+ var UploadSessionInputBase = z118.object({
29902
+ mediaKind: z118.enum([
29862
29903
  "image",
29863
29904
  "video",
29864
29905
  "mixed"
29865
29906
  ]).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."),
29866
- assetRole: z117.enum([
29907
+ assetRole: z118.enum([
29867
29908
  "media",
29868
29909
  "thumbnail"
29869
29910
  ]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
29870
- uploadPurpose: z117.enum([
29911
+ uploadPurpose: z118.enum([
29871
29912
  "product_reference",
29872
29913
  "creative",
29873
29914
  "generic"
29874
29915
  ]).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."),
29875
- maxFiles: z117.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
29916
+ maxFiles: z118.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
29876
29917
  });
29877
- var OpenAiFileReference = z117.object({
29878
- download_url: z117.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."),
29879
- file_id: z117.string().min(1),
29880
- mime_type: z117.string().min(1).optional(),
29881
- file_name: z117.string().min(1).optional()
29918
+ var OpenAiFileReference = z118.object({
29919
+ download_url: z118.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."),
29920
+ file_id: z118.string().min(1),
29921
+ mime_type: z118.string().min(1).optional(),
29922
+ file_name: z118.string().min(1).optional()
29882
29923
  });
29883
29924
  var UploadSessionToolInputShape = {
29884
29925
  ...UploadSessionInputBase.shape,
29885
- files: z117.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.")
29926
+ files: z118.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.")
29886
29927
  };
29887
- var UploadSessionToolInput = z117.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
29928
+ var UploadSessionToolInput = z118.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
29888
29929
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
29889
29930
  ctx.addIssue({
29890
- code: z117.ZodIssueCode.custom,
29931
+ code: z118.ZodIssueCode.custom,
29891
29932
  path: [
29892
29933
  "mediaKind"
29893
29934
  ],
@@ -29896,7 +29937,7 @@ var UploadSessionToolInput = z117.object(UploadSessionToolInputShape).superRefin
29896
29937
  }
29897
29938
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
29898
29939
  ctx.addIssue({
29899
- code: z117.ZodIssueCode.custom,
29940
+ code: z118.ZodIssueCode.custom,
29900
29941
  path: [
29901
29942
  "maxFiles"
29902
29943
  ],
@@ -29905,7 +29946,7 @@ var UploadSessionToolInput = z117.object(UploadSessionToolInputShape).superRefin
29905
29946
  }
29906
29947
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
29907
29948
  ctx.addIssue({
29908
- code: z117.ZodIssueCode.custom,
29949
+ code: z118.ZodIssueCode.custom,
29909
29950
  path: [
29910
29951
  "maxFiles"
29911
29952
  ],
@@ -29913,38 +29954,38 @@ var UploadSessionToolInput = z117.object(UploadSessionToolInputShape).superRefin
29913
29954
  });
29914
29955
  }
29915
29956
  });
29916
- var UploadSessionResponse = z117.object({
29917
- sessionId: z117.string().uuid(),
29918
- uploadPageUrl: z117.string().url(),
29919
- mediaKind: z117.enum([
29957
+ var UploadSessionResponse = z118.object({
29958
+ sessionId: z118.string().uuid(),
29959
+ uploadPageUrl: z118.string().url(),
29960
+ mediaKind: z118.enum([
29920
29961
  "image",
29921
29962
  "video",
29922
29963
  "mixed"
29923
29964
  ]),
29924
- assetRole: z117.enum([
29965
+ assetRole: z118.enum([
29925
29966
  "media",
29926
29967
  "thumbnail"
29927
29968
  ]),
29928
- maxFiles: z117.number().int().positive(),
29929
- expiresAt: z117.string().datetime()
29969
+ maxFiles: z118.number().int().positive(),
29970
+ expiresAt: z118.string().datetime()
29930
29971
  });
29931
- var UploadStatusInput = z117.object({
29932
- sessionId: z117.string().uuid().describe("The sessionId returned by request_media_upload.")
29972
+ var UploadStatusInput = z118.object({
29973
+ sessionId: z118.string().uuid().describe("The sessionId returned by request_media_upload.")
29933
29974
  });
29934
- var UniversalUploadStatusResponse = z117.discriminatedUnion("status", [
29935
- z117.object({
29936
- status: z117.literal("pending"),
29937
- assets: z117.array(z117.never()).length(0)
29975
+ var UniversalUploadStatusResponse = z118.discriminatedUnion("status", [
29976
+ z118.object({
29977
+ status: z118.literal("pending"),
29978
+ assets: z118.array(z118.never()).length(0)
29938
29979
  }),
29939
- z117.object({
29940
- status: z117.literal("uploaded"),
29941
- assets: z117.array(z117.object({
29942
- assetId: z117.string().uuid(),
29943
- mediaKind: z117.enum([
29980
+ z118.object({
29981
+ status: z118.literal("uploaded"),
29982
+ assets: z118.array(z118.object({
29983
+ assetId: z118.string().uuid(),
29984
+ mediaKind: z118.enum([
29944
29985
  "image",
29945
29986
  "video"
29946
29987
  ]),
29947
- assetRole: z117.enum([
29988
+ assetRole: z118.enum([
29948
29989
  "media",
29949
29990
  "thumbnail"
29950
29991
  ])
@@ -29952,13 +29993,13 @@ var UniversalUploadStatusResponse = z117.discriminatedUnion("status", [
29952
29993
  })
29953
29994
  ]);
29954
29995
  var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
29955
- uploadPurpose: z117.enum([
29996
+ uploadPurpose: z118.enum([
29956
29997
  "product_reference",
29957
29998
  "creative",
29958
29999
  "generic"
29959
30000
  ]),
29960
- checkToolName: z117.literal("check_media_upload"),
29961
- resolveEndpoint: z117.string().url()
30001
+ checkToolName: z118.literal("check_media_upload"),
30002
+ resolveEndpoint: z118.string().url()
29962
30003
  });
29963
30004
  function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
29964
30005
  const url = new URL(uploadPageUrl);
@@ -30049,15 +30090,15 @@ function registerMediaUploadTools(server, api) {
30049
30090
  __name(registerMediaUploadTools, "registerMediaUploadTools");
30050
30091
 
30051
30092
  // src/tools/campaigns.ts
30052
- import { z as z118 } from "zod";
30093
+ import { z as z119 } from "zod";
30053
30094
  var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
30054
30095
  var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
30055
- var MetaStatusInput = z118.object({
30056
- campaignId: z118.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
30096
+ var MetaStatusInput = z119.object({
30097
+ campaignId: z119.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
30057
30098
  });
30058
- var TikTokStatusInput = z118.object({
30059
- campaignId: z118.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
30060
- advertiserId: z118.string().min(1).describe("The same advertiserId used to publish the campaign.")
30099
+ var TikTokStatusInput = z119.object({
30100
+ campaignId: z119.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
30101
+ advertiserId: z119.string().min(1).describe("The same advertiserId used to publish the campaign.")
30061
30102
  });
30062
30103
  function registerCampaignTools(server, api) {
30063
30104
  server.registerTool("get_meta_campaign_status", {
@@ -30162,10 +30203,10 @@ function renderTikTokStatusMarkdown(r) {
30162
30203
  __name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
30163
30204
 
30164
30205
  // ../../packages/product-economics/src/product-costing.ts
30165
- import { z as z120 } from "zod";
30206
+ import { z as z121 } from "zod";
30166
30207
 
30167
30208
  // ../../packages/product-economics/src/product-costing-countries.ts
30168
- import { z as z119 } from "zod";
30209
+ import { z as z120 } from "zod";
30169
30210
 
30170
30211
  // ../../packages/product-economics/src/product-costing-shipping-references.json
30171
30212
  var product_costing_shipping_references_default = {
@@ -30229,21 +30270,21 @@ var product_costing_shipping_references_default = {
30229
30270
  };
30230
30271
 
30231
30272
  // ../../packages/product-economics/src/product-costing-countries.ts
30232
- var ShippingReferenceSchema = z119.object({
30233
- reference: z119.number().positive(),
30234
- min: z119.number().nonnegative(),
30235
- max: z119.number().positive(),
30236
- updatedAt: z119.string().date(),
30237
- confidence: z119.enum([
30273
+ var ShippingReferenceSchema = z120.object({
30274
+ reference: z120.number().positive(),
30275
+ min: z120.number().nonnegative(),
30276
+ max: z120.number().positive(),
30277
+ updatedAt: z120.string().date(),
30278
+ confidence: z120.enum([
30238
30279
  "high",
30239
30280
  "medium",
30240
30281
  "medium-low"
30241
30282
  ]),
30242
- sources: z119.array(z119.string().url().startsWith("https://")).min(1).max(3)
30283
+ sources: z120.array(z120.string().url().startsWith("https://")).min(1).max(3)
30243
30284
  }).superRefine(({ reference, min, max }, context) => {
30244
30285
  if (min > reference || reference > max) {
30245
30286
  context.addIssue({
30246
- code: z119.ZodIssueCode.custom,
30287
+ code: z120.ZodIssueCode.custom,
30247
30288
  message: "shipping_reference_outside_range",
30248
30289
  path: [
30249
30290
  "reference"
@@ -30251,7 +30292,7 @@ var ShippingReferenceSchema = z119.object({
30251
30292
  });
30252
30293
  }
30253
30294
  });
30254
- var SHIPPING_REFERENCES = z119.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
30295
+ var SHIPPING_REFERENCES = z120.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
30255
30296
  var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
30256
30297
  var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
30257
30298
  "MX",
@@ -30433,18 +30474,18 @@ function getProductCostingCountryName(country) {
30433
30474
  __name(getProductCostingCountryName, "getProductCostingCountryName");
30434
30475
 
30435
30476
  // ../../packages/product-economics/src/product-costing.ts
30436
- var ProductCostingInputSchema = z120.object({
30437
- country: z120.string().refine(isProductCostingCountryCode, "unsupported_country"),
30438
- supplierCost: z120.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
30439
- shippingCost: z120.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
30440
- returnRate: z120.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
30441
- cancellationRate: z120.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
30442
- adsManagerCpa: z120.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
30443
- desiredMargin: z120.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
30477
+ var ProductCostingInputSchema = z121.object({
30478
+ country: z121.string().refine(isProductCostingCountryCode, "unsupported_country"),
30479
+ supplierCost: z121.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
30480
+ shippingCost: z121.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
30481
+ returnRate: z121.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
30482
+ cancellationRate: z121.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
30483
+ adsManagerCpa: z121.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
30484
+ desiredMargin: z121.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
30444
30485
  }).superRefine(({ returnRate, cancellationRate }, context) => {
30445
30486
  if (returnRate + cancellationRate >= 1) {
30446
30487
  context.addIssue({
30447
- code: z120.ZodIssueCode.custom,
30488
+ code: z121.ZodIssueCode.custom,
30448
30489
  message: "delivery_rate_positive",
30449
30490
  path: [
30450
30491
  "cancellationRate"
@@ -30541,15 +30582,15 @@ function calculateProductCosting(rawInput) {
30541
30582
  __name(calculateProductCosting, "calculateProductCosting");
30542
30583
 
30543
30584
  // src/tools/product-costing.ts
30544
- import { z as z121 } from "zod";
30585
+ import { z as z122 } from "zod";
30545
30586
  var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
30546
- var optionalAmount = /* @__PURE__ */ __name((description) => z121.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
30547
- var optionalPercent = /* @__PURE__ */ __name((description) => z121.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
30548
- var ProductCostingToolInput = z121.object({
30549
- country: z121.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
30587
+ var optionalAmount = /* @__PURE__ */ __name((description) => z122.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
30588
+ var optionalPercent = /* @__PURE__ */ __name((description) => z122.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
30589
+ var ProductCostingToolInput = z122.object({
30590
+ country: z122.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
30550
30591
  message: "Pa\xEDs no soportado por ProductMaker."
30551
30592
  }).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
30552
- supplierCost: z121.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."),
30593
+ supplierCost: z122.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."),
30553
30594
  supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
30554
30595
  shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
30555
30596
  shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
@@ -30712,7 +30753,7 @@ function formatPercent(value) {
30712
30753
  __name(formatPercent, "formatPercent");
30713
30754
 
30714
30755
  // src/tools/product-research.ts
30715
- import { z as z122 } from "zod";
30756
+ import { z as z123 } from "zod";
30716
30757
 
30717
30758
  // src/tools/product-research-idempotency.ts
30718
30759
  var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
@@ -31083,17 +31124,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
31083
31124
  ]);
31084
31125
  var POLL_INTERVAL_MS = 5e3;
31085
31126
  var MAX_WAIT_SECONDS = 120;
31086
- var FindInput = z122.object({
31127
+ var FindInput = z123.object({
31087
31128
  targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
31088
31129
  categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
31089
- confirmed: z122.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
31090
- waitSeconds: z122.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
31130
+ confirmed: z123.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
31131
+ waitSeconds: z123.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
31091
31132
  });
31092
- var GetInput = z122.object({
31093
- runId: z122.string().uuid().describe("ID del run devuelto por find_winning_products.")
31133
+ var GetInput = z123.object({
31134
+ runId: z123.string().uuid().describe("ID del run devuelto por find_winning_products.")
31094
31135
  });
31095
- var ListInput = z122.object({
31096
- limit: z122.number().int().min(1).max(20).default(10)
31136
+ var ListInput = z123.object({
31137
+ limit: z123.number().int().min(1).max(20).default(10)
31097
31138
  });
31098
31139
  function textResult(text2) {
31099
31140
  return {
@@ -31232,17 +31273,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
31232
31273
  __name(registerProductResearchTools, "registerProductResearchTools");
31233
31274
 
31234
31275
  // src/tools/dropshipping-projects.ts
31235
- import { z as z123 } from "zod";
31276
+ import { z as z124 } from "zod";
31236
31277
  var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
31237
31278
  var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
31238
31279
  var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
31239
- var ProjectId = z123.string().uuid();
31240
- var DropshippingProjectStatus = z123.enum([
31280
+ var ProjectId = z124.string().uuid();
31281
+ var DropshippingProjectStatus = z124.enum([
31241
31282
  "active",
31242
31283
  "completed",
31243
31284
  "archived"
31244
31285
  ]);
31245
- var DropshippingProjectPhase = z123.enum([
31286
+ var DropshippingProjectPhase = z124.enum([
31246
31287
  "research",
31247
31288
  "costing",
31248
31289
  "media",
@@ -31251,21 +31292,21 @@ var DropshippingProjectPhase = z123.enum([
31251
31292
  "advertising",
31252
31293
  "complete"
31253
31294
  ]);
31254
- var DropshippingRewardMilestone = z123.enum([
31295
+ var DropshippingRewardMilestone = z124.enum([
31255
31296
  "product_selected",
31256
31297
  "costing_saved",
31257
31298
  "product_media_ready",
31258
31299
  "creatives_completed",
31259
31300
  "campaign_created"
31260
31301
  ]);
31261
- var TargetCountry = z123.enum([
31302
+ var TargetCountry = z124.enum([
31262
31303
  "CO",
31263
31304
  "MX",
31264
31305
  "PE",
31265
31306
  "EC",
31266
31307
  "CL"
31267
31308
  ]);
31268
- var ResearchCategory = z123.enum([
31309
+ var ResearchCategory = z124.enum([
31269
31310
  "auto",
31270
31311
  "automotive",
31271
31312
  "kitchen",
@@ -31280,7 +31321,7 @@ var ResearchCategory = z123.enum([
31280
31321
  "garden",
31281
31322
  "cleaning"
31282
31323
  ]);
31283
- var HttpUrl3 = z123.string().url().max(2e3).refine((value) => {
31324
+ var HttpUrl3 = z124.string().url().max(2e3).refine((value) => {
31284
31325
  try {
31285
31326
  return [
31286
31327
  "http:",
@@ -31290,45 +31331,45 @@ var HttpUrl3 = z123.string().url().max(2e3).refine((value) => {
31290
31331
  return false;
31291
31332
  }
31292
31333
  }, "URL must use HTTP(S)");
31293
- var ResearchCandidateOrigin = z123.object({
31294
- type: z123.literal("research_candidate"),
31334
+ var ResearchCandidateOrigin = z124.object({
31335
+ type: z124.literal("research_candidate"),
31295
31336
  runId: ProjectId,
31296
- candidateSourceId: z123.string().min(1).max(160)
31337
+ candidateSourceId: z124.string().min(1).max(160)
31297
31338
  });
31298
- var TaskOrigin = z123.object({
31299
- type: z123.literal("task"),
31339
+ var TaskOrigin = z124.object({
31340
+ type: z124.literal("task"),
31300
31341
  taskId: ProjectId
31301
31342
  });
31302
- var ManualOrigin = z123.object({
31303
- type: z123.literal("manual"),
31343
+ var ManualOrigin = z124.object({
31344
+ type: z124.literal("manual"),
31304
31345
  clientRequestId: ProjectId,
31305
- country: z123.string().min(2).max(3).optional()
31346
+ country: z124.string().min(2).max(3).optional()
31306
31347
  });
31307
- var StartProjectInput = z123.object({
31308
- origin: z123.discriminatedUnion("type", [
31348
+ var StartProjectInput = z124.object({
31349
+ origin: z124.discriminatedUnion("type", [
31309
31350
  ResearchCandidateOrigin,
31310
31351
  TaskOrigin,
31311
31352
  ManualOrigin
31312
31353
  ]),
31313
- productName: z123.string().trim().min(1).max(240).optional(),
31354
+ productName: z124.string().trim().min(1).max(240).optional(),
31314
31355
  productUrl: HttpUrl3.optional(),
31315
- country: z123.string().min(2).max(3).optional(),
31316
- languageCode: z123.string().min(2).max(16).optional()
31356
+ country: z124.string().min(2).max(3).optional(),
31357
+ languageCode: z124.string().min(2).max(16).optional()
31317
31358
  }).strict();
31318
- var CostProjectInput = z123.object({
31359
+ var CostProjectInput = z124.object({
31319
31360
  projectId: ProjectId,
31320
- version: z123.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
31321
- country: z123.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
31361
+ version: z124.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
31362
+ country: z124.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
31322
31363
  message: "Pa\xEDs no soportado por ProductMaker."
31323
31364
  }).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
31324
- supplierCost: z123.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."),
31325
- shippingCost: z123.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
31326
- returnRate: z123.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."),
31327
- cancellationRate: z123.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."),
31328
- adsManagerCpa: z123.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
31329
- desiredMargin: z123.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
31330
- });
31331
- var GuideInput = z123.object({
31365
+ supplierCost: z124.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."),
31366
+ shippingCost: z124.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
31367
+ returnRate: z124.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."),
31368
+ cancellationRate: z124.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."),
31369
+ adsManagerCpa: z124.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
31370
+ desiredMargin: z124.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
31371
+ });
31372
+ var GuideInput = z124.object({
31332
31373
  projectId: ProjectId.optional()
31333
31374
  }).strict();
31334
31375
  var NEXT_ACTION_KINDS = [
@@ -31346,29 +31387,29 @@ var NEXT_ACTION_KINDS = [
31346
31387
  "repair_meta_campaign",
31347
31388
  "review_paused_campaign"
31348
31389
  ];
31349
- var DropshippingProjectNextAction = z123.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z123.object({
31350
- kind: z123.literal(kind),
31351
- href: z123.string().min(1)
31390
+ var DropshippingProjectNextAction = z124.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z124.object({
31391
+ kind: z124.literal(kind),
31392
+ href: z124.string().min(1)
31352
31393
  })));
31353
- var CostingInputSchema = z123.object({
31354
- country: z123.string().min(2).max(3),
31355
- supplierCost: z123.number().finite().positive(),
31356
- shippingCost: z123.number().finite().nonnegative(),
31357
- returnRate: z123.number().finite().min(0).lt(1),
31358
- cancellationRate: z123.number().finite().min(0).lt(1),
31359
- adsManagerCpa: z123.number().finite().nonnegative(),
31360
- desiredMargin: z123.number().finite().min(0).lt(1)
31394
+ var CostingInputSchema = z124.object({
31395
+ country: z124.string().min(2).max(3),
31396
+ supplierCost: z124.number().finite().positive(),
31397
+ shippingCost: z124.number().finite().nonnegative(),
31398
+ returnRate: z124.number().finite().min(0).lt(1),
31399
+ cancellationRate: z124.number().finite().min(0).lt(1),
31400
+ adsManagerCpa: z124.number().finite().nonnegative(),
31401
+ desiredMargin: z124.number().finite().min(0).lt(1)
31361
31402
  }).superRefine(({ returnRate, cancellationRate }, context) => {
31362
31403
  if (returnRate + cancellationRate >= 1) context.addIssue({
31363
- code: z123.ZodIssueCode.custom,
31404
+ code: z124.ZodIssueCode.custom,
31364
31405
  path: [
31365
31406
  "cancellationRate"
31366
31407
  ]
31367
31408
  });
31368
31409
  });
31369
- var FiniteCostingNumber = z123.number().finite();
31370
- var CostingResultSchema = z123.object({
31371
- country: z123.string().min(2).max(3),
31410
+ var FiniteCostingNumber = z124.number().finite();
31411
+ var CostingResultSchema = z124.object({
31412
+ country: z124.string().min(2).max(3),
31372
31413
  deliveryRate: FiniteCostingNumber,
31373
31414
  adjustedShippingCost: FiniteCostingNumber,
31374
31415
  adjustedCpa: FiniteCostingNumber,
@@ -31381,45 +31422,45 @@ var CostingResultSchema = z123.object({
31381
31422
  estimatedProfit: FiniteCostingNumber,
31382
31423
  actualMargin: FiniteCostingNumber,
31383
31424
  breakEvenAdsManagerCpa: FiniteCostingNumber,
31384
- wasPriceAutoAdjusted: z123.boolean(),
31385
- profitabilityStatus: z123.literal("healthy")
31386
- });
31387
- var RewardProgressSchema = z123.object({
31388
- campaignKey: z123.literal("dropshipping-launch-v1"),
31389
- totalCredits: z123.number().int().positive(),
31390
- earnedCredits: z123.number().int().nonnegative(),
31391
- milestones: z123.array(z123.object({
31425
+ wasPriceAutoAdjusted: z124.boolean(),
31426
+ profitabilityStatus: z124.literal("healthy")
31427
+ });
31428
+ var RewardProgressSchema = z124.object({
31429
+ campaignKey: z124.literal("dropshipping-launch-v1"),
31430
+ totalCredits: z124.number().int().positive(),
31431
+ earnedCredits: z124.number().int().nonnegative(),
31432
+ milestones: z124.array(z124.object({
31392
31433
  milestone: DropshippingRewardMilestone,
31393
- credits: z123.number().int().positive(),
31394
- available: z123.boolean().optional(),
31395
- earned: z123.boolean(),
31434
+ credits: z124.number().int().positive(),
31435
+ available: z124.boolean().optional(),
31436
+ earned: z124.boolean(),
31396
31437
  grantId: ProjectId.nullable(),
31397
- grantedAt: z123.string().datetime().nullable()
31438
+ grantedAt: z124.string().datetime().nullable()
31398
31439
  })).length(DropshippingRewardMilestone.options.length)
31399
31440
  });
31400
- var ProjectResponseSchema = z123.object({
31441
+ var ProjectResponseSchema = z124.object({
31401
31442
  id: ProjectId,
31402
31443
  taskId: ProjectId.nullable(),
31403
31444
  status: DropshippingProjectStatus,
31404
- originKey: z123.string().min(1),
31445
+ originKey: z124.string().min(1),
31405
31446
  researchRunId: ProjectId.nullable(),
31406
- candidateSourceId: z123.string().nullable(),
31407
- productName: z123.string().nullable(),
31447
+ candidateSourceId: z124.string().nullable(),
31448
+ productName: z124.string().nullable(),
31408
31449
  productUrl: HttpUrl3.nullable(),
31409
31450
  referenceImageUrl: HttpUrl3.nullable(),
31410
- targetCountry: z123.string().nullable(),
31411
- languageCode: z123.string().nullable(),
31412
- hasReferenceImage: z123.boolean(),
31413
- hasWinnerReferenceImage: z123.boolean(),
31451
+ targetCountry: z124.string().nullable(),
31452
+ languageCode: z124.string().nullable(),
31453
+ hasReferenceImage: z124.boolean(),
31454
+ hasWinnerReferenceImage: z124.boolean(),
31414
31455
  costingInput: CostingInputSchema.nullable(),
31415
31456
  costingResult: CostingResultSchema.nullable(),
31416
- costingVersion: z123.number().int().positive().nullable(),
31417
- version: z123.number().int().positive(),
31457
+ costingVersion: z124.number().int().positive().nullable(),
31458
+ version: z124.number().int().positive(),
31418
31459
  phase: DropshippingProjectPhase,
31419
31460
  nextAction: DropshippingProjectNextAction.nullable(),
31420
31461
  rewards: RewardProgressSchema,
31421
- createdAt: z123.string().datetime(),
31422
- updatedAt: z123.string().datetime()
31462
+ createdAt: z124.string().datetime(),
31463
+ updatedAt: z124.string().datetime()
31423
31464
  }).passthrough();
31424
31465
  var NEXT_ACTION_GUIDANCE = {
31425
31466
  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.",
@@ -31539,58 +31580,58 @@ function registerDropshippingProjectTools(server, api) {
31539
31580
  __name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
31540
31581
 
31541
31582
  // src/tools/daily-control.ts
31542
- import { z as z124 } from "zod";
31583
+ import { z as z125 } from "zod";
31543
31584
  var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
31544
31585
  var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
31545
31586
  var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
31546
- var ProviderCampaignIdentifier = z124.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
31547
- var DateOnly = z124.string().regex(/^\d{4}-\d{2}-\d{2}$/);
31548
- var DailyControlInput = z124.object({
31587
+ var ProviderCampaignIdentifier = z125.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
31588
+ var DateOnly = z125.string().regex(/^\d{4}-\d{2}-\d{2}$/);
31589
+ var DailyControlInput = z125.object({
31549
31590
  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."),
31550
- days: z124.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
31551
- projectId: z124.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
31591
+ days: z125.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
31592
+ projectId: z125.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
31552
31593
  }).strict();
31553
- var LinkCampaignInput = z124.object({
31554
- projectId: z124.string().uuid(),
31555
- provider: z124.enum([
31594
+ var LinkCampaignInput = z125.object({
31595
+ projectId: z125.string().uuid(),
31596
+ provider: z125.enum([
31556
31597
  "meta",
31557
31598
  "tiktok"
31558
31599
  ]),
31559
31600
  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."),
31560
31601
  campaignId: ProviderCampaignIdentifier
31561
31602
  }).strict();
31562
- var ReportReturnsInput = z124.object({
31563
- projectId: z124.string().uuid(),
31603
+ var ReportReturnsInput = z125.object({
31604
+ projectId: z125.string().uuid(),
31564
31605
  date: DateOnly,
31565
- returnedOrders: z124.number().int().min(0).max(1e5),
31566
- note: z124.string().trim().max(280).optional()
31606
+ returnedOrders: z125.number().int().min(0).max(1e5),
31607
+ note: z125.string().trim().max(280).optional()
31567
31608
  }).strict();
31568
- var DailyControlStatusMirror = DailyControlStatusEnum.or(z124.string());
31569
- var DailyControlLightMirror = DailyControlLightEnum.or(z124.string());
31570
- var DailyControlSourceMirror = DailyControlSourceEnum.or(z124.string());
31571
- var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z124.string());
31572
- var DailyControlDayMirror = z124.object({
31573
- date: z124.string(),
31574
- returnedOrders: z124.number(),
31609
+ var DailyControlStatusMirror = DailyControlStatusEnum.or(z125.string());
31610
+ var DailyControlLightMirror = DailyControlLightEnum.or(z125.string());
31611
+ var DailyControlSourceMirror = DailyControlSourceEnum.or(z125.string());
31612
+ var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z125.string());
31613
+ var DailyControlDayMirror = z125.object({
31614
+ date: z125.string(),
31615
+ returnedOrders: z125.number(),
31575
31616
  returnedSource: DailyControlSourceMirror,
31576
31617
  cancelledSource: DailyControlSourceMirror,
31577
- hasEstimates: z124.boolean(),
31618
+ hasEstimates: z125.boolean(),
31578
31619
  light: DailyControlLightMirror
31579
31620
  }).passthrough();
31580
- var DailyControlProductMirror = z124.object({
31581
- projectId: z124.string().uuid(),
31582
- productName: z124.string().nullable(),
31621
+ var DailyControlProductMirror = z125.object({
31622
+ projectId: z125.string().uuid(),
31623
+ productName: z125.string().nullable(),
31583
31624
  status: DailyControlStatusMirror,
31584
- statusMessage: z124.string().nullable(),
31585
- days: z124.array(DailyControlDayMirror),
31625
+ statusMessage: z125.string().nullable(),
31626
+ days: z125.array(DailyControlDayMirror),
31586
31627
  verdict: DailyControlVerdictMirror.nullable(),
31587
- rationale: z124.string().nullable()
31628
+ rationale: z125.string().nullable()
31588
31629
  }).passthrough();
31589
- var DailyControlResponseMirror = z124.object({
31590
- since: z124.string(),
31591
- until: z124.string(),
31592
- products: z124.array(DailyControlProductMirror),
31593
- archivedProjectSpend: z124.array(z124.unknown())
31630
+ var DailyControlResponseMirror = z125.object({
31631
+ since: z125.string(),
31632
+ until: z125.string(),
31633
+ products: z125.array(DailyControlProductMirror),
31634
+ archivedProjectSpend: z125.array(z125.unknown())
31594
31635
  }).passthrough();
31595
31636
  var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
31596
31637
  function withWarnings(response) {
@@ -31665,7 +31706,7 @@ __name(registerDailyControlTools, "registerDailyControlTools");
31665
31706
  // src/tools/product-control.ts
31666
31707
  import { readFile, stat } from "fs/promises";
31667
31708
  import { basename as basename2, isAbsolute, resolve as resolve3 } from "path";
31668
- import { z as z125 } from "zod";
31709
+ import { z as z126 } from "zod";
31669
31710
  var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
31670
31711
  var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
31671
31712
  var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
@@ -31678,36 +31719,36 @@ var createOperationGuidance = getProductMakerCapabilityModelGuidance("create_ope
31678
31719
  var mergeProductsGuidance = getProductMakerCapabilityModelGuidance("merge_products");
31679
31720
  var syncShopifyOrdersGuidance = getProductMakerCapabilityModelGuidance("sync_shopify_orders");
31680
31721
  var importOrdersFileGuidance = getProductMakerCapabilityModelGuidance("import_orders_file");
31681
- var DateOnly2 = z125.string().regex(/^\d{4}-\d{2}-\d{2}$/);
31722
+ var DateOnly2 = z126.string().regex(/^\d{4}-\d{2}-\d{2}$/);
31682
31723
  var IMPORT_BATCH_MAX2 = 50;
31683
- var ProductControlListInput = z125.object({
31684
- days: z125.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
31724
+ var ProductControlListInput = z126.object({
31725
+ days: z126.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
31685
31726
  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."),
31686
- shopDomain: z125.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
31727
+ shopDomain: z126.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
31687
31728
  }).strict();
31688
- var ImportableProductsInput = z125.object({
31689
- q: z125.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
31690
- after: z125.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
31691
- shopDomain: z125.string().min(1).optional()
31729
+ var ImportableProductsInput = z126.object({
31730
+ q: z126.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
31731
+ after: z126.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
31732
+ shopDomain: z126.string().min(1).optional()
31692
31733
  }).strict();
31693
- var ImportProductControlsInput = z125.object({
31694
- shopifyProductIds: z125.array(z125.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."),
31734
+ var ImportProductControlsInput = z126.object({
31735
+ shopifyProductIds: z126.array(z126.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."),
31695
31736
  // Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
31696
31737
  // sin decir a cuál archivaría el producto bajo la tienda equivocada.
31697
- shopDomain: z125.string().min(1)
31738
+ shopDomain: z126.string().min(1)
31698
31739
  }).strict();
31699
- var SetProductCostingInput = z125.object({
31700
- shopDomain: z125.string().min(1),
31701
- shopifyProductId: z125.string().min(1).max(64),
31702
- targetCountry: z125.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
31703
- supplierCost: z125.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
31704
- shippingCost: z125.number().finite().nonnegative(),
31705
- returnRate: z125.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
31706
- cancellationRate: z125.number().finite().min(0).lt(1)
31740
+ var SetProductCostingInput = z126.object({
31741
+ shopDomain: z126.string().min(1),
31742
+ shopifyProductId: z126.string().min(1).max(64),
31743
+ targetCountry: z126.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
31744
+ supplierCost: z126.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
31745
+ shippingCost: z126.number().finite().nonnegative(),
31746
+ returnRate: z126.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
31747
+ cancellationRate: z126.number().finite().min(0).lt(1)
31707
31748
  }).strict();
31708
- var Count = z125.number().int().min(0).max(1e5).nullable().optional();
31709
- var ReportProductCountsInput = z125.object({
31710
- productControlId: z125.string().uuid().describe("El identificador que devuelve get_product_control."),
31749
+ var Count = z126.number().int().min(0).max(1e5).nullable().optional();
31750
+ var ReportProductCountsInput = z126.object({
31751
+ productControlId: z126.string().uuid().describe("El identificador que devuelve get_product_control."),
31711
31752
  date: DateOnly2,
31712
31753
  orders: Count.describe("Pedidos que entraron ese d\xEDa."),
31713
31754
  cancelledOrders: Count,
@@ -31717,36 +31758,36 @@ var ReportProductCountsInput = z125.object({
31717
31758
  }).strict();
31718
31759
  var MAX_ORDERS_FILE_BYTES = 8 * 1024 * 1024;
31719
31760
  var SyncShopifyOrdersInput = SyncShopifyOrdersSchema;
31720
- var ImportOrdersFileInput = z125.object({
31761
+ var ImportOrdersFileInput = z126.object({
31721
31762
  /** Ruta ABSOLUTA en la máquina de quien usa el MCP. */
31722
- path: z125.string().min(1),
31723
- operationId: z125.string().uuid().optional(),
31763
+ path: z126.string().min(1),
31764
+ operationId: z126.string().uuid().optional(),
31724
31765
  /** Solo mirar: devuelve el resumen y no escribe nada. */
31725
- dryRun: z125.boolean().optional()
31766
+ dryRun: z126.boolean().optional()
31726
31767
  }).strict();
31727
- var CreateOperationInput = z125.object({
31728
- countryCode: z125.string().length(2),
31729
- label: z125.string().trim().min(1).max(60).optional()
31768
+ var CreateOperationInput = z126.object({
31769
+ countryCode: z126.string().length(2),
31770
+ label: z126.string().trim().min(1).max(60).optional()
31730
31771
  }).strict();
31731
- var MergeProductsInput = z125.object({
31732
- sourceId: z125.string().uuid(),
31733
- targetId: z125.string().uuid()
31772
+ var MergeProductsInput = z126.object({
31773
+ sourceId: z126.string().uuid(),
31774
+ targetId: z126.string().uuid()
31734
31775
  }).strict();
31735
- var SetMonthlyExpenseInput = z125.object({
31736
- month: z125.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
31776
+ var SetMonthlyExpenseInput = z126.object({
31777
+ month: z126.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
31737
31778
  label: SaveMonthlyExpenseSchema.shape.label,
31738
- amount: z125.number().finite().min(0),
31739
- operationId: z125.string().uuid().optional()
31779
+ amount: z126.number().finite().min(0),
31780
+ operationId: z126.string().uuid().optional()
31740
31781
  }).strict();
31741
- var SetAdSpendInput = z125.object({
31742
- month: z125.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
31743
- operationId: z125.string().uuid().optional(),
31782
+ var SetAdSpendInput = z126.object({
31783
+ month: z126.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
31784
+ operationId: z126.string().uuid().optional(),
31744
31785
  /** null RETIRA la corrección; cero afirma que no pautó. */
31745
- amount: z125.number().finite().min(0).nullable()
31786
+ amount: z126.number().finite().min(0).nullable()
31746
31787
  }).strict();
31747
- var GetFinancesInput = z125.object({
31748
- month: z125.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."),
31749
- operationId: z125.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
31788
+ var GetFinancesInput = z126.object({
31789
+ month: z126.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."),
31790
+ operationId: z126.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
31750
31791
  }).strict();
31751
31792
  function registerProductControlTools(server, api, { transport = "http" } = {}) {
31752
31793
  server.registerTool("get_product_control", {
@@ -31936,28 +31977,28 @@ function registerProductControlTools(server, api, { transport = "http" } = {}) {
31936
31977
  __name(registerProductControlTools, "registerProductControlTools");
31937
31978
 
31938
31979
  // src/tools/market-study-estimate.ts
31939
- import { z as z126 } from "zod";
31980
+ import { z as z127 } from "zod";
31940
31981
  var estimateMarketStudyGuidance = getProductMakerCapabilityModelGuidance("estimate_market_study_cost");
31941
- var ProductTaskOutputEnum = z126.enum([
31982
+ var ProductTaskOutputEnum = z127.enum([
31942
31983
  "landing",
31943
31984
  "video",
31944
31985
  "image"
31945
31986
  ]);
31946
- var EstimateMarketStudyInput = z126.object({
31947
- kind: z126.enum([
31987
+ var EstimateMarketStudyInput = z127.object({
31988
+ kind: z127.enum([
31948
31989
  "video",
31949
31990
  "product_task"
31950
31991
  ]).describe('"video" para generate_video_creative; "product_task" para create_product_task.'),
31951
- videoAngleCount: z126.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
31952
- durationSeconds: z126.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
31992
+ videoAngleCount: z127.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
31993
+ durationSeconds: z127.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
31953
31994
  videoStructure: VideoStructureEnum.default("single_take"),
31954
31995
  videoQuality: VideoQualityEnum.default("economy"),
31955
31996
  videoResolution: VideoResolutionEnum.default("480p"),
31956
- productImageCount: z126.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
31997
+ productImageCount: z127.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
31957
31998
  outputs: ProductTaskOutputEnum.array().min(1).max(3).optional().describe('Solo para kind="product_task": los mismos outputs de create_product_task. Default: todos.'),
31958
- generateAiMusic: z126.boolean().optional(),
31999
+ generateAiMusic: z127.boolean().optional(),
31959
32000
  generateAiEdit: AiEditRequestSchema.optional(),
31960
- replicateWinnerWhenFound: z126.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.")
32001
+ replicateWinnerWhenFound: z127.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.")
31961
32002
  }).strict();
31962
32003
  function buildMarketStudyEstimateRequests(input) {
31963
32004
  const quotesVideo = input.kind === "video" || (input.outputs ?? [