@productmaker/mcp 7.2.0 → 7.3.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.
Files changed (3) hide show
  1. package/dist/http.js +792 -674
  2. package/dist/stdio.js +781 -663
  3. package/package.json +1 -1
package/dist/http.js CHANGED
@@ -3609,11 +3609,12 @@ var FreeformLandingConfigSchema = z21.object({
3609
3609
  showVariantPicker: z21.boolean().optional(),
3610
3610
  /**
3611
3611
  * Suppress the native Shopify buy form (the `BUY_FORM_MARKER` block). The page
3612
- * CTAs already carry `data-cl-buy-trigger` → they open the ReleaseIt COD popup,
3613
- * so on ReleaseIt-only stores the native add-to-cart form is a redundant second
3614
- * buy path (it rendered as a bare "price + Comprar" block). When true the
3615
- * assembler omits the marker entirely. Undefined/false = keep the native form
3616
- * (backward compatible with already-assembled configs).
3612
+ * CTAs already carry `data-cl-buy-trigger` → they open the installed COD
3613
+ * provider's popup (Releasit or EasySell), so on COD-provider stores the
3614
+ * native add-to-cart form is a redundant second buy path (it rendered as a
3615
+ * bare "price + Comprar" block). When true the assembler omits the marker
3616
+ * entirely. Undefined/false = keep the native form (backward compatible with
3617
+ * already-assembled configs).
3617
3618
  */
3618
3619
  hideNativeBuyForm: z21.boolean().optional()
3619
3620
  });
@@ -5401,6 +5402,17 @@ var CodeLandingThemeSetupResponse = z28.discriminatedUnion("status", [
5401
5402
  themeEditorDeepLink: z28.string().url(),
5402
5403
  shopDomain: z28.string()
5403
5404
  }),
5405
+ z28.object({
5406
+ /**
5407
+ * The block is missing and the store has NO products yet. Shopify's theme
5408
+ * editor cannot add an app block to a product template with nothing to
5409
+ * preview (it answers "there is a problem with the app block"), so there
5410
+ * is deliberately no deep link: the seller publishes first, and the
5411
+ * publish response carries the link aimed at the product it created.
5412
+ */
5413
+ status: z28.literal("setup_after_publish"),
5414
+ shopDomain: z28.string()
5415
+ }),
5404
5416
  z28.object({
5405
5417
  /** Not a code-landing task — the gate does not apply. */
5406
5418
  status: z28.literal("not_applicable"),
@@ -6903,7 +6915,10 @@ var ChatParseEstimationOptions = z34.object({}).strict();
6903
6915
  var CodeLandingEditEstimationOptions = z34.object({}).strict();
6904
6916
  var ServiceCreativeEstimationOptions = z34.object({
6905
6917
  mediaAssetCount: z34.number().int().min(0).max(8).optional(),
6906
- uploadedVideoDurationSeconds: z34.number().min(0).max(240).optional()
6918
+ uploadedVideoDurationSeconds: z34.number().min(0).max(240).optional(),
6919
+ /** Quality the panels render at (its registry model sets the per-second
6920
+ * price). Absent = economy, the pre-quality service default. */
6921
+ videoQuality: VideoQuality.optional()
6907
6922
  });
6908
6923
  var ActorGridEstimationOptions = z34.object({}).strict();
6909
6924
  var CostEstimationRequest = z34.discriminatedUnion("type", [
@@ -7673,7 +7688,18 @@ var KIE_SUBMIT_IMAGE_TASK_TARGETS = [
7673
7688
  "rapid_master_anchor",
7674
7689
  "clean_product_image",
7675
7690
  "single_call_anchor",
7676
- "product_view_reference"
7691
+ "product_view_reference",
7692
+ // Generated service-video presenter (text-to-image portrait). Task-owned, so
7693
+ // it lives here and not beside `actor_candidate`; it mirrors that target's
7694
+ // model, resolution and recovery policy. The fan-in resumes the service init
7695
+ // (`dispatchServiceActor`, refKey prefix `service_actor:`).
7696
+ "service_actor",
7697
+ // First frame of a generated service B-roll panel: image-to-image from the
7698
+ // service photo the planner cited, cleaned of overlaid text/graphics and
7699
+ // fitted to the shot. Mirrors `rapid_panel`'s model tier and recovery
7700
+ // policy. The same fan-in waits for the whole expected image set
7701
+ // (`dispatchServiceActor`, refKey prefix `service_broll_anchor:`).
7702
+ "service_broll_anchor"
7677
7703
  ];
7678
7704
  var ACTOR_CANDIDATE_TARGET = "actor_candidate";
7679
7705
  var ANY_KIE_SUBMIT_IMAGE_TARGETS = [
@@ -9595,6 +9621,12 @@ var DEFAULT_PRICING = {
9595
9621
  ourCostCents: 0.01,
9596
9622
  userPriceCents: 0.02
9597
9623
  },
9624
+ // Service reels harvested from the business's own public profile (per second,
9625
+ // same Whisper-1 rate). Separate action so the ledger names the source.
9626
+ "openai:service-social-transcribe": {
9627
+ ourCostCents: 0.01,
9628
+ userPriceCents: 0.02
9629
+ },
9598
9630
  // User-uploaded service reference/competitor analysis (per second, same Whisper-1 rate).
9599
9631
  // This is a separate action because its ledger entries identify the analysis source.
9600
9632
  "openai:service-reference-transcribe": {
@@ -10734,6 +10766,11 @@ var DECLARATION = DELIVERY_FAMILIES.map((family) => [
10734
10766
  ])
10735
10767
  ]);
10736
10768
 
10769
+ // ../../packages/types/src/seller-prohibitions.ts
10770
+ var MARKER = String.raw`(?:no|nunca|jam[aá]s|prohibido|evita[r]?)(?:\s*:)?\s`;
10771
+ var PROHIBITION_AT_START = new RegExp(String.raw`^(?:[-•*]\s*)?(${MARKER}[\s\S]*)$`, "iu");
10772
+ var PROHIBITION_AFTER_LABEL = new RegExp(String.raw`^(?:[-•*]\s*)?[^:.!?\n]{1,40}:\s*(${MARKER}[\s\S]*)$`, "iu");
10773
+
10737
10774
  // ../../packages/types/src/task-type.ts
10738
10775
  import { z as z50 } from "zod";
10739
10776
  var TaskTypeSchema = z50.enum([
@@ -13315,7 +13352,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
13315
13352
  "task",
13316
13353
  "product"
13317
13354
  ]),
13318
- defineCapability("create_service_video", "40551b8c5d430a494e94bc40a91f265327a2ff5f68e97160559f5219d74d8786", "credit_consuming", "creative", [
13355
+ defineCapability("create_service_video", "863884c1af5de3e168cbbe825ea3961901c84dae1899ca400f8f7fa01df91c0a", "credit_consuming", "creative", [
13319
13356
  "credit_consuming",
13320
13357
  "state_change"
13321
13358
  ], [
@@ -13339,7 +13376,11 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
13339
13376
  ]),
13340
13377
  slot("video_preset", false, [
13341
13378
  "videoPreset"
13342
- ])
13379
+ ]),
13380
+ // MCP-only for now: WhatsApp's service flow keeps the economy default.
13381
+ slot("video_quality", false, [
13382
+ "videoQuality"
13383
+ ], [])
13343
13384
  ], [
13344
13385
  "service_context"
13345
13386
  ], [
@@ -15132,6 +15173,81 @@ var WhatsAppPresentationManifestSchema = z67.object({
15132
15173
  }
15133
15174
  });
15134
15175
 
15176
+ // ../../packages/types/src/flight-recorder.ts
15177
+ import { z as z68 } from "zod";
15178
+ var FlightRecorderGenerationTypeSchema = z68.enum([
15179
+ "initial",
15180
+ "regeneration",
15181
+ "edit",
15182
+ "retry"
15183
+ ]);
15184
+ var FlightRecorderProviderSchema = z68.enum([
15185
+ "kie",
15186
+ "fal"
15187
+ ]);
15188
+ var FlightRecorderElementSchema = z68.object({
15189
+ name: z68.string().optional(),
15190
+ description: z68.string().optional(),
15191
+ frontalImageUrl: z68.string().optional(),
15192
+ referenceImageUrls: z68.array(z68.string()).optional(),
15193
+ videoUrl: z68.string().optional()
15194
+ });
15195
+ var FlightRecorderDistillationSchema = z68.object({
15196
+ actorGender: z68.enum([
15197
+ "female",
15198
+ "male",
15199
+ "mixed"
15200
+ ]).or(z68.string()).optional(),
15201
+ voiceId: z68.string().optional(),
15202
+ cameraMotion: z68.string().optional()
15203
+ }).catchall(z68.unknown());
15204
+ var FlightRecorderEntrySchema = z68.object({
15205
+ schemaVersion: z68.literal(1).optional(),
15206
+ id: z68.string().min(1),
15207
+ taskId: z68.string().min(1),
15208
+ runId: z68.string().min(1),
15209
+ sequence: z68.number().int().nonnegative(),
15210
+ timestamp: z68.string().min(1),
15211
+ provider: FlightRecorderProviderSchema.or(z68.string()),
15212
+ model: z68.string().min(1),
15213
+ prompt: z68.string(),
15214
+ durationSeconds: z68.number().nonnegative(),
15215
+ aspectRatio: z68.string().optional(),
15216
+ resolution: z68.string().optional(),
15217
+ startImageUrl: z68.string().optional(),
15218
+ endImageUrl: z68.string().optional(),
15219
+ generateAudio: z68.boolean().optional(),
15220
+ // Correlation & pipeline metadata
15221
+ angleKey: z68.string().optional(),
15222
+ sceneIndex: z68.number().int().nonnegative().optional(),
15223
+ generationType: FlightRecorderGenerationTypeSchema,
15224
+ operationId: z68.string().min(1).optional(),
15225
+ revisionId: z68.string().min(1).optional(),
15226
+ attemptNumber: z68.number().int().nonnegative().default(1),
15227
+ // Elements & Distillation
15228
+ elements: z68.array(FlightRecorderElementSchema).optional(),
15229
+ distillation: FlightRecorderDistillationSchema.optional(),
15230
+ // Raw payload (sanitized of secrets)
15231
+ rawPayload: z68.record(z68.unknown())
15232
+ });
15233
+ var FlightRecorderQuerySchema = z68.object({
15234
+ taskId: z68.string().min(1),
15235
+ runId: z68.string().optional(),
15236
+ sceneIndex: z68.number().int().nonnegative().optional(),
15237
+ angleKey: z68.string().optional(),
15238
+ generationType: FlightRecorderGenerationTypeSchema.optional(),
15239
+ cursor: z68.number().int().nonnegative().optional(),
15240
+ limit: z68.number().int().positive().optional()
15241
+ });
15242
+ var FlightRecorderResponseSchema = z68.object({
15243
+ taskId: z68.string().min(1),
15244
+ runId: z68.string().min(1),
15245
+ entries: z68.array(FlightRecorderEntrySchema),
15246
+ lastCall: FlightRecorderEntrySchema.nullable(),
15247
+ count: z68.number().int().nonnegative(),
15248
+ nextCursor: z68.number().int().nonnegative().nullable()
15249
+ });
15250
+
15135
15251
  // src/http.ts
15136
15252
  import express4 from "express";
15137
15253
  import rateLimit2 from "express-rate-limit";
@@ -15638,22 +15754,22 @@ import { InsufficientScopeError, InvalidTokenError } from "@modelcontextprotocol
15638
15754
  import { createRemoteJWKSet as createRemoteJWKSet2, jwtVerify as jwtVerify2 } from "jose";
15639
15755
 
15640
15756
  // src/auth/oauth-config.ts
15641
- import { z as z68 } from "zod";
15757
+ import { z as z69 } from "zod";
15642
15758
  var MCP_RESOURCE = new URL("https://mcp.productmaker.app/mcp");
15643
15759
  var MCP_SCOPE = "mcp:access";
15644
15760
  var STATIC_CLIENT_ISSUER = new URL(MCP_RESOURCE.origin);
15645
- var oauthEnvSchema = z68.object({
15646
- MCP_REMOTE_AUTH_MODE: z68.literal("oauth"),
15647
- MCP_AUTH0_ISSUER: z68.string().trim().min(1),
15648
- MCP_AUTH0_AUDIENCE: z68.string().trim().refine((value) => value === MCP_RESOURCE.href, {
15761
+ var oauthEnvSchema = z69.object({
15762
+ MCP_REMOTE_AUTH_MODE: z69.literal("oauth"),
15763
+ MCP_AUTH0_ISSUER: z69.string().trim().min(1),
15764
+ MCP_AUTH0_AUDIENCE: z69.string().trim().refine((value) => value === MCP_RESOURCE.href, {
15649
15765
  message: `must equal ${MCP_RESOURCE.href}`
15650
15766
  }),
15651
- MCP_AUTH0_CLIENT_ID: z68.string().trim().min(1),
15652
- MCP_AUTH0_CLIENT_SECRET: z68.string().trim().min(1),
15653
- PM_API_AUDIENCE: z68.string().trim().min(1),
15654
- AUTH0_AUDIENCE: z68.string().trim().min(1),
15655
- MCP_STATIC_CLIENT_ID: z68.string().trim().min(1).optional(),
15656
- MCP_STATIC_CLIENT_SECRET: z68.string().trim().min(1).optional()
15767
+ MCP_AUTH0_CLIENT_ID: z69.string().trim().min(1),
15768
+ MCP_AUTH0_CLIENT_SECRET: z69.string().trim().min(1),
15769
+ PM_API_AUDIENCE: z69.string().trim().min(1),
15770
+ AUTH0_AUDIENCE: z69.string().trim().min(1),
15771
+ MCP_STATIC_CLIENT_ID: z69.string().trim().min(1).optional(),
15772
+ MCP_STATIC_CLIENT_SECRET: z69.string().trim().min(1).optional()
15657
15773
  });
15658
15774
  function formatZodIssues(error) {
15659
15775
  return error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
@@ -16760,7 +16876,7 @@ var ApiClient = class {
16760
16876
  };
16761
16877
 
16762
16878
  // src/index.ts
16763
- var MCP_VERSION = "7.2.0";
16879
+ var MCP_VERSION = "7.3.0";
16764
16880
 
16765
16881
  // src/meta-upload-app.ts
16766
16882
  import { readFileSync } from "fs";
@@ -16832,7 +16948,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
16832
16948
  __name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
16833
16949
 
16834
16950
  // src/tools/tasks.ts
16835
- import { z as z72 } from "zod";
16951
+ import { z as z73 } from "zod";
16836
16952
 
16837
16953
  // src/resolve-image.ts
16838
16954
  import { lookup as dnsLookup } from "dns/promises";
@@ -17393,10 +17509,10 @@ async function resolveMediaRef(ref, opts) {
17393
17509
  __name(resolveMediaRef, "resolveMediaRef");
17394
17510
 
17395
17511
  // src/tools/shared.ts
17396
- import { z as z69 } from "zod";
17397
- var Lang = z69.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);
17398
- var Country = z69.string().min(2).max(3);
17399
- var LandingStrategyEnum = z69.enum([
17512
+ import { z as z70 } from "zod";
17513
+ var Lang = z70.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);
17514
+ var Country = z70.string().min(2).max(3);
17515
+ var LandingStrategyEnum = z70.enum([
17400
17516
  "auto",
17401
17517
  "classic",
17402
17518
  "pain_solution",
@@ -17405,12 +17521,12 @@ var LandingStrategyEnum = z69.enum([
17405
17521
  "offer_value",
17406
17522
  "lifestyle_identity"
17407
17523
  ]);
17408
- var LandingImageFormatEnum = z69.enum([
17524
+ var LandingImageFormatEnum = z70.enum([
17409
17525
  "9:16",
17410
17526
  "4:5",
17411
17527
  "1:1"
17412
17528
  ]);
17413
- var VideoPresetEnum = z69.enum([
17529
+ var VideoPresetEnum = z70.enum([
17414
17530
  "auto",
17415
17531
  "ugc_dynamic",
17416
17532
  "ugc_how_to",
@@ -17423,21 +17539,21 @@ var VideoPresetEnum = z69.enum([
17423
17539
  "pixar_problem",
17424
17540
  "pixar_sassy"
17425
17541
  ]);
17426
- var VideoStructureEnum = z69.enum([
17542
+ var VideoStructureEnum = z70.enum([
17427
17543
  "single_take",
17428
17544
  "multi_scene"
17429
17545
  ]);
17430
- var VideoQualityEnum = z69.enum([
17546
+ var VideoQualityEnum = z70.enum([
17431
17547
  "economy",
17432
17548
  "medium",
17433
17549
  "pro"
17434
17550
  ]);
17435
- var VideoRouteIdEnum = z69.enum([
17551
+ var VideoRouteIdEnum = z70.enum([
17436
17552
  "single_take",
17437
17553
  "multi_scene",
17438
17554
  "free"
17439
17555
  ]);
17440
- var TaskCreativeVariantVideoPresetEnum = z69.enum([
17556
+ var TaskCreativeVariantVideoPresetEnum = z70.enum([
17441
17557
  "auto",
17442
17558
  "ugc_dynamic",
17443
17559
  "ugc_how_to",
@@ -17508,7 +17624,7 @@ function resolveVideoPreset(preset) {
17508
17624
  return VIDEO_PRESET_RESOLUTION[preset] ?? null;
17509
17625
  }
17510
17626
  __name(resolveVideoPreset, "resolveVideoPreset");
17511
- var VideoTierEnum = z69.enum([
17627
+ var VideoTierEnum = z70.enum([
17512
17628
  "basic"
17513
17629
  ]);
17514
17630
  function resolveVideoTier(_tier) {
@@ -17548,22 +17664,22 @@ function assertSemanticVideoDurationCompatibility(structure, quality, durationSe
17548
17664
  }
17549
17665
  }
17550
17666
  __name(assertSemanticVideoDurationCompatibility, "assertSemanticVideoDurationCompatibility");
17551
- var VideoResolutionEnum = z69.enum([
17667
+ var VideoResolutionEnum = z70.enum([
17552
17668
  "480p",
17553
17669
  "720p"
17554
17670
  ]);
17555
- var CreativeGenderEnum = z69.enum([
17671
+ var CreativeGenderEnum = z70.enum([
17556
17672
  "female",
17557
17673
  "male",
17558
17674
  "mixed"
17559
17675
  ]);
17560
- var VideoStyleEnum = z69.enum([
17676
+ var VideoStyleEnum = z70.enum([
17561
17677
  "ugc",
17562
17678
  "cartoon_3d",
17563
17679
  "product_only",
17564
17680
  "ai_dynamic"
17565
17681
  ]);
17566
- var NarrativeStyleEnum = z69.enum([
17682
+ var NarrativeStyleEnum = z70.enum([
17567
17683
  "review",
17568
17684
  "ugc_how_to",
17569
17685
  "problem_product_cta",
@@ -17581,7 +17697,7 @@ var NarrativeStyleEnum = z69.enum([
17581
17697
  "ugc_demo_review",
17582
17698
  "market"
17583
17699
  ]);
17584
- var PublicNarrativeStyleEnum = z69.enum([
17700
+ var PublicNarrativeStyleEnum = z70.enum([
17585
17701
  "review",
17586
17702
  "ugc_how_to",
17587
17703
  "ugc_unboxing_chaos",
@@ -17594,7 +17710,7 @@ var PublicNarrativeStyleEnum = z69.enum([
17594
17710
  "sassy_product_pixar",
17595
17711
  "market"
17596
17712
  ]);
17597
- var VideoModelEnum = z69.enum([
17713
+ var VideoModelEnum = z70.enum([
17598
17714
  "veo",
17599
17715
  "wan",
17600
17716
  "bytedance",
@@ -17602,29 +17718,29 @@ var VideoModelEnum = z69.enum([
17602
17718
  "grok",
17603
17719
  "kling"
17604
17720
  ]);
17605
- var ProductReferenceUserChoiceEnum = z69.enum([
17721
+ var ProductReferenceUserChoiceEnum = z70.enum([
17606
17722
  "same_product",
17607
17723
  "variants",
17608
17724
  "different_products",
17609
17725
  "combo_distinct"
17610
17726
  ]);
17611
- var ProductReferenceCandidateGroupingEnum = z69.enum([
17727
+ var ProductReferenceCandidateGroupingEnum = z70.enum([
17612
17728
  "same_product_same_variant",
17613
17729
  "same_product_different_variants",
17614
17730
  "different_products",
17615
17731
  "unclear"
17616
17732
  ]);
17617
- var ProductReferenceScopeEnum = z69.enum([
17733
+ var ProductReferenceScopeEnum = z70.enum([
17618
17734
  "base",
17619
17735
  "video_view_pack"
17620
17736
  ]);
17621
- var ProductReferenceResolutionDecisionEnum = z69.enum([
17737
+ var ProductReferenceResolutionDecisionEnum = z70.enum([
17622
17738
  "approve",
17623
17739
  "reject",
17624
17740
  "observed_only",
17625
17741
  "correct_view"
17626
17742
  ]);
17627
- var ProductReferenceRejectionReasonEnum = z69.enum([
17743
+ var ProductReferenceRejectionReasonEnum = z70.enum([
17628
17744
  "replacement_requested",
17629
17745
  "wrong_product_identity",
17630
17746
  "wrong_variant",
@@ -17635,13 +17751,13 @@ var ProductReferenceRejectionReasonEnum = z69.enum([
17635
17751
  "not_a_product_photo",
17636
17752
  "other"
17637
17753
  ]);
17638
- var GapDurationChoiceMirror = z69.object({
17639
- angleIndex: z69.number().int().nonnegative(),
17640
- recommendedSec: z69.union([
17641
- z69.literal(15),
17642
- z69.literal(30)
17754
+ var GapDurationChoiceMirror = z70.object({
17755
+ angleIndex: z70.number().int().nonnegative(),
17756
+ recommendedSec: z70.union([
17757
+ z70.literal(15),
17758
+ z70.literal(30)
17643
17759
  ]),
17644
- estimatedDeltaCredits: z69.number().int().nonnegative().optional()
17760
+ estimatedDeltaCredits: z70.number().int().nonnegative().optional()
17645
17761
  });
17646
17762
  function buildSelectedImageUrlsHash(urls) {
17647
17763
  const input = [
@@ -17651,13 +17767,13 @@ function buildSelectedImageUrlsHash(urls) {
17651
17767
  return `fnv1a:${hash.toString(16).padStart(8, "0")}:${urls.length}`;
17652
17768
  }
17653
17769
  __name(buildSelectedImageUrlsHash, "buildSelectedImageUrlsHash");
17654
- var ImageCreativeStyleEnum = z69.enum([
17770
+ var ImageCreativeStyleEnum = z70.enum([
17655
17771
  "studio",
17656
17772
  "floating",
17657
17773
  "ingredients",
17658
17774
  "in_use"
17659
17775
  ]);
17660
- var ImageCreativeArchetypeEnum = z69.enum([
17776
+ var ImageCreativeArchetypeEnum = z70.enum([
17661
17777
  "direct_response_product_ad",
17662
17778
  "hero_outcome",
17663
17779
  "offer_value_prop",
@@ -17666,20 +17782,20 @@ var ImageCreativeArchetypeEnum = z69.enum([
17666
17782
  "problem_solution",
17667
17783
  "lifestyle_identity"
17668
17784
  ]);
17669
- var ImageCreativeVisualTreatmentEnum = z69.enum([
17785
+ var ImageCreativeVisualTreatmentEnum = z70.enum([
17670
17786
  "performance_product_ad",
17671
17787
  "premium_dtc_carousel"
17672
17788
  ]);
17673
- var ImageCreativeAspectRatioEnum = z69.enum([
17789
+ var ImageCreativeAspectRatioEnum = z70.enum([
17674
17790
  "1:1",
17675
17791
  "4:5",
17676
17792
  "9:16",
17677
17793
  "16:9"
17678
17794
  ]);
17679
- var ImageRefSchema = z69.object({
17680
- url: z69.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.'),
17681
- path: z69.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`.'),
17682
- assetId: z69.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.")
17795
+ var ImageRefSchema = z70.object({
17796
+ url: z70.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.'),
17797
+ path: z70.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`.'),
17798
+ assetId: z70.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.")
17683
17799
  }).refine((v) => [
17684
17800
  v.url,
17685
17801
  v.path,
@@ -17687,11 +17803,11 @@ var ImageRefSchema = z69.object({
17687
17803
  ].filter(Boolean).length === 1, {
17688
17804
  message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
17689
17805
  });
17690
- var ImagesInput = z69.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
17806
+ var ImagesInput = z70.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
17691
17807
  const assetCount = images.filter((image) => Boolean(image.assetId)).length;
17692
17808
  if (assetCount > 0 && assetCount !== images.length) {
17693
17809
  ctx.addIssue({
17694
- code: z69.ZodIssueCode.custom,
17810
+ code: z70.ZodIssueCode.custom,
17695
17811
  message: "all image entries must use assetId, or all must use URL/path sources"
17696
17812
  });
17697
17813
  }
@@ -17759,14 +17875,14 @@ async function submitCreative(api, opts) {
17759
17875
  });
17760
17876
  }
17761
17877
  __name(submitCreative, "submitCreative");
17762
- var ResearchTargetCountryEnum = z69.enum([
17878
+ var ResearchTargetCountryEnum = z70.enum([
17763
17879
  "CO",
17764
17880
  "MX",
17765
17881
  "PE",
17766
17882
  "EC",
17767
17883
  "CL"
17768
17884
  ]);
17769
- var ResearchCategoryEnum = z69.enum([
17885
+ var ResearchCategoryEnum = z70.enum([
17770
17886
  "auto",
17771
17887
  "automotive",
17772
17888
  "kitchen",
@@ -17817,7 +17933,7 @@ var OVERWRITES_EXTERNAL = {
17817
17933
  idempotentHint: false,
17818
17934
  openWorldHint: true
17819
17935
  };
17820
- var DailyControlStatusEnum = z69.enum([
17936
+ var DailyControlStatusEnum = z70.enum([
17821
17937
  "ok",
17822
17938
  "sales_unavailable",
17823
17939
  "timezone_unavailable",
@@ -17830,19 +17946,19 @@ var DailyControlStatusEnum = z69.enum([
17830
17946
  "product_missing",
17831
17947
  "store_unreachable"
17832
17948
  ]);
17833
- var DailyControlLightEnum = z69.enum([
17949
+ var DailyControlLightEnum = z70.enum([
17834
17950
  "green",
17835
17951
  "amber",
17836
17952
  "red",
17837
17953
  "none"
17838
17954
  ]);
17839
- var DailyControlVerdictEnum = z69.enum([
17955
+ var DailyControlVerdictEnum = z70.enum([
17840
17956
  "scale",
17841
17957
  "hold",
17842
17958
  "kill",
17843
17959
  "insufficient_sample"
17844
17960
  ]);
17845
- var DailyControlSourceEnum = z69.enum([
17961
+ var DailyControlSourceEnum = z70.enum([
17846
17962
  "shopify",
17847
17963
  "shopify_settling",
17848
17964
  "user",
@@ -18930,29 +19046,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
18930
19046
  __name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
18931
19047
 
18932
19048
  // src/tools/media-presentation.ts
18933
- import { z as z70 } from "zod";
18934
- var HttpsPresentationUrlSchema = z70.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
19049
+ import { z as z71 } from "zod";
19050
+ var HttpsPresentationUrlSchema = z71.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
18935
19051
  var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
18936
19052
  const hostname = new URL(value).hostname.toLowerCase();
18937
19053
  return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
18938
19054
  }, "preview URL must be owned by ProductMaker");
18939
- var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z70.number().int().positive().max(maximum), "positiveIntAtMost");
18940
- var PresentationImageSchema = z70.object({
18941
- kind: z70.literal("image"),
19055
+ var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z71.number().int().positive().max(maximum), "positiveIntAtMost");
19056
+ var PresentationImageSchema = z71.object({
19057
+ kind: z71.literal("image"),
18942
19058
  url: HttpsPresentationUrlSchema,
18943
- mimeType: z70.enum([
19059
+ mimeType: z71.enum([
18944
19060
  "image/jpeg",
18945
19061
  "image/png"
18946
19062
  ]),
18947
19063
  byteSize: positiveIntAtMost(5 * 1024 * 1024),
18948
19064
  width: positiveIntAtMost(16384),
18949
19065
  height: positiveIntAtMost(16384),
18950
- alt: z70.string().trim().min(1).max(240)
19066
+ alt: z71.string().trim().min(1).max(240)
18951
19067
  }).strict();
18952
19068
  var McpMediaPresentationSchema = PresentationImageSchema;
18953
- var GalleryImageSchema = z70.object({
19069
+ var GalleryImageSchema = z71.object({
18954
19070
  url: ProductMakerPreviewUrlSchema,
18955
- alt: z70.string().trim().min(1).max(240)
19071
+ alt: z71.string().trim().min(1).max(240)
18956
19072
  });
18957
19073
  var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
18958
19074
  async function imageBlocks(image, transport) {
@@ -19102,10 +19218,10 @@ ${summary}`,
19102
19218
  __name(requirePaidCreativeConfirmation, "requirePaidCreativeConfirmation");
19103
19219
 
19104
19220
  // src/tools/winning-product-image.ts
19105
- import { z as z71 } from "zod";
19106
- var WinnerReferenceInput = z71.object({
19107
- runId: z71.string().uuid(),
19108
- candidateSourceId: z71.string().trim().min(1).max(160)
19221
+ import { z as z72 } from "zod";
19222
+ var WinnerReferenceInput = z72.object({
19223
+ runId: z72.string().uuid(),
19224
+ candidateSourceId: z72.string().trim().min(1).max(160)
19109
19225
  }).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
19110
19226
  async function resolveWinnerImages(api, winnerReference, images) {
19111
19227
  if (!winnerReference) return images;
@@ -19142,188 +19258,189 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
19142
19258
  var createServiceVideoGuidance = getProductMakerCapabilityModelGuidance("create_service_video");
19143
19259
  var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
19144
19260
  var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
19145
- var CreateProductTaskInput = z72.object({
19261
+ var CreateProductTaskInput = z73.object({
19146
19262
  images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
19147
19263
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
19148
- projectId: z72.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
19149
- productUrl: z72.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."),
19264
+ projectId: z73.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
19265
+ productUrl: z73.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."),
19150
19266
  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.'),
19151
19267
  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.'),
19152
- price: z72.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.'),
19153
- compareAtPrice: z72.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".'),
19154
- offer: z72.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.'),
19155
- paymentMethods: z72.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.'),
19156
- productContext: z72.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."),
19157
- productLabel: z72.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.'),
19268
+ price: z73.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.'),
19269
+ compareAtPrice: z73.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".'),
19270
+ offer: z73.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.'),
19271
+ paymentMethods: z73.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.'),
19272
+ productContext: z73.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."),
19273
+ productLabel: z73.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.'),
19158
19274
  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), excepto "problem_solution", que requiere 30s Multiescena. 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.'),
19159
- durationSeconds: z72.union([
19160
- z72.literal(15),
19161
- z72.literal(30)
19275
+ durationSeconds: z73.union([
19276
+ z73.literal(15),
19277
+ z73.literal(30)
19162
19278
  ]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
19163
- pauseForAngleReview: z72.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."),
19164
- aiDecidesAll: z72.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."),
19279
+ pauseForAngleReview: z73.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."),
19280
+ aiDecidesAll: z73.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."),
19165
19281
  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.'),
19166
19282
  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.'),
19167
19283
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
19168
19284
  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).'),
19169
- videoAngleCount: z72.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."),
19285
+ videoAngleCount: z73.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."),
19170
19286
  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.'),
19171
- outputs: z72.array(z72.enum([
19287
+ outputs: z73.array(z73.enum([
19172
19288
  "landing",
19173
19289
  "video",
19174
19290
  "image"
19175
19291
  ])).min(2).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}`),
19176
- competitorScanEnabled: z72.boolean().optional().describe("Opcional. Debe enviarse true solo despu\xE9s de que el usuario acepte estudiar la competencia (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. Omitir no autoriza el estudio profundo."),
19177
- replicateWinnerWhenFound: z72.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."),
19178
- brandId: z72.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."),
19179
- actorId: z72.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."),
19292
+ competitorScanEnabled: z73.boolean().optional().describe("Opcional. Debe enviarse true solo despu\xE9s de que el usuario acepte estudiar la competencia (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. Omitir no autoriza el estudio profundo."),
19293
+ replicateWinnerWhenFound: z73.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."),
19294
+ brandId: z73.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."),
19295
+ actorId: z73.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."),
19180
19296
  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.'),
19181
- creativeDirection: z72.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.'),
19182
- headline: z72.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."),
19183
- subheadline: z72.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."),
19297
+ creativeDirection: z73.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.'),
19298
+ headline: z73.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."),
19299
+ subheadline: z73.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."),
19184
19300
  landingStrategy: LandingStrategyEnum.default("classic").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".'),
19185
19301
  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".')
19186
19302
  }).strict();
19187
- var CreateServiceVideoInput = z72.object({
19188
- landingUrl: z72.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
19189
- additionalContext: z72.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
19303
+ var CreateServiceVideoInput = z73.object({
19304
+ landingUrl: z73.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
19305
+ additionalContext: z73.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
19190
19306
  language: Lang.describe("Idioma del video: es, en o pt."),
19191
- voiceId: z72.string().trim().min(1).optional().describe('Opcional. Voz de ElevenLabs para toda la narraci\xF3n. Usa "auto" para que la IA la alinee con el presentador o env\xEDa un ID concreto de la lista de voces de la web.'),
19192
- brandId: z72.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
19193
- reviewMode: z72.enum([
19307
+ voiceId: z73.string().trim().min(1).optional().describe('Opcional. Voz de ElevenLabs para toda la narraci\xF3n. Usa "auto" para que la IA la alinee con el presentador o env\xEDa un ID concreto de la lista de voces de la web.'),
19308
+ brandId: z73.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
19309
+ reviewMode: z73.enum([
19194
19310
  "automatic",
19195
19311
  "guided"
19196
19312
  ]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
19197
- videoPreset: z72.enum([
19313
+ videoPreset: z73.enum([
19198
19314
  "auto",
19199
19315
  "ugc_dynamic",
19200
19316
  "ugc_how_to",
19201
19317
  "cinematic",
19202
19318
  "wild_card"
19203
- ]).default("auto")
19319
+ ]).default("auto"),
19320
+ videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.')
19204
19321
  }).strict();
19205
- var GetTaskStatusInput = z72.object({
19206
- taskId: z72.string().min(1),
19207
- waitSeconds: z72.number().int().min(0).max(120).optional()
19322
+ var GetTaskStatusInput = z73.object({
19323
+ taskId: z73.string().min(1),
19324
+ waitSeconds: z73.number().int().min(0).max(120).optional()
19208
19325
  });
19209
- var ListTasksInput = z72.object({
19210
- limit: z72.number().int().min(1).max(50).optional(),
19211
- offset: z72.number().int().min(0).optional(),
19212
- search: z72.string().optional()
19326
+ var ListTasksInput = z73.object({
19327
+ limit: z73.number().int().min(1).max(50).optional(),
19328
+ offset: z73.number().int().min(0).optional(),
19329
+ search: z73.string().optional()
19213
19330
  });
19214
19331
  var MCP_REVIEW_LIST_FIELD_MAX = 1500;
19215
19332
  var MCP_REVIEW_FEATURE_ITEM_MAX = 240;
19216
- var EditTaskDraftInput = z72.object({
19217
- taskId: z72.string().min(1),
19218
- angleIndex: z72.number().int().min(0),
19219
- angle: z72.object({
19220
- angle: z72.string().min(1).max(480),
19221
- buyerPersona: z72.string().min(1).max(360),
19222
- actor: z72.string().min(1).max(360).optional(),
19223
- actorId: z72.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."),
19224
- gender: z72.enum([
19333
+ var EditTaskDraftInput = z73.object({
19334
+ taskId: z73.string().min(1),
19335
+ angleIndex: z73.number().int().min(0),
19336
+ angle: z73.object({
19337
+ angle: z73.string().min(1).max(480),
19338
+ buyerPersona: z73.string().min(1).max(360),
19339
+ actor: z73.string().min(1).max(360).optional(),
19340
+ actorId: z73.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."),
19341
+ gender: z73.enum([
19225
19342
  "female",
19226
19343
  "male"
19227
19344
  ]).optional(),
19228
- scriptNotes: z72.string().max(2e3).optional()
19345
+ scriptNotes: z73.string().max(2e3).optional()
19229
19346
  })
19230
19347
  });
19231
- var PendingActionPayload = z72.discriminatedUnion("kind", [
19232
- z72.object({
19233
- kind: z72.literal("product_reference_set_approval"),
19348
+ var PendingActionPayload = z73.discriminatedUnion("kind", [
19349
+ z73.object({
19350
+ kind: z73.literal("product_reference_set_approval"),
19234
19351
  scope: ProductReferenceScopeEnum.optional(),
19235
- scopeKey: z72.string().min(1).max(120).optional(),
19236
- scopeSnapshotId: z72.string().uuid().optional(),
19237
- expectedScopeHash: z72.string().min(1).max(128).optional(),
19352
+ scopeKey: z73.string().min(1).max(120).optional(),
19353
+ scopeSnapshotId: z73.string().uuid().optional(),
19354
+ expectedScopeHash: z73.string().min(1).max(128).optional(),
19238
19355
  decision: ProductReferenceResolutionDecisionEnum,
19239
19356
  reason: ProductReferenceRejectionReasonEnum.optional(),
19240
- affectedRefKeys: z72.array(z72.string().min(1).max(200)).min(1).optional(),
19241
- affectedPhotoNumbers: z72.array(z72.number().int().positive()).min(1).optional(),
19242
- recoveryAction: z72.enum([
19357
+ affectedRefKeys: z73.array(z73.string().min(1).max(200)).min(1).optional(),
19358
+ affectedPhotoNumbers: z73.array(z73.number().int().positive()).min(1).optional(),
19359
+ recoveryAction: z73.enum([
19243
19360
  "remove",
19244
19361
  "replace",
19245
19362
  "upload",
19246
19363
  "return_to_selection"
19247
19364
  ]).optional()
19248
19365
  }),
19249
- z72.object({
19250
- kind: z72.literal("product_reference_confirmation"),
19251
- selectedPhotoNumbers: z72.array(z72.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."),
19366
+ z73.object({
19367
+ kind: z73.literal("product_reference_confirmation"),
19368
+ selectedPhotoNumbers: z73.array(z73.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."),
19252
19369
  userChoice: ProductReferenceUserChoiceEnum.optional(),
19253
- confirmedProductNames: z72.array(z72.string().min(1).max(120)).min(2).max(8).optional(),
19370
+ confirmedProductNames: z73.array(z73.string().min(1).max(120)).min(2).max(8).optional(),
19254
19371
  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."),
19255
19372
  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."),
19256
- useMultiSceneShowcase: z72.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
19373
+ useMultiSceneShowcase: z73.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
19257
19374
  }),
19258
- z72.object({
19259
- kind: z72.literal("angle_review_approval"),
19375
+ z73.object({
19376
+ kind: z73.literal("angle_review_approval"),
19260
19377
  // All edits are optional — empty action body just approves the
19261
19378
  // backend-generated draft as-is. Field shapes mirror the angle-review
19262
19379
  // request contracts in @packages/types/wizard.ts; the handler routes to
19263
19380
  // the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
19264
- customAngle: z72.string().min(1).max(480).optional(),
19381
+ customAngle: z73.string().min(1).max(480).optional(),
19265
19382
  // Keep the shared MCP action within the strictest downstream contract:
19266
19383
  // autopilot/image resume endpoints cap these fields at 1500 characters.
19267
- painPoints: z72.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
19268
- benefits: z72.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
19384
+ painPoints: z73.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
19385
+ benefits: z73.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
19269
19386
  // Same policy as the two fields above: the strictest downstream contract
19270
19387
  // wins. The image endpoint caps each feature at 240 while landing/video
19271
19388
  // accept 300, and this single action routes to whichever the task is — so
19272
19389
  // accepting 300 here turns a 250-character feature on an image task into
19273
19390
  // an opaque HTTP 400 after the model already believed it had been saved.
19274
- features: z72.array(z72.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
19275
- buyerPersona: z72.string().min(1).max(360).optional(),
19391
+ features: z73.array(z73.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
19392
+ buyerPersona: z73.string().min(1).max(360).optional(),
19276
19393
  narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n) requiere Multiescena de 30s: en un video de 15s en formato Un solo clip el servidor la rechaza.'),
19277
- actor: z72.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."),
19278
- actorId: z72.string().max(120).nullable().optional(),
19279
- creativeDirection: z72.string().max(2e3).optional(),
19280
- selectedAngleNumbers: z72.array(z72.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."),
19281
- angleEdits: z72.array(z72.object({
19282
- angleNumber: z72.number().int().positive(),
19283
- narrativeSelection: z72.enum([
19394
+ actor: z73.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."),
19395
+ actorId: z73.string().max(120).nullable().optional(),
19396
+ creativeDirection: z73.string().max(2e3).optional(),
19397
+ selectedAngleNumbers: z73.array(z73.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."),
19398
+ angleEdits: z73.array(z73.object({
19399
+ angleNumber: z73.number().int().positive(),
19400
+ narrativeSelection: z73.enum([
19284
19401
  "market",
19285
19402
  "guided"
19286
19403
  ]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
19287
- angle: z72.string().min(1).max(480).optional(),
19288
- buyerPersona: z72.string().min(1).max(360).optional(),
19404
+ angle: z73.string().min(1).max(480).optional(),
19405
+ buyerPersona: z73.string().min(1).max(360).optional(),
19289
19406
  narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n) requiere Multiescena de 30s: en un video de 15s en formato Un solo clip el servidor la rechaza.'),
19290
- actor: z72.string().min(1).max(360).optional(),
19291
- actorId: z72.string().max(120).nullable().optional(),
19292
- creativeDirection: z72.string().max(2e3).optional()
19407
+ actor: z73.string().min(1).max(360).optional(),
19408
+ actorId: z73.string().max(120).nullable().optional(),
19409
+ creativeDirection: z73.string().max(2e3).optional()
19293
19410
  }).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)."),
19294
- gapDurationSeconds: z72.union([
19295
- z72.literal(15),
19296
- z72.literal(30)
19411
+ gapDurationSeconds: z73.union([
19412
+ z73.literal(15),
19413
+ z73.literal(30)
19297
19414
  ]).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.")
19298
19415
  }),
19299
- z72.object({
19300
- kind: z72.literal("service_angle_approval"),
19301
- angleId: z72.string().uuid().optional(),
19302
- angleNumber: z72.number().int().positive().optional(),
19303
- content: z72.string().min(1).max(480).optional(),
19304
- creativeDirection: z72.string().min(1).max(1500).optional(),
19305
- actor: z72.string().min(1).max(360).optional()
19416
+ z73.object({
19417
+ kind: z73.literal("service_angle_approval"),
19418
+ angleId: z73.string().uuid().optional(),
19419
+ angleNumber: z73.number().int().positive().optional(),
19420
+ content: z73.string().min(1).max(480).optional(),
19421
+ creativeDirection: z73.string().min(1).max(1500).optional(),
19422
+ actor: z73.string().min(1).max(360).optional()
19306
19423
  }),
19307
- z72.object({
19308
- kind: z72.literal("service_script_approval"),
19309
- voiceovers: z72.record(z72.string(), z72.string().min(1).max(600)).optional(),
19310
- visualDirections: z72.record(z72.string(), z72.string().min(1).max(1200)).optional(),
19311
- voiceoversByScene: z72.record(z72.string(), z72.string().min(1).max(600)).optional(),
19312
- visualDirectionsByScene: z72.record(z72.string(), z72.string().min(1).max(1200)).optional()
19424
+ z73.object({
19425
+ kind: z73.literal("service_script_approval"),
19426
+ voiceovers: z73.record(z73.string(), z73.string().min(1).max(600)).optional(),
19427
+ visualDirections: z73.record(z73.string(), z73.string().min(1).max(1200)).optional(),
19428
+ voiceoversByScene: z73.record(z73.string(), z73.string().min(1).max(600)).optional(),
19429
+ visualDirectionsByScene: z73.record(z73.string(), z73.string().min(1).max(1200)).optional()
19313
19430
  })
19314
19431
  ]);
19315
- var ResolvePendingActionInput = z72.object({
19316
- taskId: z72.string().min(1),
19432
+ var ResolvePendingActionInput = z73.object({
19433
+ taskId: z73.string().min(1),
19317
19434
  action: PendingActionPayload
19318
19435
  }).strict();
19319
19436
  function resolveVariantConfirmVideoTier(action) {
19320
19437
  return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
19321
19438
  }
19322
19439
  __name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
19323
- var StatusForResolveSchema = z72.object({
19440
+ var StatusForResolveSchema = z73.object({
19324
19441
  // Metadata used to select the backend resume contract. Older API responses
19325
19442
  // may omit these fields, so the resolver keeps the generic fallback.
19326
- kind: z72.enum([
19443
+ kind: z73.enum([
19327
19444
  "autopilot",
19328
19445
  "video",
19329
19446
  "image",
@@ -19331,18 +19448,18 @@ var StatusForResolveSchema = z72.object({
19331
19448
  "mix",
19332
19449
  "service"
19333
19450
  ]).optional(),
19334
- selectedOutputs: z72.array(z72.enum([
19451
+ selectedOutputs: z73.array(z73.enum([
19335
19452
  "landing",
19336
19453
  "video",
19337
19454
  "image"
19338
19455
  ])).optional(),
19339
- videoAngleCount: z72.number().int().min(1).max(3).optional(),
19340
- ugcFormat: z72.enum([
19456
+ videoAngleCount: z73.number().int().min(1).max(3).optional(),
19457
+ ugcFormat: z73.enum([
19341
19458
  "single_8s",
19342
19459
  "single_15s",
19343
19460
  "double_30s"
19344
19461
  ]).optional(),
19345
- videoStyle: z72.enum([
19462
+ videoStyle: z73.enum([
19346
19463
  "ugc",
19347
19464
  "cartoon_3d",
19348
19465
  "product_only",
@@ -19351,7 +19468,7 @@ var StatusForResolveSchema = z72.object({
19351
19468
  videoStructure: VideoStructureEnum.optional(),
19352
19469
  videoQuality: VideoQualityEnum.optional(),
19353
19470
  videoRouteId: VideoRouteIdEnum.optional(),
19354
- videoModel: z72.enum([
19471
+ videoModel: z73.enum([
19355
19472
  "veo",
19356
19473
  "wan",
19357
19474
  "bytedance",
@@ -19359,71 +19476,71 @@ var StatusForResolveSchema = z72.object({
19359
19476
  "grok",
19360
19477
  "kling"
19361
19478
  ]).optional(),
19362
- videoTier: z72.enum([
19479
+ videoTier: z73.enum([
19363
19480
  "legacy",
19364
19481
  "standard",
19365
19482
  "pro",
19366
19483
  "single_call"
19367
19484
  ]).optional(),
19368
- videoResolution: z72.enum([
19485
+ videoResolution: z73.enum([
19369
19486
  "480p",
19370
19487
  "720p"
19371
19488
  ]).optional(),
19372
19489
  narrativeStyle: NarrativeStyleEnum.optional(),
19373
- pauseForVideoScriptReview: z72.boolean().optional(),
19374
- pendingUserAction: z72.object({
19375
- kind: z72.string(),
19376
- candidateGrouping: z72.string().optional(),
19377
- selectedImageUrls: z72.array(z72.string()).optional(),
19378
- proposedProductNames: z72.array(z72.string()).optional(),
19490
+ pauseForVideoScriptReview: z73.boolean().optional(),
19491
+ pendingUserAction: z73.object({
19492
+ kind: z73.string(),
19493
+ candidateGrouping: z73.string().optional(),
19494
+ selectedImageUrls: z73.array(z73.string()).optional(),
19495
+ proposedProductNames: z73.array(z73.string()).optional(),
19379
19496
  // Adaptive reference questions are server-owned. Echo only the evidence
19380
19497
  // identity and the choices shown by the current snapshot; never accept a
19381
19498
  // client-supplied reference set as authorization.
19382
- options: z72.array(ProductReferenceUserChoiceEnum).max(4).optional(),
19383
- mode: z72.enum([
19499
+ options: z73.array(ProductReferenceUserChoiceEnum).max(4).optional(),
19500
+ mode: z73.enum([
19384
19501
  "question",
19385
19502
  "visual_recovery"
19386
19503
  ]).optional(),
19387
19504
  /** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
19388
- canKeepSelection: z72.boolean().optional(),
19389
- decisionKey: z72.string().optional(),
19390
- questionOrdinal: z72.number().int().min(1).max(5).optional(),
19391
- questionCeiling: z72.union([
19392
- z72.literal(3),
19393
- z72.literal(5)
19505
+ canKeepSelection: z73.boolean().optional(),
19506
+ decisionKey: z73.string().optional(),
19507
+ questionOrdinal: z73.number().int().min(1).max(5).optional(),
19508
+ questionCeiling: z73.union([
19509
+ z73.literal(3),
19510
+ z73.literal(5)
19394
19511
  ]).optional(),
19395
- referenceEvidenceVersion: z72.number().int().positive().optional(),
19396
- expectedEvidenceHash: z72.string().optional(),
19397
- question: z72.object({
19398
- prompt: z72.string().min(1).max(240),
19399
- helpText: z72.string().min(1).max(300).optional(),
19400
- options: z72.array(z72.object({
19512
+ referenceEvidenceVersion: z73.number().int().positive().optional(),
19513
+ expectedEvidenceHash: z73.string().optional(),
19514
+ question: z73.object({
19515
+ prompt: z73.string().min(1).max(240),
19516
+ helpText: z73.string().min(1).max(300).optional(),
19517
+ options: z73.array(z73.object({
19401
19518
  value: ProductReferenceUserChoiceEnum,
19402
- label: z72.string().min(1).max(120),
19403
- description: z72.string().min(1).max(240).optional()
19519
+ label: z73.string().min(1).max(120),
19520
+ description: z73.string().min(1).max(240).optional()
19404
19521
  })).min(2).max(4)
19405
19522
  }).optional(),
19406
19523
  scope: ProductReferenceScopeEnum.optional(),
19407
- scopeKey: z72.string().optional(),
19408
- scopeSnapshotId: z72.string().uuid().optional(),
19409
- scopeHash: z72.string().optional(),
19410
- baseReferenceSetHash: z72.string().optional(),
19411
- phase: z72.enum([
19524
+ scopeKey: z73.string().optional(),
19525
+ scopeSnapshotId: z73.string().uuid().optional(),
19526
+ scopeHash: z73.string().optional(),
19527
+ baseReferenceSetHash: z73.string().optional(),
19528
+ phase: z73.enum([
19412
19529
  "preparation",
19413
19530
  "final"
19414
19531
  ]).optional(),
19415
- selectedRefKeys: z72.array(z72.string().min(1).max(200)).optional(),
19416
- allowedDecisions: z72.array(ProductReferenceResolutionDecisionEnum).optional(),
19417
- previews: z72.array(z72.object({
19418
- refKey: z72.string().min(1).max(200)
19532
+ selectedRefKeys: z73.array(z73.string().min(1).max(200)).optional(),
19533
+ allowedDecisions: z73.array(ProductReferenceResolutionDecisionEnum).optional(),
19534
+ previews: z73.array(z73.object({
19535
+ refKey: z73.string().min(1).max(200)
19419
19536
  }).passthrough()).optional(),
19420
- customAngleDraft: z72.string().optional(),
19421
- painPointsDraft: z72.string().optional(),
19422
- benefitsDraft: z72.string().optional(),
19423
- featuresDraft: z72.array(z72.string()).optional(),
19424
- angleOptions: z72.array(z72.object({
19425
- index: z72.number().int().nonnegative(),
19426
- angle: z72.string().min(1)
19537
+ customAngleDraft: z73.string().optional(),
19538
+ painPointsDraft: z73.string().optional(),
19539
+ benefitsDraft: z73.string().optional(),
19540
+ featuresDraft: z73.array(z73.string()).optional(),
19541
+ angleOptions: z73.array(z73.object({
19542
+ index: z73.number().int().nonnegative(),
19543
+ angle: z73.string().min(1)
19427
19544
  }).passthrough()).min(1).max(5).optional(),
19428
19545
  // Recommendation consumed only when the caller explicitly sends
19429
19546
  // gapDurationSeconds: 30 in the angle approval action.
@@ -19433,17 +19550,17 @@ var StatusForResolveSchema = z72.object({
19433
19550
  // keys. `actorId` (the saved custom actor the picker stored) was silently
19434
19551
  // dropped here, so the approval handler below could not echo it back on the
19435
19552
  // PATCH — the selection looked accepted and reached no render.
19436
- angles: z72.array(z72.object({
19437
- id: z72.string().uuid(),
19438
- content: z72.string(),
19439
- creativeDirection: z72.string(),
19440
- actor: z72.string(),
19441
- actorId: z72.string().nullable().optional()
19553
+ angles: z73.array(z73.object({
19554
+ id: z73.string().uuid(),
19555
+ content: z73.string(),
19556
+ creativeDirection: z73.string(),
19557
+ actor: z73.string(),
19558
+ actorId: z73.string().nullable().optional()
19442
19559
  }).passthrough()).optional(),
19443
- panels: z72.array(z72.object({
19444
- beatId: z72.string(),
19445
- voiceover: z72.string(),
19446
- visualDirection: z72.string()
19560
+ panels: z73.array(z73.object({
19561
+ beatId: z73.string(),
19562
+ voiceover: z73.string(),
19563
+ visualDirection: z73.string()
19447
19564
  }).passthrough()).optional()
19448
19565
  }).optional()
19449
19566
  }).passthrough();
@@ -19669,6 +19786,7 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
19669
19786
  voiceId: input.voiceId
19670
19787
  } : {},
19671
19788
  videoPreset: input.videoPreset,
19789
+ videoQuality: input.videoQuality,
19672
19790
  reviewMode: input.reviewMode,
19673
19791
  ...input.brandId ? {
19674
19792
  brandId: input.brandId
@@ -20273,7 +20391,7 @@ __name(registerTaskTools, "registerTaskTools");
20273
20391
 
20274
20392
  // src/tools/creatives.ts
20275
20393
  import { randomUUID } from "crypto";
20276
- import { z as z73 } from "zod";
20394
+ import { z as z74 } from "zod";
20277
20395
  var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
20278
20396
  var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
20279
20397
  var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
@@ -20283,70 +20401,70 @@ var CreativeRefs = {
20283
20401
  images: ImagesInput,
20284
20402
  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.'),
20285
20403
  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.'),
20286
- price: z73.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.'),
20287
- offer: z73.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.'),
20288
- compareAtPrice: z73.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
20289
- productContext: z73.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."),
20290
- productLabel: z73.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.'),
20291
- buyerPersona: z73.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.'),
20292
- isCombo: z73.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
20293
- competitorScanEnabled: z73.boolean().optional().describe("Opcional. Debe enviarse true solo despu\xE9s de que el usuario acepte estudiar la competencia (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. Omitir no autoriza el estudio profundo."),
20294
- brandId: z73.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.")
20404
+ price: z74.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.'),
20405
+ offer: z74.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.'),
20406
+ compareAtPrice: z74.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
20407
+ productContext: z74.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."),
20408
+ productLabel: z74.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.'),
20409
+ buyerPersona: z74.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.'),
20410
+ isCombo: z74.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
20411
+ competitorScanEnabled: z74.boolean().optional().describe("Opcional. Debe enviarse true solo despu\xE9s de que el usuario acepte estudiar la competencia (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. Omitir no autoriza el estudio profundo."),
20412
+ brandId: z74.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.")
20295
20413
  };
20296
- var VideoPresenter = z73.discriminatedUnion("mode", [
20297
- z73.object({
20298
- mode: z73.literal("none")
20414
+ var VideoPresenter = z74.discriminatedUnion("mode", [
20415
+ z74.object({
20416
+ mode: z74.literal("none")
20299
20417
  }).strict(),
20300
- z73.object({
20301
- mode: z73.literal("saved_actor"),
20302
- actorId: z73.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
20418
+ z74.object({
20419
+ mode: z74.literal("saved_actor"),
20420
+ actorId: z74.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
20303
20421
  }).strict(),
20304
- z73.object({
20305
- mode: z73.literal("described"),
20306
- description: z73.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
20422
+ z74.object({
20423
+ mode: z74.literal("described"),
20424
+ description: z74.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
20307
20425
  }).strict()
20308
20426
  ]);
20309
- var VideoCreativeSetup = z73.discriminatedUnion("mode", [
20310
- z73.object({
20311
- mode: z73.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
20427
+ var VideoCreativeSetup = z74.discriminatedUnion("mode", [
20428
+ z74.object({
20429
+ mode: z74.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
20312
20430
  }).strict(),
20313
- z73.object({
20314
- mode: z73.literal("guided"),
20431
+ z74.object({
20432
+ mode: z74.literal("guided"),
20315
20433
  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. "problem_solution" requiere 30s.'),
20316
- buyerPersona: z73.string().trim().min(1).max(360),
20434
+ buyerPersona: z74.string().trim().min(1).max(360),
20317
20435
  presenter: VideoPresenter,
20318
- creativeDirection: z73.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
20436
+ creativeDirection: z74.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
20319
20437
  }).strict()
20320
20438
  ]);
20321
- var VideoInput = z73.object({
20439
+ var VideoInput = z74.object({
20322
20440
  images: CreativeRefs.images.optional(),
20323
20441
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
20324
- title: z73.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
20325
- primaryAngle: z73.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".'),
20442
+ title: z74.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
20443
+ primaryAngle: z74.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".'),
20326
20444
  language: CreativeRefs.language,
20327
20445
  country: CreativeRefs.country,
20328
- aspectRatio: z73.enum([
20446
+ aspectRatio: z74.enum([
20329
20447
  "9:16",
20330
20448
  "16:9",
20331
20449
  "Auto"
20332
20450
  ]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
20333
- durationSeconds: z73.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."),
20334
- videoAngleCount: z73.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."),
20451
+ durationSeconds: z74.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."),
20452
+ videoAngleCount: z74.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."),
20335
20453
  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.'),
20336
20454
  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."),
20337
20455
  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.'),
20338
20456
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
20339
20457
  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.'),
20340
- features: z73.array(z73.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
20458
+ features: z74.array(z74.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
20341
20459
  price: CreativeRefs.price,
20342
20460
  offer: CreativeRefs.offer,
20343
20461
  productContext: CreativeRefs.productContext,
20344
20462
  productLabel: CreativeRefs.productLabel,
20345
- cta: z73.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.'),
20346
- scriptNotes: z73.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.'),
20463
+ cta: z74.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.'),
20464
+ scriptNotes: z74.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.'),
20347
20465
  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.'),
20348
20466
  competitorScanEnabled: CreativeRefs.competitorScanEnabled,
20349
- replicateWinnerWhenFound: z73.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."),
20467
+ replicateWinnerWhenFound: z74.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."),
20350
20468
  brandId: CreativeRefs.brandId
20351
20469
  }).strict();
20352
20470
  var FreeVideoQualityEnum = VideoQualityEnum;
@@ -20364,7 +20482,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
20364
20482
  length: 29
20365
20483
  }, (_, index) => index + 2)
20366
20484
  };
20367
- var FreeVideoModelIdEnum = z73.enum([
20485
+ var FreeVideoModelIdEnum = z74.enum([
20368
20486
  "grok-imagine-video-1-5-preview",
20369
20487
  "minimax-h3/reference-to-video",
20370
20488
  "wan/3-0-video",
@@ -20375,70 +20493,70 @@ var FREE_SELECTABLE_MODEL_IDS = [
20375
20493
  "minimax-h3/reference-to-video",
20376
20494
  "wan/3-0-video"
20377
20495
  ];
20378
- var FreeVideoInput = z73.object({
20496
+ var FreeVideoInput = z74.object({
20379
20497
  images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
20380
- rawPrompt: z73.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."),
20498
+ rawPrompt: z74.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."),
20381
20499
  language: CreativeRefs.language,
20382
20500
  quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
20383
20501
  // Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
20384
20502
  // parsed ONLY so the handler can reject it with a message naming its
20385
20503
  // replacement — dropping it silently would turn a caller's explicit
20386
20504
  // Pro++ pick into a quiet fallback to Wan.
20387
- freeProModel: z73.enum([
20505
+ freeProModel: z74.enum([
20388
20506
  "wan",
20389
20507
  "seedance"
20390
20508
  ]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
20391
20509
  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.'),
20392
- durationSeconds: z73.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."),
20510
+ durationSeconds: z74.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."),
20393
20511
  videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
20394
- generateAiMusic: z73.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
20395
- addSubtitles: z73.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
20396
- idempotencyKey: z73.string().uuid().optional().describe("Opcional. UUID para reintentar exactamente esta misma solicitud sin crear ni cobrar otro video. Reutiliza el mismo valor si el cliente no recibi\xF3 la respuesta.")
20512
+ generateAiMusic: z74.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
20513
+ addSubtitles: z74.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
20514
+ idempotencyKey: z74.string().uuid().optional().describe("Opcional. UUID para reintentar exactamente esta misma solicitud sin crear ni cobrar otro video. Reutiliza el mismo valor si el cliente no recibi\xF3 la respuesta.")
20397
20515
  }).strict();
20398
20516
  var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
20399
- var ImageCreativeSetup = z73.discriminatedUnion("mode", [
20400
- z73.object({
20401
- mode: z73.literal("automatic")
20517
+ var ImageCreativeSetup = z74.discriminatedUnion("mode", [
20518
+ z74.object({
20519
+ mode: z74.literal("automatic")
20402
20520
  }).strict(),
20403
- z73.object({
20404
- mode: z73.literal("guided"),
20405
- creativeArchetype: z73.union([
20521
+ z74.object({
20522
+ mode: z74.literal("guided"),
20523
+ creativeArchetype: z74.union([
20406
20524
  ImageCreativeArchetypeEnum,
20407
- z73.literal("ai_decides")
20525
+ z74.literal("ai_decides")
20408
20526
  ]),
20409
- visualTreatment: z73.union([
20527
+ visualTreatment: z74.union([
20410
20528
  ImageCreativeVisualTreatmentEnum,
20411
- z73.literal("ai_decides")
20529
+ z74.literal("ai_decides")
20412
20530
  ]),
20413
20531
  aspectRatio: ImageCreativeAspectRatioEnum,
20414
- nVariants: z73.union([
20415
- z73.literal(1),
20416
- z73.literal(2),
20417
- z73.literal(3),
20418
- z73.literal(4),
20419
- z73.literal(6)
20532
+ nVariants: z74.union([
20533
+ z74.literal(1),
20534
+ z74.literal(2),
20535
+ z74.literal(3),
20536
+ z74.literal(4),
20537
+ z74.literal(6)
20420
20538
  ]),
20421
- imageModel: z73.enum([
20539
+ imageModel: z74.enum([
20422
20540
  "gpt-image-2-5:1k",
20423
20541
  "gpt-image-2-5:2k",
20424
20542
  "gpt-image-2:1k",
20425
20543
  "gpt-image-2:2k"
20426
20544
  ]),
20427
- styleMix: z73.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
20428
- generateAdCopy: z73.boolean(),
20429
- competitorScanEnabled: z73.boolean(),
20430
- productContext: z73.string().trim().min(1).max(3e3).nullable(),
20431
- creativeDirection: z73.string().trim().min(1).max(500).nullable(),
20432
- brandColors: z73.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.'),
20433
- headline: z73.string().trim().min(1).max(120).nullable(),
20434
- subheadline: z73.string().trim().min(1).max(160).nullable()
20545
+ styleMix: z74.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
20546
+ generateAdCopy: z74.boolean(),
20547
+ competitorScanEnabled: z74.boolean(),
20548
+ productContext: z74.string().trim().min(1).max(3e3).nullable(),
20549
+ creativeDirection: z74.string().trim().min(1).max(500).nullable(),
20550
+ brandColors: z74.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.'),
20551
+ headline: z74.string().trim().min(1).max(120).nullable(),
20552
+ subheadline: z74.string().trim().min(1).max(160).nullable()
20435
20553
  }).strict()
20436
20554
  ]).superRefine((setup, context) => {
20437
20555
  if (setup.mode !== "guided") return;
20438
20556
  const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
20439
20557
  if (needsStyleMix && setup.styleMix === null) {
20440
20558
  context.addIssue({
20441
- code: z73.ZodIssueCode.custom,
20559
+ code: z74.ZodIssueCode.custom,
20442
20560
  path: [
20443
20561
  "styleMix"
20444
20562
  ],
@@ -20447,7 +20565,7 @@ var ImageCreativeSetup = z73.discriminatedUnion("mode", [
20447
20565
  }
20448
20566
  if (!needsStyleMix && setup.styleMix !== null) {
20449
20567
  context.addIssue({
20450
- code: z73.ZodIssueCode.custom,
20568
+ code: z74.ZodIssueCode.custom,
20451
20569
  path: [
20452
20570
  "styleMix"
20453
20571
  ],
@@ -20456,7 +20574,7 @@ var ImageCreativeSetup = z73.discriminatedUnion("mode", [
20456
20574
  }
20457
20575
  if ((setup.imageModel === "gpt-image-2:2k" || setup.imageModel === "gpt-image-2-5:2k") && setup.aspectRatio === "4:5") {
20458
20576
  context.addIssue({
20459
- code: z73.ZodIssueCode.custom,
20577
+ code: z74.ZodIssueCode.custom,
20460
20578
  path: [
20461
20579
  "aspectRatio"
20462
20580
  ],
@@ -20464,53 +20582,53 @@ var ImageCreativeSetup = z73.discriminatedUnion("mode", [
20464
20582
  });
20465
20583
  }
20466
20584
  });
20467
- var LandingCreativeSetup = z73.discriminatedUnion("mode", [
20468
- z73.object({
20469
- mode: z73.literal("automatic")
20585
+ var LandingCreativeSetup = z74.discriminatedUnion("mode", [
20586
+ z74.object({
20587
+ mode: z74.literal("automatic")
20470
20588
  }).strict(),
20471
- z73.object({
20472
- mode: z73.literal("guided"),
20589
+ z74.object({
20590
+ mode: z74.literal("guided"),
20473
20591
  landingStrategy: LandingStrategyEnum,
20474
20592
  landingImageFormat: LandingImageFormatEnum,
20475
- competitorScanEnabled: z73.boolean(),
20476
- paymentMethods: z73.string().trim().min(1).max(240).nullable(),
20477
- productContext: z73.string().trim().min(1).max(3e3).nullable(),
20478
- creativeDirection: z73.string().trim().min(1).max(500).nullable(),
20479
- headline: z73.string().trim().min(1).max(120).nullable(),
20480
- subheadline: z73.string().trim().min(1).max(160).nullable()
20593
+ competitorScanEnabled: z74.boolean(),
20594
+ paymentMethods: z74.string().trim().min(1).max(240).nullable(),
20595
+ productContext: z74.string().trim().min(1).max(3e3).nullable(),
20596
+ creativeDirection: z74.string().trim().min(1).max(500).nullable(),
20597
+ headline: z74.string().trim().min(1).max(120).nullable(),
20598
+ subheadline: z74.string().trim().min(1).max(160).nullable()
20481
20599
  }).strict()
20482
20600
  ]);
20483
- var ImageInput = z73.object({
20601
+ var ImageInput = z74.object({
20484
20602
  images: CreativeRefs.images.optional(),
20485
20603
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
20486
- productTitle: z73.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
20487
- primaryAngle: z73.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.'),
20604
+ productTitle: z74.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
20605
+ primaryAngle: z74.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.'),
20488
20606
  buyerPersona: CreativeRefs.buyerPersona,
20489
20607
  language: CreativeRefs.language,
20490
20608
  country: CreativeRefs.country,
20491
20609
  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."),
20492
20610
  imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
20493
- features: z73.array(z73.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
20611
+ features: z74.array(z74.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
20494
20612
  price: CreativeRefs.price,
20495
- omitPrice: z73.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."),
20613
+ omitPrice: z74.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."),
20496
20614
  compareAtPrice: CreativeRefs.compareAtPrice,
20497
20615
  offer: CreativeRefs.offer,
20498
20616
  productLabel: CreativeRefs.productLabel,
20499
20617
  isCombo: CreativeRefs.isCombo,
20500
20618
  brandId: CreativeRefs.brandId
20501
20619
  });
20502
- var EditImageCreativeInput = z73.object({
20503
- taskId: z73.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
20504
- variantIndex: z73.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
20505
- instruction: z73.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".')
20620
+ var EditImageCreativeInput = z74.object({
20621
+ taskId: z74.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
20622
+ variantIndex: z74.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
20623
+ instruction: z74.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".')
20506
20624
  });
20507
- var LandingInput = z73.object({
20625
+ var LandingInput = z74.object({
20508
20626
  images: CreativeRefs.images.optional(),
20509
20627
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
20510
20628
  language: CreativeRefs.language,
20511
20629
  country: CreativeRefs.country,
20512
20630
  creativeSetup: LandingCreativeSetup.describe("Configuraci\xF3n obligatoria de landing cl\xE1sica equivalente al wizard web. No expone landing editable/code mientras siga siendo admin-only."),
20513
- salesAngle: z73.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.'),
20631
+ salesAngle: z74.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.'),
20514
20632
  buyerPersona: CreativeRefs.buyerPersona,
20515
20633
  price: CreativeRefs.price,
20516
20634
  compareAtPrice: CreativeRefs.compareAtPrice,
@@ -20772,10 +20890,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
20772
20890
  __name(registerCreativeTools, "registerCreativeTools");
20773
20891
 
20774
20892
  // src/tools/creative-variants.ts
20775
- import { z as z74 } from "zod";
20893
+ import { z as z75 } from "zod";
20776
20894
  var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
20777
20895
  var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
20778
- var LandingSectionKeyEnum = z74.enum([
20896
+ var LandingSectionKeyEnum = z75.enum([
20779
20897
  "problem_hook",
20780
20898
  "problem_cost",
20781
20899
  "solution_mechanism",
@@ -20815,24 +20933,24 @@ var LandingSectionKeyEnum = z74.enum([
20815
20933
  "lifestyle_fit",
20816
20934
  "join_lifestyle"
20817
20935
  ]);
20818
- var CreativeVariantKindEnum = z74.enum([
20936
+ var CreativeVariantKindEnum = z75.enum([
20819
20937
  "video",
20820
20938
  "image",
20821
20939
  "landing"
20822
20940
  ]);
20823
- var EstimateCreativeVariantInputBase = z74.object({
20824
- sourceTaskId: z74.string().uuid().describe("ID de la tarea original completada."),
20941
+ var EstimateCreativeVariantInputBase = z75.object({
20942
+ sourceTaskId: z75.string().uuid().describe("ID de la tarea original completada."),
20825
20943
  kind: CreativeVariantKindEnum,
20826
20944
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
20827
20945
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
20828
- nVariants: z74.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
20946
+ nVariants: z75.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
20829
20947
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
20830
- instructions: z74.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.")
20948
+ instructions: z75.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.")
20831
20949
  }).strict();
20832
20950
  var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
20833
20951
  if (input.kind === "video" && input.nVariants !== void 0) {
20834
20952
  ctx.addIssue({
20835
- code: z74.ZodIssueCode.custom,
20953
+ code: z75.ZodIssueCode.custom,
20836
20954
  path: [
20837
20955
  "nVariants"
20838
20956
  ],
@@ -20842,7 +20960,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
20842
20960
  if (input.kind !== "video") {
20843
20961
  if (input.videoPreset !== void 0) {
20844
20962
  ctx.addIssue({
20845
- code: z74.ZodIssueCode.custom,
20963
+ code: z75.ZodIssueCode.custom,
20846
20964
  path: [
20847
20965
  "videoPreset"
20848
20966
  ],
@@ -20851,7 +20969,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
20851
20969
  }
20852
20970
  if (input.videoResolution !== void 0) {
20853
20971
  ctx.addIssue({
20854
- code: z74.ZodIssueCode.custom,
20972
+ code: z75.ZodIssueCode.custom,
20855
20973
  path: [
20856
20974
  "videoResolution"
20857
20975
  ],
@@ -20861,7 +20979,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
20861
20979
  }
20862
20980
  if (input.kind !== "image" && input.nVariants !== void 0) {
20863
20981
  ctx.addIssue({
20864
- code: z74.ZodIssueCode.custom,
20982
+ code: z75.ZodIssueCode.custom,
20865
20983
  path: [
20866
20984
  "nVariants"
20867
20985
  ],
@@ -20871,7 +20989,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
20871
20989
  if (input.kind !== "landing") {
20872
20990
  if (input.sectionKey !== void 0) {
20873
20991
  ctx.addIssue({
20874
- code: z74.ZodIssueCode.custom,
20992
+ code: z75.ZodIssueCode.custom,
20875
20993
  path: [
20876
20994
  "sectionKey"
20877
20995
  ],
@@ -20880,7 +20998,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
20880
20998
  }
20881
20999
  if (input.instructions !== void 0) {
20882
21000
  ctx.addIssue({
20883
- code: z74.ZodIssueCode.custom,
21001
+ code: z75.ZodIssueCode.custom,
20884
21002
  path: [
20885
21003
  "instructions"
20886
21004
  ],
@@ -20889,31 +21007,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
20889
21007
  }
20890
21008
  }
20891
21009
  });
20892
- var CreateCreativeVariantInputBase = z74.object({
20893
- sourceTaskId: z74.string().uuid().describe("ID de la tarea original completada."),
21010
+ var CreateCreativeVariantInputBase = z75.object({
21011
+ sourceTaskId: z75.string().uuid().describe("ID de la tarea original completada."),
20894
21012
  kind: CreativeVariantKindEnum,
20895
- confirm: z74.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
20896
- clientRequestId: z74.string().uuid().describe("UUID estable y obligatorio para esta intenci\xF3n. Reutil\xEDzalo ante timeouts o transporte ambiguo. Si la API devuelve status=error, una nueva generaci\xF3n exige otra confirmaci\xF3n y un UUID nuevo."),
20897
- angle: z74.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
20898
- buyerPersona: z74.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
20899
- scriptNotes: z74.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
20900
- creativeDirection: z74.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
21013
+ confirm: z75.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
21014
+ clientRequestId: z75.string().uuid().describe("UUID estable y obligatorio para esta intenci\xF3n. Reutil\xEDzalo ante timeouts o transporte ambiguo. Si la API devuelve status=error, una nueva generaci\xF3n exige otra confirmaci\xF3n y un UUID nuevo."),
21015
+ angle: z75.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
21016
+ buyerPersona: z75.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
21017
+ scriptNotes: z75.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
21018
+ creativeDirection: z75.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
20901
21019
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
20902
21020
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
20903
- generateAiMusic: z74.boolean().optional().describe("Opcional para video."),
20904
- nVariants: z74.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
21021
+ generateAiMusic: z75.boolean().optional().describe("Opcional para video."),
21022
+ nVariants: z75.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
20905
21023
  imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
20906
21024
  creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
20907
21025
  visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
20908
21026
  aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
20909
- styleMix: z74.boolean().optional().describe("Opcional para imagen."),
21027
+ styleMix: z75.boolean().optional().describe("Opcional para imagen."),
20910
21028
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
20911
- instructions: z74.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.")
21029
+ instructions: z75.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.")
20912
21030
  }).strict();
20913
21031
  var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
20914
21032
  if ((input.kind === "video" || input.kind === "image") && !input.angle) {
20915
21033
  ctx.addIssue({
20916
- code: z74.ZodIssueCode.custom,
21034
+ code: z75.ZodIssueCode.custom,
20917
21035
  path: [
20918
21036
  "angle"
20919
21037
  ],
@@ -20922,7 +21040,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
20922
21040
  }
20923
21041
  if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
20924
21042
  ctx.addIssue({
20925
- code: z74.ZodIssueCode.custom,
21043
+ code: z75.ZodIssueCode.custom,
20926
21044
  path: [
20927
21045
  "instructions"
20928
21046
  ],
@@ -20968,7 +21086,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
20968
21086
  for (const field of fieldsByKind[input.kind]) {
20969
21087
  if (input[field] !== void 0) {
20970
21088
  ctx.addIssue({
20971
- code: z74.ZodIssueCode.custom,
21089
+ code: z75.ZodIssueCode.custom,
20972
21090
  path: [
20973
21091
  field
20974
21092
  ],
@@ -21085,32 +21203,32 @@ function registerCreativeVariantTools(server, api) {
21085
21203
  __name(registerCreativeVariantTools, "registerCreativeVariantTools");
21086
21204
 
21087
21205
  // src/tools/script-review.ts
21088
- import { z as z75 } from "zod";
21206
+ import { z as z76 } from "zod";
21089
21207
  var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
21090
21208
  var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
21091
21209
  var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
21092
- var GetVideoScriptInput = z75.object({
21093
- taskId: z75.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
21094
- angleKey: z75.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.')
21210
+ var GetVideoScriptInput = z76.object({
21211
+ taskId: z76.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
21212
+ angleKey: z76.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.')
21095
21213
  }).strict();
21096
21214
  var VIDEO_SCRIPT_APPROVAL_MAX_SCENES2 = 50;
21097
21215
  var VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2 = 2e3;
21098
- var ApproveSceneEdit = z75.object({
21099
- index: z75.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
21100
- dialogue: z75.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
21216
+ var ApproveSceneEdit = z76.object({
21217
+ index: z76.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
21218
+ dialogue: z76.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
21101
21219
  message: "dialogue no puede ser s\xF3lo espacios"
21102
21220
  }).describe("Di\xE1logo final de la escena. NO puede estar vac\xEDo ni ser s\xF3lo espacios. Puede ser el original sin cambios o la edici\xF3n del usuario.")
21103
21221
  }).strict();
21104
- var ApproveVideoScriptInput = z75.object({
21105
- taskId: z75.string().min(1).describe("ID de la tarea."),
21106
- angleKey: z75.string().trim().min(1).max(120).optional().describe('Mismo angleKey usado en get_video_script. REQUERIDO en multi-angle (si se omite el backend resuelve a "angle_0" literal). En single-angle puede omitirse.'),
21107
- scenes: z75.array(ApproveSceneEdit).min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_SCENES2).describe("Escenas con los di\xE1logos finales. El backend mergea por `index` \u2014 las escenas NO incluidas conservan el di\xE1logo original. Debe haber entre 1 y 50 entradas. Para cada entrada que mandes con un dialogue distinto del original, el backend valida minWords \u2264 words \u2264 maxWords y rechaza con 400 si te sales del rango.")
21222
+ var ApproveVideoScriptInput = z76.object({
21223
+ taskId: z76.string().min(1).describe("ID de la tarea."),
21224
+ angleKey: z76.string().trim().min(1).max(120).optional().describe('Mismo angleKey usado en get_video_script. REQUERIDO en multi-angle (si se omite el backend resuelve a "angle_0" literal). En single-angle puede omitirse.'),
21225
+ scenes: z76.array(ApproveSceneEdit).min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_SCENES2).describe("Escenas con los di\xE1logos finales. El backend mergea por `index` \u2014 las escenas NO incluidas conservan el di\xE1logo original. Debe haber entre 1 y 50 entradas. Para cada entrada que mandes con un dialogue distinto del original, el backend valida minWords \u2264 words \u2264 maxWords y rechaza con 400 si te sales del rango.")
21108
21226
  }).strict();
21109
- var RegenerateVideoScriptInput = z75.object({
21110
- taskId: z75.string().min(1).describe("ID de la tarea."),
21111
- angleKey: z75.string().min(1).describe('Clave del \xE1ngulo a regenerar. Single-angle: pasa "angle_0". Multi-angle: el mismo que devuelve get_video_script. NO se puede omitir \u2014 el backend lo exige siempre.'),
21227
+ var RegenerateVideoScriptInput = z76.object({
21228
+ taskId: z76.string().min(1).describe("ID de la tarea."),
21229
+ angleKey: z76.string().min(1).describe('Clave del \xE1ngulo a regenerar. Single-angle: pasa "angle_0". Multi-angle: el mismo que devuelve get_video_script. NO se puede omitir \u2014 el backend lo exige siempre.'),
21112
21230
  narrativeStyle: NarrativeStyleEnum.describe('Narrativa para el nuevo guion. Incluye valores hist\xF3ricos porque esta herramienta tambi\xE9n regenera tareas antiguas. REQUERIDO \u2014 el backend NO acepta "mantener la actual"; siempre tienes que elegir una. Si el usuario quiere re-rolear con la misma narrativa, pasa la que ya tiene el \xE1ngulo (la ves en get_video_script o en get_task_status).'),
21113
- narrativeSelection: z75.enum([
21231
+ narrativeSelection: z76.enum([
21114
21232
  "market",
21115
21233
  "guided"
21116
21234
  ]).optional().describe("Elecci\xF3n expl\xEDcita del usuario: market usa el estudio de mercado disponible; guided usa la narrativa elegida. Omitir conserva el comportamiento existente.")
@@ -21191,14 +21309,14 @@ function registerScriptReviewTools(server, api) {
21191
21309
  __name(registerScriptReviewTools, "registerScriptReviewTools");
21192
21310
 
21193
21311
  // src/tools/connections.ts
21194
- import { z as z76 } from "zod";
21312
+ import { z as z77 } from "zod";
21195
21313
  var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
21196
21314
  var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
21197
21315
  var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
21198
21316
  var listMetaDestinationsGuidance = getProductMakerCapabilityModelGuidance("list_meta_destinations");
21199
21317
  var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list_tiktok_advertisers");
21200
21318
  function registerConnectionTools(server, api) {
21201
- server.tool("list_shopify_shops", listShopifyShopsGuidance.summary + " Si la lista est\xE1 vac\xEDa, dile al usuario que conecte una tienda en productmaker.app/integrations antes de intentar publicar.", z76.object({}).shape, READS_INTERNAL, async () => {
21319
+ server.tool("list_shopify_shops", listShopifyShopsGuidance.summary + " Si la lista est\xE1 vac\xEDa, dile al usuario que conecte una tienda en productmaker.app/integrations antes de intentar publicar.", z77.object({}).shape, READS_INTERNAL, async () => {
21202
21320
  try {
21203
21321
  const r = await api.getJson("/v1/shopify/shops");
21204
21322
  return asText(r);
@@ -21206,10 +21324,10 @@ function registerConnectionTools(server, api) {
21206
21324
  throw translateError(e);
21207
21325
  }
21208
21326
  });
21209
- server.tool("list_shopify_products", 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.', z76.object({
21210
- shopDomain: z76.string().min(3).max(120),
21211
- query: z76.string().trim().max(120).optional(),
21212
- taskId: z76.string().uuid().optional()
21327
+ server.tool("list_shopify_products", 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.', z77.object({
21328
+ shopDomain: z77.string().min(3).max(120),
21329
+ query: z77.string().trim().max(120).optional(),
21330
+ taskId: z77.string().uuid().optional()
21213
21331
  }).shape, READS_EXTERNAL, async ({ shopDomain, query, taskId }) => {
21214
21332
  try {
21215
21333
  const params = new URLSearchParams({
@@ -21223,7 +21341,7 @@ function registerConnectionTools(server, api) {
21223
21341
  throw translateError(e);
21224
21342
  }
21225
21343
  });
21226
- server.tool("list_meta_ad_accounts", 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.", z76.object({}).shape, READS_EXTERNAL, async () => {
21344
+ server.tool("list_meta_ad_accounts", 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.", z77.object({}).shape, READS_EXTERNAL, async () => {
21227
21345
  try {
21228
21346
  const r = await api.getJson("/v1/facebook/ad-accounts");
21229
21347
  return asText(r);
@@ -21233,7 +21351,7 @@ function registerConnectionTools(server, api) {
21233
21351
  });
21234
21352
  server.registerTool("list_meta_destinations", {
21235
21353
  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.",
21236
- inputSchema: z76.object({}).shape,
21354
+ inputSchema: z77.object({}).shape,
21237
21355
  annotations: READS_EXTERNAL,
21238
21356
  _meta: {
21239
21357
  "openai/widgetAccessible": true
@@ -21246,7 +21364,7 @@ function registerConnectionTools(server, api) {
21246
21364
  throw translateError(e);
21247
21365
  }
21248
21366
  });
21249
- server.tool("list_tiktok_advertisers", listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.", z76.object({}).shape, READS_EXTERNAL, async () => {
21367
+ server.tool("list_tiktok_advertisers", listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.", z77.object({}).shape, READS_EXTERNAL, async () => {
21250
21368
  try {
21251
21369
  const r = await api.getJson("/v1/tiktok/advertisers");
21252
21370
  return asText(r);
@@ -21258,10 +21376,10 @@ function registerConnectionTools(server, api) {
21258
21376
  __name(registerConnectionTools, "registerConnectionTools");
21259
21377
 
21260
21378
  // src/tools/actors.ts
21261
- import { z as z77 } from "zod";
21379
+ import { z as z78 } from "zod";
21262
21380
  var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
21263
21381
  function registerActorTools(server, api) {
21264
- server.tool("list_actors", listActorsGuidance.summary + " Devuelve id, nombre, descripci\xF3n, g\xE9nero y voz. Usa el `id` como `actorId` al crear o editar una tarea. Solo aparecen los personajes listos para usar; si la lista est\xE1 vac\xEDa, dile al usuario que cree uno en productmaker.app antes de intentar asignarlo. No modifica nada.", z77.object({}).shape, READS_INTERNAL, async () => {
21382
+ server.tool("list_actors", listActorsGuidance.summary + " Devuelve id, nombre, descripci\xF3n, g\xE9nero y voz. Usa el `id` como `actorId` al crear o editar una tarea. Solo aparecen los personajes listos para usar; si la lista est\xE1 vac\xEDa, dile al usuario que cree uno en productmaker.app antes de intentar asignarlo. No modifica nada.", z78.object({}).shape, READS_INTERNAL, async () => {
21265
21383
  try {
21266
21384
  const rows = await api.getJson("/v1/actors");
21267
21385
  const actors = (Array.isArray(rows) ? rows : []).filter((actor) => actor.status === "ready").map(({ id, name, description, gender, voiceId }) => ({
@@ -21282,7 +21400,7 @@ function registerActorTools(server, api) {
21282
21400
  __name(registerActorTools, "registerActorTools");
21283
21401
 
21284
21402
  // src/tools/publish.ts
21285
- import { z as z78 } from "zod";
21403
+ import { z as z79 } from "zod";
21286
21404
 
21287
21405
  // src/tools/stable-uuid.ts
21288
21406
  import { createHash as createHash3 } from "crypto";
@@ -21354,40 +21472,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
21354
21472
  var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
21355
21473
  var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
21356
21474
  var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
21357
- var ShopifyInput = z78.object({
21358
- taskId: z78.string().min(1),
21359
- shopDomain: z78.string().min(1),
21475
+ var ShopifyInput = z79.object({
21476
+ taskId: z79.string().min(1),
21477
+ shopDomain: z79.string().min(1),
21360
21478
  /** Override: number of landing images to include. Default = ALL images the
21361
21479
  * task generated (the MCP fetches /v1/results first to count). Bounded
21362
21480
  * generously here; the backend validates each index against
21363
21481
  * landing.images.length and rejects out-of-range. */
21364
- numLandingImages: z78.number().int().min(1).max(20).optional(),
21365
- variantIndex: z78.number().int().min(0).optional(),
21482
+ numLandingImages: z79.number().int().min(1).max(20).optional(),
21483
+ variantIndex: z79.number().int().min(0).optional(),
21366
21484
  /** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
21367
21485
  * When true, the landing renders variant-picker pills; when false, it ships
21368
21486
  * a single-option product page. Defaults to false. */
21369
- showVariantPicker: z78.boolean().optional(),
21487
+ showVariantPicker: z79.boolean().optional(),
21370
21488
  /** Default `auto` updates the product previously published for this task and
21371
21489
  * shop. Use `existing` with targetProductId to choose another product, or
21372
21490
  * `new` only when the user explicitly wants a duplicate/new listing. */
21373
- publicationMode: z78.enum([
21491
+ publicationMode: z79.enum([
21374
21492
  "auto",
21375
21493
  "existing",
21376
21494
  "new"
21377
21495
  ]).optional(),
21378
21496
  /** Shopify product GID, numeric id, or admin product URL. Required when
21379
21497
  * publicationMode is `existing`. */
21380
- targetProductId: z78.string().trim().min(1).max(300).optional(),
21498
+ targetProductId: z79.string().trim().min(1).max(300).optional(),
21381
21499
  /** Add an announcement bar text above add-to-cart (optional). */
21382
- announcementBarEnabled: z78.boolean().optional(),
21383
- announcementBarText: z78.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
21500
+ announcementBarEnabled: z79.boolean().optional(),
21501
+ announcementBarText: z79.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
21384
21502
  commerceCorrection: PublishCommerceCorrectionSchema.optional().describe("Complete seller-confirmed commerce values, with the revision and fingerprint returned in recovery. Never invent missing prices or convert currency."),
21385
- confirmed: z78.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
21503
+ confirmed: z79.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
21386
21504
  });
21387
21505
  var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
21388
21506
  if (value.commerceCorrection && value.confirmed !== true) {
21389
21507
  ctx.addIssue({
21390
- code: z78.ZodIssueCode.custom,
21508
+ code: z79.ZodIssueCode.custom,
21391
21509
  path: [
21392
21510
  "confirmed"
21393
21511
  ],
@@ -21396,7 +21514,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
21396
21514
  }
21397
21515
  if (value.announcementBarEnabled && !value.announcementBarText) {
21398
21516
  ctx.addIssue({
21399
- code: z78.ZodIssueCode.custom,
21517
+ code: z79.ZodIssueCode.custom,
21400
21518
  path: [
21401
21519
  "announcementBarText"
21402
21520
  ],
@@ -21405,7 +21523,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
21405
21523
  }
21406
21524
  if (!value.announcementBarEnabled && value.announcementBarText) {
21407
21525
  ctx.addIssue({
21408
- code: z78.ZodIssueCode.custom,
21526
+ code: z79.ZodIssueCode.custom,
21409
21527
  path: [
21410
21528
  "announcementBarText"
21411
21529
  ],
@@ -21419,91 +21537,91 @@ function parseShopifyInput(rawInput) {
21419
21537
  return parsed.data;
21420
21538
  }
21421
21539
  __name(parseShopifyInput, "parseShopifyInput");
21422
- var McpCampaignConfig = z78.object({
21540
+ var McpCampaignConfig = z79.object({
21423
21541
  /** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
21424
21542
  * converts to the account currency server-side. Do NOT pre-convert: on a COP
21425
21543
  * account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
21426
- dailyBudgetUsd: z78.number().positive().optional(),
21544
+ dailyBudgetUsd: z79.number().positive().optional(),
21427
21545
  /** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
21428
21546
  * normalizes at validation). Meta accepts max 1 (single-country ad set).
21429
21547
  * TikTok takes only the first entry. */
21430
- targetCountries: z78.array(CountryIso2Schema).max(1).optional(),
21431
- campaignName: z78.string().trim().min(1).max(100).optional()
21548
+ targetCountries: z79.array(CountryIso2Schema).max(1).optional(),
21549
+ campaignName: z79.string().trim().min(1).max(100).optional()
21432
21550
  });
21433
21551
  var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
21434
- var MetaInput = z78.object({
21435
- taskId: z78.string().min(1),
21552
+ var MetaInput = z79.object({
21553
+ taskId: z79.string().min(1),
21436
21554
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
21437
- portfolioId: z78.string().trim().min(1),
21555
+ portfolioId: z79.string().trim().min(1),
21438
21556
  /** Exact Facebook Page selected from `list_meta_destinations`. */
21439
- pageId: z78.string().trim().min(1),
21557
+ pageId: z79.string().trim().min(1),
21440
21558
  adAccountId: McpAdAccountId,
21441
- pixelId: z78.string().min(1).optional(),
21442
- landingUrl: z78.string().url().optional(),
21559
+ pixelId: z79.string().min(1).optional(),
21560
+ landingUrl: z79.string().url().optional(),
21443
21561
  /** Select which angles to publish by 0-based index. Omit to publish all
21444
21562
  * successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
21445
- angleIndexes: z78.array(z78.number().int().nonnegative()).optional(),
21563
+ angleIndexes: z79.array(z79.number().int().nonnegative()).optional(),
21446
21564
  campaignConfig: McpCampaignConfig.optional(),
21447
21565
  /** Override the ad's primary text (body copy). If omitted, ProductMaker
21448
21566
  * uses the auto-generated copy attached to the task. Capped at 500 chars
21449
21567
  * (Meta's primary-text limit). */
21450
- primaryText: z78.string().trim().min(1).max(500).optional(),
21568
+ primaryText: z79.string().trim().min(1).max(500).optional(),
21451
21569
  /** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
21452
21570
  * (wa.me) instead of a landing page. */
21453
- phoneNumber: z78.string().min(8).max(32).optional()
21571
+ phoneNumber: z79.string().min(8).max(32).optional()
21454
21572
  });
21455
- var GroupedTaskSource = z78.object({
21456
- type: z78.literal("task"),
21457
- taskId: z78.string().min(1),
21458
- angleIndex: z78.number().int().min(0).optional(),
21459
- videoVariant: z78.enum([
21573
+ var GroupedTaskSource = z79.object({
21574
+ type: z79.literal("task"),
21575
+ taskId: z79.string().min(1),
21576
+ angleIndex: z79.number().int().min(0).optional(),
21577
+ videoVariant: z79.enum([
21460
21578
  "with_subtitles",
21461
21579
  "without_subtitles"
21462
21580
  ]).optional(),
21463
- imageVariantIndex: z78.number().int().min(0).optional()
21464
- });
21465
- var GroupedMediaSource = z78.object({
21466
- type: z78.literal("media"),
21467
- url: z78.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
21468
- path: z78.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".'),
21469
- thumbnailUrl: z78.string().url().optional(),
21470
- thumbnailPath: z78.string().min(1).optional()
21581
+ imageVariantIndex: z79.number().int().min(0).optional()
21582
+ });
21583
+ var GroupedMediaSource = z79.object({
21584
+ type: z79.literal("media"),
21585
+ url: z79.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
21586
+ path: z79.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".'),
21587
+ thumbnailUrl: z79.string().url().optional(),
21588
+ thumbnailPath: z79.string().min(1).optional()
21471
21589
  }).refine((value) => Boolean(value.url) !== Boolean(value.path), {
21472
21590
  message: "media source needs exactly one of `url` or `path`"
21473
21591
  }).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
21474
21592
  message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
21475
21593
  });
21476
- var GroupedUploadedAssetSource = z78.object({
21477
- type: z78.literal("asset"),
21594
+ var GroupedUploadedAssetSource = z79.object({
21595
+ type: z79.literal("asset"),
21478
21596
  /** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
21479
- assetId: z78.string().uuid(),
21480
- thumbnailAssetId: z78.string().uuid().optional()
21597
+ assetId: z79.string().uuid(),
21598
+ thumbnailAssetId: z79.string().uuid().optional()
21481
21599
  });
21482
- var GroupedCreative = z78.object({
21483
- type: z78.enum([
21600
+ var GroupedCreative = z79.object({
21601
+ type: z79.enum([
21484
21602
  "image",
21485
21603
  "video"
21486
21604
  ]),
21487
- source: z78.union([
21605
+ source: z79.union([
21488
21606
  GroupedTaskSource,
21489
21607
  GroupedMediaSource,
21490
21608
  GroupedUploadedAssetSource
21491
21609
  ]),
21492
- title: z78.string().max(120).optional(),
21493
- description: z78.string().max(500).optional(),
21610
+ title: z79.string().max(120).optional(),
21611
+ description: z79.string().max(500).optional(),
21494
21612
  cta: MetaCtaType.optional(),
21495
- creativeId: z78.string().min(1).optional()
21613
+ creativeId: z79.string().min(1).optional()
21496
21614
  });
21497
- var GroupedCampaignConfigBase = z78.object({
21615
+ var GroupedCampaignConfigBase = z79.object({
21498
21616
  campaignType: MetaCampaignType.default("sales"),
21499
21617
  optimizationMode: MetaOptimizationMode.default("advantage_plus"),
21500
21618
  budgetMode: MetaBudgetMode.optional(),
21501
- campaignDailyBudget: z78.number().int().positive().optional(),
21502
- adSets: z78.array(z78.object({
21503
- tempId: z78.string().min(1).max(80),
21504
- name: z78.string().min(1).max(100),
21505
- dailyBudget: z78.number().int().positive().optional(),
21506
- creativeIds: z78.array(z78.string().min(1)).min(1)
21619
+ campaignDailyBudget: z79.number().int().positive().optional(),
21620
+ adSets: z79.array(z79.object({
21621
+ tempId: z79.string().min(1).max(80),
21622
+ name: z79.string().min(1).max(100),
21623
+ dailyBudget: z79.number().int().positive().optional(),
21624
+ creativeIds: z79.array(z79.string().min(1)).min(1)
21507
21625
  })).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
21508
21626
  /**
21509
21627
  * Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
@@ -21511,17 +21629,17 @@ var GroupedCampaignConfigBase = z78.object({
21511
21629
  * opaque `invalid_literal` and made the WhatsApp destination — supported by
21512
21630
  * the API since #849 — unreachable from this tool.
21513
21631
  */
21514
- destination: z78.discriminatedUnion("type", [
21515
- z78.object({
21516
- type: z78.literal("landing"),
21517
- landingUrl: z78.string().url()
21632
+ destination: z79.discriminatedUnion("type", [
21633
+ z79.object({
21634
+ type: z79.literal("landing"),
21635
+ landingUrl: z79.string().url()
21518
21636
  }),
21519
- z78.object({
21520
- type: z78.literal("whatsapp"),
21521
- phoneNumber: z78.string().min(8).max(32)
21637
+ z79.object({
21638
+ type: z79.literal("whatsapp"),
21639
+ phoneNumber: z79.string().min(8).max(32)
21522
21640
  })
21523
21641
  ]),
21524
- saveAsDefault: z78.boolean().default(false),
21642
+ saveAsDefault: z79.boolean().default(false),
21525
21643
  budgetPolicy: MetaBudgetPolicy.optional()
21526
21644
  });
21527
21645
  function resolveBudgetMode(value) {
@@ -21535,7 +21653,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
21535
21653
  const budgetMode = resolveBudgetMode(value);
21536
21654
  if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
21537
21655
  ctx.addIssue({
21538
- code: z78.ZodIssueCode.custom,
21656
+ code: z79.ZodIssueCode.custom,
21539
21657
  path: [
21540
21658
  "campaignDailyBudget"
21541
21659
  ],
@@ -21546,7 +21664,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
21546
21664
  value.adSets.forEach((adSet, index) => {
21547
21665
  if (adSet.dailyBudget === void 0) {
21548
21666
  ctx.addIssue({
21549
- code: z78.ZodIssueCode.custom,
21667
+ code: z79.ZodIssueCode.custom,
21550
21668
  path: [
21551
21669
  "adSets",
21552
21670
  index,
@@ -21561,28 +21679,28 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
21561
21679
  ...value,
21562
21680
  budgetMode: resolveBudgetMode(value)
21563
21681
  }));
21564
- var PublishCreativesToMetaInputBase = z78.object({
21565
- creatives: z78.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
21682
+ var PublishCreativesToMetaInputBase = z79.object({
21683
+ creatives: z79.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
21566
21684
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
21567
- portfolioId: z78.string().trim().min(1),
21685
+ portfolioId: z79.string().trim().min(1),
21568
21686
  /** Exact Facebook Page selected from `list_meta_destinations`. */
21569
- pageId: z78.string().trim().min(1),
21687
+ pageId: z79.string().trim().min(1),
21570
21688
  adAccountId: McpAdAccountId,
21571
- pixelId: z78.string().min(1).optional(),
21689
+ pixelId: z79.string().min(1).optional(),
21572
21690
  /** Required unless `campaignConfig.destination` is whatsapp — see the
21573
21691
  * superRefine below. Mirrors the API's `FacebookCreateCampaignFromTasksBodySchema`. */
21574
- landingUrl: z78.string().url().optional(),
21692
+ landingUrl: z79.string().url().optional(),
21575
21693
  /** ISO-2 code or resolvable country name — mirrors the API contract
21576
21694
  * (CountryIso2Schema), which normalizes names to alpha-2 at validation. */
21577
21695
  targetCountry: CountryIso2Schema,
21578
- campaignName: z78.string().trim().min(1).max(100),
21696
+ campaignName: z79.string().trim().min(1).max(100),
21579
21697
  campaignConfig: GroupedCampaignConfig.optional()
21580
21698
  });
21581
21699
  var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
21582
21700
  const destination = value.campaignConfig?.destination;
21583
21701
  if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
21584
21702
  ctx.addIssue({
21585
- code: z78.ZodIssueCode.custom,
21703
+ code: z79.ZodIssueCode.custom,
21586
21704
  path: [
21587
21705
  "landingUrl"
21588
21706
  ],
@@ -21591,7 +21709,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
21591
21709
  }
21592
21710
  if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
21593
21711
  ctx.addIssue({
21594
- code: z78.ZodIssueCode.custom,
21712
+ code: z79.ZodIssueCode.custom,
21595
21713
  path: [
21596
21714
  "campaignConfig",
21597
21715
  "destination",
@@ -21610,16 +21728,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
21610
21728
  }
21611
21729
  return value;
21612
21730
  });
21613
- var PresignUploadResponseSchema = z78.object({
21614
- uploadUrl: z78.string().url().refine((value) => {
21731
+ var PresignUploadResponseSchema = z79.object({
21732
+ uploadUrl: z79.string().url().refine((value) => {
21615
21733
  const url = new URL(value);
21616
21734
  return !url.username && !url.password && url.protocol === "https:";
21617
21735
  }, "presigned upload URL must be HTTPS without embedded credentials"),
21618
- publicUrl: z78.string().url().refine((value) => {
21736
+ publicUrl: z79.string().url().refine((value) => {
21619
21737
  const url = new URL(value);
21620
21738
  return !url.username && !url.password;
21621
21739
  }, "public media URL must not contain embedded credentials"),
21622
- stagingAssetId: z78.string().uuid()
21740
+ stagingAssetId: z79.string().uuid()
21623
21741
  });
21624
21742
  async function uploadResolvedMedia(api, media, assetRole) {
21625
21743
  if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
@@ -21644,16 +21762,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
21644
21762
  return uploadResolvedMedia(api, media, assetRole);
21645
21763
  }
21646
21764
  __name(resolveAndUploadMedia, "resolveAndUploadMedia");
21647
- var TikTokInput = z78.object({
21648
- taskId: z78.string().min(1),
21649
- advertiserId: z78.string().min(1),
21650
- pixelId: z78.string().min(1).optional(),
21651
- landingUrl: z78.string().url().optional(),
21652
- angleIndexes: z78.array(z78.number().int().nonnegative()).optional(),
21765
+ var TikTokInput = z79.object({
21766
+ taskId: z79.string().min(1),
21767
+ advertiserId: z79.string().min(1),
21768
+ pixelId: z79.string().min(1).optional(),
21769
+ landingUrl: z79.string().url().optional(),
21770
+ angleIndexes: z79.array(z79.number().int().nonnegative()).optional(),
21653
21771
  campaignConfig: McpCampaignConfig.optional(),
21654
21772
  /** Override the ad's description (TikTok's body copy). If omitted,
21655
21773
  * ProductMaker uses the auto-generated copy attached to the task. */
21656
- primaryText: z78.string().trim().min(1).max(500).optional()
21774
+ primaryText: z79.string().trim().min(1).max(500).optional()
21657
21775
  });
21658
21776
  function registerPublishTools(server, api, opts = {}) {
21659
21777
  const transport = opts.transport ?? "http";
@@ -21981,39 +22099,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
21981
22099
 
21982
22100
  // src/tools/meta-upload.ts
21983
22101
  import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
21984
- import { z as z79 } from "zod";
22102
+ import { z as z80 } from "zod";
21985
22103
  var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
21986
- var UploadSessionInputBase = z79.object({
21987
- mediaKind: z79.enum([
22104
+ var UploadSessionInputBase = z80.object({
22105
+ mediaKind: z80.enum([
21988
22106
  "image",
21989
22107
  "video",
21990
22108
  "mixed"
21991
22109
  ]).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."),
21992
- assetRole: z79.enum([
22110
+ assetRole: z80.enum([
21993
22111
  "media",
21994
22112
  "thumbnail"
21995
22113
  ]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
21996
- uploadPurpose: z79.enum([
22114
+ uploadPurpose: z80.enum([
21997
22115
  "product_reference",
21998
22116
  "creative",
21999
22117
  "generic"
22000
22118
  ]).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."),
22001
- maxFiles: z79.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
22119
+ maxFiles: z80.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
22002
22120
  });
22003
- var OpenAiFileReference = z79.object({
22004
- download_url: z79.string().url().optional().describe("Optional host-provided download URL. The App prefers getFileDownloadUrl(file_id) and the server never fetches this URL."),
22005
- file_id: z79.string().min(1),
22006
- mime_type: z79.string().min(1).optional(),
22007
- file_name: z79.string().min(1).optional()
22121
+ var OpenAiFileReference = z80.object({
22122
+ download_url: z80.string().url().optional().describe("Optional host-provided download URL. The App prefers getFileDownloadUrl(file_id) and the server never fetches this URL."),
22123
+ file_id: z80.string().min(1),
22124
+ mime_type: z80.string().min(1).optional(),
22125
+ file_name: z80.string().min(1).optional()
22008
22126
  });
22009
22127
  var UploadSessionToolInputShape = {
22010
22128
  ...UploadSessionInputBase.shape,
22011
- files: z79.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.")
22129
+ files: z80.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.")
22012
22130
  };
22013
- var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
22131
+ var UploadSessionToolInput = z80.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
22014
22132
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
22015
22133
  ctx.addIssue({
22016
- code: z79.ZodIssueCode.custom,
22134
+ code: z80.ZodIssueCode.custom,
22017
22135
  path: [
22018
22136
  "mediaKind"
22019
22137
  ],
@@ -22022,7 +22140,7 @@ var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine
22022
22140
  }
22023
22141
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
22024
22142
  ctx.addIssue({
22025
- code: z79.ZodIssueCode.custom,
22143
+ code: z80.ZodIssueCode.custom,
22026
22144
  path: [
22027
22145
  "maxFiles"
22028
22146
  ],
@@ -22031,7 +22149,7 @@ var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine
22031
22149
  }
22032
22150
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
22033
22151
  ctx.addIssue({
22034
- code: z79.ZodIssueCode.custom,
22152
+ code: z80.ZodIssueCode.custom,
22035
22153
  path: [
22036
22154
  "maxFiles"
22037
22155
  ],
@@ -22039,38 +22157,38 @@ var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine
22039
22157
  });
22040
22158
  }
22041
22159
  });
22042
- var UploadSessionResponse = z79.object({
22043
- sessionId: z79.string().uuid(),
22044
- uploadPageUrl: z79.string().url(),
22045
- mediaKind: z79.enum([
22160
+ var UploadSessionResponse = z80.object({
22161
+ sessionId: z80.string().uuid(),
22162
+ uploadPageUrl: z80.string().url(),
22163
+ mediaKind: z80.enum([
22046
22164
  "image",
22047
22165
  "video",
22048
22166
  "mixed"
22049
22167
  ]),
22050
- assetRole: z79.enum([
22168
+ assetRole: z80.enum([
22051
22169
  "media",
22052
22170
  "thumbnail"
22053
22171
  ]),
22054
- maxFiles: z79.number().int().positive(),
22055
- expiresAt: z79.string().datetime()
22172
+ maxFiles: z80.number().int().positive(),
22173
+ expiresAt: z80.string().datetime()
22056
22174
  });
22057
- var UploadStatusInput = z79.object({
22058
- sessionId: z79.string().uuid().describe("The sessionId returned by request_media_upload.")
22175
+ var UploadStatusInput = z80.object({
22176
+ sessionId: z80.string().uuid().describe("The sessionId returned by request_media_upload.")
22059
22177
  });
22060
- var UniversalUploadStatusResponse = z79.discriminatedUnion("status", [
22061
- z79.object({
22062
- status: z79.literal("pending"),
22063
- assets: z79.array(z79.never()).length(0)
22178
+ var UniversalUploadStatusResponse = z80.discriminatedUnion("status", [
22179
+ z80.object({
22180
+ status: z80.literal("pending"),
22181
+ assets: z80.array(z80.never()).length(0)
22064
22182
  }),
22065
- z79.object({
22066
- status: z79.literal("uploaded"),
22067
- assets: z79.array(z79.object({
22068
- assetId: z79.string().uuid(),
22069
- mediaKind: z79.enum([
22183
+ z80.object({
22184
+ status: z80.literal("uploaded"),
22185
+ assets: z80.array(z80.object({
22186
+ assetId: z80.string().uuid(),
22187
+ mediaKind: z80.enum([
22070
22188
  "image",
22071
22189
  "video"
22072
22190
  ]),
22073
- assetRole: z79.enum([
22191
+ assetRole: z80.enum([
22074
22192
  "media",
22075
22193
  "thumbnail"
22076
22194
  ])
@@ -22078,13 +22196,13 @@ var UniversalUploadStatusResponse = z79.discriminatedUnion("status", [
22078
22196
  })
22079
22197
  ]);
22080
22198
  var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
22081
- uploadPurpose: z79.enum([
22199
+ uploadPurpose: z80.enum([
22082
22200
  "product_reference",
22083
22201
  "creative",
22084
22202
  "generic"
22085
22203
  ]),
22086
- checkToolName: z79.literal("check_media_upload"),
22087
- resolveEndpoint: z79.string().url()
22204
+ checkToolName: z80.literal("check_media_upload"),
22205
+ resolveEndpoint: z80.string().url()
22088
22206
  });
22089
22207
  function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
22090
22208
  const url = new URL(uploadPageUrl);
@@ -22175,15 +22293,15 @@ function registerMediaUploadTools(server, api) {
22175
22293
  __name(registerMediaUploadTools, "registerMediaUploadTools");
22176
22294
 
22177
22295
  // src/tools/campaigns.ts
22178
- import { z as z80 } from "zod";
22296
+ import { z as z81 } from "zod";
22179
22297
  var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
22180
22298
  var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
22181
- var MetaStatusInput = z80.object({
22182
- campaignId: z80.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
22299
+ var MetaStatusInput = z81.object({
22300
+ campaignId: z81.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
22183
22301
  });
22184
- var TikTokStatusInput = z80.object({
22185
- campaignId: z80.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
22186
- advertiserId: z80.string().min(1).describe("The same advertiserId used to publish the campaign.")
22302
+ var TikTokStatusInput = z81.object({
22303
+ campaignId: z81.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
22304
+ advertiserId: z81.string().min(1).describe("The same advertiserId used to publish the campaign.")
22187
22305
  });
22188
22306
  function registerCampaignTools(server, api) {
22189
22307
  server.tool("get_meta_campaign_status", getMetaCampaignStatusGuidance.summary + " Llama esto DESPU\xC9S de `publish_to_meta` para confirmar que la campa\xF1a se cre\xF3 correctamente y para reportar performance al usuario. Es read-only \u2014 no modifica nada en Meta Ads Manager.", MetaStatusInput.shape, READS_EXTERNAL, async (input) => {
@@ -22280,10 +22398,10 @@ function renderTikTokStatusMarkdown(r) {
22280
22398
  __name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
22281
22399
 
22282
22400
  // ../../packages/product-economics/src/product-costing.ts
22283
- import { z as z82 } from "zod";
22401
+ import { z as z83 } from "zod";
22284
22402
 
22285
22403
  // ../../packages/product-economics/src/product-costing-countries.ts
22286
- import { z as z81 } from "zod";
22404
+ import { z as z82 } from "zod";
22287
22405
 
22288
22406
  // ../../packages/product-economics/src/product-costing-shipping-references.json
22289
22407
  var product_costing_shipping_references_default = {
@@ -22347,21 +22465,21 @@ var product_costing_shipping_references_default = {
22347
22465
  };
22348
22466
 
22349
22467
  // ../../packages/product-economics/src/product-costing-countries.ts
22350
- var ShippingReferenceSchema = z81.object({
22351
- reference: z81.number().positive(),
22352
- min: z81.number().nonnegative(),
22353
- max: z81.number().positive(),
22354
- updatedAt: z81.string().date(),
22355
- confidence: z81.enum([
22468
+ var ShippingReferenceSchema = z82.object({
22469
+ reference: z82.number().positive(),
22470
+ min: z82.number().nonnegative(),
22471
+ max: z82.number().positive(),
22472
+ updatedAt: z82.string().date(),
22473
+ confidence: z82.enum([
22356
22474
  "high",
22357
22475
  "medium",
22358
22476
  "medium-low"
22359
22477
  ]),
22360
- sources: z81.array(z81.string().url().startsWith("https://")).min(1).max(3)
22478
+ sources: z82.array(z82.string().url().startsWith("https://")).min(1).max(3)
22361
22479
  }).superRefine(({ reference, min, max }, context) => {
22362
22480
  if (min > reference || reference > max) {
22363
22481
  context.addIssue({
22364
- code: z81.ZodIssueCode.custom,
22482
+ code: z82.ZodIssueCode.custom,
22365
22483
  message: "shipping_reference_outside_range",
22366
22484
  path: [
22367
22485
  "reference"
@@ -22369,7 +22487,7 @@ var ShippingReferenceSchema = z81.object({
22369
22487
  });
22370
22488
  }
22371
22489
  });
22372
- var SHIPPING_REFERENCES = z81.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
22490
+ var SHIPPING_REFERENCES = z82.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
22373
22491
  var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
22374
22492
  var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
22375
22493
  "MX",
@@ -22551,18 +22669,18 @@ function getProductCostingCountryName(country) {
22551
22669
  __name(getProductCostingCountryName, "getProductCostingCountryName");
22552
22670
 
22553
22671
  // ../../packages/product-economics/src/product-costing.ts
22554
- var ProductCostingInputSchema = z82.object({
22555
- country: z82.string().refine(isProductCostingCountryCode, "unsupported_country"),
22556
- supplierCost: z82.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
22557
- shippingCost: z82.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
22558
- returnRate: z82.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
22559
- cancellationRate: z82.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
22560
- adsManagerCpa: z82.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
22561
- desiredMargin: z82.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
22672
+ var ProductCostingInputSchema = z83.object({
22673
+ country: z83.string().refine(isProductCostingCountryCode, "unsupported_country"),
22674
+ supplierCost: z83.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
22675
+ shippingCost: z83.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
22676
+ returnRate: z83.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
22677
+ cancellationRate: z83.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
22678
+ adsManagerCpa: z83.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
22679
+ desiredMargin: z83.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
22562
22680
  }).superRefine(({ returnRate, cancellationRate }, context) => {
22563
22681
  if (returnRate + cancellationRate >= 1) {
22564
22682
  context.addIssue({
22565
- code: z82.ZodIssueCode.custom,
22683
+ code: z83.ZodIssueCode.custom,
22566
22684
  message: "delivery_rate_positive",
22567
22685
  path: [
22568
22686
  "cancellationRate"
@@ -22659,15 +22777,15 @@ function calculateProductCosting(rawInput) {
22659
22777
  __name(calculateProductCosting, "calculateProductCosting");
22660
22778
 
22661
22779
  // src/tools/product-costing.ts
22662
- import { z as z83 } from "zod";
22780
+ import { z as z84 } from "zod";
22663
22781
  var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
22664
- var optionalAmount = /* @__PURE__ */ __name((description) => z83.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
22665
- var optionalPercent = /* @__PURE__ */ __name((description) => z83.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
22666
- var ProductCostingToolInput = z83.object({
22667
- country: z83.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
22782
+ var optionalAmount = /* @__PURE__ */ __name((description) => z84.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
22783
+ var optionalPercent = /* @__PURE__ */ __name((description) => z84.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
22784
+ var ProductCostingToolInput = z84.object({
22785
+ country: z84.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
22668
22786
  message: "Pa\xEDs no soportado por ProductMaker."
22669
22787
  }).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
22670
- supplierCost: z83.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."),
22788
+ supplierCost: z84.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."),
22671
22789
  supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
22672
22790
  shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
22673
22791
  shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
@@ -22826,7 +22944,7 @@ function formatPercent(value) {
22826
22944
  __name(formatPercent, "formatPercent");
22827
22945
 
22828
22946
  // src/tools/product-research.ts
22829
- import { z as z84 } from "zod";
22947
+ import { z as z85 } from "zod";
22830
22948
 
22831
22949
  // src/tools/product-research-idempotency.ts
22832
22950
  var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
@@ -23197,17 +23315,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
23197
23315
  ]);
23198
23316
  var POLL_INTERVAL_MS = 5e3;
23199
23317
  var MAX_WAIT_SECONDS = 120;
23200
- var FindInput = z84.object({
23318
+ var FindInput = z85.object({
23201
23319
  targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
23202
23320
  categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
23203
- confirmed: z84.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
23204
- waitSeconds: z84.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
23321
+ confirmed: z85.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
23322
+ waitSeconds: z85.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
23205
23323
  });
23206
- var GetInput = z84.object({
23207
- runId: z84.string().uuid().describe("ID del run devuelto por find_winning_products.")
23324
+ var GetInput = z85.object({
23325
+ runId: z85.string().uuid().describe("ID del run devuelto por find_winning_products.")
23208
23326
  });
23209
- var ListInput = z84.object({
23210
- limit: z84.number().int().min(1).max(20).default(10)
23327
+ var ListInput = z85.object({
23328
+ limit: z85.number().int().min(1).max(20).default(10)
23211
23329
  });
23212
23330
  function textResult(text) {
23213
23331
  return {
@@ -23330,17 +23448,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
23330
23448
  __name(registerProductResearchTools, "registerProductResearchTools");
23331
23449
 
23332
23450
  // src/tools/dropshipping-projects.ts
23333
- import { z as z85 } from "zod";
23451
+ import { z as z86 } from "zod";
23334
23452
  var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
23335
23453
  var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
23336
23454
  var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
23337
- var ProjectId = z85.string().uuid();
23338
- var DropshippingProjectStatus = z85.enum([
23455
+ var ProjectId = z86.string().uuid();
23456
+ var DropshippingProjectStatus = z86.enum([
23339
23457
  "active",
23340
23458
  "completed",
23341
23459
  "archived"
23342
23460
  ]);
23343
- var DropshippingProjectPhase = z85.enum([
23461
+ var DropshippingProjectPhase = z86.enum([
23344
23462
  "research",
23345
23463
  "costing",
23346
23464
  "media",
@@ -23349,21 +23467,21 @@ var DropshippingProjectPhase = z85.enum([
23349
23467
  "advertising",
23350
23468
  "complete"
23351
23469
  ]);
23352
- var DropshippingRewardMilestone = z85.enum([
23470
+ var DropshippingRewardMilestone = z86.enum([
23353
23471
  "product_selected",
23354
23472
  "costing_saved",
23355
23473
  "product_media_ready",
23356
23474
  "creatives_completed",
23357
23475
  "campaign_created"
23358
23476
  ]);
23359
- var TargetCountry = z85.enum([
23477
+ var TargetCountry = z86.enum([
23360
23478
  "CO",
23361
23479
  "MX",
23362
23480
  "PE",
23363
23481
  "EC",
23364
23482
  "CL"
23365
23483
  ]);
23366
- var ResearchCategory = z85.enum([
23484
+ var ResearchCategory = z86.enum([
23367
23485
  "auto",
23368
23486
  "automotive",
23369
23487
  "kitchen",
@@ -23378,7 +23496,7 @@ var ResearchCategory = z85.enum([
23378
23496
  "garden",
23379
23497
  "cleaning"
23380
23498
  ]);
23381
- var HttpUrl3 = z85.string().url().max(2e3).refine((value) => {
23499
+ var HttpUrl3 = z86.string().url().max(2e3).refine((value) => {
23382
23500
  try {
23383
23501
  return [
23384
23502
  "http:",
@@ -23388,45 +23506,45 @@ var HttpUrl3 = z85.string().url().max(2e3).refine((value) => {
23388
23506
  return false;
23389
23507
  }
23390
23508
  }, "URL must use HTTP(S)");
23391
- var ResearchCandidateOrigin = z85.object({
23392
- type: z85.literal("research_candidate"),
23509
+ var ResearchCandidateOrigin = z86.object({
23510
+ type: z86.literal("research_candidate"),
23393
23511
  runId: ProjectId,
23394
- candidateSourceId: z85.string().min(1).max(160)
23512
+ candidateSourceId: z86.string().min(1).max(160)
23395
23513
  });
23396
- var TaskOrigin = z85.object({
23397
- type: z85.literal("task"),
23514
+ var TaskOrigin = z86.object({
23515
+ type: z86.literal("task"),
23398
23516
  taskId: ProjectId
23399
23517
  });
23400
- var ManualOrigin = z85.object({
23401
- type: z85.literal("manual"),
23518
+ var ManualOrigin = z86.object({
23519
+ type: z86.literal("manual"),
23402
23520
  clientRequestId: ProjectId,
23403
- country: z85.string().min(2).max(3).optional()
23521
+ country: z86.string().min(2).max(3).optional()
23404
23522
  });
23405
- var StartProjectInput = z85.object({
23406
- origin: z85.discriminatedUnion("type", [
23523
+ var StartProjectInput = z86.object({
23524
+ origin: z86.discriminatedUnion("type", [
23407
23525
  ResearchCandidateOrigin,
23408
23526
  TaskOrigin,
23409
23527
  ManualOrigin
23410
23528
  ]),
23411
- productName: z85.string().trim().min(1).max(240).optional(),
23529
+ productName: z86.string().trim().min(1).max(240).optional(),
23412
23530
  productUrl: HttpUrl3.optional(),
23413
- country: z85.string().min(2).max(3).optional(),
23414
- languageCode: z85.string().min(2).max(16).optional()
23531
+ country: z86.string().min(2).max(3).optional(),
23532
+ languageCode: z86.string().min(2).max(16).optional()
23415
23533
  }).strict();
23416
- var CostProjectInput = z85.object({
23534
+ var CostProjectInput = z86.object({
23417
23535
  projectId: ProjectId,
23418
- version: z85.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
23419
- country: z85.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
23536
+ version: z86.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
23537
+ country: z86.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
23420
23538
  message: "Pa\xEDs no soportado por ProductMaker."
23421
23539
  }).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
23422
- supplierCost: z85.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."),
23423
- shippingCost: z85.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
23424
- returnRate: z85.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."),
23425
- cancellationRate: z85.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."),
23426
- adsManagerCpa: z85.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
23427
- desiredMargin: z85.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
23428
- });
23429
- var GuideInput = z85.object({
23540
+ supplierCost: z86.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."),
23541
+ shippingCost: z86.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
23542
+ returnRate: z86.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."),
23543
+ cancellationRate: z86.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."),
23544
+ adsManagerCpa: z86.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
23545
+ desiredMargin: z86.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
23546
+ });
23547
+ var GuideInput = z86.object({
23430
23548
  projectId: ProjectId.optional()
23431
23549
  }).strict();
23432
23550
  var NEXT_ACTION_KINDS = [
@@ -23444,29 +23562,29 @@ var NEXT_ACTION_KINDS = [
23444
23562
  "repair_meta_campaign",
23445
23563
  "review_paused_campaign"
23446
23564
  ];
23447
- var DropshippingProjectNextAction = z85.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z85.object({
23448
- kind: z85.literal(kind),
23449
- href: z85.string().min(1)
23565
+ var DropshippingProjectNextAction = z86.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z86.object({
23566
+ kind: z86.literal(kind),
23567
+ href: z86.string().min(1)
23450
23568
  })));
23451
- var CostingInputSchema = z85.object({
23452
- country: z85.string().min(2).max(3),
23453
- supplierCost: z85.number().finite().positive(),
23454
- shippingCost: z85.number().finite().nonnegative(),
23455
- returnRate: z85.number().finite().min(0).lt(1),
23456
- cancellationRate: z85.number().finite().min(0).lt(1),
23457
- adsManagerCpa: z85.number().finite().nonnegative(),
23458
- desiredMargin: z85.number().finite().min(0).lt(1)
23569
+ var CostingInputSchema = z86.object({
23570
+ country: z86.string().min(2).max(3),
23571
+ supplierCost: z86.number().finite().positive(),
23572
+ shippingCost: z86.number().finite().nonnegative(),
23573
+ returnRate: z86.number().finite().min(0).lt(1),
23574
+ cancellationRate: z86.number().finite().min(0).lt(1),
23575
+ adsManagerCpa: z86.number().finite().nonnegative(),
23576
+ desiredMargin: z86.number().finite().min(0).lt(1)
23459
23577
  }).superRefine(({ returnRate, cancellationRate }, context) => {
23460
23578
  if (returnRate + cancellationRate >= 1) context.addIssue({
23461
- code: z85.ZodIssueCode.custom,
23579
+ code: z86.ZodIssueCode.custom,
23462
23580
  path: [
23463
23581
  "cancellationRate"
23464
23582
  ]
23465
23583
  });
23466
23584
  });
23467
- var FiniteCostingNumber = z85.number().finite();
23468
- var CostingResultSchema = z85.object({
23469
- country: z85.string().min(2).max(3),
23585
+ var FiniteCostingNumber = z86.number().finite();
23586
+ var CostingResultSchema = z86.object({
23587
+ country: z86.string().min(2).max(3),
23470
23588
  deliveryRate: FiniteCostingNumber,
23471
23589
  adjustedShippingCost: FiniteCostingNumber,
23472
23590
  adjustedCpa: FiniteCostingNumber,
@@ -23479,45 +23597,45 @@ var CostingResultSchema = z85.object({
23479
23597
  estimatedProfit: FiniteCostingNumber,
23480
23598
  actualMargin: FiniteCostingNumber,
23481
23599
  breakEvenAdsManagerCpa: FiniteCostingNumber,
23482
- wasPriceAutoAdjusted: z85.boolean(),
23483
- profitabilityStatus: z85.literal("healthy")
23484
- });
23485
- var RewardProgressSchema = z85.object({
23486
- campaignKey: z85.literal("dropshipping-launch-v1"),
23487
- totalCredits: z85.number().int().positive(),
23488
- earnedCredits: z85.number().int().nonnegative(),
23489
- milestones: z85.array(z85.object({
23600
+ wasPriceAutoAdjusted: z86.boolean(),
23601
+ profitabilityStatus: z86.literal("healthy")
23602
+ });
23603
+ var RewardProgressSchema = z86.object({
23604
+ campaignKey: z86.literal("dropshipping-launch-v1"),
23605
+ totalCredits: z86.number().int().positive(),
23606
+ earnedCredits: z86.number().int().nonnegative(),
23607
+ milestones: z86.array(z86.object({
23490
23608
  milestone: DropshippingRewardMilestone,
23491
- credits: z85.number().int().positive(),
23492
- available: z85.boolean().optional(),
23493
- earned: z85.boolean(),
23609
+ credits: z86.number().int().positive(),
23610
+ available: z86.boolean().optional(),
23611
+ earned: z86.boolean(),
23494
23612
  grantId: ProjectId.nullable(),
23495
- grantedAt: z85.string().datetime().nullable()
23613
+ grantedAt: z86.string().datetime().nullable()
23496
23614
  })).length(DropshippingRewardMilestone.options.length)
23497
23615
  });
23498
- var ProjectResponseSchema = z85.object({
23616
+ var ProjectResponseSchema = z86.object({
23499
23617
  id: ProjectId,
23500
23618
  taskId: ProjectId.nullable(),
23501
23619
  status: DropshippingProjectStatus,
23502
- originKey: z85.string().min(1),
23620
+ originKey: z86.string().min(1),
23503
23621
  researchRunId: ProjectId.nullable(),
23504
- candidateSourceId: z85.string().nullable(),
23505
- productName: z85.string().nullable(),
23622
+ candidateSourceId: z86.string().nullable(),
23623
+ productName: z86.string().nullable(),
23506
23624
  productUrl: HttpUrl3.nullable(),
23507
23625
  referenceImageUrl: HttpUrl3.nullable(),
23508
- targetCountry: z85.string().nullable(),
23509
- languageCode: z85.string().nullable(),
23510
- hasReferenceImage: z85.boolean(),
23511
- hasWinnerReferenceImage: z85.boolean(),
23626
+ targetCountry: z86.string().nullable(),
23627
+ languageCode: z86.string().nullable(),
23628
+ hasReferenceImage: z86.boolean(),
23629
+ hasWinnerReferenceImage: z86.boolean(),
23512
23630
  costingInput: CostingInputSchema.nullable(),
23513
23631
  costingResult: CostingResultSchema.nullable(),
23514
- costingVersion: z85.number().int().positive().nullable(),
23515
- version: z85.number().int().positive(),
23632
+ costingVersion: z86.number().int().positive().nullable(),
23633
+ version: z86.number().int().positive(),
23516
23634
  phase: DropshippingProjectPhase,
23517
23635
  nextAction: DropshippingProjectNextAction.nullable(),
23518
23636
  rewards: RewardProgressSchema,
23519
- createdAt: z85.string().datetime(),
23520
- updatedAt: z85.string().datetime()
23637
+ createdAt: z86.string().datetime(),
23638
+ updatedAt: z86.string().datetime()
23521
23639
  }).passthrough();
23522
23640
  var NEXT_ACTION_GUIDANCE = {
23523
23641
  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.",
@@ -23635,58 +23753,58 @@ function registerDropshippingProjectTools(server, api) {
23635
23753
  __name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
23636
23754
 
23637
23755
  // src/tools/daily-control.ts
23638
- import { z as z86 } from "zod";
23756
+ import { z as z87 } from "zod";
23639
23757
  var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
23640
23758
  var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
23641
23759
  var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
23642
- var ProviderCampaignIdentifier = z86.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
23643
- var DateOnly = z86.string().regex(/^\d{4}-\d{2}-\d{2}$/);
23644
- var DailyControlInput = z86.object({
23760
+ var ProviderCampaignIdentifier = z87.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
23761
+ var DateOnly = z87.string().regex(/^\d{4}-\d{2}-\d{2}$/);
23762
+ var DailyControlInput = z87.object({
23645
23763
  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."),
23646
- days: z86.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
23647
- projectId: z86.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
23764
+ days: z87.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
23765
+ projectId: z87.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
23648
23766
  }).strict();
23649
- var LinkCampaignInput = z86.object({
23650
- projectId: z86.string().uuid(),
23651
- provider: z86.enum([
23767
+ var LinkCampaignInput = z87.object({
23768
+ projectId: z87.string().uuid(),
23769
+ provider: z87.enum([
23652
23770
  "meta",
23653
23771
  "tiktok"
23654
23772
  ]),
23655
23773
  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."),
23656
23774
  campaignId: ProviderCampaignIdentifier
23657
23775
  }).strict();
23658
- var ReportReturnsInput = z86.object({
23659
- projectId: z86.string().uuid(),
23776
+ var ReportReturnsInput = z87.object({
23777
+ projectId: z87.string().uuid(),
23660
23778
  date: DateOnly,
23661
- returnedOrders: z86.number().int().min(0).max(1e5),
23662
- note: z86.string().trim().max(280).optional()
23779
+ returnedOrders: z87.number().int().min(0).max(1e5),
23780
+ note: z87.string().trim().max(280).optional()
23663
23781
  }).strict();
23664
- var DailyControlStatusMirror = DailyControlStatusEnum.or(z86.string());
23665
- var DailyControlLightMirror = DailyControlLightEnum.or(z86.string());
23666
- var DailyControlSourceMirror = DailyControlSourceEnum.or(z86.string());
23667
- var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z86.string());
23668
- var DailyControlDayMirror = z86.object({
23669
- date: z86.string(),
23670
- returnedOrders: z86.number(),
23782
+ var DailyControlStatusMirror = DailyControlStatusEnum.or(z87.string());
23783
+ var DailyControlLightMirror = DailyControlLightEnum.or(z87.string());
23784
+ var DailyControlSourceMirror = DailyControlSourceEnum.or(z87.string());
23785
+ var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z87.string());
23786
+ var DailyControlDayMirror = z87.object({
23787
+ date: z87.string(),
23788
+ returnedOrders: z87.number(),
23671
23789
  returnedSource: DailyControlSourceMirror,
23672
23790
  cancelledSource: DailyControlSourceMirror,
23673
- hasEstimates: z86.boolean(),
23791
+ hasEstimates: z87.boolean(),
23674
23792
  light: DailyControlLightMirror
23675
23793
  }).passthrough();
23676
- var DailyControlProductMirror = z86.object({
23677
- projectId: z86.string().uuid(),
23678
- productName: z86.string().nullable(),
23794
+ var DailyControlProductMirror = z87.object({
23795
+ projectId: z87.string().uuid(),
23796
+ productName: z87.string().nullable(),
23679
23797
  status: DailyControlStatusMirror,
23680
- statusMessage: z86.string().nullable(),
23681
- days: z86.array(DailyControlDayMirror),
23798
+ statusMessage: z87.string().nullable(),
23799
+ days: z87.array(DailyControlDayMirror),
23682
23800
  verdict: DailyControlVerdictMirror.nullable(),
23683
- rationale: z86.string().nullable()
23801
+ rationale: z87.string().nullable()
23684
23802
  }).passthrough();
23685
- var DailyControlResponseMirror = z86.object({
23686
- since: z86.string(),
23687
- until: z86.string(),
23688
- products: z86.array(DailyControlProductMirror),
23689
- archivedProjectSpend: z86.array(z86.unknown())
23803
+ var DailyControlResponseMirror = z87.object({
23804
+ since: z87.string(),
23805
+ until: z87.string(),
23806
+ products: z87.array(DailyControlProductMirror),
23807
+ archivedProjectSpend: z87.array(z87.unknown())
23690
23808
  }).passthrough();
23691
23809
  var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
23692
23810
  function withWarnings(response) {
@@ -23770,42 +23888,42 @@ function registerDailyControlTools(server, api) {
23770
23888
  __name(registerDailyControlTools, "registerDailyControlTools");
23771
23889
 
23772
23890
  // src/tools/product-control.ts
23773
- import { z as z87 } from "zod";
23891
+ import { z as z88 } from "zod";
23774
23892
  var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
23775
23893
  var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
23776
23894
  var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
23777
23895
  var setProductCostingGuidance = getProductMakerCapabilityModelGuidance("set_product_costing");
23778
23896
  var reportProductCountsGuidance = getProductMakerCapabilityModelGuidance("report_product_counts");
23779
- var DateOnly2 = z87.string().regex(/^\d{4}-\d{2}-\d{2}$/);
23897
+ var DateOnly2 = z88.string().regex(/^\d{4}-\d{2}-\d{2}$/);
23780
23898
  var IMPORT_BATCH_MAX2 = 50;
23781
- var ProductControlListInput = z87.object({
23782
- days: z87.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
23899
+ var ProductControlListInput = z88.object({
23900
+ days: z88.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
23783
23901
  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."),
23784
- shopDomain: z87.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
23902
+ shopDomain: z88.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
23785
23903
  }).strict();
23786
- var ImportableProductsInput = z87.object({
23787
- q: z87.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
23788
- after: z87.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
23789
- shopDomain: z87.string().min(1).optional()
23904
+ var ImportableProductsInput = z88.object({
23905
+ q: z88.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
23906
+ after: z88.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
23907
+ shopDomain: z88.string().min(1).optional()
23790
23908
  }).strict();
23791
- var ImportProductControlsInput = z87.object({
23792
- shopifyProductIds: z87.array(z87.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."),
23909
+ var ImportProductControlsInput = z88.object({
23910
+ shopifyProductIds: z88.array(z88.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."),
23793
23911
  // Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
23794
23912
  // sin decir a cuál archivaría el producto bajo la tienda equivocada.
23795
- shopDomain: z87.string().min(1)
23913
+ shopDomain: z88.string().min(1)
23796
23914
  }).strict();
23797
- var SetProductCostingInput = z87.object({
23798
- shopDomain: z87.string().min(1),
23799
- shopifyProductId: z87.string().min(1).max(64),
23800
- targetCountry: z87.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
23801
- supplierCost: z87.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
23802
- shippingCost: z87.number().finite().nonnegative(),
23803
- returnRate: z87.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
23804
- cancellationRate: z87.number().finite().min(0).lt(1)
23915
+ var SetProductCostingInput = z88.object({
23916
+ shopDomain: z88.string().min(1),
23917
+ shopifyProductId: z88.string().min(1).max(64),
23918
+ targetCountry: z88.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
23919
+ supplierCost: z88.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
23920
+ shippingCost: z88.number().finite().nonnegative(),
23921
+ returnRate: z88.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
23922
+ cancellationRate: z88.number().finite().min(0).lt(1)
23805
23923
  }).strict();
23806
- var Count = z87.number().int().min(0).max(1e5).nullable().optional();
23807
- var ReportProductCountsInput = z87.object({
23808
- productControlId: z87.string().uuid().describe("El identificador que devuelve get_product_control."),
23924
+ var Count = z88.number().int().min(0).max(1e5).nullable().optional();
23925
+ var ReportProductCountsInput = z88.object({
23926
+ productControlId: z88.string().uuid().describe("El identificador que devuelve get_product_control."),
23809
23927
  date: DateOnly2,
23810
23928
  orders: Count.describe("Pedidos que entraron ese d\xEDa."),
23811
23929
  cancelledOrders: Count,