@productmaker/mcp 11.3.3 → 11.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/http.js CHANGED
@@ -9676,13 +9676,23 @@ var FacebookCreateCampaignFromTasksBodySchema = z51.object({
9676
9676
  portfolioId: z51.string().min(1),
9677
9677
  pageId: z51.string().min(1),
9678
9678
  pixelId: z51.string().optional(),
9679
+ /**
9680
+ * Omitted: a campaign with task creatives lands on the published service
9681
+ * landing of its service tasks (resolved server side, META_NO_LANDING_URL
9682
+ * when there is none); a media-only campaign must name it.
9683
+ */
9679
9684
  landingUrl: HttpUrl2.optional(),
9680
- targetCountry: CountryIso2Schema.default("US"),
9685
+ /**
9686
+ * Omitted: the brand country of its service tasks; a product-only campaign
9687
+ * keeps "US". Never a hardcoded country for a service (META_NO_TARGET_COUNTRY).
9688
+ */
9689
+ targetCountry: CountryIso2Schema.optional(),
9681
9690
  campaignName: z51.string().min(1).max(100),
9682
9691
  campaignConfig: MetaCampaignConfig.optional()
9683
9692
  }).superRefine((value, ctx) => {
9684
9693
  const isWhatsapp = value.campaignConfig?.destination?.type === "whatsapp";
9685
- if (!isWhatsapp && !value.landingUrl) {
9694
+ const hasTaskCreative = value.creatives.some((creative) => creative.source.type === "task");
9695
+ if (!isWhatsapp && !value.landingUrl && !hasTaskCreative) {
9686
9696
  ctx.addIssue({
9687
9697
  code: z51.ZodIssueCode.custom,
9688
9698
  path: [
@@ -18759,7 +18769,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
18759
18769
  ], [
18760
18770
  "tiktok_advertiser"
18761
18771
  ]),
18762
- defineCapability("publish_creatives_to_meta", "554d977e26e824490ffe3e027f34889b1e29d5969e6e9c0320f79e7c5a03584c", "external_mutation", "publishing", [
18772
+ defineCapability("publish_creatives_to_meta", "dff962c84ed7d0393444dcbe86cb6f4016b5928c1d0005f78ce9a365f1923ac3", "external_mutation", "publishing", [
18763
18773
  "external_mutation",
18764
18774
  "state_change"
18765
18775
  ], [
@@ -22109,19 +22119,37 @@ var ServiceImageContextSchema = z106.object({
22109
22119
  referenceKeys: z106.array(z106.string()).max(10)
22110
22120
  }).strict();
22111
22121
 
22112
- // ../../packages/types/src/service-website-capture.ts
22122
+ // ../../packages/types/src/task-ad-defaults.ts
22113
22123
  import { z as z107 } from "zod";
22124
+ var AD_HEADLINE_MAX_CHARS = 255;
22125
+ var TaskAdDefaultsSchema = z107.object({
22126
+ subjectKind: z107.enum([
22127
+ "product",
22128
+ "service"
22129
+ ]),
22130
+ landingUrl: z107.string().url().nullable(),
22131
+ landingSource: z107.enum([
22132
+ "shopify",
22133
+ "service_page"
22134
+ ]).nullable(),
22135
+ headline: z107.string().min(1).max(AD_HEADLINE_MAX_CHARS).nullable(),
22136
+ /** ISO 3166-1 alpha-2 when known. */
22137
+ country: z107.string().min(2).nullable()
22138
+ });
22139
+
22140
+ // ../../packages/types/src/service-website-capture.ts
22141
+ import { z as z108 } from "zod";
22114
22142
  var WEBSITE_CAPTURE_MAX_RESEARCH_BYTES = 1024 * 1024;
22115
22143
  var WEBSITE_CAPTURE_MAX_FILES = 100;
22116
22144
  var WEBSITE_CAPTURE_MAX_FILE_BYTES = 8 * 1024 * 1024;
22117
22145
  var WEBSITE_CAPTURE_MAX_BUNDLE_BYTES = 30 * 1024 * 1024;
22118
- var WebsiteCaptureCauseSchema = z107.enum([
22146
+ var WebsiteCaptureCauseSchema = z108.enum([
22119
22147
  "site_blocked",
22120
22148
  "site_unreachable",
22121
22149
  "not_enough_content",
22122
22150
  "internal"
22123
22151
  ]);
22124
- var WebsiteCaptureStatusSchema = z107.enum([
22152
+ var WebsiteCaptureStatusSchema = z108.enum([
22125
22153
  "queued",
22126
22154
  "capturing",
22127
22155
  "ready",
@@ -22143,143 +22171,143 @@ function normalizeWebsiteCaptureUrl(value) {
22143
22171
  }
22144
22172
  }
22145
22173
  __name(normalizeWebsiteCaptureUrl, "normalizeWebsiteCaptureUrl");
22146
- var WebsiteCaptureRequestSchema = z107.object({
22147
- url: z107.string().trim().max(2048).url().refine((value) => normalizeWebsiteCaptureUrl(value) !== null, "Use an HTTP(S) URL without credentials").transform((value) => normalizeWebsiteCaptureUrl(value)),
22174
+ var WebsiteCaptureRequestSchema = z108.object({
22175
+ url: z108.string().trim().max(2048).url().refine((value) => normalizeWebsiteCaptureUrl(value) !== null, "Use an HTTP(S) URL without credentials").transform((value) => normalizeWebsiteCaptureUrl(value)),
22148
22176
  language: MotionGraphicsLanguageSchema
22149
22177
  }).strict();
22150
- var WebsiteCaptureResponseSchema = z107.object({
22151
- captureId: z107.string().uuid(),
22178
+ var WebsiteCaptureResponseSchema = z108.object({
22179
+ captureId: z108.string().uuid(),
22152
22180
  status: WebsiteCaptureStatusSchema,
22153
- expiresAt: z107.string().datetime(),
22154
- previewUrl: z107.string().url().optional(),
22181
+ expiresAt: z108.string().datetime(),
22182
+ previewUrl: z108.string().url().optional(),
22155
22183
  cause: WebsiteCaptureCauseSchema.optional()
22156
22184
  });
22157
22185
  var WebsiteCaptureJobSchema = WebsiteCaptureRequestSchema.extend({
22158
- captureId: z107.string().uuid(),
22159
- attempt: z107.number().int().positive(),
22160
- leaseUntil: z107.string().datetime()
22186
+ captureId: z108.string().uuid(),
22187
+ attempt: z108.number().int().positive(),
22188
+ leaseUntil: z108.string().datetime()
22161
22189
  });
22162
- var WebsiteCaptureClaimResponseSchema = z107.object({
22190
+ var WebsiteCaptureClaimResponseSchema = z108.object({
22163
22191
  capture: WebsiteCaptureJobSchema.nullable()
22164
22192
  });
22165
22193
  var attempt = {
22166
- attempt: z107.number().int().positive()
22194
+ attempt: z108.number().int().positive()
22167
22195
  };
22168
- var digest = z107.string().regex(/^[a-f0-9]{64}$/);
22169
- var WebsiteCaptureUploadRequestSchema = z107.object({
22196
+ var digest = z108.string().regex(/^[a-f0-9]{64}$/);
22197
+ var WebsiteCaptureUploadRequestSchema = z108.object({
22170
22198
  ...attempt,
22171
- contentLength: z107.number().int().positive().max(WEBSITE_CAPTURE_MAX_BUNDLE_BYTES),
22199
+ contentLength: z108.number().int().positive().max(WEBSITE_CAPTURE_MAX_BUNDLE_BYTES),
22172
22200
  sha256: digest
22173
22201
  }).strict();
22174
- var WebsiteCaptureDoneRequestSchema = z107.object({
22202
+ var WebsiteCaptureDoneRequestSchema = z108.object({
22175
22203
  ...attempt,
22176
22204
  sha256: digest
22177
22205
  }).strict();
22178
- var WebsiteCaptureFailedRequestSchema = z107.object({
22206
+ var WebsiteCaptureFailedRequestSchema = z108.object({
22179
22207
  ...attempt,
22180
22208
  cause: WebsiteCaptureCauseSchema
22181
22209
  }).strict();
22182
- var WebsiteCaptureBundleSchema = z107.object({
22183
- version: z107.literal(1),
22184
- files: z107.array(z107.object({
22185
- path: z107.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))$/),
22186
- base64: z107.string().max(Math.ceil(WEBSITE_CAPTURE_MAX_FILE_BYTES / 3) * 4).regex(/^[A-Za-z0-9+/]*={0,2}$/).refine((value) => value.length % 4 === 0),
22210
+ var WebsiteCaptureBundleSchema = z108.object({
22211
+ version: z108.literal(1),
22212
+ files: z108.array(z108.object({
22213
+ path: z108.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))$/),
22214
+ base64: z108.string().max(Math.ceil(WEBSITE_CAPTURE_MAX_FILE_BYTES / 3) * 4).regex(/^[A-Za-z0-9+/]*={0,2}$/).refine((value) => value.length % 4 === 0),
22187
22215
  sha256: digest
22188
22216
  }).strict()).min(1).max(WEBSITE_CAPTURE_MAX_FILES)
22189
22217
  }).strict().refine((bundle) => new Set(bundle.files.map((file) => file.path)).size === bundle.files.length, "Duplicate capture file");
22190
- var WebsiteCaptureScreenshotSchema = z107.object({
22191
- file: z107.string(),
22192
- scrollTop: z107.number()
22193
- });
22194
- var WebsiteCaptureAccessSchema = z107.object({
22195
- publicContentText: z107.string().max(8e3),
22196
- passwordGate: z107.boolean(),
22197
- challengeGate: z107.boolean(),
22198
- blockingOverlay: z107.boolean(),
22218
+ var WebsiteCaptureScreenshotSchema = z108.object({
22219
+ file: z108.string(),
22220
+ scrollTop: z108.number()
22221
+ });
22222
+ var WebsiteCaptureAccessSchema = z108.object({
22223
+ publicContentText: z108.string().max(8e3),
22224
+ passwordGate: z108.boolean(),
22225
+ challengeGate: z108.boolean(),
22226
+ blockingOverlay: z108.boolean(),
22199
22227
  // Decoded, substantial images visible outside access walls and page chrome.
22200
22228
  // Optional for compatibility with already captured text-led research.
22201
- publicImageUrls: z107.array(z107.string().url().max(8192)).max(20).optional()
22202
- });
22203
- var WebsiteCaptureResearchSchema = z107.object({
22204
- requestedUrl: z107.string().url(),
22205
- capturedAt: z107.string().datetime(),
22206
- locale: z107.string(),
22207
- bodyTextTruncated: z107.boolean(),
22208
- finalUrl: z107.string().url(),
22209
- lang: z107.string().nullable(),
22210
- title: z107.string(),
22211
- description: z107.string(),
22212
- openGraph: z107.object({
22213
- title: z107.string(),
22214
- description: z107.string(),
22215
- image: z107.string(),
22216
- siteName: z107.string()
22229
+ publicImageUrls: z108.array(z108.string().url().max(8192)).max(20).optional()
22230
+ });
22231
+ var WebsiteCaptureResearchSchema = z108.object({
22232
+ requestedUrl: z108.string().url(),
22233
+ capturedAt: z108.string().datetime(),
22234
+ locale: z108.string(),
22235
+ bodyTextTruncated: z108.boolean(),
22236
+ finalUrl: z108.string().url(),
22237
+ lang: z108.string().nullable(),
22238
+ title: z108.string(),
22239
+ description: z108.string(),
22240
+ openGraph: z108.object({
22241
+ title: z108.string(),
22242
+ description: z108.string(),
22243
+ image: z108.string(),
22244
+ siteName: z108.string()
22217
22245
  }),
22218
- themeColor: z107.string(),
22219
- headings: z107.object({
22220
- h1: z107.array(z107.string()),
22221
- h2: z107.array(z107.string()),
22222
- h3: z107.array(z107.string())
22246
+ themeColor: z108.string(),
22247
+ headings: z108.object({
22248
+ h1: z108.array(z108.string()),
22249
+ h2: z108.array(z108.string()),
22250
+ h3: z108.array(z108.string())
22223
22251
  }),
22224
- callsToAction: z107.array(z107.string()),
22225
- listItems: z107.array(z107.string()),
22226
- bodyText: z107.string(),
22252
+ callsToAction: z108.array(z108.string()),
22253
+ listItems: z108.array(z108.string()),
22254
+ bodyText: z108.string(),
22227
22255
  access: WebsiteCaptureAccessSchema.optional(),
22228
- consent: z107.object({
22229
- pressed: z107.string().nullable(),
22230
- removed: z107.number().nonnegative()
22256
+ consent: z108.object({
22257
+ pressed: z108.string().nullable(),
22258
+ removed: z108.number().nonnegative()
22231
22259
  }).optional(),
22232
- overlaysDismissed: z107.number().int().nonnegative().optional(),
22233
- style: z107.object({
22234
- bodyBackground: z107.string(),
22235
- bodyColor: z107.string(),
22236
- bodyFont: z107.string(),
22237
- headingFont: z107.string().nullable(),
22238
- headingColor: z107.string().nullable(),
22239
- actionColors: z107.array(z107.object({
22240
- color: z107.string(),
22241
- uses: z107.number()
22260
+ overlaysDismissed: z108.number().int().nonnegative().optional(),
22261
+ style: z108.object({
22262
+ bodyBackground: z108.string(),
22263
+ bodyColor: z108.string(),
22264
+ bodyFont: z108.string(),
22265
+ headingFont: z108.string().nullable(),
22266
+ headingColor: z108.string().nullable(),
22267
+ actionColors: z108.array(z108.object({
22268
+ color: z108.string(),
22269
+ uses: z108.number()
22242
22270
  }))
22243
22271
  }),
22244
- images: z107.array(z107.object({
22245
- file: z107.string(),
22246
- src: z107.string(),
22247
- alt: z107.string(),
22248
- width: z107.number().nullable(),
22249
- height: z107.number().nullable(),
22250
- isOpenGraph: z107.boolean()
22272
+ images: z108.array(z108.object({
22273
+ file: z108.string(),
22274
+ src: z108.string(),
22275
+ alt: z108.string(),
22276
+ width: z108.number().nullable(),
22277
+ height: z108.number().nullable(),
22278
+ isOpenGraph: z108.boolean()
22251
22279
  })),
22252
- logo: z107.object({
22253
- file: z107.literal("logo.png"),
22254
- svg: z107.literal("logo.svg").optional(),
22255
- width: z107.number(),
22256
- height: z107.number()
22280
+ logo: z108.object({
22281
+ file: z108.literal("logo.png"),
22282
+ svg: z108.literal("logo.svg").optional(),
22283
+ width: z108.number(),
22284
+ height: z108.number()
22257
22285
  }).nullable(),
22258
- fonts: z107.array(z107.object({
22259
- family: z107.string(),
22260
- weight: z107.string(),
22261
- style: z107.string(),
22262
- unicodeRange: z107.string().nullable(),
22263
- file: z107.string().optional()
22286
+ fonts: z108.array(z108.object({
22287
+ family: z108.string(),
22288
+ weight: z108.string(),
22289
+ style: z108.string(),
22290
+ unicodeRange: z108.string().nullable(),
22291
+ file: z108.string().optional()
22264
22292
  }).transform((font) => ({
22265
22293
  ...font,
22266
22294
  file: font.file
22267
22295
  }))),
22268
- screenshots: z107.object({
22269
- desktop: z107.array(WebsiteCaptureScreenshotSchema),
22270
- mobile: z107.array(WebsiteCaptureScreenshotSchema)
22296
+ screenshots: z108.object({
22297
+ desktop: z108.array(WebsiteCaptureScreenshotSchema),
22298
+ mobile: z108.array(WebsiteCaptureScreenshotSchema)
22271
22299
  })
22272
22300
  });
22273
22301
 
22274
22302
  // ../../packages/types/src/demo-mode.ts
22275
- import { z as z108 } from "zod";
22303
+ import { z as z109 } from "zod";
22276
22304
  var DEMO_MODE_FLOWS = [
22277
22305
  "brand",
22278
22306
  "servicePage",
22279
22307
  "motion",
22280
22308
  "image"
22281
22309
  ];
22282
- var DemoModeFlowSchema = z108.enum(DEMO_MODE_FLOWS);
22310
+ var DemoModeFlowSchema = z109.enum(DEMO_MODE_FLOWS);
22283
22311
  var DEMO_MODE_STEPS = [
22284
22312
  "running",
22285
22313
  "research",
@@ -22292,27 +22320,27 @@ var DEMO_MODE_STEPS = [
22292
22320
  "final",
22293
22321
  "watchdog"
22294
22322
  ];
22295
- var DemoModeStepSchema = z108.enum(DEMO_MODE_STEPS);
22323
+ var DemoModeStepSchema = z109.enum(DEMO_MODE_STEPS);
22296
22324
  var DEMO_MODE_WAIT_SECONDS = {
22297
22325
  min: 30,
22298
22326
  max: 450,
22299
22327
  default: 150
22300
22328
  };
22301
- var centsSchema = z108.number().int().min(0).max(1e5);
22302
- var emailSchema = z108.string().trim().toLowerCase().email();
22303
- var DemoModeTemplatesSchema = z108.object({
22304
- brandId: z108.string().uuid(),
22305
- servicePageId: z108.string().uuid(),
22306
- motionTaskId: z108.string().uuid(),
22307
- imageTaskId: z108.string().uuid()
22308
- });
22309
- var DemoModeEditableSchema = z108.object({
22310
- enabled: z108.boolean(),
22311
- emails: z108.array(emailSchema).max(50).transform((list) => [
22329
+ var centsSchema = z109.number().int().min(0).max(1e5);
22330
+ var emailSchema = z109.string().trim().toLowerCase().email();
22331
+ var DemoModeTemplatesSchema = z109.object({
22332
+ brandId: z109.string().uuid(),
22333
+ servicePageId: z109.string().uuid(),
22334
+ motionTaskId: z109.string().uuid(),
22335
+ imageTaskId: z109.string().uuid()
22336
+ });
22337
+ var DemoModeEditableSchema = z109.object({
22338
+ enabled: z109.boolean(),
22339
+ emails: z109.array(emailSchema).max(50).transform((list) => [
22312
22340
  ...new Set(list)
22313
22341
  ]),
22314
- waitSeconds: z108.number().int().min(DEMO_MODE_WAIT_SECONDS.min).max(DEMO_MODE_WAIT_SECONDS.max),
22315
- chargeCents: z108.object({
22342
+ waitSeconds: z109.number().int().min(DEMO_MODE_WAIT_SECONDS.min).max(DEMO_MODE_WAIT_SECONDS.max),
22343
+ chargeCents: z109.object({
22316
22344
  brand: centsSchema,
22317
22345
  servicePage: centsSchema,
22318
22346
  motion: centsSchema,
@@ -22320,73 +22348,73 @@ var DemoModeEditableSchema = z108.object({
22320
22348
  }),
22321
22349
  templates: DemoModeTemplatesSchema
22322
22350
  });
22323
- var nullableString = z108.string().nullable();
22324
- var DemoModeSnapshotSchema = z108.object({
22325
- brand: z108.object({
22351
+ var nullableString = z109.string().nullable();
22352
+ var DemoModeSnapshotSchema = z109.object({
22353
+ brand: z109.object({
22326
22354
  /** Columnas de identidad de `Brand` listas para un `update` (sin id/userId/slug/estado/fechas). */
22327
- identity: z108.record(z108.unknown()),
22328
- productSamples: z108.array(z108.object({
22329
- name: z108.string(),
22330
- priceCents: z108.number().int().nullable(),
22355
+ identity: z109.record(z109.unknown()),
22356
+ productSamples: z109.array(z109.object({
22357
+ name: z109.string(),
22358
+ priceCents: z109.number().int().nullable(),
22331
22359
  currency: nullableString,
22332
- imageKey: z108.string(),
22360
+ imageKey: z109.string(),
22333
22361
  productUrl: nullableString,
22334
- position: z108.number().int()
22362
+ position: z109.number().int()
22335
22363
  })),
22336
- personas: z108.array(z108.object({
22337
- name: z108.string(),
22364
+ personas: z109.array(z109.object({
22365
+ name: z109.string(),
22338
22366
  demographics: nullableString,
22339
22367
  painPoints: nullableString,
22340
22368
  motivations: nullableString,
22341
22369
  objections: nullableString,
22342
22370
  gender: nullableString,
22343
- isDefault: z108.boolean()
22371
+ isDefault: z109.boolean()
22344
22372
  }))
22345
22373
  }),
22346
- servicePage: z108.object({
22347
- facts: z108.unknown(),
22348
- review: z108.unknown(),
22349
- artifact: z108.unknown()
22374
+ servicePage: z109.object({
22375
+ facts: z109.unknown(),
22376
+ review: z109.unknown(),
22377
+ artifact: z109.unknown()
22350
22378
  }),
22351
- motion: z108.object({
22379
+ motion: z109.object({
22352
22380
  outputs: MotionGraphicsOutputsSchema,
22353
22381
  /**
22354
22382
  * La captura REAL de la web de la plantilla (nunca una fabricada por la
22355
22383
  * demo). Null cuando la plantilla no tiene ninguna: la captura demo nunca
22356
22384
  * va live, así que el servicio usa `DEMO_MODE_PLACEHOLDER_CAPTURE`.
22357
22385
  */
22358
- capture: z108.object({
22359
- bundleKey: z108.string(),
22360
- sha256: z108.string(),
22361
- uploadBytes: z108.number().int().nullable(),
22386
+ capture: z109.object({
22387
+ bundleKey: z109.string(),
22388
+ sha256: z109.string(),
22389
+ uploadBytes: z109.number().int().nullable(),
22362
22390
  previewKey: nullableString
22363
22391
  }).nullable()
22364
22392
  }),
22365
- image: z108.object({
22366
- provider: z108.string(),
22367
- model: z108.string(),
22368
- prompt: z108.string(),
22369
- imageUrl: z108.string(),
22370
- width: z108.number().int(),
22371
- height: z108.number().int(),
22393
+ image: z109.object({
22394
+ provider: z109.string(),
22395
+ model: z109.string(),
22396
+ prompt: z109.string(),
22397
+ imageUrl: z109.string(),
22398
+ width: z109.number().int(),
22399
+ height: z109.number().int(),
22372
22400
  adCopy: nullableString,
22373
- rawResponse: z108.unknown()
22401
+ rawResponse: z109.unknown()
22374
22402
  })
22375
22403
  });
22376
22404
  var DemoModeConfigSchema = DemoModeEditableSchema.extend({
22377
22405
  snapshot: DemoModeSnapshotSchema.nullable(),
22378
- snapshotAt: z108.string().datetime().nullable()
22406
+ snapshotAt: z109.string().datetime().nullable()
22379
22407
  });
22380
22408
  var DemoModeAdminViewSchema = DemoModeEditableSchema.extend({
22381
22409
  // Sin configurar, la API devuelve ids vacíos ("" no es uuid): la vista los
22382
22410
  // admite; el PUT sí exige uuid (`DemoModeEditableSchema`).
22383
- templates: z108.object({
22384
- brandId: z108.string(),
22385
- servicePageId: z108.string(),
22386
- motionTaskId: z108.string(),
22387
- imageTaskId: z108.string()
22411
+ templates: z109.object({
22412
+ brandId: z109.string(),
22413
+ servicePageId: z109.string(),
22414
+ motionTaskId: z109.string(),
22415
+ imageTaskId: z109.string()
22388
22416
  }),
22389
- snapshotAt: z108.string().nullable()
22417
+ snapshotAt: z109.string().nullable()
22390
22418
  });
22391
22419
  var DEMO_MODE_TEMPLATE_PROBLEMS = [
22392
22420
  "not_found",
@@ -22397,31 +22425,31 @@ var DEMO_MODE_TEMPLATE_PROBLEMS = [
22397
22425
  "no_video",
22398
22426
  "no_creative"
22399
22427
  ];
22400
- var DemoModeTemplateVerdictSchema = z108.discriminatedUnion("ok", [
22401
- z108.object({
22402
- ok: z108.literal(true)
22428
+ var DemoModeTemplateVerdictSchema = z109.discriminatedUnion("ok", [
22429
+ z109.object({
22430
+ ok: z109.literal(true)
22403
22431
  }),
22404
- z108.object({
22405
- ok: z108.literal(false),
22406
- problem: z108.enum(DEMO_MODE_TEMPLATE_PROBLEMS)
22432
+ z109.object({
22433
+ ok: z109.literal(false),
22434
+ problem: z109.enum(DEMO_MODE_TEMPLATE_PROBLEMS)
22407
22435
  })
22408
22436
  ]);
22409
- var DemoModeValidationSchema = z108.object({
22437
+ var DemoModeValidationSchema = z109.object({
22410
22438
  brandId: DemoModeTemplateVerdictSchema,
22411
22439
  servicePageId: DemoModeTemplateVerdictSchema,
22412
22440
  motionTaskId: DemoModeTemplateVerdictSchema,
22413
22441
  imageTaskId: DemoModeTemplateVerdictSchema
22414
22442
  });
22415
- var DemoModeJobSchema = z108.object({
22443
+ var DemoModeJobSchema = z109.object({
22416
22444
  flow: DemoModeFlowSchema,
22417
22445
  step: DemoModeStepSchema,
22418
22446
  /** brandId | servicePageOperationId | taskId según el flujo. */
22419
- targetId: z108.string().uuid(),
22420
- userId: z108.string().min(1),
22447
+ targetId: z109.string().uuid(),
22448
+ userId: z109.string().min(1),
22421
22449
  /** Solo marca: la generación de extracción que el guion completa. */
22422
- generation: z108.number().int().positive().optional(),
22450
+ generation: z109.number().int().positive().optional(),
22423
22451
  /** Solo `final`/`watchdog`: la parte del snapshot de ESTE flujo, congelada al empezar. */
22424
- result: z108.unknown().optional()
22452
+ result: z109.unknown().optional()
22425
22453
  });
22426
22454
 
22427
22455
  // src/http.ts
@@ -22933,23 +22961,23 @@ import { InsufficientScopeError, InvalidTokenError } from "@modelcontextprotocol
22933
22961
  import { createRemoteJWKSet as createRemoteJWKSet2, jwtVerify as jwtVerify2 } from "jose";
22934
22962
 
22935
22963
  // src/auth/oauth-config.ts
22936
- import { z as z109 } from "zod";
22964
+ import { z as z110 } from "zod";
22937
22965
  var MCP_RESOURCE = new URL("https://mcp.productmaker.app/mcp");
22938
22966
  var MCP_SCOPE = "mcp:access";
22939
22967
  var REFRESH_SCOPE = "offline_access";
22940
22968
  var STATIC_CLIENT_ISSUER = new URL(MCP_RESOURCE.origin);
22941
- var oauthEnvSchema = z109.object({
22942
- MCP_REMOTE_AUTH_MODE: z109.literal("oauth"),
22943
- MCP_AUTH0_ISSUER: z109.string().trim().min(1),
22944
- MCP_AUTH0_AUDIENCE: z109.string().trim().refine((value) => value === MCP_RESOURCE.href, {
22969
+ var oauthEnvSchema = z110.object({
22970
+ MCP_REMOTE_AUTH_MODE: z110.literal("oauth"),
22971
+ MCP_AUTH0_ISSUER: z110.string().trim().min(1),
22972
+ MCP_AUTH0_AUDIENCE: z110.string().trim().refine((value) => value === MCP_RESOURCE.href, {
22945
22973
  message: `must equal ${MCP_RESOURCE.href}`
22946
22974
  }),
22947
- MCP_AUTH0_CLIENT_ID: z109.string().trim().min(1),
22948
- MCP_AUTH0_CLIENT_SECRET: z109.string().trim().min(1),
22949
- PM_API_AUDIENCE: z109.string().trim().min(1),
22950
- AUTH0_AUDIENCE: z109.string().trim().min(1),
22951
- MCP_STATIC_CLIENT_ID: z109.string().trim().min(1).optional(),
22952
- MCP_STATIC_CLIENT_SECRET: z109.string().trim().min(1).optional()
22975
+ MCP_AUTH0_CLIENT_ID: z110.string().trim().min(1),
22976
+ MCP_AUTH0_CLIENT_SECRET: z110.string().trim().min(1),
22977
+ PM_API_AUDIENCE: z110.string().trim().min(1),
22978
+ AUTH0_AUDIENCE: z110.string().trim().min(1),
22979
+ MCP_STATIC_CLIENT_ID: z110.string().trim().min(1).optional(),
22980
+ MCP_STATIC_CLIENT_SECRET: z110.string().trim().min(1).optional()
22953
22981
  });
22954
22982
  function formatZodIssues(error) {
22955
22983
  return error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
@@ -24105,7 +24133,7 @@ var ApiClient = class {
24105
24133
  };
24106
24134
 
24107
24135
  // src/index.ts
24108
- var MCP_VERSION = "11.3.3";
24136
+ var MCP_VERSION = "11.4.0";
24109
24137
 
24110
24138
  // src/meta-upload-app.ts
24111
24139
  import { readFileSync } from "fs";
@@ -24177,7 +24205,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
24177
24205
  __name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
24178
24206
 
24179
24207
  // src/tools/tasks.ts
24180
- import { z as z114 } from "zod";
24208
+ import { z as z115 } from "zod";
24181
24209
 
24182
24210
  // src/resolve-image.ts
24183
24211
  import { lookup as dnsLookup } from "dns/promises";
@@ -24738,9 +24766,9 @@ async function resolveMediaRef(ref, opts) {
24738
24766
  __name(resolveMediaRef, "resolveMediaRef");
24739
24767
 
24740
24768
  // src/tools/shared.ts
24741
- import { z as z110 } from "zod";
24742
- var Lang = z110.string().regex(/^[a-z]{2}(?:[-_][a-zA-Z]{2})?$/, "Usa un c\xF3digo de idioma BCP-47, por ejemplo es, en-US o pt-BR").max(10);
24743
- var Country = z110.string().min(2).max(3);
24769
+ import { z as z111 } from "zod";
24770
+ var Lang = z111.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);
24771
+ var Country = z111.string().min(2).max(3);
24744
24772
  var LandingStrategyEnum = LandingStrategySchema;
24745
24773
  var LandingImageFormatEnum = LandingImageFormatSchema;
24746
24774
  var VideoPresetEnum = VideoPreset.extract([
@@ -24844,7 +24872,7 @@ function animationStyleApplies(videoPreset, angleNarratives) {
24844
24872
  return ANIMATED_VIDEO_PRESETS.has(videoPreset ?? "") || (angleNarratives ?? []).some((n) => ANIMATED_NARRATIVE_STYLES.has(n));
24845
24873
  }
24846
24874
  __name(animationStyleApplies, "animationStyleApplies");
24847
- var VideoTierEnum = z110.enum([
24875
+ var VideoTierEnum = z111.enum([
24848
24876
  "basic"
24849
24877
  ]);
24850
24878
  function resolveVideoTier(_tier) {
@@ -24902,10 +24930,10 @@ var ImageCreativeStyleEnum = ImageCreativeStyle;
24902
24930
  var ImageCreativeArchetypeEnum = ImageCreativeArchetype;
24903
24931
  var ImageCreativeVisualTreatmentEnum = ImageCreativeVisualTreatment;
24904
24932
  var ImageCreativeAspectRatioEnum = ImageCreativeAspectRatio;
24905
- var ImageRefSchema = z110.object({
24906
- url: z110.string().url().optional().describe('URL p\xFAblica HTTPS de la foto. Ej: una URL de Shopify CDN, Cloudinary, Imgur. \xDAsala cuando el usuario te diga "est\xE1 en X.com/foto.jpg" o cuando la foto ya est\xE9 hospedada.'),
24907
- path: z110.string().min(1).optional().describe('Ruta del archivo en el computador del usuario. Ej: "/Users/maria/Desktop/foto.jpg", "~/Pictures/camiseta.png", "C:\\Users\\Maria\\Desktop\\foto.jpg". El MCP local la lee del disco y la sube. SOLO funciona cuando el MCP corre local (stdio). NO funciona en mcp.productmaker.app (HTTP) \u2014 ah\xED usa `url`.'),
24908
- assetId: z110.string().uuid().optional().describe("ID opaco devuelto por check_media_upload. \xDAsalo para una imagen subida desde el MCP App; ProductMaker adopta el archivo directamente y el MCP nunca descarga sus bytes.")
24933
+ var ImageRefSchema = z111.object({
24934
+ url: z111.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.'),
24935
+ path: z111.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`.'),
24936
+ assetId: z111.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.")
24909
24937
  }).refine((v) => [
24910
24938
  v.url,
24911
24939
  v.path,
@@ -24913,11 +24941,11 @@ var ImageRefSchema = z110.object({
24913
24941
  ].filter(Boolean).length === 1, {
24914
24942
  message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
24915
24943
  });
24916
- var ImagesInput = z110.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
24944
+ var ImagesInput = z111.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
24917
24945
  const assetCount = images.filter((image) => Boolean(image.assetId)).length;
24918
24946
  if (assetCount > 0 && assetCount !== images.length) {
24919
24947
  ctx.addIssue({
24920
- code: z110.ZodIssueCode.custom,
24948
+ code: z111.ZodIssueCode.custom,
24921
24949
  message: "all image entries must use assetId, or all must use URL/path sources"
24922
24950
  });
24923
24951
  }
@@ -24998,14 +25026,14 @@ async function submitCreative(api, opts) {
24998
25026
  });
24999
25027
  }
25000
25028
  __name(submitCreative, "submitCreative");
25001
- var ResearchTargetCountryEnum = z110.enum([
25029
+ var ResearchTargetCountryEnum = z111.enum([
25002
25030
  "CO",
25003
25031
  "MX",
25004
25032
  "PE",
25005
25033
  "EC",
25006
25034
  "CL"
25007
25035
  ]);
25008
- var ResearchCategoryEnum = z110.enum([
25036
+ var ResearchCategoryEnum = z111.enum([
25009
25037
  "auto",
25010
25038
  "automotive",
25011
25039
  "kitchen",
@@ -25135,6 +25163,7 @@ var McpErrorCode = {
25135
25163
  CAMPAIGN_NOT_FOUND: "CAMPAIGN_NOT_FOUND",
25136
25164
  CAMPAIGN_TASK_NOT_FOUND: "CAMPAIGN_TASK_NOT_FOUND",
25137
25165
  CAMPAIGN_MISSING_LANDING_URL: "CAMPAIGN_MISSING_LANDING_URL",
25166
+ CAMPAIGN_MISSING_TARGET_COUNTRY: "CAMPAIGN_MISSING_TARGET_COUNTRY",
25138
25167
  CAMPAIGN_NO_CREATIVES: "CAMPAIGN_NO_CREATIVES",
25139
25168
  CAMPAIGN_MISSING_THUMBNAILS: "CAMPAIGN_MISSING_THUMBNAILS",
25140
25169
  CAMPAIGN_RECONCILIATION_REQUIRED: "CAMPAIGN_RECONCILIATION_REQUIRED",
@@ -25174,6 +25203,7 @@ var McpErrorCode = {
25174
25203
  META_NO_ASSETS_READY: "META_NO_ASSETS_READY",
25175
25204
  META_NO_THUMBNAIL_SOURCE: "META_NO_THUMBNAIL_SOURCE",
25176
25205
  META_NO_LANDING_URL: "META_NO_LANDING_URL",
25206
+ META_NO_TARGET_COUNTRY: "META_NO_TARGET_COUNTRY",
25177
25207
  META_TASK_NOT_FOUND: "META_TASK_NOT_FOUND",
25178
25208
  META_INVALID_DATA: "META_INVALID_DATA",
25179
25209
  META_INVALID_AD_ACCOUNT: "META_INVALID_AD_ACCOUNT",
@@ -25261,7 +25291,8 @@ var CODE_MESSAGES = {
25261
25291
  META_NO_ADS_CREATED: "No ads could be created. Most likely: the Meta Ads account has no payment method, no Facebook Page is linked, or the Facebook app lost permissions. Verify all three at https://business.facebook.com.",
25262
25292
  META_NO_ASSETS_READY: "The task has no videos or ad creative ready to publish yet. Wait for generation to finish or regenerate the assets.",
25263
25293
  META_NO_THUMBNAIL_SOURCE: "No image is available to use as the video thumbnail. Upload a product image or generate the ad creative before publishing.",
25264
- META_NO_LANDING_URL: "Missing landing URL. Pass it in `landingUrl` or publish to Shopify first with `publish_to_shopify`.",
25294
+ META_NO_LANDING_URL: "Missing landing URL. Pass it in `landingUrl`, or publish first: a product to Shopify with `publish_to_shopify`, a service to its service landing.",
25295
+ META_NO_TARGET_COUNTRY: "This service ad has no target country (its brand sets none). Ask the user which country and pass it in `campaignConfig.targetCountries`; never assume one.",
25265
25296
  META_TASK_NOT_FOUND: "Task not found or does not belong to this user. Verify the `taskId`.",
25266
25297
  META_INVALID_DATA: "Meta rejected the request due to invalid data. Verify that `adAccountId` and `pixelId` are correct.",
25267
25298
  META_INVALID_AD_ACCOUNT: "Ad account not found or no access. Confirm the `adAccountId` with `list_meta_ad_accounts`.",
@@ -25300,7 +25331,8 @@ var CODE_MESSAGES = {
25300
25331
  // Campaign (shared)
25301
25332
  CAMPAIGN_NOT_FOUND: "Campaign not found or does not belong to this user. Verify the `campaignId`.",
25302
25333
  CAMPAIGN_TASK_NOT_FOUND: "Campaign task not found. Verify the `taskId`.",
25303
- CAMPAIGN_MISSING_LANDING_URL: "Missing landing URL for the campaign. Publish to Shopify first or pass `landingUrl` explicitly.",
25334
+ CAMPAIGN_MISSING_LANDING_URL: "Missing landing URL for the campaign. Publish first (a product to Shopify, a service to its service landing) or pass `landingUrl` explicitly.",
25335
+ CAMPAIGN_MISSING_TARGET_COUNTRY: "This service ad has no target country (its brand sets none). Ask the user which country and pass it in `campaignConfig.targetCountries`; never assume one.",
25304
25336
  CAMPAIGN_NO_CREATIVES: "The task has no creatives (video/image) ready for the campaign. Wait for generation to finish.",
25305
25337
  CAMPAIGN_MISSING_THUMBNAILS: "Missing thumbnails for the videos. Verify that image/video generation has finished.",
25306
25338
  CAMPAIGN_RECONCILIATION_REQUIRED: "A campaign may already have been created. Do not retry creation; reopen the project and reconcile it or contact support.",
@@ -25392,8 +25424,10 @@ var INVALID_PARAM_CODES = /* @__PURE__ */ new Set([
25392
25424
  McpErrorCode.TIKTOK_ADVERTISER_REQUIRED,
25393
25425
  McpErrorCode.TIKTOK_PIXEL_NOT_FOUND,
25394
25426
  McpErrorCode.CAMPAIGN_MISSING_LANDING_URL,
25427
+ McpErrorCode.CAMPAIGN_MISSING_TARGET_COUNTRY,
25395
25428
  McpErrorCode.CAMPAIGN_RECONCILIATION_REQUIRED,
25396
25429
  McpErrorCode.META_NO_LANDING_URL,
25430
+ McpErrorCode.META_NO_TARGET_COUNTRY,
25397
25431
  McpErrorCode.META_PORTFOLIO_MISMATCH,
25398
25432
  McpErrorCode.META_PAGE_SELECTION_REQUIRED,
25399
25433
  McpErrorCode.META_INVALID_PAGE,
@@ -25504,6 +25538,7 @@ var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
25504
25538
  McpErrorCode.META_NO_ASSETS_READY,
25505
25539
  McpErrorCode.META_NO_THUMBNAIL_SOURCE,
25506
25540
  McpErrorCode.META_NO_LANDING_URL,
25541
+ McpErrorCode.META_NO_TARGET_COUNTRY,
25507
25542
  McpErrorCode.META_TASK_NOT_FOUND,
25508
25543
  McpErrorCode.META_INVALID_DATA,
25509
25544
  McpErrorCode.META_INVALID_AD_ACCOUNT,
@@ -25551,6 +25586,7 @@ var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
25551
25586
  McpErrorCode.CAMPAIGN_NOT_FOUND,
25552
25587
  McpErrorCode.CAMPAIGN_TASK_NOT_FOUND,
25553
25588
  McpErrorCode.CAMPAIGN_MISSING_LANDING_URL,
25589
+ McpErrorCode.CAMPAIGN_MISSING_TARGET_COUNTRY,
25554
25590
  McpErrorCode.CAMPAIGN_NO_CREATIVES,
25555
25591
  McpErrorCode.CAMPAIGN_MISSING_THUMBNAILS,
25556
25592
  McpErrorCode.CAMPAIGN_RECONCILIATION_REQUIRED,
@@ -26317,29 +26353,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
26317
26353
  __name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
26318
26354
 
26319
26355
  // src/tools/media-presentation.ts
26320
- import { z as z111 } from "zod";
26321
- var HttpsPresentationUrlSchema = z111.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
26356
+ import { z as z112 } from "zod";
26357
+ var HttpsPresentationUrlSchema = z112.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
26322
26358
  var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
26323
26359
  const hostname = new URL(value).hostname.toLowerCase();
26324
26360
  return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
26325
26361
  }, "preview URL must be owned by ProductMaker");
26326
- var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z111.number().int().positive().max(maximum), "positiveIntAtMost");
26327
- var PresentationImageSchema = z111.object({
26328
- kind: z111.literal("image"),
26362
+ var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z112.number().int().positive().max(maximum), "positiveIntAtMost");
26363
+ var PresentationImageSchema = z112.object({
26364
+ kind: z112.literal("image"),
26329
26365
  url: HttpsPresentationUrlSchema,
26330
- mimeType: z111.enum([
26366
+ mimeType: z112.enum([
26331
26367
  "image/jpeg",
26332
26368
  "image/png"
26333
26369
  ]),
26334
26370
  byteSize: positiveIntAtMost(5 * 1024 * 1024),
26335
26371
  width: positiveIntAtMost(16384),
26336
26372
  height: positiveIntAtMost(16384),
26337
- alt: z111.string().trim().min(1).max(240)
26373
+ alt: z112.string().trim().min(1).max(240)
26338
26374
  }).strict();
26339
26375
  var McpMediaPresentationSchema = PresentationImageSchema;
26340
- var GalleryImageSchema = z111.object({
26376
+ var GalleryImageSchema = z112.object({
26341
26377
  url: ProductMakerPreviewUrlSchema,
26342
- alt: z111.string().trim().min(1).max(240)
26378
+ alt: z112.string().trim().min(1).max(240)
26343
26379
  });
26344
26380
  var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
26345
26381
  async function imageBlocks(image, transport) {
@@ -26396,12 +26432,12 @@ async function buildMcpMediaPresentationContent(rawPresentation, transport = "ht
26396
26432
  ];
26397
26433
  }
26398
26434
  __name(buildMcpMediaPresentationContent, "buildMcpMediaPresentationContent");
26399
- var OwnedImagePreviewSchema = z111.object({
26435
+ var OwnedImagePreviewSchema = z112.object({
26400
26436
  url: HttpsPresentationUrlSchema.refine((value) => {
26401
26437
  const url = new URL(value);
26402
26438
  return !url.username && !url.password && !isPrivateHost(url.hostname);
26403
26439
  }, "Preview URL must be public HTTPS without credentials"),
26404
- alt: z111.string().trim().min(1).max(240)
26440
+ alt: z112.string().trim().min(1).max(240)
26405
26441
  });
26406
26442
  async function buildMcpImagePreviewContent(rawPreview, transport = "http") {
26407
26443
  const preview2 = OwnedImagePreviewSchema.safeParse(rawPreview);
@@ -26484,7 +26520,7 @@ async function buildMcpImageGalleryContent(rawItems, transport = "http") {
26484
26520
  __name(buildMcpImageGalleryContent, "buildMcpImageGalleryContent");
26485
26521
 
26486
26522
  // src/tools/animated-video.ts
26487
- import { z as z112 } from "zod";
26523
+ import { z as z113 } from "zod";
26488
26524
 
26489
26525
  // src/tools/paid-confirmation.ts
26490
26526
  function describeMarketStudyChoice(enabled) {
@@ -26734,27 +26770,27 @@ function hookVariantsLabel(count) {
26734
26770
  return count === 1 ? "1 versi\xF3n del gancho" : `${count} versiones del gancho`;
26735
26771
  }
26736
26772
  __name(hookVariantsLabel, "hookVariantsLabel");
26737
- var DurationInput = z112.union(MOTION_GRAPHICS_DURATIONS.map((d) => z112.literal(d)));
26738
- var CreateAnimatedVideoInput = z112.object({
26739
- action: z112.enum([
26773
+ var DurationInput = z113.union(MOTION_GRAPHICS_DURATIONS.map((d) => z113.literal(d)));
26774
+ var CreateAnimatedVideoInput = z113.object({
26775
+ action: z113.enum([
26740
26776
  "prepare",
26741
26777
  "status",
26742
26778
  "cancel",
26743
26779
  "generate"
26744
26780
  ]).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."),
26745
- websiteCaptureId: z112.string().uuid().optional().describe("ID de la captura preparada. Obligatorio para status/cancel/generate; no inventarlo."),
26746
- generationRequestId: z112.string().uuid().optional().describe("Identidad opcional de una generaci\xF3n confirmada. Repite el mismo UUID al recuperar una respuesta perdida; usa otro \xFAnicamente cuando el usuario pida y confirme otro video, nunca por un error de transporte."),
26747
- confirmed: z112.boolean().optional().describe("Solo true despu\xE9s de que el usuario confirme esta captura, formato, duraci\xF3n, idioma y precio. Obligatorio para generate; preparar no genera ni cobra."),
26781
+ websiteCaptureId: z113.string().uuid().optional().describe("ID de la captura preparada. Obligatorio para status/cancel/generate; no inventarlo."),
26782
+ generationRequestId: z113.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."),
26783
+ confirmed: z113.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."),
26748
26784
  // Plain text, not `.url()`: users type «cal.com», and the web accepts it.
26749
26785
  // normalizeWebAddress (shared with the web) adds https:// and refuses
26750
26786
  // anything that is not a public http(s) address.
26751
- landingUrl: z112.string().trim().min(1).optional().describe("Enlace p\xFAblico de la p\xE1gina del servicio, como lo dio el usuario (\xABcal.com\xBB o \xABhttps://cal.com\xBB). El video sale de lo que muestra esa p\xE1gina: su marca, colores y mensajes."),
26787
+ landingUrl: z113.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."),
26752
26788
  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.'),
26753
26789
  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.`),
26754
26790
  language: MotionGraphicsLanguageSchema.optional().describe('Idioma de los textos del video: "es", "en" o "pt".'),
26755
- notes: z112.string().trim().max(MOTION_GRAPHICS_NOTES_MAX_CHARS).optional().describe("Opcional. Indicaciones para el video en lenguaje natural (ej. enf\xF3cate en los precios, tono m\xE1s formal, menciona la prueba gratis)."),
26791
+ notes: z113.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)."),
26756
26792
  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.`),
26757
- music: z112.boolean().optional().describe("Opcional. M\xFAsica de fondo (por defecto true). false hace el video sin m\xFAsica, m\xE1s crudo, estilo UGC: quedan la voz y los efectos de sonido. Mismo precio. \xDAsalo solo si el usuario lo pide.")
26793
+ music: z113.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.")
26758
26794
  }).strict();
26759
26795
  function captureNextAction(capture) {
26760
26796
  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.";
@@ -26787,43 +26823,43 @@ var FORMAT_LABELS = {
26787
26823
  square: "cuadrado 1:1",
26788
26824
  horizontal: "horizontal 16:9"
26789
26825
  };
26790
- var AnimatedVideoResultSchema = z112.object({
26791
- status: z112.enum([
26826
+ var AnimatedVideoResultSchema = z113.object({
26827
+ status: z113.enum([
26792
26828
  "pending",
26793
26829
  "done",
26794
26830
  "error"
26795
26831
  ]),
26796
- serviceMode: z112.literal("motion_graphics"),
26797
- finalMp4Url: z112.string().optional(),
26798
- error: z112.string().optional(),
26799
- motionGraphics: z112.object({
26832
+ serviceMode: z113.literal("motion_graphics"),
26833
+ finalMp4Url: z113.string().optional(),
26834
+ error: z113.string().optional(),
26835
+ motionGraphics: z113.object({
26800
26836
  stage: MotionGraphicsStageSchema,
26801
26837
  format: MotionGraphicsFormatSchema,
26802
- durationSec: z112.number(),
26803
- width: z112.number().optional(),
26804
- height: z112.number().optional(),
26838
+ durationSec: z113.number(),
26839
+ width: z113.number().optional(),
26840
+ height: z113.number().optional(),
26805
26841
  language: MotionGraphicsLanguageSchema.optional(),
26806
- queuedAt: z112.string().optional(),
26807
- jobsAhead: z112.number().int().nonnegative().optional(),
26808
- stageStartedAt: z112.string().optional(),
26809
- renderProgress: z112.number().optional(),
26842
+ queuedAt: z113.string().optional(),
26843
+ jobsAhead: z113.number().int().nonnegative().optional(),
26844
+ stageStartedAt: z113.string().optional(),
26845
+ renderProgress: z113.number().optional(),
26810
26846
  // AI clip fields (absent on a video paid before clips, or from an API
26811
26847
  // that predates them). Lenient: an unreadable value is dropped
26812
26848
  // instead of hiding the status.
26813
- clipCount: z112.number().int().nonnegative().optional().catch(void 0),
26814
- clipsUsed: z112.number().int().nonnegative().optional().catch(void 0),
26815
- clipPriceCents: z112.number().finite().nonnegative().optional().catch(void 0),
26816
- clipsRefunded: z112.number().int().nonnegative().optional().catch(void 0),
26849
+ clipCount: z113.number().int().nonnegative().optional().catch(void 0),
26850
+ clipsUsed: z113.number().int().nonnegative().optional().catch(void 0),
26851
+ clipPriceCents: z113.number().finite().nonnegative().optional().catch(void 0),
26852
+ clipsRefunded: z113.number().int().nonnegative().optional().catch(void 0),
26817
26853
  // Hook versions (absent from an API or a video before them): the
26818
26854
  // count ordered and, once done, the signed URLs of the EXTRA versions
26819
26855
  // (hook 2, hook 3); `finalMp4Url` is hook 1.
26820
- hookVariants: z112.number().int().min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).optional().catch(void 0),
26821
- variantUrls: z112.array(z112.string().min(1)).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
26856
+ hookVariants: z113.number().int().min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).optional().catch(void 0),
26857
+ variantUrls: z113.array(z113.string().min(1)).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
26822
26858
  // Extra hook versions given back, as the task recorded it once the
26823
26859
  // refunds landed (absent until then, and from an API before it).
26824
- variantsRefunded: z112.number().int().nonnegative().optional().catch(void 0),
26825
- activity: z112.array(MotionGraphicsActivitySchema).optional().catch(void 0),
26826
- previewUrl: z112.string().optional()
26860
+ variantsRefunded: z113.number().int().nonnegative().optional().catch(void 0),
26861
+ activity: z113.array(MotionGraphicsActivitySchema).optional().catch(void 0),
26862
+ previewUrl: z113.string().optional()
26827
26863
  }).passthrough()
26828
26864
  }).passthrough();
26829
26865
  function parseAnimatedVideoResult(value) {
@@ -27079,10 +27115,10 @@ function registerAnimatedVideoTools(server, api) {
27079
27115
  __name(registerAnimatedVideoTools, "registerAnimatedVideoTools");
27080
27116
 
27081
27117
  // src/tools/winning-product-image.ts
27082
- import { z as z113 } from "zod";
27083
- var WinnerReferenceInput = z113.object({
27084
- runId: z113.string().uuid(),
27085
- candidateSourceId: z113.string().trim().min(1).max(160)
27118
+ import { z as z114 } from "zod";
27119
+ var WinnerReferenceInput = z114.object({
27120
+ runId: z114.string().uuid(),
27121
+ candidateSourceId: z114.string().trim().min(1).max(160)
27086
27122
  }).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
27087
27123
  async function resolveWinnerImages(api, winnerReference, images) {
27088
27124
  if (!winnerReference) return images;
@@ -27119,62 +27155,62 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
27119
27155
  var CREATE_SERVICE_VIDEO_ON_MCP = PRODUCTMAKER_MCP_CAPABILITY_NAMES.includes("create_service_video");
27120
27156
  var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
27121
27157
  var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
27122
- var CreateProductTaskInput = z114.object({
27158
+ var CreateProductTaskInput = z115.object({
27123
27159
  images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
27124
27160
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
27125
- projectId: z114.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
27126
- productUrl: z114.string().url().optional().describe("Opcional. URL de la p\xE1gina del producto (Shopify, AliExpress, Amazon, etc.) para enriquecer el contexto. Si se omite, la IA infiere todo desde la imagen."),
27161
+ projectId: z115.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
27162
+ productUrl: z115.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."),
27127
27163
  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.'),
27128
27164
  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.'),
27129
- price: z114.string().min(1).max(120).optional().describe('Precio que se mostrar\xE1 en la landing y video. Formato libre \u2014 ej. "$89.900", "USD 29.99", "MXN 599". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar. Si te dice "t\xFA elige", om\xEDtelo y el backend sugiere uno.'),
27130
- compareAtPrice: z114.string().min(1).max(120).optional().describe('Opcional. Precio anterior para comunicar un descuento real en landing e im\xE1genes. Ej. "$129.000" cuando price="$89.900".'),
27131
- offer: z114.string().min(1).max(240).optional().describe('Oferta o promoci\xF3n a destacar. Ej. "2x1", "Env\xEDo gratis hoy", "50% OFF". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar (es v\xE1lido que diga "sin oferta"). Si te dice "t\xFA elige", om\xEDtelo.'),
27132
- paymentMethods: z114.string().min(1).max(240).optional().describe('Opcional. M\xE9todos de pago que puede mostrar la landing. Ej. "Tarjeta, PSE, Nequi, Contraentrega". Si se omite, la landing no muestra m\xE9todos de pago.'),
27133
- productContext: z114.string().max(PRODUCT_CONTEXT_MAX_CHARS).optional().describe("Opcional. Informacion adicional del producto que la IA debe usar como contexto prioritario: uso real, comprador, restricciones, diferenciadores o direccion creativa. No reemplaza la investigacion de competencia; si hay competencia, guia el primer angulo y los outputs no deben contradecirlo."),
27134
- productLabel: z114.string().trim().max(80).optional().describe('Opcional. Qu\xE9 es el producto, en pocas palabras (ej. "quita pelusas para ropa"). Es AUTORITATIVO: si lo env\xEDas, la IA usa esta identidad y no la reemplaza por otra categor\xEDa. Si lo omites, la IA detecta el producto desde la imagen.'),
27165
+ price: z115.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.'),
27166
+ compareAtPrice: z115.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".'),
27167
+ offer: z115.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.'),
27168
+ paymentMethods: z115.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.'),
27169
+ productContext: z115.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."),
27170
+ productLabel: z115.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.'),
27135
27171
  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.'),
27136
27172
  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.'),
27137
- durationSeconds: z114.union([
27138
- z114.literal(15),
27139
- z114.literal(30)
27173
+ durationSeconds: z115.union([
27174
+ z115.literal(15),
27175
+ z115.literal(30)
27140
27176
  ]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
27141
- pauseForAngleReview: z114.boolean().optional().describe("Compatibilidad heredada. MCP deriva esta pausa de aiDecidesAll: manual siempre pausa y autom\xE1tico siempre la omite. No uses este campo para saltar reviews."),
27142
- aiDecidesAll: z114.boolean().optional().describe("Mapea el toggle web \u201CDejar que la IA decida todo\u201D. Si true, ProductMaker omite reviews. Act\xEDvalo \xFAnicamente cuando el usuario lo pida expl\xEDcitamente. Omitido/false = reviews conversacionales."),
27177
+ pauseForAngleReview: z115.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."),
27178
+ aiDecidesAll: z115.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."),
27143
27179
  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.'),
27144
27180
  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.'),
27145
27181
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
27146
27182
  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).'),
27147
- videoAngleCount: z114.number().int().min(1).max(3).optional().describe("Cantidad de videos a renderizar: 1, 2 o 3. REQUERIDO cuando outputs incluye video (o se omite outputs, cuyo default incluye video); om\xEDtelo s\xF3lo cuando no se generar\xE1 video. Preg\xFAntalo incluso con aiDecidesAll=true porque cambia el costo."),
27183
+ videoAngleCount: z115.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."),
27148
27184
  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.'),
27149
- outputs: z114.array(z114.enum([
27185
+ outputs: z115.array(z115.enum([
27150
27186
  "landing",
27151
27187
  "video",
27152
27188
  "image"
27153
27189
  ])).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}`),
27154
- includeInitialLandingGif: z114.boolean().optional().describe("Opcional. En nuevas landings cl\xE1sicas habilitadas, omitirlo incluye el primer GIF del producto y su coste en el total. Env\xEDa false si el usuario lo excluye: no se genera ni se reserva su coste. Conserva la elecci\xF3n al confirmar y al reintentar."),
27155
- competitorScanEnabled: z114.boolean().optional().describe("Opcional. Default false: omitirlo significa SIN estudio de mercado. Antes de crear, llama estimate_market_study_cost con kind=product_task, muestra al usuario el costo con y sin estudio y preg\xFAntale si lo quiere; env\xEDa true solo si lo acepta (o si solicita la narrativa an\xE1lisis de mercado). Si la tarea incluye video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico."),
27190
+ includeInitialLandingGif: z115.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."),
27191
+ competitorScanEnabled: z115.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."),
27156
27192
  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.'),
27157
- replicateWinnerWhenFound: z114.boolean().optional().describe("Conserva la preferencia de copiar un ganador si existe. false estudia el mercado sin reemplazar un \xE1ngulo por el anuncio ganador. No a\xF1ade una pregunta obligatoria."),
27158
- brandId: z114.string().uuid().optional().describe("Opcional. ID de una marca del usuario; si se env\xEDa, el sistema usa su voz, colores y persona para enriquecer los outputs generados."),
27159
- actorId: z114.string().trim().min(1).max(120).optional().describe("Opcional. ID de un personaje guardado (usa list_actors para verlos). Si lo env\xEDas, su foto y su voz mandan sobre la descripci\xF3n de texto."),
27193
+ replicateWinnerWhenFound: z115.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."),
27194
+ brandId: z115.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."),
27195
+ actorId: z115.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."),
27160
27196
  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.'),
27161
- creativeDirection: z114.string().max(500).optional().describe('Opcional. Direcci\xF3n creativa en texto libre (colores, mood, estilo) que aplica a los outputs de IMAGEN y LANDING (no al video \u2014 el estilo/ambiente del video se dirige con scriptNotes). M\xC1XIMA PRIORIDAD: anula marca, colores y estilo por defecto. Ej. "amarillo y azul, minimalista". M\xE1x 500 caracteres.'),
27162
- headline: z114.string().max(120).optional().describe("Opcional. Titular EXACTO a renderizar. Se imprime tal cual: la IA no lo reescribe, no lo acorta y no lo traduce. Se aplica a las IM\xC1GENES y a la portada de la landing de esta task (el video no lo usa; para el video usa scriptNotes). \xDAsalo cuando el copy es de marca y no es negociable. M\xE1x 120 caracteres. Si lo omites, la IA escribe el titular."),
27163
- subheadline: z114.string().max(160).optional().describe("Opcional. Subt\xEDtulo EXACTO a renderizar, misma regla que headline. Independiente: puedes fijar solo el subt\xEDtulo. M\xE1x 160 caracteres."),
27197
+ creativeDirection: z115.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.'),
27198
+ headline: z115.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."),
27199
+ subheadline: z115.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."),
27164
27200
  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".'),
27165
27201
  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".')
27166
27202
  }).strict();
27167
- var CreateServiceVideoInput = z114.object({
27168
- landingUrl: z114.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
27169
- additionalContext: z114.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
27203
+ var CreateServiceVideoInput = z115.object({
27204
+ landingUrl: z115.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
27205
+ additionalContext: z115.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
27170
27206
  language: Lang.describe("Idioma del video: es, en o pt."),
27171
- voiceId: z114.string().trim().min(1).pipe(VoiceId).optional().describe('Opcional. Voz para toda la narraci\xF3n. Usa "auto" para que la IA la alinee con el presentador. Las voces del banco compartido fueron retiradas.'),
27172
- brandId: z114.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
27173
- reviewMode: z114.enum([
27207
+ voiceId: z115.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.'),
27208
+ brandId: z115.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
27209
+ reviewMode: z115.enum([
27174
27210
  "automatic",
27175
27211
  "guided"
27176
27212
  ]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
27177
- videoPreset: z114.enum([
27213
+ videoPreset: z115.enum([
27178
27214
  "auto",
27179
27215
  "ugc_dynamic",
27180
27216
  "ugc_how_to",
@@ -27184,128 +27220,128 @@ var CreateServiceVideoInput = z114.object({
27184
27220
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
27185
27221
  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.')
27186
27222
  }).strict();
27187
- var GetTaskStatusInput = z114.object({
27188
- taskId: z114.string().min(1),
27189
- waitSeconds: z114.number().int().min(0).max(120).optional()
27223
+ var GetTaskStatusInput = z115.object({
27224
+ taskId: z115.string().min(1),
27225
+ waitSeconds: z115.number().int().min(0).max(120).optional()
27190
27226
  });
27191
- var ListTasksInput = z114.object({
27192
- limit: z114.number().int().min(1).max(50).optional(),
27193
- offset: z114.number().int().min(0).optional(),
27194
- search: z114.string().optional()
27227
+ var ListTasksInput = z115.object({
27228
+ limit: z115.number().int().min(1).max(50).optional(),
27229
+ offset: z115.number().int().min(0).optional(),
27230
+ search: z115.string().optional()
27195
27231
  });
27196
27232
  var MCP_REVIEW_LIST_FIELD_MAX = IMAGE_WIZARD_LIST_FIELD_MAX;
27197
27233
  var MCP_REVIEW_FEATURE_ITEM_MAX = IMAGE_FEATURE_ITEM_MAX;
27198
- var EditTaskDraftInput = z114.object({
27199
- taskId: z114.string().min(1),
27200
- angleIndex: z114.number().int().min(0),
27201
- angle: z114.object({
27202
- angle: z114.string().min(1).max(480),
27203
- buyerPersona: z114.string().min(1).max(360),
27204
- actor: z114.string().min(1).max(360).optional(),
27205
- actorId: z114.string().trim().min(1).optional().describe("Opcional. ID de un personaje guardado (usa list_actors para verlos). Si lo env\xEDas, su foto y su voz mandan sobre la descripci\xF3n de texto."),
27206
- gender: z114.enum([
27234
+ var EditTaskDraftInput = z115.object({
27235
+ taskId: z115.string().min(1),
27236
+ angleIndex: z115.number().int().min(0),
27237
+ angle: z115.object({
27238
+ angle: z115.string().min(1).max(480),
27239
+ buyerPersona: z115.string().min(1).max(360),
27240
+ actor: z115.string().min(1).max(360).optional(),
27241
+ actorId: z115.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."),
27242
+ gender: z115.enum([
27207
27243
  "female",
27208
27244
  "male"
27209
27245
  ]).optional(),
27210
- scriptNotes: z114.string().max(2e3).optional()
27246
+ scriptNotes: z115.string().max(2e3).optional()
27211
27247
  })
27212
27248
  });
27213
- var PendingActionPayload = z114.discriminatedUnion("kind", [
27214
- z114.object({
27215
- kind: z114.literal("product_reference_set_approval"),
27249
+ var PendingActionPayload = z115.discriminatedUnion("kind", [
27250
+ z115.object({
27251
+ kind: z115.literal("product_reference_set_approval"),
27216
27252
  scope: ProductReferenceScopeEnum.optional(),
27217
- scopeKey: z114.string().min(1).max(120).optional(),
27218
- scopeSnapshotId: z114.string().uuid().optional(),
27219
- expectedScopeHash: z114.string().min(1).max(128).optional(),
27253
+ scopeKey: z115.string().min(1).max(120).optional(),
27254
+ scopeSnapshotId: z115.string().uuid().optional(),
27255
+ expectedScopeHash: z115.string().min(1).max(128).optional(),
27220
27256
  decision: ProductReferenceResolutionDecisionEnum,
27221
27257
  reason: ProductReferenceRejectionReasonEnum.optional(),
27222
- affectedRefKeys: z114.array(z114.string().min(1).max(200)).min(1).optional(),
27223
- affectedPhotoNumbers: z114.array(z114.number().int().positive()).min(1).optional(),
27224
- recoveryAction: z114.enum([
27258
+ affectedRefKeys: z115.array(z115.string().min(1).max(200)).min(1).optional(),
27259
+ affectedPhotoNumbers: z115.array(z115.number().int().positive()).min(1).optional(),
27260
+ recoveryAction: z115.enum([
27225
27261
  "remove",
27226
27262
  "replace",
27227
27263
  "upload",
27228
27264
  "return_to_selection"
27229
27265
  ]).optional()
27230
27266
  }),
27231
- z114.object({
27232
- kind: z114.literal("product_reference_confirmation"),
27233
- selectedPhotoNumbers: z114.array(z114.number().int().positive().max(5)).min(1).max(5).optional().describe("Opcional. N\xFAmeros visibles de las fotos que el usuario quiere conservar; las dem\xE1s se deseleccionan. Debe quedar al menos una."),
27267
+ z115.object({
27268
+ kind: z115.literal("product_reference_confirmation"),
27269
+ selectedPhotoNumbers: z115.array(z115.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."),
27234
27270
  userChoice: ProductReferenceUserChoiceEnum.optional(),
27235
- confirmedProductNames: z114.array(z114.string().min(1).max(120)).min(2).max(8).optional(),
27271
+ confirmedProductNames: z115.array(z115.string().min(1).max(120)).min(2).max(8).optional(),
27236
27272
  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."),
27237
27273
  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."),
27238
- useMultiSceneShowcase: z114.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
27274
+ useMultiSceneShowcase: z115.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
27239
27275
  }),
27240
- z114.object({
27241
- kind: z114.literal("angle_review_approval"),
27276
+ z115.object({
27277
+ kind: z115.literal("angle_review_approval"),
27242
27278
  // All edits are optional — empty action body just approves the
27243
27279
  // backend-generated draft as-is. Field shapes mirror the angle-review
27244
27280
  // request contracts in @packages/types/wizard.ts; the handler routes to
27245
27281
  // the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
27246
- customAngle: z114.string().min(1).max(480).optional(),
27282
+ customAngle: z115.string().min(1).max(480).optional(),
27247
27283
  // Keep the shared MCP action within the strictest downstream contract:
27248
27284
  // autopilot/image resume endpoints cap these fields at 1500 characters.
27249
- painPoints: z114.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
27250
- benefits: z114.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
27285
+ painPoints: z115.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
27286
+ benefits: z115.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
27251
27287
  // Same policy as the two fields above: the strictest downstream contract
27252
27288
  // wins. The image endpoint caps each feature at 240 while landing/video
27253
27289
  // accept 300, and this single action routes to whichever the task is — so
27254
27290
  // accepting 300 here turns a 250-character feature on an image task into
27255
27291
  // an opaque HTTP 400 after the model already believed it had been saved.
27256
- features: z114.array(z114.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
27257
- buyerPersona: z114.string().min(1).max(360).optional(),
27292
+ features: z115.array(z115.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
27293
+ buyerPersona: z115.string().min(1).max(360).optional(),
27258
27294
  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.'),
27259
- actor: z114.string().min(1).max(360).optional().describe("Nueva descripci\xF3n del presentador. Al enviarla sin actorId, se elimina autom\xE1ticamente cualquier actor guardado previo de esos \xE1ngulos."),
27260
- actorId: z114.string().max(120).nullable().optional(),
27261
- creativeDirection: z114.string().max(2e3).optional(),
27262
- selectedAngleNumbers: z114.array(z114.number().int().positive()).min(1).max(3).optional().describe("N\xFAmeros visibles (1-based) de los \xE1ngulos que el usuario quiere renderizar. Deben ser \xFAnicos, existir en la review y no superar el videoAngleCount autorizado."),
27263
- angleEdits: z114.array(z114.object({
27264
- angleNumber: z114.number().int().positive(),
27265
- narrativeSelection: z114.enum([
27295
+ actor: z115.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."),
27296
+ actorId: z115.string().max(120).nullable().optional(),
27297
+ creativeDirection: z115.string().max(2e3).optional(),
27298
+ selectedAngleNumbers: z115.array(z115.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."),
27299
+ angleEdits: z115.array(z115.object({
27300
+ angleNumber: z115.number().int().positive(),
27301
+ narrativeSelection: z115.enum([
27266
27302
  "market",
27267
27303
  "guided"
27268
27304
  ]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
27269
- angle: z114.string().min(1).max(480).optional(),
27270
- buyerPersona: z114.string().min(1).max(360).optional(),
27305
+ angle: z115.string().min(1).max(480).optional(),
27306
+ buyerPersona: z115.string().min(1).max(360).optional(),
27271
27307
  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.'),
27272
- actor: z114.string().min(1).max(360).optional(),
27273
- actorId: z114.string().max(120).nullable().optional(),
27274
- creativeDirection: z114.string().max(2e3).optional()
27308
+ actor: z115.string().min(1).max(360).optional(),
27309
+ actorId: z115.string().max(120).nullable().optional(),
27310
+ creativeDirection: z115.string().max(2e3).optional()
27275
27311
  }).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)."),
27276
- gapDurationSeconds: z114.union([
27277
- z114.literal(15),
27278
- z114.literal(30)
27312
+ gapDurationSeconds: z115.union([
27313
+ z115.literal(15),
27314
+ z115.literal(30)
27279
27315
  ]).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.")
27280
27316
  }),
27281
- z114.object({
27282
- kind: z114.literal("service_angle_approval"),
27283
- angleId: z114.string().uuid().optional(),
27284
- angleNumber: z114.number().int().positive().optional(),
27285
- content: z114.string().min(1).max(480).optional(),
27286
- creativeDirection: z114.string().min(1).max(1500).optional(),
27287
- actor: z114.string().min(1).max(360).optional()
27317
+ z115.object({
27318
+ kind: z115.literal("service_angle_approval"),
27319
+ angleId: z115.string().uuid().optional(),
27320
+ angleNumber: z115.number().int().positive().optional(),
27321
+ content: z115.string().min(1).max(480).optional(),
27322
+ creativeDirection: z115.string().min(1).max(1500).optional(),
27323
+ actor: z115.string().min(1).max(360).optional()
27288
27324
  }),
27289
- z114.object({
27290
- kind: z114.literal("service_script_approval"),
27291
- voiceovers: z114.record(z114.string(), z114.string().min(1).max(600)).optional(),
27292
- visualDirections: z114.record(z114.string(), z114.string().min(1).max(1200)).optional(),
27293
- voiceoversByScene: z114.record(z114.string(), z114.string().min(1).max(600)).optional(),
27294
- visualDirectionsByScene: z114.record(z114.string(), z114.string().min(1).max(1200)).optional()
27325
+ z115.object({
27326
+ kind: z115.literal("service_script_approval"),
27327
+ voiceovers: z115.record(z115.string(), z115.string().min(1).max(600)).optional(),
27328
+ visualDirections: z115.record(z115.string(), z115.string().min(1).max(1200)).optional(),
27329
+ voiceoversByScene: z115.record(z115.string(), z115.string().min(1).max(600)).optional(),
27330
+ visualDirectionsByScene: z115.record(z115.string(), z115.string().min(1).max(1200)).optional()
27295
27331
  })
27296
27332
  ]);
27297
- var ResolvePendingActionInput = z114.object({
27298
- taskId: z114.string().min(1),
27333
+ var ResolvePendingActionInput = z115.object({
27334
+ taskId: z115.string().min(1),
27299
27335
  action: PendingActionPayload
27300
27336
  }).strict();
27301
27337
  function resolveVariantConfirmVideoTier(action) {
27302
27338
  return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
27303
27339
  }
27304
27340
  __name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
27305
- var StatusForResolveSchema = z114.object({
27341
+ var StatusForResolveSchema = z115.object({
27306
27342
  // Metadata used to select the backend resume contract. Older API responses
27307
27343
  // may omit these fields, so the resolver keeps the generic fallback.
27308
- kind: z114.enum([
27344
+ kind: z115.enum([
27309
27345
  "autopilot",
27310
27346
  "video",
27311
27347
  "image",
@@ -27313,18 +27349,18 @@ var StatusForResolveSchema = z114.object({
27313
27349
  "mix",
27314
27350
  "service"
27315
27351
  ]).optional(),
27316
- selectedOutputs: z114.array(z114.enum([
27352
+ selectedOutputs: z115.array(z115.enum([
27317
27353
  "landing",
27318
27354
  "video",
27319
27355
  "image"
27320
27356
  ])).optional(),
27321
- videoAngleCount: z114.number().int().min(1).max(3).optional(),
27322
- ugcFormat: z114.enum([
27357
+ videoAngleCount: z115.number().int().min(1).max(3).optional(),
27358
+ ugcFormat: z115.enum([
27323
27359
  "single_8s",
27324
27360
  "single_15s",
27325
27361
  "double_30s"
27326
27362
  ]).optional(),
27327
- videoStyle: z114.enum([
27363
+ videoStyle: z115.enum([
27328
27364
  "ugc",
27329
27365
  "cartoon_3d",
27330
27366
  "product_only",
@@ -27334,13 +27370,13 @@ var StatusForResolveSchema = z114.object({
27334
27370
  videoQuality: VideoQualityEnum.optional(),
27335
27371
  videoRouteId: VideoRouteIdEnum.optional(),
27336
27372
  videoModel: TaskVideoModelEnum.optional(),
27337
- videoTier: z114.enum([
27373
+ videoTier: z115.enum([
27338
27374
  "legacy",
27339
27375
  "standard",
27340
27376
  "pro",
27341
27377
  "single_call"
27342
27378
  ]).optional(),
27343
- videoResolution: z114.enum([
27379
+ videoResolution: z115.enum([
27344
27380
  "480p",
27345
27381
  "720p"
27346
27382
  ]).optional(),
@@ -27348,60 +27384,60 @@ var StatusForResolveSchema = z114.object({
27348
27384
  // A task created before a narrative was blocked/hidden must still parse,
27349
27385
  // or resolve_pending_action could never approve it.
27350
27386
  narrativeStyle: NarrativeStyle.optional(),
27351
- pauseForVideoScriptReview: z114.boolean().optional(),
27352
- pendingUserAction: z114.object({
27353
- kind: z114.string(),
27354
- candidateGrouping: z114.string().optional(),
27355
- selectedImageUrls: z114.array(z114.string()).optional(),
27356
- proposedProductNames: z114.array(z114.string()).optional(),
27387
+ pauseForVideoScriptReview: z115.boolean().optional(),
27388
+ pendingUserAction: z115.object({
27389
+ kind: z115.string(),
27390
+ candidateGrouping: z115.string().optional(),
27391
+ selectedImageUrls: z115.array(z115.string()).optional(),
27392
+ proposedProductNames: z115.array(z115.string()).optional(),
27357
27393
  // Adaptive reference questions are server-owned. Echo only the evidence
27358
27394
  // identity and the choices shown by the current snapshot; never accept a
27359
27395
  // client-supplied reference set as authorization.
27360
- options: z114.array(ProductReferenceUserChoiceEnum).max(4).optional(),
27361
- mode: z114.enum([
27396
+ options: z115.array(ProductReferenceUserChoiceEnum).max(4).optional(),
27397
+ mode: z115.enum([
27362
27398
  "question",
27363
27399
  "visual_recovery"
27364
27400
  ]).optional(),
27365
27401
  /** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
27366
- canKeepSelection: z114.boolean().optional(),
27367
- decisionKey: z114.string().optional(),
27368
- questionOrdinal: z114.number().int().min(1).max(5).optional(),
27369
- questionCeiling: z114.union([
27370
- z114.literal(3),
27371
- z114.literal(5)
27402
+ canKeepSelection: z115.boolean().optional(),
27403
+ decisionKey: z115.string().optional(),
27404
+ questionOrdinal: z115.number().int().min(1).max(5).optional(),
27405
+ questionCeiling: z115.union([
27406
+ z115.literal(3),
27407
+ z115.literal(5)
27372
27408
  ]).optional(),
27373
- referenceEvidenceVersion: z114.number().int().positive().optional(),
27374
- expectedEvidenceHash: z114.string().optional(),
27375
- question: z114.object({
27376
- prompt: z114.string().min(1).max(240),
27377
- helpText: z114.string().min(1).max(300).optional(),
27378
- options: z114.array(z114.object({
27409
+ referenceEvidenceVersion: z115.number().int().positive().optional(),
27410
+ expectedEvidenceHash: z115.string().optional(),
27411
+ question: z115.object({
27412
+ prompt: z115.string().min(1).max(240),
27413
+ helpText: z115.string().min(1).max(300).optional(),
27414
+ options: z115.array(z115.object({
27379
27415
  value: ProductReferenceUserChoiceEnum,
27380
- label: z114.string().min(1).max(120),
27381
- description: z114.string().min(1).max(240).optional()
27416
+ label: z115.string().min(1).max(120),
27417
+ description: z115.string().min(1).max(240).optional()
27382
27418
  })).min(2).max(4)
27383
27419
  }).optional(),
27384
27420
  scope: ProductReferenceScopeEnum.optional(),
27385
- scopeKey: z114.string().optional(),
27386
- scopeSnapshotId: z114.string().uuid().optional(),
27387
- scopeHash: z114.string().optional(),
27388
- baseReferenceSetHash: z114.string().optional(),
27389
- phase: z114.enum([
27421
+ scopeKey: z115.string().optional(),
27422
+ scopeSnapshotId: z115.string().uuid().optional(),
27423
+ scopeHash: z115.string().optional(),
27424
+ baseReferenceSetHash: z115.string().optional(),
27425
+ phase: z115.enum([
27390
27426
  "preparation",
27391
27427
  "final"
27392
27428
  ]).optional(),
27393
- selectedRefKeys: z114.array(z114.string().min(1).max(200)).optional(),
27394
- allowedDecisions: z114.array(ProductReferenceResolutionDecisionEnum).optional(),
27395
- previews: z114.array(z114.object({
27396
- refKey: z114.string().min(1).max(200)
27429
+ selectedRefKeys: z115.array(z115.string().min(1).max(200)).optional(),
27430
+ allowedDecisions: z115.array(ProductReferenceResolutionDecisionEnum).optional(),
27431
+ previews: z115.array(z115.object({
27432
+ refKey: z115.string().min(1).max(200)
27397
27433
  }).passthrough()).optional(),
27398
- customAngleDraft: z114.string().optional(),
27399
- painPointsDraft: z114.string().optional(),
27400
- benefitsDraft: z114.string().optional(),
27401
- featuresDraft: z114.array(z114.string()).optional(),
27402
- angleOptions: z114.array(z114.object({
27403
- index: z114.number().int().nonnegative(),
27404
- angle: z114.string().min(1)
27434
+ customAngleDraft: z115.string().optional(),
27435
+ painPointsDraft: z115.string().optional(),
27436
+ benefitsDraft: z115.string().optional(),
27437
+ featuresDraft: z115.array(z115.string()).optional(),
27438
+ angleOptions: z115.array(z115.object({
27439
+ index: z115.number().int().nonnegative(),
27440
+ angle: z115.string().min(1)
27405
27441
  }).passthrough()).min(1).max(5).optional(),
27406
27442
  // Recommendation consumed only when the caller explicitly sends
27407
27443
  // gapDurationSeconds: 30 in the angle approval action.
@@ -27411,17 +27447,17 @@ var StatusForResolveSchema = z114.object({
27411
27447
  // keys. `actorId` (the saved custom actor the picker stored) was silently
27412
27448
  // dropped here, so the approval handler below could not echo it back on the
27413
27449
  // PATCH — the selection looked accepted and reached no render.
27414
- angles: z114.array(z114.object({
27415
- id: z114.string().uuid(),
27416
- content: z114.string(),
27417
- creativeDirection: z114.string(),
27418
- actor: z114.string(),
27419
- actorId: z114.string().nullable().optional()
27450
+ angles: z115.array(z115.object({
27451
+ id: z115.string().uuid(),
27452
+ content: z115.string(),
27453
+ creativeDirection: z115.string(),
27454
+ actor: z115.string(),
27455
+ actorId: z115.string().nullable().optional()
27420
27456
  }).passthrough()).optional(),
27421
- panels: z114.array(z114.object({
27422
- beatId: z114.string(),
27423
- voiceover: z114.string(),
27424
- visualDirection: z114.string()
27457
+ panels: z115.array(z115.object({
27458
+ beatId: z115.string(),
27459
+ voiceover: z115.string(),
27460
+ visualDirection: z115.string()
27425
27461
  }).passthrough()).optional()
27426
27462
  }).optional()
27427
27463
  }).passthrough();
@@ -27773,8 +27809,8 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
27773
27809
  server.registerTool("verify_landing_commerce", {
27774
27810
  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.",
27775
27811
  inputSchema: {
27776
- taskId: z114.string().uuid(),
27777
- editId: z114.string().uuid()
27812
+ taskId: z115.string().uuid(),
27813
+ editId: z115.string().uuid()
27778
27814
  },
27779
27815
  annotations: OVERWRITES_EXTERNAL
27780
27816
  }, async (input) => {
@@ -28420,25 +28456,25 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
28420
28456
  __name(registerTaskTools, "registerTaskTools");
28421
28457
 
28422
28458
  // src/tools/brands.ts
28423
- import { z as z115 } from "zod";
28459
+ import { z as z116 } from "zod";
28424
28460
  var guidance2 = getProductMakerCapabilityModelGuidance("create_brand");
28425
28461
  var BRAND_START_REPLAY_WINDOW_MS = 15 * 60 * 1e3;
28426
28462
  var BRAND_NOTES_MAX_CHARS = 2e4;
28427
- var CreateBrandInput = z115.object({
28428
- action: z115.enum([
28463
+ var CreateBrandInput = z116.object({
28464
+ action: z116.enum([
28429
28465
  "start",
28430
28466
  "status",
28431
28467
  "list"
28432
28468
  ]).default("start").describe("start cotiza (sin confirmed) o inicia (confirmed=true) el an\xE1lisis; status consulta brandId hasta ready o failed; list muestra las marcas que el usuario ya tiene."),
28433
- sourceUrl: z115.string().trim().min(1).max(500).optional().describe("Instagram, Facebook, TikTok o web p\xFAblica del negocio, como la dio el usuario (\xAB@sanlucasbarberia\xBB, \xABinstagram.com/sanlucasbarberia\xBB, \xABmibarberia.com\xBB). Obligatorio para start."),
28434
- businessNotes: z115.string().trim().max(BRAND_NOTES_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cuente de su negocio en el chat (servicios y precios, WhatsApp, ciudad o zona, horarios). Se guarda como documento del negocio y llega tal cual a la marca y a su landing. Copia sus palabras; no inventes datos."),
28435
- language: z115.enum([
28469
+ sourceUrl: z116.string().trim().min(1).max(500).optional().describe("Instagram, Facebook, TikTok o web p\xFAblica del negocio, como la dio el usuario (\xAB@sanlucasbarberia\xBB, \xABinstagram.com/sanlucasbarberia\xBB, \xABmibarberia.com\xBB). Obligatorio para start."),
28470
+ businessNotes: z116.string().trim().max(BRAND_NOTES_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cuente de su negocio en el chat (servicios y precios, WhatsApp, ciudad o zona, horarios). Se guarda como documento del negocio y llega tal cual a la marca y a su landing. Copia sus palabras; no inventes datos."),
28471
+ language: z116.enum([
28436
28472
  "es",
28437
28473
  "en",
28438
28474
  "pt"
28439
28475
  ]).optional().describe("Idioma de la conversaci\xF3n. Solo se usa si la p\xE1gina del negocio no deja claro su idioma."),
28440
- confirmed: z115.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, start solo cotiza y no cobra."),
28441
- brandId: z115.string().uuid().optional().describe("ID de la marca. Obligatorio para status; no lo inventes.")
28476
+ confirmed: z116.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, start solo cotiza y no cobra."),
28477
+ brandId: z116.string().uuid().optional().describe("ID de la marca. Obligatorio para status; no lo inventes.")
28442
28478
  }).strict();
28443
28479
  function normalizeBrandSourceUrl(raw) {
28444
28480
  const value = raw.trim();
@@ -28678,24 +28714,24 @@ __name(registerBrandTools, "registerBrandTools");
28678
28714
 
28679
28715
  // src/tools/service-landing.ts
28680
28716
  import { createHash as createHash4 } from "crypto";
28681
- import { z as z116 } from "zod";
28717
+ import { z as z117 } from "zod";
28682
28718
  var guidance3 = getProductMakerCapabilityModelGuidance("create_service_landing");
28683
28719
  var SERVICE_LANDING_KEY_NAMESPACE = "6f1d8c2a-3b4e-5f60-8a7b-9c0d1e2f3a4b";
28684
28720
  var SERVICE_LANDING_INFO_MAX_CHARS = 2e4;
28685
- var CreateServiceLandingInput = z116.object({
28686
- action: z116.enum([
28721
+ var CreateServiceLandingInput = z117.object({
28722
+ action: z117.enum([
28687
28723
  "prepare",
28688
28724
  "build",
28689
28725
  "status",
28690
28726
  "publish"
28691
28727
  ]).default("prepare").describe("prepare (gratis) crea o retoma la landing de la marca y da el precio; build (pagado, confirmed=true) lee los datos del negocio y luego crea la p\xE1gina; status sigue el avance; publish la publica y devuelve su enlace."),
28692
- brandId: z116.string().uuid().optional().describe("ID de la marca (de create_brand). Obligatorio para prepare. Nunca un taskId de producto."),
28693
- servicePageId: z116.string().uuid().optional().describe("ID de la landing que devolvi\xF3 prepare. Obligatorio para build, status y publish."),
28694
- businessInfo: z116.string().trim().max(SERVICE_LANDING_INFO_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cont\xF3 del negocio y no estaba en su marca: servicios y precios, WhatsApp o tel\xE9fono, ciudad o zona, horarios. Copia sus palabras; no inventes datos."),
28695
- confirmed: z116.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio total y que el usuario acepte. Obligatorio para build."),
28696
- maxCredits: z116.number().int().positive().optional().describe("El total en cr\xE9ditos que el usuario acept\xF3 (el que devolvi\xF3 prepare). Obligatorio para build: ninguna etapa se inicia si su precio supera este total."),
28697
- operationId: z116.string().uuid().optional().describe("Opcional en status: la operaci\xF3n que devolvi\xF3 build."),
28698
- slug: z116.string().trim().toLowerCase().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).max(64).optional().describe("Opcional en publish: la direcci\xF3n corta de la p\xE1gina (ej. sanlucas-barberia). Si falta se usa la sugerida desde el nombre del negocio.")
28728
+ brandId: z117.string().uuid().optional().describe("ID de la marca (de create_brand). Obligatorio para prepare. Nunca un taskId de producto."),
28729
+ servicePageId: z117.string().uuid().optional().describe("ID de la landing que devolvi\xF3 prepare. Obligatorio para build, status y publish."),
28730
+ businessInfo: z117.string().trim().max(SERVICE_LANDING_INFO_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cont\xF3 del negocio y no estaba en su marca: servicios y precios, WhatsApp o tel\xE9fono, ciudad o zona, horarios. Copia sus palabras; no inventes datos."),
28731
+ confirmed: z117.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio total y que el usuario acepte. Obligatorio para build."),
28732
+ maxCredits: z117.number().int().positive().optional().describe("El total en cr\xE9ditos que el usuario acept\xF3 (el que devolvi\xF3 prepare). Obligatorio para build: ninguna etapa se inicia si su precio supera este total."),
28733
+ operationId: z117.string().uuid().optional().describe("Opcional en status: la operaci\xF3n que devolvi\xF3 build."),
28734
+ slug: z117.string().trim().toLowerCase().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).max(64).optional().describe("Opcional en publish: la direcci\xF3n corta de la p\xE1gina (ej. sanlucas-barberia). Si falta se usa la sugerida desde el nombre del negocio.")
28699
28735
  }).strict();
28700
28736
  var SERVICE_LANDING_MAX_BUILD_ATTEMPTS = 10;
28701
28737
  function serviceKey(...parts) {
@@ -29028,7 +29064,7 @@ function registerServiceLandingTools(server, api) {
29028
29064
  __name(registerServiceLandingTools, "registerServiceLandingTools");
29029
29065
 
29030
29066
  // src/tools/service-images.ts
29031
- import { z as z117 } from "zod";
29067
+ import { z as z118 } from "zod";
29032
29068
  var guidance4 = getProductMakerCapabilityModelGuidance("create_service_images");
29033
29069
  var SERVICE_IMAGE_FORMATS = [
29034
29070
  "4:5",
@@ -29041,23 +29077,23 @@ var LANGUAGE_TAGS = {
29041
29077
  en: "en-US",
29042
29078
  pt: "pt-BR"
29043
29079
  };
29044
- var CreateServiceImagesInput = z117.object({
29045
- brandId: z117.string().uuid().optional().describe("ID de la marca (de create_brand). Recomendado: da nombre, colores, tono y servicios. Nunca un taskId de producto."),
29046
- instruction: z117.string().trim().max(4e3).optional().describe("Qu\xE9 servicio o promoci\xF3n mostrar, con las palabras del usuario (ej. \xABcorte + barba a $35.000 los martes\xBB). Si el usuario deja que la IA decida, om\xEDtelo y usa delegateToAi=true."),
29047
- delegateToAi: z117.boolean().optional().describe("true si el usuario prefiere que la IA elija qu\xE9 mostrar a partir de su marca."),
29048
- format: z117.enum(SERVICE_IMAGE_FORMATS).optional().describe('Formato: "4:5" (feed, por defecto), "9:16" (historias/reels) o "1:1" (cuadrado).'),
29049
- count: z117.number().int().min(1).max(SERVICE_IMAGE_MAX_COUNT).optional().describe("Cu\xE1ntas im\xE1genes, de 1 a 3 (por defecto 1)."),
29050
- quality: z117.enum([
29080
+ var CreateServiceImagesInput = z118.object({
29081
+ brandId: z118.string().uuid().optional().describe("ID de la marca (de create_brand). Recomendado: da nombre, colores, tono y servicios. Nunca un taskId de producto."),
29082
+ instruction: z118.string().trim().max(4e3).optional().describe("Qu\xE9 servicio o promoci\xF3n mostrar, con las palabras del usuario (ej. \xABcorte + barba a $35.000 los martes\xBB). Si el usuario deja que la IA decida, om\xEDtelo y usa delegateToAi=true."),
29083
+ delegateToAi: z118.boolean().optional().describe("true si el usuario prefiere que la IA elija qu\xE9 mostrar a partir de su marca."),
29084
+ format: z118.enum(SERVICE_IMAGE_FORMATS).optional().describe('Formato: "4:5" (feed, por defecto), "9:16" (historias/reels) o "1:1" (cuadrado).'),
29085
+ count: z118.number().int().min(1).max(SERVICE_IMAGE_MAX_COUNT).optional().describe("Cu\xE1ntas im\xE1genes, de 1 a 3 (por defecto 1)."),
29086
+ quality: z118.enum([
29051
29087
  "standard",
29052
29088
  "high"
29053
29089
  ]).optional().describe('Calidad: "standard" (por defecto) o "high" (m\xE1s cara; no disponible en 4:5).'),
29054
- language: z117.enum([
29090
+ language: z118.enum([
29055
29091
  "es",
29056
29092
  "en",
29057
29093
  "pt"
29058
29094
  ]).optional().describe("Idioma de los textos de la imagen (por defecto es)."),
29059
- adCopy: z117.boolean().optional().describe("Opcional. true agrega textos para el anuncio (titular y descripci\xF3n). Por defecto false."),
29060
- confirmed: z117.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, solo cotiza y no cobra.")
29095
+ adCopy: z118.boolean().optional().describe("Opcional. true agrega textos para el anuncio (titular y descripci\xF3n). Por defecto false."),
29096
+ confirmed: z118.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, solo cotiza y no cobra.")
29061
29097
  }).strict();
29062
29098
  function serviceImageModel(quality) {
29063
29099
  return quality === "high" ? AD_CREATIVE_MODELS.PREMIUM : AD_CREATIVE_MODELS.STANDARD;
@@ -29168,7 +29204,7 @@ function registerServiceImageTools(server, api, options = {}) {
29168
29204
  nextAction: "Dile al usuario que est\xE1s creando sus im\xE1genes. Llama get_task_status con este taskId (waitSeconds=45) hasta done (trae las im\xE1genes) o error."
29169
29205
  });
29170
29206
  } catch (error) {
29171
- if (error instanceof z117.ZodError) throw invalidInputFromZod(error);
29207
+ if (error instanceof z118.ZodError) throw invalidInputFromZod(error);
29172
29208
  throw translateError(error);
29173
29209
  }
29174
29210
  });
@@ -29176,7 +29212,7 @@ function registerServiceImageTools(server, api, options = {}) {
29176
29212
  __name(registerServiceImageTools, "registerServiceImageTools");
29177
29213
 
29178
29214
  // src/tools/creatives.ts
29179
- import { z as z118 } from "zod";
29215
+ import { z as z119 } from "zod";
29180
29216
  var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
29181
29217
  var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
29182
29218
  var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
@@ -29187,72 +29223,72 @@ var CreativeRefs = {
29187
29223
  images: ImagesInput,
29188
29224
  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.'),
29189
29225
  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.'),
29190
- price: z118.string().min(1).max(120).optional().describe('Precio en formato libre \u2014 ej. "$89.900", "USD 29.99". Opcional pero MUY IMPACTANTE para conversi\xF3n: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar. Si el usuario te dice "t\xFA elige", omite el campo y la IA del backend sugiere uno.'),
29191
- offer: z118.string().min(1).max(240).optional().describe('Oferta a destacar \u2014 ej. "2x1", "Env\xEDo gratis", "50% OFF". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar (es v\xE1lido que diga "sin oferta"). Si el usuario te dice "t\xFA elige", omite el campo.'),
29192
- compareAtPrice: z118.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
29193
- productContext: z118.string().max(3e3).optional().describe("Opcional. Informacion adicional del producto que la IA debe usar como contexto prioritario: uso real, comprador, restricciones, diferenciadores o direccion creativa. No reemplaza la investigacion de competencia; si hay competencia, guia el primer angulo y los outputs no deben contradecirlo."),
29194
- productLabel: z118.string().trim().max(80).optional().describe('Opcional. Nombre o tipo del producto en pocas palabras (ej. "collar de oro", "quita pelusas para ropa"). Es AUTORITATIVO: la IA usa esta identidad y no la reemplaza por otra categor\xEDa. Si lo omites, la IA lo detecta desde la imagen. NO salta la extracci\xF3n.'),
29195
- buyerPersona: z118.string().optional().describe('Opcional. Descripci\xF3n del comprador objetivo. Ej. "Mujeres 35-50, profesionales urbanas". Si se omite, la IA infiere desde el \xE1ngulo y producto.'),
29196
- isCombo: z118.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
29197
- competitorScanEnabled: z118.boolean().optional().describe("Opcional. Default false: omitirlo significa SIN estudio de mercado. Antes de crear, llama estimate_market_study_cost, muestra al usuario el costo con y sin estudio y preg\xFAntale si lo quiere; env\xEDa true solo si lo acepta (o si solicita la narrativa an\xE1lisis de mercado). En video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico."),
29198
- brandId: z118.string().uuid().optional().describe("Opcional. ID de una marca del usuario; si se env\xEDa, el sistema usa su voz, colores y persona para enriquecer el creativo.")
29226
+ price: z119.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.'),
29227
+ offer: z119.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.'),
29228
+ compareAtPrice: z119.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
29229
+ productContext: z119.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."),
29230
+ productLabel: z119.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.'),
29231
+ buyerPersona: z119.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.'),
29232
+ isCombo: z119.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
29233
+ competitorScanEnabled: z119.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."),
29234
+ brandId: z119.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.")
29199
29235
  };
29200
- var VideoPresenter = z118.discriminatedUnion("mode", [
29201
- z118.object({
29202
- mode: z118.literal("none")
29236
+ var VideoPresenter = z119.discriminatedUnion("mode", [
29237
+ z119.object({
29238
+ mode: z119.literal("none")
29203
29239
  }).strict(),
29204
- z118.object({
29205
- mode: z118.literal("saved_actor"),
29206
- actorId: z118.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
29240
+ z119.object({
29241
+ mode: z119.literal("saved_actor"),
29242
+ actorId: z119.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
29207
29243
  }).strict(),
29208
- z118.object({
29209
- mode: z118.literal("described"),
29210
- description: z118.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
29244
+ z119.object({
29245
+ mode: z119.literal("described"),
29246
+ description: z119.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
29211
29247
  }).strict()
29212
29248
  ]);
29213
- var VideoCreativeSetup = z118.discriminatedUnion("mode", [
29214
- z118.object({
29215
- mode: z118.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
29249
+ var VideoCreativeSetup = z119.discriminatedUnion("mode", [
29250
+ z119.object({
29251
+ mode: z119.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
29216
29252
  }).strict(),
29217
- z118.object({
29218
- mode: z118.literal("guided"),
29253
+ z119.object({
29254
+ mode: z119.literal("guided"),
29219
29255
  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.'),
29220
- buyerPersona: z118.string().trim().min(1).max(360),
29256
+ buyerPersona: z119.string().trim().min(1).max(360),
29221
29257
  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.'),
29222
29258
  presenter: VideoPresenter,
29223
- creativeDirection: z118.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
29259
+ creativeDirection: z119.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
29224
29260
  }).strict()
29225
29261
  ]);
29226
- var VideoInput = z118.object({
29262
+ var VideoInput = z119.object({
29227
29263
  images: CreativeRefs.images.optional(),
29228
29264
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
29229
- title: z118.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
29230
- primaryAngle: z118.string().min(1).describe('\xC1ngulo de venta principal (frase del beneficio). Ej. "Reduce arrugas en 14 d\xEDas" o "Para quienes odian las cremas grasosas".'),
29265
+ title: z119.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
29266
+ primaryAngle: z119.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".'),
29231
29267
  language: CreativeRefs.language,
29232
29268
  country: CreativeRefs.country,
29233
- aspectRatio: z118.enum([
29269
+ aspectRatio: z119.enum([
29234
29270
  "9:16",
29235
29271
  "16:9",
29236
29272
  "Auto"
29237
29273
  ]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
29238
29274
  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.'),
29239
- durationSeconds: z118.number().int().min(4).max(30).default(15).describe("Opcional. Duraci\xF3n objetivo: Un solo clip Econ\xF3mico o Medio usa 15s; Un solo clip Pro usa 15s o 30s; Multiescena usa 15s o 30s totales. La combinaci\xF3n de formato y calidad determina la ruta y el costo."),
29240
- videoAngleCount: z118.number().int().min(1).max(3).describe("Cantidad de videos a renderizar: 1, 2 o 3. Es una decisi\xF3n de costo obligatoria: preg\xFAntala incluso cuando creativeSetup.mode=automatic."),
29275
+ durationSeconds: z119.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."),
29276
+ videoAngleCount: z119.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."),
29241
29277
  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.'),
29242
29278
  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."),
29243
29279
  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.'),
29244
29280
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
29245
29281
  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.'),
29246
- features: z118.array(z118.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
29282
+ features: z119.array(z119.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
29247
29283
  price: CreativeRefs.price,
29248
29284
  offer: CreativeRefs.offer,
29249
29285
  productContext: CreativeRefs.productContext,
29250
29286
  productLabel: CreativeRefs.productLabel,
29251
- cta: z118.string().optional().describe('Opcional. Call-to-action final del video. Ej. "Compra ahora", "Pide el tuyo hoy", "Link en bio". Si se omite, la IA escribe uno.'),
29252
- scriptNotes: z118.string().optional().describe('Opcional. Notas/restricciones para el guion (la IA las usa al redactar). Ej. "No mencionar la marca X", "Tono divertido, no cl\xEDnico", "Mencionar 2x1". NO es el guion literal: creativeSetup.mode=guided activa siempre la revisi\xF3n palabra-por-palabra con get_video_script / approve_video_script.'),
29287
+ cta: z119.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.'),
29288
+ scriptNotes: z119.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.'),
29253
29289
  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.'),
29254
29290
  competitorScanEnabled: CreativeRefs.competitorScanEnabled,
29255
- replicateWinnerWhenFound: z118.boolean().optional().describe("Conserva la preferencia de copiar un ganador si existe. false permite estudiar el mercado sin reemplazar un \xE1ngulo por el anuncio ganador. No a\xF1adas una pregunta obligatoria para este campo."),
29291
+ replicateWinnerWhenFound: z119.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."),
29256
29292
  brandId: CreativeRefs.brandId
29257
29293
  }).strict();
29258
29294
  var FreeVideoQualityEnum = VideoQualityEnum;
@@ -29270,7 +29306,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
29270
29306
  length: 29
29271
29307
  }, (_, index) => index + 2)
29272
29308
  };
29273
- var FreeVideoModelIdEnum = z118.enum([
29309
+ var FreeVideoModelIdEnum = z119.enum([
29274
29310
  "grok-imagine-video-1-5-preview",
29275
29311
  "minimax-h3/reference-to-video",
29276
29312
  "wan/3-0-video",
@@ -29281,66 +29317,66 @@ var FREE_SELECTABLE_MODEL_IDS = [
29281
29317
  "minimax-h3/reference-to-video",
29282
29318
  "wan/3-0-video"
29283
29319
  ];
29284
- var FreeVideoInput = z118.object({
29320
+ var FreeVideoInput = z119.object({
29285
29321
  images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
29286
- rawPrompt: z118.string().trim().min(1).max(2e3).describe("Prompt o guion exacto del video. Si activas subt\xEDtulos, este mismo texto se usa como guion de subt\xEDtulos."),
29322
+ rawPrompt: z119.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."),
29287
29323
  language: CreativeRefs.language,
29288
29324
  quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
29289
29325
  // Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
29290
29326
  // parsed ONLY so the handler can reject it with a message naming its
29291
29327
  // replacement — dropping it silently would turn a caller's explicit
29292
29328
  // Pro++ pick into a quiet fallback to Wan.
29293
- freeProModel: z118.enum([
29329
+ freeProModel: z119.enum([
29294
29330
  "wan",
29295
29331
  "seedance"
29296
29332
  ]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
29297
29333
  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.'),
29298
- durationSeconds: z118.number().int().min(2).max(30).describe("Duraci\xF3n exacta. Econ\xF3mico: 6, 8, 10 o 15s; Medio: enteros de 4 a 15s; Pro Wan: 2 a 30s; Pro++ Seedance: 4 a 30s."),
29334
+ durationSeconds: z119.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."),
29299
29335
  videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
29300
- generateAiMusic: z118.boolean().default(false).describe('Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false. Equivale a generateAiEdit (nivel "pro"): la Edici\xF3n con IA trae su propia m\xFAsica.'),
29336
+ generateAiMusic: z119.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.'),
29301
29337
  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.'),
29302
- addSubtitles: z118.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
29303
- idempotencyKey: z118.string().uuid().optional().describe("Opcional. Se acepta por compatibilidad pero se ignora: la identidad del reintento se deriva autom\xE1ticamente de los argumentos sem\xE1nticos, as\xED que un retry con los mismos argumentos ya es idempotente sin este campo.")
29338
+ addSubtitles: z119.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
29339
+ idempotencyKey: z119.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.")
29304
29340
  }).strict();
29305
29341
  var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
29306
- var ImageCreativeSetup = z118.discriminatedUnion("mode", [
29307
- z118.object({
29308
- mode: z118.literal("automatic")
29342
+ var ImageCreativeSetup = z119.discriminatedUnion("mode", [
29343
+ z119.object({
29344
+ mode: z119.literal("automatic")
29309
29345
  }).strict(),
29310
- z118.object({
29311
- mode: z118.literal("guided"),
29312
- creativeArchetype: z118.union([
29346
+ z119.object({
29347
+ mode: z119.literal("guided"),
29348
+ creativeArchetype: z119.union([
29313
29349
  ImageCreativeArchetypeEnum,
29314
- z118.literal("ai_decides")
29350
+ z119.literal("ai_decides")
29315
29351
  ]),
29316
- visualTreatment: z118.union([
29352
+ visualTreatment: z119.union([
29317
29353
  ImageCreativeVisualTreatmentEnum,
29318
- z118.literal("ai_decides")
29354
+ z119.literal("ai_decides")
29319
29355
  ]),
29320
29356
  aspectRatio: ImageCreativeAspectRatioEnum,
29321
- nVariants: z118.union([
29322
- z118.literal(1),
29323
- z118.literal(2),
29324
- z118.literal(3),
29325
- z118.literal(4),
29326
- z118.literal(6)
29357
+ nVariants: z119.union([
29358
+ z119.literal(1),
29359
+ z119.literal(2),
29360
+ z119.literal(3),
29361
+ z119.literal(4),
29362
+ z119.literal(6)
29327
29363
  ]),
29328
- imageModel: z118.enum(PUBLIC_IMAGE_QUALITY_INPUTS).describe('Calidad: "image:1k" (Est\xE1ndar) o "image:2k" (Premium). Los tokens gpt-image-2-5:{1k,2k} y gpt-image-2:{1k,2k} se siguen aceptando.'),
29329
- styleMix: z118.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
29330
- generateAdCopy: z118.boolean(),
29331
- competitorScanEnabled: z118.boolean(),
29332
- productContext: z118.string().trim().min(1).max(3e3).nullable(),
29333
- creativeDirection: z118.string().trim().min(1).max(500).nullable(),
29334
- brandColors: z118.string().trim().min(1).max(240).nullable().describe('Colores en lenguaje natural, igual que en el chat web. Ej. "Azul y Dorado". null significa sin colores espec\xEDficos.'),
29335
- headline: z118.string().trim().min(1).max(120).nullable(),
29336
- subheadline: z118.string().trim().min(1).max(160).nullable()
29364
+ imageModel: z119.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.'),
29365
+ styleMix: z119.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
29366
+ generateAdCopy: z119.boolean(),
29367
+ competitorScanEnabled: z119.boolean(),
29368
+ productContext: z119.string().trim().min(1).max(3e3).nullable(),
29369
+ creativeDirection: z119.string().trim().min(1).max(500).nullable(),
29370
+ brandColors: z119.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.'),
29371
+ headline: z119.string().trim().min(1).max(120).nullable(),
29372
+ subheadline: z119.string().trim().min(1).max(160).nullable()
29337
29373
  }).strict()
29338
29374
  ]).superRefine((setup, context) => {
29339
29375
  if (setup.mode !== "guided") return;
29340
29376
  const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
29341
29377
  if (needsStyleMix && setup.styleMix === null) {
29342
29378
  context.addIssue({
29343
- code: z118.ZodIssueCode.custom,
29379
+ code: z119.ZodIssueCode.custom,
29344
29380
  path: [
29345
29381
  "styleMix"
29346
29382
  ],
@@ -29349,7 +29385,7 @@ var ImageCreativeSetup = z118.discriminatedUnion("mode", [
29349
29385
  }
29350
29386
  if (!needsStyleMix && setup.styleMix !== null) {
29351
29387
  context.addIssue({
29352
- code: z118.ZodIssueCode.custom,
29388
+ code: z119.ZodIssueCode.custom,
29353
29389
  path: [
29354
29390
  "styleMix"
29355
29391
  ],
@@ -29358,7 +29394,7 @@ var ImageCreativeSetup = z118.discriminatedUnion("mode", [
29358
29394
  }
29359
29395
  if (imageResolutionOf(setup.imageModel) === "2k" && setup.aspectRatio === "4:5") {
29360
29396
  context.addIssue({
29361
- code: z118.ZodIssueCode.custom,
29397
+ code: z119.ZodIssueCode.custom,
29362
29398
  path: [
29363
29399
  "aspectRatio"
29364
29400
  ],
@@ -29366,55 +29402,55 @@ var ImageCreativeSetup = z118.discriminatedUnion("mode", [
29366
29402
  });
29367
29403
  }
29368
29404
  });
29369
- var LandingCreativeSetup = z118.discriminatedUnion("mode", [
29370
- z118.object({
29371
- mode: z118.literal("automatic")
29405
+ var LandingCreativeSetup = z119.discriminatedUnion("mode", [
29406
+ z119.object({
29407
+ mode: z119.literal("automatic")
29372
29408
  }).strict(),
29373
- z118.object({
29374
- mode: z118.literal("guided"),
29409
+ z119.object({
29410
+ mode: z119.literal("guided"),
29375
29411
  landingStrategy: LandingStrategyEnum,
29376
29412
  landingImageFormat: LandingImageFormatEnum,
29377
- competitorScanEnabled: z118.boolean(),
29378
- paymentMethods: z118.string().trim().min(1).max(240).nullable(),
29379
- productContext: z118.string().trim().min(1).max(3e3).nullable(),
29380
- creativeDirection: z118.string().trim().min(1).max(500).nullable(),
29381
- headline: z118.string().trim().min(1).max(120).nullable(),
29382
- subheadline: z118.string().trim().min(1).max(160).nullable()
29413
+ competitorScanEnabled: z119.boolean(),
29414
+ paymentMethods: z119.string().trim().min(1).max(240).nullable(),
29415
+ productContext: z119.string().trim().min(1).max(3e3).nullable(),
29416
+ creativeDirection: z119.string().trim().min(1).max(500).nullable(),
29417
+ headline: z119.string().trim().min(1).max(120).nullable(),
29418
+ subheadline: z119.string().trim().min(1).max(160).nullable()
29383
29419
  }).strict()
29384
29420
  ]);
29385
- var ImageInput = z118.object({
29421
+ var ImageInput = z119.object({
29386
29422
  images: CreativeRefs.images.optional(),
29387
29423
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
29388
- productTitle: z118.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
29389
- primaryAngle: z118.string().min(1).optional().describe('Opcional. \xC1ngulo de venta principal. Si se omite, ProductMaker lo genera y creativeSetup.mode="guided" lo muestra para revisi\xF3n antes de crear las im\xE1genes.'),
29424
+ productTitle: z119.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
29425
+ primaryAngle: z119.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.'),
29390
29426
  buyerPersona: CreativeRefs.buyerPersona,
29391
29427
  language: CreativeRefs.language,
29392
29428
  country: CreativeRefs.country,
29393
29429
  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."),
29394
29430
  imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
29395
- features: z118.array(z118.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
29431
+ features: z119.array(z119.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
29396
29432
  price: CreativeRefs.price,
29397
- omitPrice: z118.boolean().optional().describe("Pon true \xFAnicamente cuando el usuario pida expl\xEDcitamente una imagen sin precio. Evita que el backend reutilice un precio extra\xEDdo del producto. No lo combines con price ni compareAtPrice."),
29433
+ omitPrice: z119.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."),
29398
29434
  compareAtPrice: CreativeRefs.compareAtPrice,
29399
29435
  offer: CreativeRefs.offer,
29400
29436
  productLabel: CreativeRefs.productLabel,
29401
29437
  isCombo: CreativeRefs.isCombo,
29402
29438
  brandId: CreativeRefs.brandId
29403
29439
  });
29404
- var EditImageCreativeInput = z118.object({
29405
- taskId: z118.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
29406
- variantIndex: z118.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
29407
- clientRequestId: z118.string().min(1).max(160).optional().describe("Identidad estable de esta correcci\xF3n; reutil\xEDzala al reconciliar una respuesta perdida, no para otra instrucci\xF3n."),
29408
- instruction: z118.string().min(1).max(1e3).describe('Qu\xE9 cambiar en esa imagen. Ej. "quita el badge de env\xEDo gratis", "cambia el fondo a blanco".')
29440
+ var EditImageCreativeInput = z119.object({
29441
+ taskId: z119.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
29442
+ variantIndex: z119.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
29443
+ clientRequestId: z119.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."),
29444
+ instruction: z119.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".')
29409
29445
  });
29410
- var LandingInput = z118.object({
29411
- includeInitialLandingGif: z118.boolean().optional().describe("Opcional. En nuevas landings cl\xE1sicas habilitadas, omitirlo incluye el primer GIF del producto y su coste en el total. Env\xEDa false si el usuario lo excluye: no se genera ni se reserva su coste. Conserva la elecci\xF3n al confirmar y al reintentar."),
29446
+ var LandingInput = z119.object({
29447
+ includeInitialLandingGif: z119.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."),
29412
29448
  images: CreativeRefs.images.optional(),
29413
29449
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
29414
29450
  language: CreativeRefs.language,
29415
29451
  country: CreativeRefs.country,
29416
29452
  creativeSetup: LandingCreativeSetup.describe("Configuraci\xF3n obligatoria de landing cl\xE1sica equivalente al wizard web. No expone landing editable/code mientras siga siendo admin-only."),
29417
- salesAngle: z118.string().optional().describe('Opcional. \xC1ngulo de venta principal. Ej. "Reduce arrugas en 14 d\xEDas". Si se omite, la IA lo deduce de la imagen.'),
29453
+ salesAngle: z119.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.'),
29418
29454
  buyerPersona: CreativeRefs.buyerPersona,
29419
29455
  price: CreativeRefs.price,
29420
29456
  compareAtPrice: CreativeRefs.compareAtPrice,
@@ -29696,8 +29732,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
29696
29732
  server.registerTool("get_image_edit_status", {
29697
29733
  description: imageEditStatusGuidance.summary,
29698
29734
  inputSchema: {
29699
- taskId: z118.string().uuid(),
29700
- operationId: z118.string().uuid()
29735
+ taskId: z119.string().uuid(),
29736
+ operationId: z119.string().uuid()
29701
29737
  },
29702
29738
  annotations: READS_INTERNAL
29703
29739
  }, async (input) => {
@@ -29754,10 +29790,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
29754
29790
  __name(registerCreativeTools, "registerCreativeTools");
29755
29791
 
29756
29792
  // src/tools/creative-variants.ts
29757
- import { z as z119 } from "zod";
29793
+ import { z as z120 } from "zod";
29758
29794
  var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
29759
29795
  var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
29760
- var LandingSectionKeyEnum = z119.enum([
29796
+ var LandingSectionKeyEnum = z120.enum([
29761
29797
  "problem_hook",
29762
29798
  "problem_cost",
29763
29799
  "solution_mechanism",
@@ -29797,24 +29833,24 @@ var LandingSectionKeyEnum = z119.enum([
29797
29833
  "lifestyle_fit",
29798
29834
  "join_lifestyle"
29799
29835
  ]);
29800
- var CreativeVariantKindEnum = z119.enum([
29836
+ var CreativeVariantKindEnum = z120.enum([
29801
29837
  "video",
29802
29838
  "image",
29803
29839
  "landing"
29804
29840
  ]);
29805
- var EstimateCreativeVariantInputBase = z119.object({
29806
- sourceTaskId: z119.string().uuid().describe("ID de la tarea original completada."),
29841
+ var EstimateCreativeVariantInputBase = z120.object({
29842
+ sourceTaskId: z120.string().uuid().describe("ID de la tarea original completada."),
29807
29843
  kind: CreativeVariantKindEnum,
29808
29844
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
29809
29845
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
29810
- nVariants: z119.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
29846
+ nVariants: z120.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
29811
29847
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
29812
- instructions: z119.string().trim().min(1).max(2e3).optional().describe("Opcional para landing. Si se env\xEDa sin sectionKey, el estimado suma la clasificaci\xF3n pagada con IA.")
29848
+ instructions: z120.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.")
29813
29849
  }).strict();
29814
29850
  var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
29815
29851
  if (input.kind === "video" && input.nVariants !== void 0) {
29816
29852
  ctx.addIssue({
29817
- code: z119.ZodIssueCode.custom,
29853
+ code: z120.ZodIssueCode.custom,
29818
29854
  path: [
29819
29855
  "nVariants"
29820
29856
  ],
@@ -29824,7 +29860,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
29824
29860
  if (input.kind !== "video") {
29825
29861
  if (input.videoPreset !== void 0) {
29826
29862
  ctx.addIssue({
29827
- code: z119.ZodIssueCode.custom,
29863
+ code: z120.ZodIssueCode.custom,
29828
29864
  path: [
29829
29865
  "videoPreset"
29830
29866
  ],
@@ -29833,7 +29869,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
29833
29869
  }
29834
29870
  if (input.videoResolution !== void 0) {
29835
29871
  ctx.addIssue({
29836
- code: z119.ZodIssueCode.custom,
29872
+ code: z120.ZodIssueCode.custom,
29837
29873
  path: [
29838
29874
  "videoResolution"
29839
29875
  ],
@@ -29843,7 +29879,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
29843
29879
  }
29844
29880
  if (input.kind !== "image" && input.nVariants !== void 0) {
29845
29881
  ctx.addIssue({
29846
- code: z119.ZodIssueCode.custom,
29882
+ code: z120.ZodIssueCode.custom,
29847
29883
  path: [
29848
29884
  "nVariants"
29849
29885
  ],
@@ -29853,7 +29889,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
29853
29889
  if (input.kind !== "landing") {
29854
29890
  if (input.sectionKey !== void 0) {
29855
29891
  ctx.addIssue({
29856
- code: z119.ZodIssueCode.custom,
29892
+ code: z120.ZodIssueCode.custom,
29857
29893
  path: [
29858
29894
  "sectionKey"
29859
29895
  ],
@@ -29862,7 +29898,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
29862
29898
  }
29863
29899
  if (input.instructions !== void 0) {
29864
29900
  ctx.addIssue({
29865
- code: z119.ZodIssueCode.custom,
29901
+ code: z120.ZodIssueCode.custom,
29866
29902
  path: [
29867
29903
  "instructions"
29868
29904
  ],
@@ -29871,31 +29907,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
29871
29907
  }
29872
29908
  }
29873
29909
  });
29874
- var CreateCreativeVariantInputBase = z119.object({
29875
- sourceTaskId: z119.string().uuid().describe("ID de la tarea original completada."),
29910
+ var CreateCreativeVariantInputBase = z120.object({
29911
+ sourceTaskId: z120.string().uuid().describe("ID de la tarea original completada."),
29876
29912
  kind: CreativeVariantKindEnum,
29877
- confirm: z119.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
29878
- clientRequestId: z119.string().uuid().describe("UUID estable para esta intenci\xF3n (obligatorio por compatibilidad de contrato; el servidor deriva la identidad real del request desde los argumentos sem\xE1nticos, as\xED que un UUID nuevo en un retry NO crea una variante duplicada). Si la API devuelve status=error, una nueva generaci\xF3n exige otra confirmaci\xF3n."),
29879
- angle: z119.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
29880
- buyerPersona: z119.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
29881
- scriptNotes: z119.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
29882
- creativeDirection: z119.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
29913
+ confirm: z120.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
29914
+ clientRequestId: z120.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."),
29915
+ angle: z120.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
29916
+ buyerPersona: z120.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
29917
+ scriptNotes: z120.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
29918
+ creativeDirection: z120.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
29883
29919
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
29884
29920
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
29885
- generateAiMusic: z119.boolean().optional().describe("Opcional para video."),
29886
- nVariants: z119.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
29921
+ generateAiMusic: z120.boolean().optional().describe("Opcional para video."),
29922
+ nVariants: z120.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
29887
29923
  imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
29888
29924
  creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
29889
29925
  visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
29890
29926
  aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
29891
- styleMix: z119.boolean().optional().describe("Opcional para imagen."),
29927
+ styleMix: z120.boolean().optional().describe("Opcional para imagen."),
29892
29928
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
29893
- instructions: z119.string().trim().min(1).max(2e3).optional().describe("Solicitud libre para una nueva secci\xF3n de landing. La IA la clasifica si no env\xEDas sectionKey.")
29929
+ instructions: z120.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.")
29894
29930
  }).strict();
29895
29931
  var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
29896
29932
  if ((input.kind === "video" || input.kind === "image") && !input.angle) {
29897
29933
  ctx.addIssue({
29898
- code: z119.ZodIssueCode.custom,
29934
+ code: z120.ZodIssueCode.custom,
29899
29935
  path: [
29900
29936
  "angle"
29901
29937
  ],
@@ -29904,7 +29940,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
29904
29940
  }
29905
29941
  if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
29906
29942
  ctx.addIssue({
29907
- code: z119.ZodIssueCode.custom,
29943
+ code: z120.ZodIssueCode.custom,
29908
29944
  path: [
29909
29945
  "instructions"
29910
29946
  ],
@@ -29950,7 +29986,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
29950
29986
  for (const field of fieldsByKind[input.kind]) {
29951
29987
  if (input[field] !== void 0) {
29952
29988
  ctx.addIssue({
29953
- code: z119.ZodIssueCode.custom,
29989
+ code: z120.ZodIssueCode.custom,
29954
29990
  path: [
29955
29991
  field
29956
29992
  ],
@@ -30083,13 +30119,13 @@ function registerCreativeVariantTools(server, api) {
30083
30119
  __name(registerCreativeVariantTools, "registerCreativeVariantTools");
30084
30120
 
30085
30121
  // src/tools/script-review.ts
30086
- import { z as z120 } from "zod";
30122
+ import { z as z121 } from "zod";
30087
30123
  var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
30088
30124
  var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
30089
30125
  var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
30090
- var GetVideoScriptInput = z120.object({
30091
- taskId: z120.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
30092
- angleKey: z120.string().min(1).optional().describe('Clave del \xE1ngulo cuyo guion se quiere leer (formato "angle_0", "angle_1", ...). REQUERIDO para tareas multi-angle: si se omite, el backend resuelve a "angle_0" LITERAL (no "el primer pendiente"), as\xED que en multi-angle donde angle_0 ya est\xE9 aprobado/saltado obtendr\xEDas status="approved" y nunca alcanzar\xEDas el \xE1ngulo realmente pendiente. Para single-angle puede omitirse.')
30126
+ var GetVideoScriptInput = z121.object({
30127
+ taskId: z121.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
30128
+ angleKey: z121.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.')
30093
30129
  }).strict();
30094
30130
  var ApproveVideoScriptInput = ApproveVideoScriptCapabilityRequest;
30095
30131
  var RegenerateVideoScriptInput = RegenerateVideoScriptCapabilityRequest.extend({
@@ -30172,7 +30208,7 @@ function registerScriptReviewTools(server, api) {
30172
30208
  __name(registerScriptReviewTools, "registerScriptReviewTools");
30173
30209
 
30174
30210
  // src/tools/connections.ts
30175
- import { z as z121 } from "zod";
30211
+ import { z as z122 } from "zod";
30176
30212
  var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
30177
30213
  var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
30178
30214
  var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
@@ -30181,7 +30217,7 @@ var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list
30181
30217
  function registerConnectionTools(server, api) {
30182
30218
  server.registerTool("list_shopify_shops", {
30183
30219
  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.",
30184
- inputSchema: z121.object({}).shape,
30220
+ inputSchema: z122.object({}).shape,
30185
30221
  annotations: READS_INTERNAL
30186
30222
  }, async () => {
30187
30223
  try {
@@ -30193,10 +30229,10 @@ function registerConnectionTools(server, api) {
30193
30229
  });
30194
30230
  server.registerTool("list_shopify_products", {
30195
30231
  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.',
30196
- inputSchema: z121.object({
30197
- shopDomain: z121.string().min(3).max(120),
30198
- query: z121.string().trim().max(120).optional(),
30199
- taskId: z121.string().uuid().optional()
30232
+ inputSchema: z122.object({
30233
+ shopDomain: z122.string().min(3).max(120),
30234
+ query: z122.string().trim().max(120).optional(),
30235
+ taskId: z122.string().uuid().optional()
30200
30236
  }).shape,
30201
30237
  annotations: READS_EXTERNAL
30202
30238
  }, async ({ shopDomain, query, taskId }) => {
@@ -30214,7 +30250,7 @@ function registerConnectionTools(server, api) {
30214
30250
  });
30215
30251
  server.registerTool("list_meta_ad_accounts", {
30216
30252
  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.",
30217
- inputSchema: z121.object({}).shape,
30253
+ inputSchema: z122.object({}).shape,
30218
30254
  annotations: READS_EXTERNAL
30219
30255
  }, async () => {
30220
30256
  try {
@@ -30226,7 +30262,7 @@ function registerConnectionTools(server, api) {
30226
30262
  });
30227
30263
  server.registerTool("list_meta_destinations", {
30228
30264
  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.",
30229
- inputSchema: z121.object({}).shape,
30265
+ inputSchema: z122.object({}).shape,
30230
30266
  annotations: READS_EXTERNAL,
30231
30267
  _meta: {
30232
30268
  "openai/widgetAccessible": true
@@ -30241,7 +30277,7 @@ function registerConnectionTools(server, api) {
30241
30277
  });
30242
30278
  server.registerTool("list_tiktok_advertisers", {
30243
30279
  description: listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.",
30244
- inputSchema: z121.object({}).shape,
30280
+ inputSchema: z122.object({}).shape,
30245
30281
  annotations: READS_EXTERNAL
30246
30282
  }, async () => {
30247
30283
  try {
@@ -30255,7 +30291,7 @@ function registerConnectionTools(server, api) {
30255
30291
  __name(registerConnectionTools, "registerConnectionTools");
30256
30292
 
30257
30293
  // src/tools/actors.ts
30258
- import { z as z122 } from "zod";
30294
+ import { z as z123 } from "zod";
30259
30295
  var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
30260
30296
  var actorVoiceGuidance = {
30261
30297
  capabilities: getProductMakerCapabilityModelGuidance("get_actor_voice_capabilities"),
@@ -30295,7 +30331,7 @@ function sanitizeVoiceResult(value) {
30295
30331
  __name(sanitizeVoiceResult, "sanitizeVoiceResult");
30296
30332
  function registerActorTools(server, api) {
30297
30333
  const actor = {
30298
- actorId: z122.string().min(1).max(64)
30334
+ actorId: z123.string().min(1).max(64)
30299
30335
  };
30300
30336
  const safe = /* @__PURE__ */ __name(async (request) => {
30301
30337
  try {
@@ -30324,8 +30360,8 @@ function registerActorTools(server, api) {
30324
30360
  inputSchema: {
30325
30361
  ...actor,
30326
30362
  draft: ActorVoiceDraftSchema,
30327
- requestKey: z122.string().trim().min(1).max(128),
30328
- acceptedQuoteId: z122.string().trim().min(1).max(128)
30363
+ requestKey: z123.string().trim().min(1).max(128),
30364
+ acceptedQuoteId: z123.string().trim().min(1).max(128)
30329
30365
  },
30330
30366
  annotations: CREATES_PAID
30331
30367
  }, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/previews`, body)));
@@ -30333,7 +30369,7 @@ function registerActorTools(server, api) {
30333
30369
  description: actorVoiceGuidance.get.summary,
30334
30370
  inputSchema: {
30335
30371
  ...actor,
30336
- candidateId: z122.string().min(1).max(64)
30372
+ candidateId: z123.string().min(1).max(64)
30337
30373
  },
30338
30374
  // Polling can resume the first paid submission of an accepted quote.
30339
30375
  // The immutable candidate/operation key keeps recovery idempotent.
@@ -30346,16 +30382,16 @@ function registerActorTools(server, api) {
30346
30382
  description: actorVoiceGuidance.approve.summary,
30347
30383
  inputSchema: {
30348
30384
  ...actor,
30349
- candidateId: z122.string().min(1).max(64),
30350
- expectedRevision: z122.number().int().positive(),
30351
- expectedApprovedRevision: z122.number().int().positive().nullable().optional()
30385
+ candidateId: z123.string().min(1).max(64),
30386
+ expectedRevision: z123.number().int().positive(),
30387
+ expectedApprovedRevision: z123.number().int().positive().nullable().optional()
30352
30388
  },
30353
30389
  // Replaces the selected voice and withdraws the old catalog grants.
30354
30390
  annotations: OVERWRITES_INTERNAL
30355
30391
  }, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/approve`, body)));
30356
30392
  server.registerTool("list_actors", {
30357
30393
  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.",
30358
- inputSchema: z122.object({}).shape,
30394
+ inputSchema: z123.object({}).shape,
30359
30395
  annotations: READS_INTERNAL
30360
30396
  }, async () => {
30361
30397
  try {
@@ -30388,7 +30424,7 @@ function registerActorTools(server, api) {
30388
30424
  __name(registerActorTools, "registerActorTools");
30389
30425
 
30390
30426
  // src/tools/publish.ts
30391
- import { z as z123 } from "zod";
30427
+ import { z as z124 } from "zod";
30392
30428
 
30393
30429
  // src/tools/meta-publish-attempt-id.ts
30394
30430
  var META_PUBLISH_NAMESPACE = "7b19c9ac-b4eb-4db1-970e-c2f24ce30b98";
@@ -30427,40 +30463,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
30427
30463
  var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
30428
30464
  var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
30429
30465
  var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
30430
- var ShopifyInput = z123.object({
30431
- taskId: z123.string().min(1),
30432
- shopDomain: z123.string().min(1),
30466
+ var ShopifyInput = z124.object({
30467
+ taskId: z124.string().min(1),
30468
+ shopDomain: z124.string().min(1),
30433
30469
  /** Override: number of landing images to include. Default = ALL images the
30434
30470
  * task generated (the MCP fetches /v1/results first to count). Bounded
30435
30471
  * generously here; the backend validates each index against
30436
30472
  * landing.images.length and rejects out-of-range. */
30437
- numLandingImages: z123.number().int().min(1).max(20).optional(),
30438
- variantIndex: z123.number().int().min(0).optional(),
30473
+ numLandingImages: z124.number().int().min(1).max(20).optional(),
30474
+ variantIndex: z124.number().int().min(0).optional(),
30439
30475
  /** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
30440
30476
  * When true, the landing renders variant-picker pills; when false, it ships
30441
30477
  * a single-option product page. Defaults to false. */
30442
- showVariantPicker: z123.boolean().optional(),
30478
+ showVariantPicker: z124.boolean().optional(),
30443
30479
  /** Default `auto` updates the product previously published for this task and
30444
30480
  * shop. Use `existing` with targetProductId to choose another product, or
30445
30481
  * `new` only when the user explicitly wants a duplicate/new listing. */
30446
- publicationMode: z123.enum([
30482
+ publicationMode: z124.enum([
30447
30483
  "auto",
30448
30484
  "existing",
30449
30485
  "new"
30450
30486
  ]).optional(),
30451
30487
  /** Shopify product GID, numeric id, or admin product URL. Required when
30452
30488
  * publicationMode is `existing`. */
30453
- targetProductId: z123.string().trim().min(1).max(300).optional(),
30489
+ targetProductId: z124.string().trim().min(1).max(300).optional(),
30454
30490
  /** Add an announcement bar text above add-to-cart (optional). */
30455
- announcementBarEnabled: z123.boolean().optional(),
30456
- announcementBarText: z123.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
30491
+ announcementBarEnabled: z124.boolean().optional(),
30492
+ announcementBarText: z124.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
30457
30493
  commerceCorrection: PublishCommerceCorrectionSchema.optional().describe("Complete seller-confirmed commerce values, with the revision and fingerprint returned in recovery. Never invent missing prices or convert currency."),
30458
- confirmed: z123.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
30494
+ confirmed: z124.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
30459
30495
  });
30460
30496
  var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
30461
30497
  if (value.commerceCorrection && value.confirmed !== true) {
30462
30498
  ctx.addIssue({
30463
- code: z123.ZodIssueCode.custom,
30499
+ code: z124.ZodIssueCode.custom,
30464
30500
  path: [
30465
30501
  "confirmed"
30466
30502
  ],
@@ -30469,7 +30505,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
30469
30505
  }
30470
30506
  if (value.announcementBarEnabled && !value.announcementBarText) {
30471
30507
  ctx.addIssue({
30472
- code: z123.ZodIssueCode.custom,
30508
+ code: z124.ZodIssueCode.custom,
30473
30509
  path: [
30474
30510
  "announcementBarText"
30475
30511
  ],
@@ -30478,7 +30514,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
30478
30514
  }
30479
30515
  if (!value.announcementBarEnabled && value.announcementBarText) {
30480
30516
  ctx.addIssue({
30481
- code: z123.ZodIssueCode.custom,
30517
+ code: z124.ZodIssueCode.custom,
30482
30518
  path: [
30483
30519
  "announcementBarText"
30484
30520
  ],
@@ -30492,91 +30528,91 @@ function parseShopifyInput(rawInput) {
30492
30528
  return parsed.data;
30493
30529
  }
30494
30530
  __name(parseShopifyInput, "parseShopifyInput");
30495
- var McpCampaignConfig = z123.object({
30531
+ var McpCampaignConfig = z124.object({
30496
30532
  /** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
30497
30533
  * converts to the account currency server-side. Do NOT pre-convert: on a COP
30498
30534
  * account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
30499
- dailyBudgetUsd: z123.number().positive().optional(),
30535
+ dailyBudgetUsd: z124.number().positive().optional(),
30500
30536
  /** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
30501
30537
  * normalizes at validation). Meta accepts max 1 (single-country ad set).
30502
30538
  * TikTok takes only the first entry. */
30503
- targetCountries: z123.array(CountryIso2Schema).max(1).optional(),
30504
- campaignName: z123.string().trim().min(1).max(100).optional()
30539
+ targetCountries: z124.array(CountryIso2Schema).max(1).optional(),
30540
+ campaignName: z124.string().trim().min(1).max(100).optional()
30505
30541
  });
30506
30542
  var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
30507
- var MetaInput = z123.object({
30508
- taskId: z123.string().min(1),
30543
+ var MetaInput = z124.object({
30544
+ taskId: z124.string().min(1),
30509
30545
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
30510
- portfolioId: z123.string().trim().min(1),
30546
+ portfolioId: z124.string().trim().min(1),
30511
30547
  /** Exact Facebook Page selected from `list_meta_destinations`. */
30512
- pageId: z123.string().trim().min(1),
30548
+ pageId: z124.string().trim().min(1),
30513
30549
  adAccountId: McpAdAccountId,
30514
- pixelId: z123.string().min(1).optional(),
30515
- landingUrl: z123.string().url().optional(),
30550
+ pixelId: z124.string().min(1).optional(),
30551
+ landingUrl: z124.string().url().optional(),
30516
30552
  /** Select which angles to publish by 0-based index. Omit to publish all
30517
30553
  * successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
30518
- angleIndexes: z123.array(z123.number().int().nonnegative()).optional(),
30554
+ angleIndexes: z124.array(z124.number().int().nonnegative()).optional(),
30519
30555
  campaignConfig: McpCampaignConfig.optional(),
30520
30556
  /** Override the ad's primary text (body copy). If omitted, ProductMaker
30521
30557
  * uses the auto-generated copy attached to the task. Capped at 500 chars
30522
30558
  * (Meta's primary-text limit). */
30523
- primaryText: z123.string().trim().min(1).max(500).optional(),
30559
+ primaryText: z124.string().trim().min(1).max(500).optional(),
30524
30560
  /** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
30525
30561
  * (wa.me) instead of a landing page. */
30526
- phoneNumber: z123.string().min(8).max(32).optional()
30562
+ phoneNumber: z124.string().min(8).max(32).optional()
30527
30563
  });
30528
- var GroupedTaskSource = z123.object({
30529
- type: z123.literal("task"),
30530
- taskId: z123.string().min(1),
30531
- angleIndex: z123.number().int().min(0).optional(),
30532
- videoVariant: z123.enum([
30564
+ var GroupedTaskSource = z124.object({
30565
+ type: z124.literal("task"),
30566
+ taskId: z124.string().min(1),
30567
+ angleIndex: z124.number().int().min(0).optional(),
30568
+ videoVariant: z124.enum([
30533
30569
  "with_subtitles",
30534
30570
  "without_subtitles"
30535
30571
  ]).optional(),
30536
- imageVariantIndex: z123.number().int().min(0).optional()
30537
- });
30538
- var GroupedMediaSource = z123.object({
30539
- type: z123.literal("media"),
30540
- url: z123.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
30541
- path: z123.string().min(1).optional().describe('Local file path only when this MCP runs over stdio. On the hosted MCP, call request_media_upload and then use source.type="asset".'),
30542
- thumbnailUrl: z123.string().url().optional(),
30543
- thumbnailPath: z123.string().min(1).optional()
30572
+ imageVariantIndex: z124.number().int().min(0).optional()
30573
+ });
30574
+ var GroupedMediaSource = z124.object({
30575
+ type: z124.literal("media"),
30576
+ url: z124.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
30577
+ path: z124.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".'),
30578
+ thumbnailUrl: z124.string().url().optional(),
30579
+ thumbnailPath: z124.string().min(1).optional()
30544
30580
  }).refine((value) => Boolean(value.url) !== Boolean(value.path), {
30545
30581
  message: "media source needs exactly one of `url` or `path`"
30546
30582
  }).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
30547
30583
  message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
30548
30584
  });
30549
- var GroupedUploadedAssetSource = z123.object({
30550
- type: z123.literal("asset"),
30585
+ var GroupedUploadedAssetSource = z124.object({
30586
+ type: z124.literal("asset"),
30551
30587
  /** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
30552
- assetId: z123.string().uuid(),
30553
- thumbnailAssetId: z123.string().uuid().optional()
30588
+ assetId: z124.string().uuid(),
30589
+ thumbnailAssetId: z124.string().uuid().optional()
30554
30590
  });
30555
- var GroupedCreative = z123.object({
30556
- type: z123.enum([
30591
+ var GroupedCreative = z124.object({
30592
+ type: z124.enum([
30557
30593
  "image",
30558
30594
  "video"
30559
30595
  ]),
30560
- source: z123.union([
30596
+ source: z124.union([
30561
30597
  GroupedTaskSource,
30562
30598
  GroupedMediaSource,
30563
30599
  GroupedUploadedAssetSource
30564
30600
  ]),
30565
- title: z123.string().max(120).optional(),
30566
- description: z123.string().max(500).optional(),
30601
+ title: z124.string().max(120).optional(),
30602
+ description: z124.string().max(500).optional(),
30567
30603
  cta: MetaCtaType.optional(),
30568
- creativeId: z123.string().min(1).optional()
30604
+ creativeId: z124.string().min(1).optional()
30569
30605
  });
30570
- var GroupedCampaignConfigBase = z123.object({
30606
+ var GroupedCampaignConfigBase = z124.object({
30571
30607
  campaignType: MetaCampaignType.default("sales"),
30572
30608
  optimizationMode: MetaOptimizationMode.default("advantage_plus"),
30573
30609
  budgetMode: MetaBudgetMode.optional(),
30574
- campaignDailyBudget: z123.number().int().positive().optional(),
30575
- adSets: z123.array(z123.object({
30576
- tempId: z123.string().min(1).max(80),
30577
- name: z123.string().min(1).max(100),
30578
- dailyBudget: z123.number().int().positive().optional(),
30579
- creativeIds: z123.array(z123.string().min(1)).min(1)
30610
+ campaignDailyBudget: z124.number().int().positive().optional(),
30611
+ adSets: z124.array(z124.object({
30612
+ tempId: z124.string().min(1).max(80),
30613
+ name: z124.string().min(1).max(100),
30614
+ dailyBudget: z124.number().int().positive().optional(),
30615
+ creativeIds: z124.array(z124.string().min(1)).min(1)
30580
30616
  })).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
30581
30617
  /**
30582
30618
  * Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
@@ -30584,17 +30620,17 @@ var GroupedCampaignConfigBase = z123.object({
30584
30620
  * opaque `invalid_literal` and made the WhatsApp destination — supported by
30585
30621
  * the API since #849 — unreachable from this tool.
30586
30622
  */
30587
- destination: z123.discriminatedUnion("type", [
30588
- z123.object({
30589
- type: z123.literal("landing"),
30590
- landingUrl: z123.string().url()
30623
+ destination: z124.discriminatedUnion("type", [
30624
+ z124.object({
30625
+ type: z124.literal("landing"),
30626
+ landingUrl: z124.string().url()
30591
30627
  }),
30592
- z123.object({
30593
- type: z123.literal("whatsapp"),
30594
- phoneNumber: z123.string().min(8).max(32)
30628
+ z124.object({
30629
+ type: z124.literal("whatsapp"),
30630
+ phoneNumber: z124.string().min(8).max(32)
30595
30631
  })
30596
30632
  ]),
30597
- saveAsDefault: z123.boolean().default(false),
30633
+ saveAsDefault: z124.boolean().default(false),
30598
30634
  budgetPolicy: MetaBudgetPolicy.optional()
30599
30635
  });
30600
30636
  function resolveBudgetMode(value) {
@@ -30608,7 +30644,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
30608
30644
  const budgetMode = resolveBudgetMode(value);
30609
30645
  if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
30610
30646
  ctx.addIssue({
30611
- code: z123.ZodIssueCode.custom,
30647
+ code: z124.ZodIssueCode.custom,
30612
30648
  path: [
30613
30649
  "campaignDailyBudget"
30614
30650
  ],
@@ -30619,7 +30655,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
30619
30655
  value.adSets.forEach((adSet, index) => {
30620
30656
  if (adSet.dailyBudget === void 0) {
30621
30657
  ctx.addIssue({
30622
- code: z123.ZodIssueCode.custom,
30658
+ code: z124.ZodIssueCode.custom,
30623
30659
  path: [
30624
30660
  "adSets",
30625
30661
  index,
@@ -30634,28 +30670,33 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
30634
30670
  ...value,
30635
30671
  budgetMode: resolveBudgetMode(value)
30636
30672
  }));
30637
- var PublishCreativesToMetaInputBase = z123.object({
30638
- creatives: z123.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
30673
+ var PublishCreativesToMetaInputBase = z124.object({
30674
+ creatives: z124.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
30639
30675
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
30640
- portfolioId: z123.string().trim().min(1),
30676
+ portfolioId: z124.string().trim().min(1),
30641
30677
  /** Exact Facebook Page selected from `list_meta_destinations`. */
30642
- pageId: z123.string().trim().min(1),
30678
+ pageId: z124.string().trim().min(1),
30643
30679
  adAccountId: McpAdAccountId,
30644
- pixelId: z123.string().min(1).optional(),
30645
- /** Required unless `campaignConfig.destination` is whatsapp — see the
30646
- * superRefine below. Mirrors the API's `FacebookCreateCampaignFromTasksBodySchema`. */
30647
- landingUrl: z123.string().url().optional(),
30680
+ pixelId: z124.string().min(1).optional(),
30681
+ /** Required unless `campaignConfig.destination` is whatsapp or a creative
30682
+ * comes from a task (the API then lands on the published service landing
30683
+ * of its service tasks) — see the superRefine below. Mirrors the API's
30684
+ * `FacebookCreateCampaignFromTasksBodySchema`. */
30685
+ landingUrl: z124.string().url().optional(),
30648
30686
  /** ISO-2 code or resolvable country name — mirrors the API contract
30649
- * (CountryIso2Schema), which normalizes names to alpha-2 at validation. */
30650
- targetCountry: CountryIso2Schema,
30651
- campaignName: z123.string().trim().min(1).max(100),
30687
+ * (CountryIso2Schema), which normalizes names to alpha-2 at validation.
30688
+ * Omitted: the brand country of its service tasks (the API answers
30689
+ * META_NO_TARGET_COUNTRY when it has none); "US" for products. */
30690
+ targetCountry: CountryIso2Schema.optional(),
30691
+ campaignName: z124.string().trim().min(1).max(100),
30652
30692
  campaignConfig: GroupedCampaignConfig.optional()
30653
30693
  });
30654
30694
  var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
30655
30695
  const destination = value.campaignConfig?.destination;
30656
- if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
30696
+ const hasTaskCreative = value.creatives.some((creative) => creative.source.type === "task");
30697
+ if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl && !hasTaskCreative) {
30657
30698
  ctx.addIssue({
30658
- code: z123.ZodIssueCode.custom,
30699
+ code: z124.ZodIssueCode.custom,
30659
30700
  path: [
30660
30701
  "landingUrl"
30661
30702
  ],
@@ -30664,7 +30705,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
30664
30705
  }
30665
30706
  if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
30666
30707
  ctx.addIssue({
30667
- code: z123.ZodIssueCode.custom,
30708
+ code: z124.ZodIssueCode.custom,
30668
30709
  path: [
30669
30710
  "campaignConfig",
30670
30711
  "destination",
@@ -30683,16 +30724,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
30683
30724
  }
30684
30725
  return value;
30685
30726
  });
30686
- var PresignUploadResponseSchema = z123.object({
30687
- uploadUrl: z123.string().url().refine((value) => {
30727
+ var PresignUploadResponseSchema = z124.object({
30728
+ uploadUrl: z124.string().url().refine((value) => {
30688
30729
  const url = new URL(value);
30689
30730
  return !url.username && !url.password && url.protocol === "https:";
30690
30731
  }, "presigned upload URL must be HTTPS without embedded credentials"),
30691
- publicUrl: z123.string().url().refine((value) => {
30732
+ publicUrl: z124.string().url().refine((value) => {
30692
30733
  const url = new URL(value);
30693
30734
  return !url.username && !url.password;
30694
30735
  }, "public media URL must not contain embedded credentials"),
30695
- stagingAssetId: z123.string().uuid()
30736
+ stagingAssetId: z124.string().uuid()
30696
30737
  });
30697
30738
  async function uploadResolvedMedia(api, media, assetRole) {
30698
30739
  if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
@@ -30717,16 +30758,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
30717
30758
  return uploadResolvedMedia(api, media, assetRole);
30718
30759
  }
30719
30760
  __name(resolveAndUploadMedia, "resolveAndUploadMedia");
30720
- var TikTokInput = z123.object({
30721
- taskId: z123.string().min(1),
30722
- advertiserId: z123.string().min(1),
30723
- pixelId: z123.string().min(1).optional(),
30724
- landingUrl: z123.string().url().optional(),
30725
- angleIndexes: z123.array(z123.number().int().nonnegative()).optional(),
30761
+ var TikTokInput = z124.object({
30762
+ taskId: z124.string().min(1),
30763
+ advertiserId: z124.string().min(1),
30764
+ pixelId: z124.string().min(1).optional(),
30765
+ landingUrl: z124.string().url().optional(),
30766
+ angleIndexes: z124.array(z124.number().int().nonnegative()).optional(),
30726
30767
  campaignConfig: McpCampaignConfig.optional(),
30727
30768
  /** Override the ad's description (TikTok's body copy). If omitted,
30728
30769
  * ProductMaker uses the auto-generated copy attached to the task. */
30729
- primaryText: z123.string().trim().min(1).max(500).optional()
30770
+ primaryText: z124.string().trim().min(1).max(500).optional()
30730
30771
  });
30731
30772
  function registerPublishTools(server, api, opts = {}) {
30732
30773
  const transport = opts.transport ?? "http";
@@ -30848,7 +30889,7 @@ function registerPublishTools(server, api, opts = {}) {
30848
30889
  }
30849
30890
  });
30850
30891
  server.registerTool("publish_creatives_to_meta", {
30851
- description: publishCreativesToMetaGuidance.summary + ' Publica tus creativos en Meta sin gastar cr\xE9ditos de ProductMaker. El presupuesto de anuncios se paga directamente desde tu cuenta de Meta. Crear creativos o copy con IA sigue usando cr\xE9ditos. Si la petici\xF3n natural adjunta o menciona archivos locales, llama primero `request_media_upload`; tras OK usa cada resultado como `source.type="asset"` con su `assetId` y el `type` que coincide con `mediaKind`. No pidas path ni URL. Despu\xE9s llama `list_meta_destinations` y pregunta en el chat por el `portfolioId`, `adAccountId` y `pageId` exactos; el App es solo para archivos. Si la carga fue parcial, conserva los assets confirmados, procesa s\xF3lo los pendientes y publica \xFAnicamente assets confirmados; nunca inventes assets ni superes diez creativos. Las rutas locales s\xF3lo funcionan con MCP stdio. Los medios propios se eliminan despu\xE9s de publicar correctamente; si falla antes de enviar una mutaci\xF3n a Meta, quedan durante el TTL. Para videos la miniatura es opcional y ProductMaker puede generarla con FFmpeg. `campaignConfig.destination` acepta landing o WhatsApp. Para landing basta `campaignConfig.destination.landingUrl`; no dupliques la URL arriba. Si omites `budgetMode`, se infiere `ad_set` cuando cada ad set trae `dailyBudget`, o `campaign` cuando env\xEDas `campaignDailyBudget`. No actives la campa\xF1a autom\xE1ticamente. Si el resultado es ambiguo, NO reenv\xEDes: revisa Meta Ads Manager.',
30892
+ description: publishCreativesToMetaGuidance.summary + ' Publica tus creativos en Meta sin gastar cr\xE9ditos de ProductMaker. El presupuesto de anuncios se paga directamente desde tu cuenta de Meta. Crear creativos o copy con IA sigue usando cr\xE9ditos. Si la petici\xF3n natural adjunta o menciona archivos locales, llama primero `request_media_upload`; tras OK usa cada resultado como `source.type="asset"` con su `assetId` y el `type` que coincide con `mediaKind`. No pidas path ni URL. Despu\xE9s llama `list_meta_destinations` y pregunta en el chat por el `portfolioId`, `adAccountId` y `pageId` exactos; el App es solo para archivos. Si la carga fue parcial, conserva los assets confirmados, procesa s\xF3lo los pendientes y publica \xFAnicamente assets confirmados; nunca inventes assets ni superes diez creativos. Las rutas locales s\xF3lo funcionan con MCP stdio. Los medios propios se eliminan despu\xE9s de publicar correctamente; si falla antes de enviar una mutaci\xF3n a Meta, quedan durante el TTL. Para videos la miniatura es opcional y ProductMaker puede generarla con FFmpeg. `campaignConfig.destination` acepta landing o WhatsApp. Para landing basta `campaignConfig.destination.landingUrl`; no dupliques la URL arriba. Con creativos de tarea de servicio puedes omitir `landingUrl` y `targetCountry`: se usan su landing de servicio publicada y el pa\xEDs de su marca; si falta alguno, pregunta al usuario (nunca asumas un pa\xEDs). Si omites `budgetMode`, se infiere `ad_set` cuando cada ad set trae `dailyBudget`, o `campaign` cuando env\xEDas `campaignDailyBudget`. No actives la campa\xF1a autom\xE1ticamente. Si el resultado es ambiguo, NO reenv\xEDes: revisa Meta Ads Manager.',
30852
30893
  inputSchema: PublishCreativesToMetaInputBase.shape,
30853
30894
  annotations: CREATES_EXTERNAL
30854
30895
  }, async (rawInput, extra) => {
@@ -31078,39 +31119,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
31078
31119
 
31079
31120
  // src/tools/meta-upload.ts
31080
31121
  import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
31081
- import { z as z124 } from "zod";
31122
+ import { z as z125 } from "zod";
31082
31123
  var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
31083
- var UploadSessionInputBase = z124.object({
31084
- mediaKind: z124.enum([
31124
+ var UploadSessionInputBase = z125.object({
31125
+ mediaKind: z125.enum([
31085
31126
  "image",
31086
31127
  "video",
31087
31128
  "mixed"
31088
31129
  ]).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."),
31089
- assetRole: z124.enum([
31130
+ assetRole: z125.enum([
31090
31131
  "media",
31091
31132
  "thumbnail"
31092
31133
  ]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
31093
- uploadPurpose: z124.enum([
31134
+ uploadPurpose: z125.enum([
31094
31135
  "product_reference",
31095
31136
  "creative",
31096
31137
  "generic"
31097
31138
  ]).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."),
31098
- maxFiles: z124.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
31139
+ maxFiles: z125.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
31099
31140
  });
31100
- var OpenAiFileReference = z124.object({
31101
- download_url: z124.string().url().describe("Required by ChatGPT's openai/fileParams schema. The App prefers getFileDownloadUrl(file_id) for a fresh URL, and the server never fetches this value."),
31102
- file_id: z124.string().min(1),
31103
- mime_type: z124.string().min(1).optional(),
31104
- file_name: z124.string().min(1).optional()
31141
+ var OpenAiFileReference = z125.object({
31142
+ download_url: z125.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."),
31143
+ file_id: z125.string().min(1),
31144
+ mime_type: z125.string().min(1).optional(),
31145
+ file_name: z125.string().min(1).optional()
31105
31146
  });
31106
31147
  var UploadSessionToolInputShape = {
31107
31148
  ...UploadSessionInputBase.shape,
31108
- files: z124.array(OpenAiFileReference).max(10).optional().describe("Optional OpenAI-hosted file references provided by ChatGPT. They are only metadata for the UI bridge and are never forwarded to ProductMaker.")
31149
+ files: z125.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.")
31109
31150
  };
31110
- var UploadSessionToolInput = z124.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
31151
+ var UploadSessionToolInput = z125.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
31111
31152
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
31112
31153
  ctx.addIssue({
31113
- code: z124.ZodIssueCode.custom,
31154
+ code: z125.ZodIssueCode.custom,
31114
31155
  path: [
31115
31156
  "mediaKind"
31116
31157
  ],
@@ -31119,7 +31160,7 @@ var UploadSessionToolInput = z124.object(UploadSessionToolInputShape).superRefin
31119
31160
  }
31120
31161
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
31121
31162
  ctx.addIssue({
31122
- code: z124.ZodIssueCode.custom,
31163
+ code: z125.ZodIssueCode.custom,
31123
31164
  path: [
31124
31165
  "maxFiles"
31125
31166
  ],
@@ -31128,7 +31169,7 @@ var UploadSessionToolInput = z124.object(UploadSessionToolInputShape).superRefin
31128
31169
  }
31129
31170
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
31130
31171
  ctx.addIssue({
31131
- code: z124.ZodIssueCode.custom,
31172
+ code: z125.ZodIssueCode.custom,
31132
31173
  path: [
31133
31174
  "maxFiles"
31134
31175
  ],
@@ -31136,38 +31177,38 @@ var UploadSessionToolInput = z124.object(UploadSessionToolInputShape).superRefin
31136
31177
  });
31137
31178
  }
31138
31179
  });
31139
- var UploadSessionResponse = z124.object({
31140
- sessionId: z124.string().uuid(),
31141
- uploadPageUrl: z124.string().url(),
31142
- mediaKind: z124.enum([
31180
+ var UploadSessionResponse = z125.object({
31181
+ sessionId: z125.string().uuid(),
31182
+ uploadPageUrl: z125.string().url(),
31183
+ mediaKind: z125.enum([
31143
31184
  "image",
31144
31185
  "video",
31145
31186
  "mixed"
31146
31187
  ]),
31147
- assetRole: z124.enum([
31188
+ assetRole: z125.enum([
31148
31189
  "media",
31149
31190
  "thumbnail"
31150
31191
  ]),
31151
- maxFiles: z124.number().int().positive(),
31152
- expiresAt: z124.string().datetime()
31192
+ maxFiles: z125.number().int().positive(),
31193
+ expiresAt: z125.string().datetime()
31153
31194
  });
31154
- var UploadStatusInput = z124.object({
31155
- sessionId: z124.string().uuid().describe("The sessionId returned by request_media_upload.")
31195
+ var UploadStatusInput = z125.object({
31196
+ sessionId: z125.string().uuid().describe("The sessionId returned by request_media_upload.")
31156
31197
  });
31157
- var UniversalUploadStatusResponse = z124.discriminatedUnion("status", [
31158
- z124.object({
31159
- status: z124.literal("pending"),
31160
- assets: z124.array(z124.never()).length(0)
31198
+ var UniversalUploadStatusResponse = z125.discriminatedUnion("status", [
31199
+ z125.object({
31200
+ status: z125.literal("pending"),
31201
+ assets: z125.array(z125.never()).length(0)
31161
31202
  }),
31162
- z124.object({
31163
- status: z124.literal("uploaded"),
31164
- assets: z124.array(z124.object({
31165
- assetId: z124.string().uuid(),
31166
- mediaKind: z124.enum([
31203
+ z125.object({
31204
+ status: z125.literal("uploaded"),
31205
+ assets: z125.array(z125.object({
31206
+ assetId: z125.string().uuid(),
31207
+ mediaKind: z125.enum([
31167
31208
  "image",
31168
31209
  "video"
31169
31210
  ]),
31170
- assetRole: z124.enum([
31211
+ assetRole: z125.enum([
31171
31212
  "media",
31172
31213
  "thumbnail"
31173
31214
  ])
@@ -31175,13 +31216,13 @@ var UniversalUploadStatusResponse = z124.discriminatedUnion("status", [
31175
31216
  })
31176
31217
  ]);
31177
31218
  var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
31178
- uploadPurpose: z124.enum([
31219
+ uploadPurpose: z125.enum([
31179
31220
  "product_reference",
31180
31221
  "creative",
31181
31222
  "generic"
31182
31223
  ]),
31183
- checkToolName: z124.literal("check_media_upload"),
31184
- resolveEndpoint: z124.string().url()
31224
+ checkToolName: z125.literal("check_media_upload"),
31225
+ resolveEndpoint: z125.string().url()
31185
31226
  });
31186
31227
  function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
31187
31228
  const url = new URL(uploadPageUrl);
@@ -31272,15 +31313,15 @@ function registerMediaUploadTools(server, api) {
31272
31313
  __name(registerMediaUploadTools, "registerMediaUploadTools");
31273
31314
 
31274
31315
  // src/tools/campaigns.ts
31275
- import { z as z125 } from "zod";
31316
+ import { z as z126 } from "zod";
31276
31317
  var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
31277
31318
  var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
31278
- var MetaStatusInput = z125.object({
31279
- campaignId: z125.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
31319
+ var MetaStatusInput = z126.object({
31320
+ campaignId: z126.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
31280
31321
  });
31281
- var TikTokStatusInput = z125.object({
31282
- campaignId: z125.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
31283
- advertiserId: z125.string().min(1).describe("The same advertiserId used to publish the campaign.")
31322
+ var TikTokStatusInput = z126.object({
31323
+ campaignId: z126.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
31324
+ advertiserId: z126.string().min(1).describe("The same advertiserId used to publish the campaign.")
31284
31325
  });
31285
31326
  function registerCampaignTools(server, api) {
31286
31327
  server.registerTool("get_meta_campaign_status", {
@@ -31385,10 +31426,10 @@ function renderTikTokStatusMarkdown(r) {
31385
31426
  __name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
31386
31427
 
31387
31428
  // ../../packages/product-economics/src/product-costing.ts
31388
- import { z as z127 } from "zod";
31429
+ import { z as z128 } from "zod";
31389
31430
 
31390
31431
  // ../../packages/product-economics/src/product-costing-countries.ts
31391
- import { z as z126 } from "zod";
31432
+ import { z as z127 } from "zod";
31392
31433
 
31393
31434
  // ../../packages/product-economics/src/product-costing-shipping-references.json
31394
31435
  var product_costing_shipping_references_default = {
@@ -31452,21 +31493,21 @@ var product_costing_shipping_references_default = {
31452
31493
  };
31453
31494
 
31454
31495
  // ../../packages/product-economics/src/product-costing-countries.ts
31455
- var ShippingReferenceSchema = z126.object({
31456
- reference: z126.number().positive(),
31457
- min: z126.number().nonnegative(),
31458
- max: z126.number().positive(),
31459
- updatedAt: z126.string().date(),
31460
- confidence: z126.enum([
31496
+ var ShippingReferenceSchema = z127.object({
31497
+ reference: z127.number().positive(),
31498
+ min: z127.number().nonnegative(),
31499
+ max: z127.number().positive(),
31500
+ updatedAt: z127.string().date(),
31501
+ confidence: z127.enum([
31461
31502
  "high",
31462
31503
  "medium",
31463
31504
  "medium-low"
31464
31505
  ]),
31465
- sources: z126.array(z126.string().url().startsWith("https://")).min(1).max(3)
31506
+ sources: z127.array(z127.string().url().startsWith("https://")).min(1).max(3)
31466
31507
  }).superRefine(({ reference, min, max }, context) => {
31467
31508
  if (min > reference || reference > max) {
31468
31509
  context.addIssue({
31469
- code: z126.ZodIssueCode.custom,
31510
+ code: z127.ZodIssueCode.custom,
31470
31511
  message: "shipping_reference_outside_range",
31471
31512
  path: [
31472
31513
  "reference"
@@ -31474,7 +31515,7 @@ var ShippingReferenceSchema = z126.object({
31474
31515
  });
31475
31516
  }
31476
31517
  });
31477
- var SHIPPING_REFERENCES = z126.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
31518
+ var SHIPPING_REFERENCES = z127.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
31478
31519
  var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
31479
31520
  var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
31480
31521
  "MX",
@@ -31656,18 +31697,18 @@ function getProductCostingCountryName(country) {
31656
31697
  __name(getProductCostingCountryName, "getProductCostingCountryName");
31657
31698
 
31658
31699
  // ../../packages/product-economics/src/product-costing.ts
31659
- var ProductCostingInputSchema = z127.object({
31660
- country: z127.string().refine(isProductCostingCountryCode, "unsupported_country"),
31661
- supplierCost: z127.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
31662
- shippingCost: z127.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
31663
- returnRate: z127.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
31664
- cancellationRate: z127.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
31665
- adsManagerCpa: z127.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
31666
- desiredMargin: z127.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
31700
+ var ProductCostingInputSchema = z128.object({
31701
+ country: z128.string().refine(isProductCostingCountryCode, "unsupported_country"),
31702
+ supplierCost: z128.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
31703
+ shippingCost: z128.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
31704
+ returnRate: z128.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
31705
+ cancellationRate: z128.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
31706
+ adsManagerCpa: z128.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
31707
+ desiredMargin: z128.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
31667
31708
  }).superRefine(({ returnRate, cancellationRate }, context) => {
31668
31709
  if (returnRate + cancellationRate >= 1) {
31669
31710
  context.addIssue({
31670
- code: z127.ZodIssueCode.custom,
31711
+ code: z128.ZodIssueCode.custom,
31671
31712
  message: "delivery_rate_positive",
31672
31713
  path: [
31673
31714
  "cancellationRate"
@@ -31764,15 +31805,15 @@ function calculateProductCosting(rawInput) {
31764
31805
  __name(calculateProductCosting, "calculateProductCosting");
31765
31806
 
31766
31807
  // src/tools/product-costing.ts
31767
- import { z as z128 } from "zod";
31808
+ import { z as z129 } from "zod";
31768
31809
  var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
31769
- var optionalAmount = /* @__PURE__ */ __name((description) => z128.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
31770
- var optionalPercent = /* @__PURE__ */ __name((description) => z128.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
31771
- var ProductCostingToolInput = z128.object({
31772
- country: z128.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
31810
+ var optionalAmount = /* @__PURE__ */ __name((description) => z129.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
31811
+ var optionalPercent = /* @__PURE__ */ __name((description) => z129.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
31812
+ var ProductCostingToolInput = z129.object({
31813
+ country: z129.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
31773
31814
  message: "Pa\xEDs no soportado por ProductMaker."
31774
31815
  }).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
31775
- supplierCost: z128.number().finite().max(Number.MAX_SAFE_INTEGER).positive().optional().describe("Costo real de una unidad con el proveedor, en la moneda del pa\xEDs. Requerido salvo que uses supplierCostCop para Colombia."),
31816
+ supplierCost: z129.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."),
31776
31817
  supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
31777
31818
  shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
31778
31819
  shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
@@ -31935,7 +31976,7 @@ function formatPercent(value) {
31935
31976
  __name(formatPercent, "formatPercent");
31936
31977
 
31937
31978
  // src/tools/product-research.ts
31938
- import { z as z129 } from "zod";
31979
+ import { z as z130 } from "zod";
31939
31980
 
31940
31981
  // src/tools/product-research-idempotency.ts
31941
31982
  var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
@@ -32306,17 +32347,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
32306
32347
  ]);
32307
32348
  var POLL_INTERVAL_MS = 5e3;
32308
32349
  var MAX_WAIT_SECONDS = 120;
32309
- var FindInput = z129.object({
32350
+ var FindInput = z130.object({
32310
32351
  targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
32311
32352
  categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
32312
- confirmed: z129.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
32313
- waitSeconds: z129.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
32353
+ confirmed: z130.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
32354
+ waitSeconds: z130.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
32314
32355
  });
32315
- var GetInput = z129.object({
32316
- runId: z129.string().uuid().describe("ID del run devuelto por find_winning_products.")
32356
+ var GetInput = z130.object({
32357
+ runId: z130.string().uuid().describe("ID del run devuelto por find_winning_products.")
32317
32358
  });
32318
- var ListInput = z129.object({
32319
- limit: z129.number().int().min(1).max(20).default(10)
32359
+ var ListInput = z130.object({
32360
+ limit: z130.number().int().min(1).max(20).default(10)
32320
32361
  });
32321
32362
  function textResult(text2) {
32322
32363
  return {
@@ -32455,17 +32496,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
32455
32496
  __name(registerProductResearchTools, "registerProductResearchTools");
32456
32497
 
32457
32498
  // src/tools/dropshipping-projects.ts
32458
- import { z as z130 } from "zod";
32499
+ import { z as z131 } from "zod";
32459
32500
  var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
32460
32501
  var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
32461
32502
  var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
32462
- var ProjectId = z130.string().uuid();
32463
- var DropshippingProjectStatus = z130.enum([
32503
+ var ProjectId = z131.string().uuid();
32504
+ var DropshippingProjectStatus = z131.enum([
32464
32505
  "active",
32465
32506
  "completed",
32466
32507
  "archived"
32467
32508
  ]);
32468
- var DropshippingProjectPhase = z130.enum([
32509
+ var DropshippingProjectPhase = z131.enum([
32469
32510
  "research",
32470
32511
  "costing",
32471
32512
  "media",
@@ -32474,21 +32515,21 @@ var DropshippingProjectPhase = z130.enum([
32474
32515
  "advertising",
32475
32516
  "complete"
32476
32517
  ]);
32477
- var DropshippingRewardMilestone = z130.enum([
32518
+ var DropshippingRewardMilestone = z131.enum([
32478
32519
  "product_selected",
32479
32520
  "costing_saved",
32480
32521
  "product_media_ready",
32481
32522
  "creatives_completed",
32482
32523
  "campaign_created"
32483
32524
  ]);
32484
- var TargetCountry = z130.enum([
32525
+ var TargetCountry = z131.enum([
32485
32526
  "CO",
32486
32527
  "MX",
32487
32528
  "PE",
32488
32529
  "EC",
32489
32530
  "CL"
32490
32531
  ]);
32491
- var ResearchCategory = z130.enum([
32532
+ var ResearchCategory = z131.enum([
32492
32533
  "auto",
32493
32534
  "automotive",
32494
32535
  "kitchen",
@@ -32503,7 +32544,7 @@ var ResearchCategory = z130.enum([
32503
32544
  "garden",
32504
32545
  "cleaning"
32505
32546
  ]);
32506
- var HttpUrl3 = z130.string().url().max(2e3).refine((value) => {
32547
+ var HttpUrl3 = z131.string().url().max(2e3).refine((value) => {
32507
32548
  try {
32508
32549
  return [
32509
32550
  "http:",
@@ -32513,45 +32554,45 @@ var HttpUrl3 = z130.string().url().max(2e3).refine((value) => {
32513
32554
  return false;
32514
32555
  }
32515
32556
  }, "URL must use HTTP(S)");
32516
- var ResearchCandidateOrigin = z130.object({
32517
- type: z130.literal("research_candidate"),
32557
+ var ResearchCandidateOrigin = z131.object({
32558
+ type: z131.literal("research_candidate"),
32518
32559
  runId: ProjectId,
32519
- candidateSourceId: z130.string().min(1).max(160)
32560
+ candidateSourceId: z131.string().min(1).max(160)
32520
32561
  });
32521
- var TaskOrigin = z130.object({
32522
- type: z130.literal("task"),
32562
+ var TaskOrigin = z131.object({
32563
+ type: z131.literal("task"),
32523
32564
  taskId: ProjectId
32524
32565
  });
32525
- var ManualOrigin = z130.object({
32526
- type: z130.literal("manual"),
32566
+ var ManualOrigin = z131.object({
32567
+ type: z131.literal("manual"),
32527
32568
  clientRequestId: ProjectId,
32528
- country: z130.string().min(2).max(3).optional()
32569
+ country: z131.string().min(2).max(3).optional()
32529
32570
  });
32530
- var StartProjectInput = z130.object({
32531
- origin: z130.discriminatedUnion("type", [
32571
+ var StartProjectInput = z131.object({
32572
+ origin: z131.discriminatedUnion("type", [
32532
32573
  ResearchCandidateOrigin,
32533
32574
  TaskOrigin,
32534
32575
  ManualOrigin
32535
32576
  ]),
32536
- productName: z130.string().trim().min(1).max(240).optional(),
32577
+ productName: z131.string().trim().min(1).max(240).optional(),
32537
32578
  productUrl: HttpUrl3.optional(),
32538
- country: z130.string().min(2).max(3).optional(),
32539
- languageCode: z130.string().min(2).max(16).optional()
32579
+ country: z131.string().min(2).max(3).optional(),
32580
+ languageCode: z131.string().min(2).max(16).optional()
32540
32581
  }).strict();
32541
- var CostProjectInput = z130.object({
32582
+ var CostProjectInput = z131.object({
32542
32583
  projectId: ProjectId,
32543
- version: z130.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
32544
- country: z130.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
32584
+ version: z131.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
32585
+ country: z131.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
32545
32586
  message: "Pa\xEDs no soportado por ProductMaker."
32546
32587
  }).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
32547
- supplierCost: z130.number().finite().positive().describe("Costo real de una unidad con el proveedor, en la moneda del pa\xEDs. \xDANICO dato que debes pedirle al usuario: nunca lo inventes."),
32548
- shippingCost: z130.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
32549
- returnRate: z130.number().finite().min(0).lt(1).optional().describe("Fracci\xF3n de pedidos devueltos (0.25 = 25%). Omite para usar el valor gu\xEDa del pa\xEDs."),
32550
- cancellationRate: z130.number().finite().min(0).lt(1).optional().describe("Fracci\xF3n de pedidos cancelados (0.15 = 15%). Omite para usar el valor gu\xEDa del pa\xEDs."),
32551
- adsManagerCpa: z130.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
32552
- desiredMargin: z130.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
32553
- });
32554
- var GuideInput = z130.object({
32588
+ supplierCost: z131.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."),
32589
+ shippingCost: z131.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
32590
+ returnRate: z131.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."),
32591
+ cancellationRate: z131.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."),
32592
+ adsManagerCpa: z131.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
32593
+ desiredMargin: z131.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
32594
+ });
32595
+ var GuideInput = z131.object({
32555
32596
  projectId: ProjectId.optional()
32556
32597
  }).strict();
32557
32598
  var NEXT_ACTION_KINDS = [
@@ -32569,29 +32610,29 @@ var NEXT_ACTION_KINDS = [
32569
32610
  "repair_meta_campaign",
32570
32611
  "review_paused_campaign"
32571
32612
  ];
32572
- var DropshippingProjectNextAction = z130.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z130.object({
32573
- kind: z130.literal(kind),
32574
- href: z130.string().min(1)
32613
+ var DropshippingProjectNextAction = z131.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z131.object({
32614
+ kind: z131.literal(kind),
32615
+ href: z131.string().min(1)
32575
32616
  })));
32576
- var CostingInputSchema = z130.object({
32577
- country: z130.string().min(2).max(3),
32578
- supplierCost: z130.number().finite().positive(),
32579
- shippingCost: z130.number().finite().nonnegative(),
32580
- returnRate: z130.number().finite().min(0).lt(1),
32581
- cancellationRate: z130.number().finite().min(0).lt(1),
32582
- adsManagerCpa: z130.number().finite().nonnegative(),
32583
- desiredMargin: z130.number().finite().min(0).lt(1)
32617
+ var CostingInputSchema = z131.object({
32618
+ country: z131.string().min(2).max(3),
32619
+ supplierCost: z131.number().finite().positive(),
32620
+ shippingCost: z131.number().finite().nonnegative(),
32621
+ returnRate: z131.number().finite().min(0).lt(1),
32622
+ cancellationRate: z131.number().finite().min(0).lt(1),
32623
+ adsManagerCpa: z131.number().finite().nonnegative(),
32624
+ desiredMargin: z131.number().finite().min(0).lt(1)
32584
32625
  }).superRefine(({ returnRate, cancellationRate }, context) => {
32585
32626
  if (returnRate + cancellationRate >= 1) context.addIssue({
32586
- code: z130.ZodIssueCode.custom,
32627
+ code: z131.ZodIssueCode.custom,
32587
32628
  path: [
32588
32629
  "cancellationRate"
32589
32630
  ]
32590
32631
  });
32591
32632
  });
32592
- var FiniteCostingNumber = z130.number().finite();
32593
- var CostingResultSchema = z130.object({
32594
- country: z130.string().min(2).max(3),
32633
+ var FiniteCostingNumber = z131.number().finite();
32634
+ var CostingResultSchema = z131.object({
32635
+ country: z131.string().min(2).max(3),
32595
32636
  deliveryRate: FiniteCostingNumber,
32596
32637
  adjustedShippingCost: FiniteCostingNumber,
32597
32638
  adjustedCpa: FiniteCostingNumber,
@@ -32604,45 +32645,45 @@ var CostingResultSchema = z130.object({
32604
32645
  estimatedProfit: FiniteCostingNumber,
32605
32646
  actualMargin: FiniteCostingNumber,
32606
32647
  breakEvenAdsManagerCpa: FiniteCostingNumber,
32607
- wasPriceAutoAdjusted: z130.boolean(),
32608
- profitabilityStatus: z130.literal("healthy")
32609
- });
32610
- var RewardProgressSchema = z130.object({
32611
- campaignKey: z130.literal("dropshipping-launch-v1"),
32612
- totalCredits: z130.number().int().positive(),
32613
- earnedCredits: z130.number().int().nonnegative(),
32614
- milestones: z130.array(z130.object({
32648
+ wasPriceAutoAdjusted: z131.boolean(),
32649
+ profitabilityStatus: z131.literal("healthy")
32650
+ });
32651
+ var RewardProgressSchema = z131.object({
32652
+ campaignKey: z131.literal("dropshipping-launch-v1"),
32653
+ totalCredits: z131.number().int().positive(),
32654
+ earnedCredits: z131.number().int().nonnegative(),
32655
+ milestones: z131.array(z131.object({
32615
32656
  milestone: DropshippingRewardMilestone,
32616
- credits: z130.number().int().positive(),
32617
- available: z130.boolean().optional(),
32618
- earned: z130.boolean(),
32657
+ credits: z131.number().int().positive(),
32658
+ available: z131.boolean().optional(),
32659
+ earned: z131.boolean(),
32619
32660
  grantId: ProjectId.nullable(),
32620
- grantedAt: z130.string().datetime().nullable()
32661
+ grantedAt: z131.string().datetime().nullable()
32621
32662
  })).length(DropshippingRewardMilestone.options.length)
32622
32663
  });
32623
- var ProjectResponseSchema = z130.object({
32664
+ var ProjectResponseSchema = z131.object({
32624
32665
  id: ProjectId,
32625
32666
  taskId: ProjectId.nullable(),
32626
32667
  status: DropshippingProjectStatus,
32627
- originKey: z130.string().min(1),
32668
+ originKey: z131.string().min(1),
32628
32669
  researchRunId: ProjectId.nullable(),
32629
- candidateSourceId: z130.string().nullable(),
32630
- productName: z130.string().nullable(),
32670
+ candidateSourceId: z131.string().nullable(),
32671
+ productName: z131.string().nullable(),
32631
32672
  productUrl: HttpUrl3.nullable(),
32632
32673
  referenceImageUrl: HttpUrl3.nullable(),
32633
- targetCountry: z130.string().nullable(),
32634
- languageCode: z130.string().nullable(),
32635
- hasReferenceImage: z130.boolean(),
32636
- hasWinnerReferenceImage: z130.boolean(),
32674
+ targetCountry: z131.string().nullable(),
32675
+ languageCode: z131.string().nullable(),
32676
+ hasReferenceImage: z131.boolean(),
32677
+ hasWinnerReferenceImage: z131.boolean(),
32637
32678
  costingInput: CostingInputSchema.nullable(),
32638
32679
  costingResult: CostingResultSchema.nullable(),
32639
- costingVersion: z130.number().int().positive().nullable(),
32640
- version: z130.number().int().positive(),
32680
+ costingVersion: z131.number().int().positive().nullable(),
32681
+ version: z131.number().int().positive(),
32641
32682
  phase: DropshippingProjectPhase,
32642
32683
  nextAction: DropshippingProjectNextAction.nullable(),
32643
32684
  rewards: RewardProgressSchema,
32644
- createdAt: z130.string().datetime(),
32645
- updatedAt: z130.string().datetime()
32685
+ createdAt: z131.string().datetime(),
32686
+ updatedAt: z131.string().datetime()
32646
32687
  }).passthrough();
32647
32688
  var NEXT_ACTION_GUIDANCE = {
32648
32689
  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.",
@@ -32762,58 +32803,58 @@ function registerDropshippingProjectTools(server, api) {
32762
32803
  __name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
32763
32804
 
32764
32805
  // src/tools/daily-control.ts
32765
- import { z as z131 } from "zod";
32806
+ import { z as z132 } from "zod";
32766
32807
  var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
32767
32808
  var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
32768
32809
  var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
32769
- var ProviderCampaignIdentifier = z131.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
32770
- var DateOnly = z131.string().regex(/^\d{4}-\d{2}-\d{2}$/);
32771
- var DailyControlInput = z131.object({
32810
+ var ProviderCampaignIdentifier = z132.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
32811
+ var DateOnly = z132.string().regex(/^\d{4}-\d{2}-\d{2}$/);
32812
+ var DailyControlInput = z132.object({
32772
32813
  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."),
32773
- days: z131.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
32774
- projectId: z131.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
32814
+ days: z132.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
32815
+ projectId: z132.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
32775
32816
  }).strict();
32776
- var LinkCampaignInput = z131.object({
32777
- projectId: z131.string().uuid(),
32778
- provider: z131.enum([
32817
+ var LinkCampaignInput = z132.object({
32818
+ projectId: z132.string().uuid(),
32819
+ provider: z132.enum([
32779
32820
  "meta",
32780
32821
  "tiktok"
32781
32822
  ]),
32782
32823
  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."),
32783
32824
  campaignId: ProviderCampaignIdentifier
32784
32825
  }).strict();
32785
- var ReportReturnsInput = z131.object({
32786
- projectId: z131.string().uuid(),
32826
+ var ReportReturnsInput = z132.object({
32827
+ projectId: z132.string().uuid(),
32787
32828
  date: DateOnly,
32788
- returnedOrders: z131.number().int().min(0).max(1e5),
32789
- note: z131.string().trim().max(280).optional()
32829
+ returnedOrders: z132.number().int().min(0).max(1e5),
32830
+ note: z132.string().trim().max(280).optional()
32790
32831
  }).strict();
32791
- var DailyControlStatusMirror = DailyControlStatusEnum.or(z131.string());
32792
- var DailyControlLightMirror = DailyControlLightEnum.or(z131.string());
32793
- var DailyControlSourceMirror = DailyControlSourceEnum.or(z131.string());
32794
- var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z131.string());
32795
- var DailyControlDayMirror = z131.object({
32796
- date: z131.string(),
32797
- returnedOrders: z131.number(),
32832
+ var DailyControlStatusMirror = DailyControlStatusEnum.or(z132.string());
32833
+ var DailyControlLightMirror = DailyControlLightEnum.or(z132.string());
32834
+ var DailyControlSourceMirror = DailyControlSourceEnum.or(z132.string());
32835
+ var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z132.string());
32836
+ var DailyControlDayMirror = z132.object({
32837
+ date: z132.string(),
32838
+ returnedOrders: z132.number(),
32798
32839
  returnedSource: DailyControlSourceMirror,
32799
32840
  cancelledSource: DailyControlSourceMirror,
32800
- hasEstimates: z131.boolean(),
32841
+ hasEstimates: z132.boolean(),
32801
32842
  light: DailyControlLightMirror
32802
32843
  }).passthrough();
32803
- var DailyControlProductMirror = z131.object({
32804
- projectId: z131.string().uuid(),
32805
- productName: z131.string().nullable(),
32844
+ var DailyControlProductMirror = z132.object({
32845
+ projectId: z132.string().uuid(),
32846
+ productName: z132.string().nullable(),
32806
32847
  status: DailyControlStatusMirror,
32807
- statusMessage: z131.string().nullable(),
32808
- days: z131.array(DailyControlDayMirror),
32848
+ statusMessage: z132.string().nullable(),
32849
+ days: z132.array(DailyControlDayMirror),
32809
32850
  verdict: DailyControlVerdictMirror.nullable(),
32810
- rationale: z131.string().nullable()
32851
+ rationale: z132.string().nullable()
32811
32852
  }).passthrough();
32812
- var DailyControlResponseMirror = z131.object({
32813
- since: z131.string(),
32814
- until: z131.string(),
32815
- products: z131.array(DailyControlProductMirror),
32816
- archivedProjectSpend: z131.array(z131.unknown())
32853
+ var DailyControlResponseMirror = z132.object({
32854
+ since: z132.string(),
32855
+ until: z132.string(),
32856
+ products: z132.array(DailyControlProductMirror),
32857
+ archivedProjectSpend: z132.array(z132.unknown())
32817
32858
  }).passthrough();
32818
32859
  var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
32819
32860
  function withWarnings(response) {
@@ -32888,7 +32929,7 @@ __name(registerDailyControlTools, "registerDailyControlTools");
32888
32929
  // src/tools/product-control.ts
32889
32930
  import { readFile, stat } from "fs/promises";
32890
32931
  import { basename as basename2, isAbsolute, resolve as resolve3 } from "path";
32891
- import { z as z132 } from "zod";
32932
+ import { z as z133 } from "zod";
32892
32933
  var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
32893
32934
  var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
32894
32935
  var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
@@ -32901,36 +32942,36 @@ var createOperationGuidance = getProductMakerCapabilityModelGuidance("create_ope
32901
32942
  var mergeProductsGuidance = getProductMakerCapabilityModelGuidance("merge_products");
32902
32943
  var syncShopifyOrdersGuidance = getProductMakerCapabilityModelGuidance("sync_shopify_orders");
32903
32944
  var importOrdersFileGuidance = getProductMakerCapabilityModelGuidance("import_orders_file");
32904
- var DateOnly2 = z132.string().regex(/^\d{4}-\d{2}-\d{2}$/);
32945
+ var DateOnly2 = z133.string().regex(/^\d{4}-\d{2}-\d{2}$/);
32905
32946
  var IMPORT_BATCH_MAX2 = 50;
32906
- var ProductControlListInput = z132.object({
32907
- days: z132.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
32947
+ var ProductControlListInput = z133.object({
32948
+ days: z133.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
32908
32949
  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."),
32909
- shopDomain: z132.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
32950
+ shopDomain: z133.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
32910
32951
  }).strict();
32911
- var ImportableProductsInput = z132.object({
32912
- q: z132.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
32913
- after: z132.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
32914
- shopDomain: z132.string().min(1).optional()
32952
+ var ImportableProductsInput = z133.object({
32953
+ q: z133.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
32954
+ after: z133.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
32955
+ shopDomain: z133.string().min(1).optional()
32915
32956
  }).strict();
32916
- var ImportProductControlsInput = z132.object({
32917
- shopifyProductIds: z132.array(z132.string().min(1).max(64)).min(1).max(IMPORT_BATCH_MAX2).describe("Identificadores tal como vinieron de list_importable_products. NO los inventes ni los deduzcas del t\xEDtulo."),
32957
+ var ImportProductControlsInput = z133.object({
32958
+ shopifyProductIds: z133.array(z133.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."),
32918
32959
  // Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
32919
32960
  // sin decir a cuál archivaría el producto bajo la tienda equivocada.
32920
- shopDomain: z132.string().min(1)
32961
+ shopDomain: z133.string().min(1)
32921
32962
  }).strict();
32922
- var SetProductCostingInput = z132.object({
32923
- shopDomain: z132.string().min(1),
32924
- shopifyProductId: z132.string().min(1).max(64),
32925
- targetCountry: z132.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
32926
- supplierCost: z132.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
32927
- shippingCost: z132.number().finite().nonnegative(),
32928
- returnRate: z132.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
32929
- cancellationRate: z132.number().finite().min(0).lt(1)
32963
+ var SetProductCostingInput = z133.object({
32964
+ shopDomain: z133.string().min(1),
32965
+ shopifyProductId: z133.string().min(1).max(64),
32966
+ targetCountry: z133.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
32967
+ supplierCost: z133.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
32968
+ shippingCost: z133.number().finite().nonnegative(),
32969
+ returnRate: z133.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
32970
+ cancellationRate: z133.number().finite().min(0).lt(1)
32930
32971
  }).strict();
32931
- var Count = z132.number().int().min(0).max(1e5).nullable().optional();
32932
- var ReportProductCountsInput = z132.object({
32933
- productControlId: z132.string().uuid().describe("El identificador que devuelve get_product_control."),
32972
+ var Count = z133.number().int().min(0).max(1e5).nullable().optional();
32973
+ var ReportProductCountsInput = z133.object({
32974
+ productControlId: z133.string().uuid().describe("El identificador que devuelve get_product_control."),
32934
32975
  date: DateOnly2,
32935
32976
  orders: Count.describe("Pedidos que entraron ese d\xEDa."),
32936
32977
  cancelledOrders: Count,
@@ -32940,36 +32981,36 @@ var ReportProductCountsInput = z132.object({
32940
32981
  }).strict();
32941
32982
  var MAX_ORDERS_FILE_BYTES = 8 * 1024 * 1024;
32942
32983
  var SyncShopifyOrdersInput = SyncShopifyOrdersSchema;
32943
- var ImportOrdersFileInput = z132.object({
32984
+ var ImportOrdersFileInput = z133.object({
32944
32985
  /** Ruta ABSOLUTA en la máquina de quien usa el MCP. */
32945
- path: z132.string().min(1),
32946
- operationId: z132.string().uuid().optional(),
32986
+ path: z133.string().min(1),
32987
+ operationId: z133.string().uuid().optional(),
32947
32988
  /** Solo mirar: devuelve el resumen y no escribe nada. */
32948
- dryRun: z132.boolean().optional()
32989
+ dryRun: z133.boolean().optional()
32949
32990
  }).strict();
32950
- var CreateOperationInput = z132.object({
32951
- countryCode: z132.string().length(2),
32952
- label: z132.string().trim().min(1).max(60).optional()
32991
+ var CreateOperationInput = z133.object({
32992
+ countryCode: z133.string().length(2),
32993
+ label: z133.string().trim().min(1).max(60).optional()
32953
32994
  }).strict();
32954
- var MergeProductsInput = z132.object({
32955
- sourceId: z132.string().uuid(),
32956
- targetId: z132.string().uuid()
32995
+ var MergeProductsInput = z133.object({
32996
+ sourceId: z133.string().uuid(),
32997
+ targetId: z133.string().uuid()
32957
32998
  }).strict();
32958
- var SetMonthlyExpenseInput = z132.object({
32959
- month: z132.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
32999
+ var SetMonthlyExpenseInput = z133.object({
33000
+ month: z133.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
32960
33001
  label: SaveMonthlyExpenseSchema.shape.label,
32961
- amount: z132.number().finite().min(0),
32962
- operationId: z132.string().uuid().optional()
33002
+ amount: z133.number().finite().min(0),
33003
+ operationId: z133.string().uuid().optional()
32963
33004
  }).strict();
32964
- var SetAdSpendInput = z132.object({
32965
- month: z132.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
32966
- operationId: z132.string().uuid().optional(),
33005
+ var SetAdSpendInput = z133.object({
33006
+ month: z133.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
33007
+ operationId: z133.string().uuid().optional(),
32967
33008
  /** null RETIRA la corrección; cero afirma que no pautó. */
32968
- amount: z132.number().finite().min(0).nullable()
33009
+ amount: z133.number().finite().min(0).nullable()
32969
33010
  }).strict();
32970
- var GetFinancesInput = z132.object({
32971
- month: z132.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional().describe("Mes en YYYY-MM. Si se omite, el mes en curso. Solo mes calendario."),
32972
- operationId: z132.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
33011
+ var GetFinancesInput = z133.object({
33012
+ month: z133.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."),
33013
+ operationId: z133.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
32973
33014
  }).strict();
32974
33015
  function registerProductControlTools(server, api, { transport = "http" } = {}) {
32975
33016
  server.registerTool("get_product_control", {
@@ -33161,28 +33202,28 @@ function registerProductControlTools(server, api, { transport = "http" } = {}) {
33161
33202
  __name(registerProductControlTools, "registerProductControlTools");
33162
33203
 
33163
33204
  // src/tools/market-study-estimate.ts
33164
- import { z as z133 } from "zod";
33205
+ import { z as z134 } from "zod";
33165
33206
  var estimateMarketStudyGuidance = getProductMakerCapabilityModelGuidance("estimate_market_study_cost");
33166
- var ProductTaskOutputEnum = z133.enum([
33207
+ var ProductTaskOutputEnum = z134.enum([
33167
33208
  "landing",
33168
33209
  "video",
33169
33210
  "image"
33170
33211
  ]);
33171
- var EstimateMarketStudyInput = z133.object({
33172
- kind: z133.enum([
33212
+ var EstimateMarketStudyInput = z134.object({
33213
+ kind: z134.enum([
33173
33214
  "video",
33174
33215
  "product_task"
33175
33216
  ]).describe('"video" para generate_video_creative; "product_task" para create_product_task.'),
33176
- videoAngleCount: z133.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
33177
- durationSeconds: z133.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
33217
+ videoAngleCount: z134.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
33218
+ durationSeconds: z134.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
33178
33219
  videoStructure: VideoStructureEnum.default("single_take"),
33179
33220
  videoQuality: VideoQualityEnum.default("economy"),
33180
33221
  videoResolution: VideoResolutionEnum.default("480p"),
33181
- productImageCount: z133.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
33222
+ productImageCount: z134.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
33182
33223
  outputs: ProductTaskOutputEnum.array().min(1).max(3).optional().describe('Solo para kind="product_task": los mismos outputs de create_product_task. Default: todos.'),
33183
- generateAiMusic: z133.boolean().optional(),
33224
+ generateAiMusic: z134.boolean().optional(),
33184
33225
  generateAiEdit: AiEditRequestSchema.optional(),
33185
- replicateWinnerWhenFound: z133.boolean().optional().describe("La misma preferencia que enviar\xE1s al crear. false excluye la reserva de r\xE9plica del ganador de la cotizaci\xF3n con estudio.")
33226
+ replicateWinnerWhenFound: z134.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.")
33186
33227
  }).strict();
33187
33228
  function buildMarketStudyEstimateRequests(input) {
33188
33229
  const quotesVideo = input.kind === "video" || (input.outputs ?? [