@productmaker/mcp 12.1.2 → 12.1.4

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 (4) hide show
  1. package/README.md +11 -0
  2. package/dist/http.js +1053 -888
  3. package/dist/stdio.js +1040 -875
  4. package/package.json +1 -1
package/dist/stdio.js CHANGED
@@ -2788,9 +2788,9 @@ var ClassicLandingSelectionSnapshotSchema = z18.object({
2788
2788
  }).strict().superRefine((snapshot, ctx) => {
2789
2789
  if (snapshot.images) {
2790
2790
  const selectedImages = snapshot.blocks.filter((block) => block.kind === "image");
2791
- const ids = snapshot.images.map((image) => classicLandingBlockId({
2791
+ const ids = snapshot.images.map((image2) => classicLandingBlockId({
2792
2792
  kind: "image",
2793
- ...image
2793
+ ...image2
2794
2794
  }));
2795
2795
  if (new Set(ids).size !== ids.length || ids.length !== selectedImages.length || selectedImages.some((block) => !ids.includes(classicLandingBlockId(block)))) ctx.addIssue({
2796
2796
  code: z18.ZodIssueCode.custom,
@@ -15491,9 +15491,9 @@ var MotionGraphicsVoiceDirectionSchema = z78.object({
15491
15491
  pace: z78.enum(MOTION_GRAPHICS_VOICE_PACES)
15492
15492
  }).strict();
15493
15493
  var AUDIO_TAG = /\[(?:sighs|laughs softly|short pause|emphatic|whispers|gasps|hesitant|warmly)\]/g;
15494
- function motionGraphicsTaggedSpeechMatches(text3, tagged) {
15494
+ function motionGraphicsTaggedSpeechMatches(text4, tagged) {
15495
15495
  const normalize = /* @__PURE__ */ __name((value) => value.normalize("NFC").replace(/\s+/g, " ").trim(), "normalize");
15496
- return normalize(tagged.replace(AUDIO_TAG, "")) === normalize(text3);
15496
+ return normalize(tagged.replace(AUDIO_TAG, "")) === normalize(text4);
15497
15497
  }
15498
15498
  __name(motionGraphicsTaggedSpeechMatches, "motionGraphicsTaggedSpeechMatches");
15499
15499
  var MotionGraphicsTaggedSpeechSchema = z78.string().trim().min(1).max(1200);
@@ -21658,10 +21658,10 @@ var GENDER_ALIASES = {
21658
21658
  };
21659
21659
  function matchAlias(raw, aliases) {
21660
21660
  if (typeof raw !== "string") return void 0;
21661
- const text3 = raw.trim().toLowerCase();
21662
- const exact = aliases[text3];
21661
+ const text4 = raw.trim().toLowerCase();
21662
+ const exact = aliases[text4];
21663
21663
  if (exact) return exact;
21664
- const words = new Set(text3.split(/[^a-z]+/).filter(Boolean));
21664
+ const words = new Set(text4.split(/[^a-z]+/).filter(Boolean));
21665
21665
  for (const [alias, value] of Object.entries(aliases)) {
21666
21666
  if (words.has(alias)) return value;
21667
21667
  }
@@ -23553,26 +23553,122 @@ var WebsiteCaptureResearchSchema = z116.object({
23553
23553
  });
23554
23554
 
23555
23555
  // ../../packages/types/src/demo-mode.ts
23556
- import { z as z118 } from "zod";
23556
+ import { z as z119 } from "zod";
23557
23557
 
23558
- // ../../packages/types/src/demo-mode-service-page-assets.ts
23558
+ // ../../packages/types/src/demo-mode-product.ts
23559
23559
  import { z as z117 } from "zod";
23560
- var DemoServicePageAssetSourceSchema = z117.object({
23561
- pageId: z117.string().uuid(),
23562
- ownerId: z117.string().min(1),
23563
- assets: z117.array(z117.object({
23564
- id: z117.string().uuid(),
23565
- storageKey: z117.string().min(1).max(1024),
23566
- mediaType: z117.enum([
23560
+ var text3 = z117.string().trim().min(1).max(2e5);
23561
+ var nullableText = z117.string().max(2e5).nullable();
23562
+ var image = z117.object({
23563
+ provider: text3,
23564
+ model: text3,
23565
+ prompt: z117.string().max(2e5),
23566
+ imageUrl: text3,
23567
+ width: z117.number().int().positive(),
23568
+ height: z117.number().int().positive(),
23569
+ adCopy: nullableText,
23570
+ rawResponse: z117.unknown()
23571
+ });
23572
+ var ProductDemoSnapshotSchema = z117.object({
23573
+ /** Optional only for packs frozen before seller review drafts were captured. */
23574
+ customAngleOverride: nullableText.optional(),
23575
+ painPoints: nullableText.optional(),
23576
+ benefits: nullableText.optional(),
23577
+ product: z117.object({
23578
+ title: text3,
23579
+ price: nullableText,
23580
+ country: nullableText,
23581
+ features: z117.array(text3).max(100),
23582
+ form: nullableText,
23583
+ details: z117.unknown(),
23584
+ isCombo: z117.boolean(),
23585
+ comboItems: z117.unknown(),
23586
+ images: z117.array(text3).min(1).max(50),
23587
+ cleanImages: z117.array(text3).max(50),
23588
+ cleanImagesMeta: z117.unknown()
23589
+ }),
23590
+ angles: z117.array(z117.object({
23591
+ content: text3,
23592
+ buyerPersona: nullableText,
23593
+ actor: nullableText,
23594
+ scriptNotes: nullableText
23595
+ })).min(1).max(10),
23596
+ videos: z117.array(z117.object({
23597
+ /** Present only for explicit multi-template packs; legacy arrays keep selection-order playback. */
23598
+ reviewAngleIndex: z117.number().int().min(0).max(9).optional(),
23599
+ provider: text3,
23600
+ model: text3,
23601
+ script: text3,
23602
+ prompt: z117.string().max(2e5),
23603
+ imageUrl: text3,
23604
+ durationSeconds: z117.number().int().positive().nullable(),
23605
+ format: VideoFormat,
23606
+ resultUrls: z117.array(text3).min(1).max(10),
23607
+ rawResponse: z117.unknown(),
23608
+ adCopy: nullableText
23609
+ })).min(1).max(10),
23610
+ landingImages: z117.array(z117.object({
23611
+ role: LandingRole,
23612
+ indexNum: z117.number().int().min(1),
23613
+ url: text3,
23614
+ width: z117.number().int().positive(),
23615
+ height: z117.number().int().positive(),
23616
+ notes: nullableText
23617
+ })).max(20),
23618
+ landingConfig: z117.unknown(),
23619
+ image,
23620
+ productUseSheet: z117.unknown(),
23621
+ productTruth: z117.unknown(),
23622
+ productReference: z117.object({
23623
+ referenceEvidenceVersion: z117.number().int().nonnegative(),
23624
+ planVersion: z117.number().int().positive(),
23625
+ baseReferenceSetHash: text3,
23626
+ referenceSet: z117.unknown(),
23627
+ preparationPlan: z117.unknown(),
23628
+ canonicalIdentityAnchors: z117.unknown()
23629
+ })
23630
+ });
23631
+ var ProductDemoPhaseSchema = z117.enum([
23632
+ "preparing",
23633
+ "angles",
23634
+ "preparing_scripts",
23635
+ "scripts",
23636
+ "generating",
23637
+ "done"
23638
+ ]);
23639
+ var ProductDemoJobPhaseSchema = z117.enum([
23640
+ "preparing",
23641
+ "scripts",
23642
+ "generating"
23643
+ ]);
23644
+ var ProductDemoTaskStateSchema = z117.object({
23645
+ admitted: z117.boolean().default(false),
23646
+ phase: ProductDemoPhaseSchema,
23647
+ waitMs: z117.number().int().positive(),
23648
+ snapshot: ProductDemoSnapshotSchema,
23649
+ selectedAngleIndices: z117.array(z117.number().int().min(0).max(9)).max(10),
23650
+ chargeCents: z117.number().int().min(0).max(1e5),
23651
+ maxCents: z117.number().int().min(0).optional()
23652
+ });
23653
+
23654
+ // ../../packages/types/src/demo-mode-service-page-assets.ts
23655
+ import { z as z118 } from "zod";
23656
+ var DemoServicePageAssetSourceSchema = z118.object({
23657
+ pageId: z118.string().uuid(),
23658
+ ownerId: z118.string().min(1),
23659
+ assets: z118.array(z118.object({
23660
+ id: z118.string().uuid(),
23661
+ storageKey: z118.string().min(1).max(1024),
23662
+ mediaType: z118.enum([
23567
23663
  "image/webp",
23568
23664
  "video/mp4"
23569
23665
  ]),
23570
- byteSize: z117.number().int().positive().max(32 * 1024 * 1024),
23571
- width: z117.number().int().positive().max(1920),
23572
- height: z117.number().int().positive().max(1920),
23573
- contentHash: z117.string().regex(/^[a-f0-9]{64}$/i),
23666
+ byteSize: z118.number().int().positive().max(32 * 1024 * 1024),
23667
+ width: z118.number().int().positive().max(1920),
23668
+ height: z118.number().int().positive().max(1920),
23669
+ contentHash: z118.string().regex(/^[a-f0-9]{64}$/i),
23574
23670
  sourceKind: ServicePageSourceKindSchema,
23575
- approvedAt: z117.string().datetime()
23671
+ approvedAt: z118.string().datetime()
23576
23672
  }).strict()).max(24)
23577
23673
  }).strict();
23578
23674
 
@@ -23581,9 +23677,10 @@ var DEMO_MODE_FLOWS = [
23581
23677
  "brand",
23582
23678
  "servicePage",
23583
23679
  "motion",
23584
- "image"
23680
+ "image",
23681
+ "product"
23585
23682
  ];
23586
- var DemoModeFlowSchema = z118.enum(DEMO_MODE_FLOWS);
23683
+ var DemoModeFlowSchema = z119.enum(DEMO_MODE_FLOWS);
23587
23684
  var DEMO_MODE_STEPS = [
23588
23685
  "running",
23589
23686
  "research",
@@ -23596,108 +23693,166 @@ var DEMO_MODE_STEPS = [
23596
23693
  "final",
23597
23694
  "watchdog"
23598
23695
  ];
23599
- var DemoModeStepSchema = z118.enum(DEMO_MODE_STEPS);
23696
+ var DemoModeStepSchema = z119.enum(DEMO_MODE_STEPS);
23600
23697
  var DEMO_MODE_WAIT_SECONDS = {
23601
23698
  min: 30,
23602
23699
  max: 450,
23603
23700
  default: 150
23604
23701
  };
23605
- var centsSchema = z118.number().int().min(0).max(1e5);
23606
- var emailSchema = z118.string().trim().toLowerCase().email();
23607
- var optionalTemplateId = z118.preprocess((value) => value === "" ? void 0 : value, z118.string().uuid().optional());
23608
- var DemoModeTemplatesSchema = z118.object({
23609
- brandId: z118.string().uuid(),
23610
- servicePageId: z118.string().uuid(),
23611
- motionTaskId: z118.string().uuid(),
23702
+ var DEMO_MODE_DEFAULT_CHARGE_CENTS = {
23703
+ brand: 100,
23704
+ servicePage: 300,
23705
+ motion: 1500,
23706
+ image: 200,
23707
+ product: 1500
23708
+ };
23709
+ var centsSchema = z119.number().int().min(0).max(1e5);
23710
+ var emailSchema = z119.string().trim().toLowerCase().email();
23711
+ var DEMO_MODE_OPTIONAL_MOTION_TEMPLATE_KEYS = [
23712
+ "motionVariantTaskId",
23713
+ "motionThirdTaskId"
23714
+ ];
23715
+ var DEMO_MODE_OPTIONAL_PRODUCT_VIDEO_TEMPLATE_KEYS = [
23716
+ "productVideoVariantTaskId",
23717
+ "productVideoThirdTaskId"
23718
+ ];
23719
+ var DEMO_MODE_PRODUCT_VIDEO_TEMPLATE_KEYS = [
23720
+ "productVideoTaskId",
23721
+ ...DEMO_MODE_OPTIONAL_PRODUCT_VIDEO_TEMPLATE_KEYS
23722
+ ];
23723
+ var DEMO_MODE_PRODUCT_TEMPLATE_KEYS = [
23724
+ "productLandingTaskId",
23725
+ "productVideoTaskId",
23726
+ "productImageTaskId"
23727
+ ];
23728
+ var DEMO_MODE_PRODUCT_ALL_TEMPLATE_KEYS = [
23729
+ ...DEMO_MODE_PRODUCT_TEMPLATE_KEYS,
23730
+ ...DEMO_MODE_OPTIONAL_PRODUCT_VIDEO_TEMPLATE_KEYS
23731
+ ];
23732
+ var DEMO_MODE_OPTIONAL_TEMPLATE_KEYS = [
23733
+ ...DEMO_MODE_OPTIONAL_MOTION_TEMPLATE_KEYS,
23734
+ ...DEMO_MODE_PRODUCT_ALL_TEMPLATE_KEYS
23735
+ ];
23736
+ var optionalTemplateId = z119.preprocess((value) => value === "" ? void 0 : value, z119.string().uuid().optional());
23737
+ var DemoModeTemplatesSchema = z119.object({
23738
+ brandId: z119.string().uuid(),
23739
+ servicePageId: z119.string().uuid(),
23740
+ motionTaskId: z119.string().uuid(),
23612
23741
  motionVariantTaskId: optionalTemplateId,
23613
23742
  motionThirdTaskId: optionalTemplateId,
23614
- imageTaskId: z118.string().uuid()
23615
- });
23616
- var DemoModeEditableSchema = z118.object({
23617
- enabled: z118.boolean(),
23618
- emails: z118.array(emailSchema).max(50).transform((list) => [
23743
+ imageTaskId: z119.string().uuid(),
23744
+ productLandingTaskId: optionalTemplateId,
23745
+ productVideoTaskId: optionalTemplateId,
23746
+ productVideoVariantTaskId: optionalTemplateId,
23747
+ productVideoThirdTaskId: optionalTemplateId,
23748
+ productImageTaskId: optionalTemplateId
23749
+ });
23750
+ var DemoModeEditableObjectSchema = z119.object({
23751
+ productsEnabled: z119.boolean().default(false),
23752
+ enabled: z119.boolean(),
23753
+ emails: z119.array(emailSchema).max(50).transform((list) => [
23619
23754
  ...new Set(list)
23620
23755
  ]),
23621
- waitSeconds: z118.number().int().min(DEMO_MODE_WAIT_SECONDS.min).max(DEMO_MODE_WAIT_SECONDS.max),
23622
- chargeCents: z118.object({
23756
+ waitSeconds: z119.number().int().min(DEMO_MODE_WAIT_SECONDS.min).max(DEMO_MODE_WAIT_SECONDS.max),
23757
+ chargeCents: z119.object({
23623
23758
  brand: centsSchema,
23624
23759
  servicePage: centsSchema,
23625
23760
  motion: centsSchema,
23626
- image: centsSchema
23761
+ image: centsSchema,
23762
+ product: centsSchema.default(DEMO_MODE_DEFAULT_CHARGE_CENTS.product)
23627
23763
  }),
23628
23764
  templates: DemoModeTemplatesSchema
23629
23765
  });
23630
- var nullableString = z118.string().nullable();
23631
- var DemoModeSnapshotSchema = z118.object({
23632
- brand: z118.object({
23766
+ var DemoModeEditableSchema = DemoModeEditableObjectSchema.superRefine((value, ctx) => {
23767
+ if (!value.productsEnabled) return;
23768
+ for (const key of DEMO_MODE_PRODUCT_TEMPLATE_KEYS) {
23769
+ if (!value.templates[key]) ctx.addIssue({
23770
+ code: z119.ZodIssueCode.custom,
23771
+ path: [
23772
+ "templates",
23773
+ key
23774
+ ],
23775
+ message: "Product demo requires all three templates"
23776
+ });
23777
+ }
23778
+ });
23779
+ var nullableString = z119.string().nullable();
23780
+ var DemoModeSnapshotSchema = z119.object({
23781
+ product: ProductDemoSnapshotSchema.optional(),
23782
+ brand: z119.object({
23633
23783
  /** Columnas de identidad de `Brand` listas para un `update` (sin id/userId/slug/estado/fechas). */
23634
- identity: z118.record(z118.unknown()),
23635
- productSamples: z118.array(z118.object({
23636
- name: z118.string(),
23637
- priceCents: z118.number().int().nullable(),
23784
+ identity: z119.record(z119.unknown()),
23785
+ productSamples: z119.array(z119.object({
23786
+ name: z119.string(),
23787
+ priceCents: z119.number().int().nullable(),
23638
23788
  currency: nullableString,
23639
- imageKey: z118.string(),
23789
+ imageKey: z119.string(),
23640
23790
  productUrl: nullableString,
23641
- position: z118.number().int()
23791
+ position: z119.number().int()
23642
23792
  })),
23643
- personas: z118.array(z118.object({
23644
- name: z118.string(),
23793
+ personas: z119.array(z119.object({
23794
+ name: z119.string(),
23645
23795
  demographics: nullableString,
23646
23796
  painPoints: nullableString,
23647
23797
  motivations: nullableString,
23648
23798
  objections: nullableString,
23649
23799
  gender: nullableString,
23650
- isDefault: z118.boolean()
23800
+ isDefault: z119.boolean()
23651
23801
  }))
23652
23802
  }),
23653
- servicePage: z118.object({
23654
- facts: z118.unknown(),
23655
- review: z118.unknown(),
23656
- artifact: z118.unknown(),
23803
+ servicePage: z119.object({
23804
+ facts: z119.unknown(),
23805
+ review: z119.unknown(),
23806
+ artifact: z119.unknown(),
23657
23807
  /** Optional only for snapshots saved before page-owned demo media. */
23658
23808
  assetSource: DemoServicePageAssetSourceSchema.optional()
23659
23809
  }),
23660
- motion: z118.object({
23810
+ motion: z119.object({
23661
23811
  outputs: MotionGraphicsOutputsSchema,
23662
23812
  /**
23663
23813
  * La captura REAL de la web de la plantilla (nunca una fabricada por la
23664
23814
  * demo). Null cuando la plantilla no tiene ninguna: la captura demo nunca
23665
23815
  * va live, así que el servicio usa `DEMO_MODE_PLACEHOLDER_CAPTURE`.
23666
23816
  */
23667
- capture: z118.object({
23668
- bundleKey: z118.string(),
23669
- sha256: z118.string(),
23670
- uploadBytes: z118.number().int().nullable(),
23817
+ capture: z119.object({
23818
+ bundleKey: z119.string(),
23819
+ sha256: z119.string(),
23820
+ uploadBytes: z119.number().int().nullable(),
23671
23821
  previewKey: nullableString
23672
23822
  }).nullable()
23673
23823
  }),
23674
- image: z118.object({
23675
- provider: z118.string(),
23676
- model: z118.string(),
23677
- prompt: z118.string(),
23678
- imageUrl: z118.string(),
23679
- width: z118.number().int(),
23680
- height: z118.number().int(),
23824
+ image: z119.object({
23825
+ provider: z119.string(),
23826
+ model: z119.string(),
23827
+ prompt: z119.string(),
23828
+ imageUrl: z119.string(),
23829
+ width: z119.number().int(),
23830
+ height: z119.number().int(),
23681
23831
  adCopy: nullableString,
23682
- rawResponse: z118.unknown()
23832
+ rawResponse: z119.unknown()
23683
23833
  })
23684
23834
  });
23685
- var DemoModeConfigSchema = DemoModeEditableSchema.extend({
23835
+ var DemoModeConfigSchema = DemoModeEditableObjectSchema.extend({
23686
23836
  snapshot: DemoModeSnapshotSchema.nullable(),
23687
- snapshotAt: z118.string().datetime().nullable()
23837
+ snapshotAt: z119.string().datetime().nullable()
23688
23838
  });
23689
- var DemoModeAdminViewSchema = DemoModeEditableSchema.extend({
23839
+ var DemoModeAdminViewSchema = DemoModeEditableObjectSchema.extend({
23690
23840
  // Sin configurar, la API devuelve ids vacíos ("" no es uuid): la vista los
23691
23841
  // admite; el PUT sí exige uuid (`DemoModeEditableSchema`).
23692
- templates: z118.object({
23693
- brandId: z118.string(),
23694
- servicePageId: z118.string(),
23695
- motionTaskId: z118.string(),
23696
- motionVariantTaskId: z118.string().optional(),
23697
- motionThirdTaskId: z118.string().optional(),
23698
- imageTaskId: z118.string()
23842
+ templates: z119.object({
23843
+ brandId: z119.string(),
23844
+ servicePageId: z119.string(),
23845
+ motionTaskId: z119.string(),
23846
+ motionVariantTaskId: z119.string().optional(),
23847
+ motionThirdTaskId: z119.string().optional(),
23848
+ imageTaskId: z119.string(),
23849
+ productLandingTaskId: z119.string().optional(),
23850
+ productVideoTaskId: z119.string().optional(),
23851
+ productVideoVariantTaskId: z119.string().optional(),
23852
+ productVideoThirdTaskId: z119.string().optional(),
23853
+ productImageTaskId: z119.string().optional()
23699
23854
  }),
23700
- snapshotAt: z118.string().nullable()
23855
+ snapshotAt: z119.string().nullable()
23701
23856
  });
23702
23857
  var DEMO_MODE_TEMPLATE_PROBLEMS = [
23703
23858
  "not_found",
@@ -23706,35 +23861,45 @@ var DEMO_MODE_TEMPLATE_PROBLEMS = [
23706
23861
  "artifact_invalid",
23707
23862
  "task_not_done",
23708
23863
  "no_video",
23709
- "no_creative"
23864
+ "no_creative",
23865
+ "product_invalid",
23866
+ "product_mismatch",
23867
+ "no_angles",
23868
+ "no_landing"
23710
23869
  ];
23711
- var DemoModeTemplateVerdictSchema = z118.discriminatedUnion("ok", [
23712
- z118.object({
23713
- ok: z118.literal(true)
23870
+ var DemoModeTemplateVerdictSchema = z119.discriminatedUnion("ok", [
23871
+ z119.object({
23872
+ ok: z119.literal(true)
23714
23873
  }),
23715
- z118.object({
23716
- ok: z118.literal(false),
23717
- problem: z118.enum(DEMO_MODE_TEMPLATE_PROBLEMS)
23874
+ z119.object({
23875
+ ok: z119.literal(false),
23876
+ problem: z119.enum(DEMO_MODE_TEMPLATE_PROBLEMS)
23718
23877
  })
23719
23878
  ]);
23720
- var DemoModeValidationSchema = z118.object({
23879
+ var DemoModeValidationSchema = z119.object({
23721
23880
  brandId: DemoModeTemplateVerdictSchema,
23722
23881
  servicePageId: DemoModeTemplateVerdictSchema,
23723
23882
  motionTaskId: DemoModeTemplateVerdictSchema,
23724
23883
  motionVariantTaskId: DemoModeTemplateVerdictSchema.optional(),
23725
23884
  motionThirdTaskId: DemoModeTemplateVerdictSchema.optional(),
23726
- imageTaskId: DemoModeTemplateVerdictSchema
23727
- });
23728
- var DemoModeJobSchema = z118.object({
23885
+ imageTaskId: DemoModeTemplateVerdictSchema,
23886
+ productLandingTaskId: DemoModeTemplateVerdictSchema.optional(),
23887
+ productVideoTaskId: DemoModeTemplateVerdictSchema.optional(),
23888
+ productVideoVariantTaskId: DemoModeTemplateVerdictSchema.optional(),
23889
+ productVideoThirdTaskId: DemoModeTemplateVerdictSchema.optional(),
23890
+ productImageTaskId: DemoModeTemplateVerdictSchema.optional()
23891
+ });
23892
+ var DemoModeJobSchema = z119.object({
23729
23893
  flow: DemoModeFlowSchema,
23894
+ productPhase: ProductDemoJobPhaseSchema.optional(),
23730
23895
  step: DemoModeStepSchema,
23731
23896
  /** brandId | servicePageOperationId | taskId según el flujo. */
23732
- targetId: z118.string().uuid(),
23733
- userId: z118.string().min(1),
23897
+ targetId: z119.string().uuid(),
23898
+ userId: z119.string().min(1),
23734
23899
  /** Solo marca: la generación de extracción que el guion completa. */
23735
- generation: z118.number().int().positive().optional(),
23900
+ generation: z119.number().int().positive().optional(),
23736
23901
  /** Solo `final`/`watchdog`: la parte del snapshot de ESTE flujo, congelada al empezar. */
23737
- result: z118.unknown().optional()
23902
+ result: z119.unknown().optional()
23738
23903
  });
23739
23904
 
23740
23905
  // ../../packages/utils/src/retry-after.ts
@@ -24210,7 +24375,7 @@ var ApiClient = class {
24210
24375
  };
24211
24376
 
24212
24377
  // src/index.ts
24213
- var MCP_VERSION = "12.1.2";
24378
+ var MCP_VERSION = "12.1.4";
24214
24379
 
24215
24380
  // src/meta-upload-app.ts
24216
24381
  import { readFileSync } from "fs";
@@ -24307,12 +24472,12 @@ function buildTaskResultsView(media, proxyBaseUrl) {
24307
24472
  return null;
24308
24473
  }
24309
24474
  }, "safeUrl");
24310
- const images = media.images.flatMap((image, index) => {
24311
- const url = safeUrl(image.url);
24475
+ const images = media.images.flatMap((image2, index) => {
24476
+ const url = safeUrl(image2.url);
24312
24477
  return url ? [
24313
24478
  {
24314
24479
  url,
24315
- alt: image.alt?.slice(0, 160) ?? `ProductMaker image ${index + 1}`
24480
+ alt: image2.alt?.slice(0, 160) ?? `ProductMaker image ${index + 1}`
24316
24481
  }
24317
24482
  ] : [];
24318
24483
  });
@@ -24397,7 +24562,7 @@ function registerTaskResultsAppResource(server, proxyBaseUrl) {
24397
24562
  __name(registerTaskResultsAppResource, "registerTaskResultsAppResource");
24398
24563
 
24399
24564
  // src/tools/tasks.ts
24400
- import { z as z124 } from "zod";
24565
+ import { z as z125 } from "zod";
24401
24566
 
24402
24567
  // src/resolve-image.ts
24403
24568
  import { lookup as dnsLookup } from "dns/promises";
@@ -24958,9 +25123,9 @@ async function resolveMediaRef(ref, opts) {
24958
25123
  __name(resolveMediaRef, "resolveMediaRef");
24959
25124
 
24960
25125
  // src/tools/shared.ts
24961
- import { z as z119 } from "zod";
24962
- var Lang = z119.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);
24963
- var Country = z119.string().min(2).max(3);
25126
+ import { z as z120 } from "zod";
25127
+ var Lang = z120.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);
25128
+ var Country = z120.string().min(2).max(3);
24964
25129
  var LandingStrategyEnum = LandingStrategySchema;
24965
25130
  var LandingImageFormatEnum = LandingImageFormatSchema;
24966
25131
  var VideoPresetEnum = VideoPreset.extract([
@@ -25064,7 +25229,7 @@ function animationStyleApplies(videoPreset, angleNarratives) {
25064
25229
  return ANIMATED_VIDEO_PRESETS.has(videoPreset ?? "") || (angleNarratives ?? []).some((n) => ANIMATED_NARRATIVE_STYLES.has(n));
25065
25230
  }
25066
25231
  __name(animationStyleApplies, "animationStyleApplies");
25067
- var VideoTierEnum = z119.enum([
25232
+ var VideoTierEnum = z120.enum([
25068
25233
  "basic"
25069
25234
  ]);
25070
25235
  function resolveVideoTier(_tier) {
@@ -25122,10 +25287,10 @@ var ImageCreativeStyleEnum = ImageCreativeStyle;
25122
25287
  var ImageCreativeArchetypeEnum = ImageCreativeArchetype;
25123
25288
  var ImageCreativeVisualTreatmentEnum = ImageCreativeVisualTreatment;
25124
25289
  var ImageCreativeAspectRatioEnum = ImageCreativeAspectRatio;
25125
- var ImageRefSchema = z119.object({
25126
- url: z119.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.'),
25127
- path: z119.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`.'),
25128
- assetId: z119.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.")
25290
+ var ImageRefSchema = z120.object({
25291
+ url: z120.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.'),
25292
+ path: z120.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`.'),
25293
+ assetId: z120.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.")
25129
25294
  }).refine((v) => [
25130
25295
  v.url,
25131
25296
  v.path,
@@ -25133,18 +25298,18 @@ var ImageRefSchema = z119.object({
25133
25298
  ].filter(Boolean).length === 1, {
25134
25299
  message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
25135
25300
  });
25136
- var ImagesInput = z119.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
25137
- const assetCount = images.filter((image) => Boolean(image.assetId)).length;
25301
+ var ImagesInput = z120.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
25302
+ const assetCount = images.filter((image2) => Boolean(image2.assetId)).length;
25138
25303
  if (assetCount > 0 && assetCount !== images.length) {
25139
25304
  ctx.addIssue({
25140
- code: z119.ZodIssueCode.custom,
25305
+ code: z120.ZodIssueCode.custom,
25141
25306
  message: "all image entries must use assetId, or all must use URL/path sources"
25142
25307
  });
25143
25308
  }
25144
25309
  }).describe('1 a 5 fotos del MISMO producto. La PRIMERA es la principal (hero); las dem\xE1s son \xE1ngulos adicionales. NO mezcles productos distintos en una sola llamada.\n\nCada entrada tiene EXACTAMENTE uno de:\n\u2022 `url` \u2014 URL p\xFAblica HTTPS (Shopify CDN, Cloudinary). Prefi\xE9rela si la foto ya est\xE1 hospedada.\n\u2022 `path` \u2014 Ruta del archivo en el computador del usuario (ej. "/Users/maria/Desktop/foto.jpg", "~/Downloads/camiseta.png"). \xDAsala cuando el usuario te dijo d\xF3nde guard\xF3 la foto. Solo MCP local \u2014 el cliente web rechaza paths.\n\n\u2022 `assetId` \u2014 ID opaco devuelto por `check_media_upload`. En MCP remoto, si el usuario quiere usar una foto de su laptop, llama `request_media_upload` y no pidas una ruta local ni URL.\n\nNo mezcles assetId con URL/path en la misma llamada. Los paths se conservan solo para MCP local por stdio.');
25145
25310
  function uploadedAssetIds(images) {
25146
- if (!images.length || !images.every((image) => Boolean(image.assetId))) return null;
25147
- return images.map((image) => image.assetId);
25311
+ if (!images.length || !images.every((image2) => Boolean(image2.assetId))) return null;
25312
+ return images.map((image2) => image2.assetId);
25148
25313
  }
25149
25314
  __name(uploadedAssetIds, "uploadedAssetIds");
25150
25315
  function asText(value) {
@@ -25218,14 +25383,14 @@ async function submitCreative(api, opts) {
25218
25383
  });
25219
25384
  }
25220
25385
  __name(submitCreative, "submitCreative");
25221
- var ResearchTargetCountryEnum = z119.enum([
25386
+ var ResearchTargetCountryEnum = z120.enum([
25222
25387
  "CO",
25223
25388
  "MX",
25224
25389
  "PE",
25225
25390
  "EC",
25226
25391
  "CL"
25227
25392
  ]);
25228
- var ResearchCategoryEnum = z119.enum([
25393
+ var ResearchCategoryEnum = z120.enum([
25229
25394
  "auto",
25230
25395
  "automotive",
25231
25396
  "kitchen",
@@ -26020,7 +26185,7 @@ function approveRefusalMessage(reason) {
26020
26185
  __name(approveRefusalMessage, "approveRefusalMessage");
26021
26186
 
26022
26187
  // src/tools/task-outputs.ts
26023
- import { z as z120 } from "zod";
26188
+ import { z as z121 } from "zod";
26024
26189
 
26025
26190
  // src/asset-proxy.ts
26026
26191
  import { createHmac, timingSafeEqual } from "crypto";
@@ -26204,12 +26369,12 @@ function serviceVideoResultMedia(result) {
26204
26369
  };
26205
26370
  }
26206
26371
  __name(serviceVideoResultMedia, "serviceVideoResultMedia");
26207
- var CreativeVariantIdentity = z120.object({
26208
- variantTaskId: z120.string().uuid(),
26209
- sourceTaskId: z120.string().uuid(),
26372
+ var CreativeVariantIdentity = z121.object({
26373
+ variantTaskId: z121.string().uuid(),
26374
+ sourceTaskId: z121.string().uuid(),
26210
26375
  kind: TaskCreativeVariantKind,
26211
26376
  status: TaskStatusSchema,
26212
- error: z120.string().optional()
26377
+ error: z121.string().optional()
26213
26378
  });
26214
26379
  function proxifyOutputs(outputs, proxyBaseUrl) {
26215
26380
  if (!proxyBaseUrl || !isProxyEnabled()) return outputs;
@@ -26813,59 +26978,59 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
26813
26978
  __name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
26814
26979
 
26815
26980
  // src/tools/media-presentation.ts
26816
- import { z as z121 } from "zod";
26817
- var HttpsPresentationUrlSchema = z121.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
26981
+ import { z as z122 } from "zod";
26982
+ var HttpsPresentationUrlSchema = z122.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
26818
26983
  var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
26819
26984
  const hostname = new URL(value).hostname.toLowerCase();
26820
26985
  return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
26821
26986
  }, "preview URL must be owned by ProductMaker");
26822
- var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z121.number().int().positive().max(maximum), "positiveIntAtMost");
26823
- var PresentationImageSchema = z121.object({
26824
- kind: z121.literal("image"),
26987
+ var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z122.number().int().positive().max(maximum), "positiveIntAtMost");
26988
+ var PresentationImageSchema = z122.object({
26989
+ kind: z122.literal("image"),
26825
26990
  url: HttpsPresentationUrlSchema,
26826
- mimeType: z121.enum([
26991
+ mimeType: z122.enum([
26827
26992
  "image/jpeg",
26828
26993
  "image/png"
26829
26994
  ]),
26830
26995
  byteSize: positiveIntAtMost(5 * 1024 * 1024),
26831
26996
  width: positiveIntAtMost(16384),
26832
26997
  height: positiveIntAtMost(16384),
26833
- alt: z121.string().trim().min(1).max(240)
26998
+ alt: z122.string().trim().min(1).max(240)
26834
26999
  }).strict();
26835
27000
  var McpMediaPresentationSchema = PresentationImageSchema;
26836
- var GalleryImageSchema = z121.object({
27001
+ var GalleryImageSchema = z122.object({
26837
27002
  url: ProductMakerPreviewUrlSchema,
26838
- alt: z121.string().trim().min(1).max(240)
27003
+ alt: z122.string().trim().min(1).max(240)
26839
27004
  });
26840
27005
  var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
26841
- async function imageBlocks(image, transport) {
27006
+ async function imageBlocks(image2, transport) {
26842
27007
  const portableFallback = [
26843
27008
  {
26844
27009
  type: "resource_link",
26845
- uri: image.url,
26846
- name: image.alt,
26847
- ...image.mimeType ? {
26848
- mimeType: image.mimeType
27010
+ uri: image2.url,
27011
+ name: image2.alt,
27012
+ ...image2.mimeType ? {
27013
+ mimeType: image2.mimeType
26849
27014
  } : {},
26850
- ...image.byteSize ? {
26851
- size: image.byteSize
27015
+ ...image2.byteSize ? {
27016
+ size: image2.byteSize
26852
27017
  } : {}
26853
27018
  },
26854
27019
  {
26855
27020
  type: "text",
26856
- text: `Si no ves la imagen, \xE1brela aqu\xED: ${image.url}`
27021
+ text: `Si no ves la imagen, \xE1brela aqu\xED: ${image2.url}`
26857
27022
  }
26858
27023
  ];
26859
27024
  try {
26860
27025
  const [resolved] = await resolveImages([
26861
27026
  {
26862
- url: image.url
27027
+ url: image2.url
26863
27028
  }
26864
27029
  ], {
26865
27030
  transport,
26866
- maxBytes: image.byteSize ?? MCP_GALLERY_IMAGE_MAX_BYTES
27031
+ maxBytes: image2.byteSize ?? MCP_GALLERY_IMAGE_MAX_BYTES
26867
27032
  });
26868
- if (!resolved || image.mimeType && resolved.mimetype !== image.mimeType || resolved.buffer.byteLength > (image.byteSize ?? MCP_GALLERY_IMAGE_MAX_BYTES)) {
27033
+ if (!resolved || image2.mimeType && resolved.mimetype !== image2.mimeType || resolved.buffer.byteLength > (image2.byteSize ?? MCP_GALLERY_IMAGE_MAX_BYTES)) {
26869
27034
  return portableFallback;
26870
27035
  }
26871
27036
  return [
@@ -26892,12 +27057,12 @@ async function buildMcpMediaPresentationContent(rawPresentation, transport = "ht
26892
27057
  ];
26893
27058
  }
26894
27059
  __name(buildMcpMediaPresentationContent, "buildMcpMediaPresentationContent");
26895
- var OwnedImagePreviewSchema = z121.object({
27060
+ var OwnedImagePreviewSchema = z122.object({
26896
27061
  url: HttpsPresentationUrlSchema.refine((value) => {
26897
27062
  const url = new URL(value);
26898
27063
  return !url.username && !url.password && !isPrivateHost(url.hostname);
26899
27064
  }, "Preview URL must be public HTTPS without credentials"),
26900
- alt: z121.string().trim().min(1).max(240)
27065
+ alt: z122.string().trim().min(1).max(240)
26901
27066
  });
26902
27067
  async function buildMcpImagePreviewContent(rawPreview, transport = "http") {
26903
27068
  const preview2 = OwnedImagePreviewSchema.safeParse(rawPreview);
@@ -26973,24 +27138,24 @@ async function buildMcpImageGalleryContent(rawItems, transport = "http") {
26973
27138
  }
26974
27139
  ];
26975
27140
  }
26976
- const image = parsed.data;
27141
+ const image2 = parsed.data;
26977
27142
  const heading = {
26978
27143
  type: "text",
26979
- text: `Foto ${index + 1}: ${image.alt}`
27144
+ text: `Foto ${index + 1}: ${image2.alt}`
26980
27145
  };
26981
27146
  const fallback = {
26982
27147
  type: "resource_link",
26983
- uri: image.url,
26984
- name: `Abrir foto ${index + 1}: ${image.alt}`
27148
+ uri: image2.url,
27149
+ name: `Abrir foto ${index + 1}: ${image2.alt}`
26985
27150
  };
26986
27151
  const textFallback = {
26987
27152
  type: "text",
26988
- text: `Si no ves la foto ${index + 1}, \xE1brela aqu\xED: ${image.url}`
27153
+ text: `Si no ves la foto ${index + 1}, \xE1brela aqu\xED: ${image2.url}`
26989
27154
  };
26990
27155
  try {
26991
27156
  const [resolved] = await resolveImages([
26992
27157
  {
26993
- url: image.url
27158
+ url: image2.url
26994
27159
  }
26995
27160
  ], {
26996
27161
  transport,
@@ -27193,7 +27358,7 @@ async function observeMcpMediaDelivery(fingerprint, work) {
27193
27358
  __name(observeMcpMediaDelivery, "observeMcpMediaDelivery");
27194
27359
 
27195
27360
  // src/tools/animated-video.ts
27196
- import { z as z122 } from "zod";
27361
+ import { z as z123 } from "zod";
27197
27362
 
27198
27363
  // src/tools/paid-confirmation.ts
27199
27364
  function describeMarketStudyChoice(enabled) {
@@ -27442,30 +27607,30 @@ function hookVariantsLabel(count) {
27442
27607
  return count === 1 ? "1 versi\xF3n del gancho" : `${count} versiones del gancho`;
27443
27608
  }
27444
27609
  __name(hookVariantsLabel, "hookVariantsLabel");
27445
- var DurationInput = z122.union(MOTION_GRAPHICS_DURATIONS.map((d) => z122.literal(d)));
27446
- var CreateAnimatedVideoInput = z122.object({
27447
- action: z122.enum([
27610
+ var DurationInput = z123.union(MOTION_GRAPHICS_DURATIONS.map((d) => z123.literal(d)));
27611
+ var CreateAnimatedVideoInput = z123.object({
27612
+ action: z123.enum([
27448
27613
  "prepare",
27449
27614
  "status",
27450
27615
  "cancel",
27451
27616
  "generate"
27452
27617
  ]).default("prepare").describe("prepare inicia una captura gratuita; status consulta websiteCaptureId; cancel la cancela; generate requiere captura ready y confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrar vista previa y precio."),
27453
- brandId: z122.string().uuid().optional().describe("ID de un servicio propio y listo (de create_brand). Obligatorio al preparar y crear videos nuevos. Conserva el mismo brandId en reintentos; si recuperas una generaci\xF3n hist\xF3rica aceptada sin este campo, om\xEDtelo como en la petici\xF3n original. status/cancel no lo necesitan."),
27454
- websiteCaptureId: z122.string().uuid().optional().describe("ID de la captura preparada. Obligatorio para status/cancel/generate; no inventarlo."),
27455
- generationRequestId: z122.string().uuid().optional().describe("Identidad opcional de una generaci\xF3n confirmada. Repite el mismo UUID al recuperar una respuesta perdida; usa otro \xFAnicamente cuando el usuario pida y confirme otro video, nunca por un error de transporte."),
27456
- confirmed: z122.boolean().optional().describe("Solo true despu\xE9s de que el usuario confirme esta captura, formato, duraci\xF3n, idioma y precio. Obligatorio para generate; preparar no genera ni cobra."),
27618
+ brandId: z123.string().uuid().optional().describe("ID de un servicio propio y listo (de create_brand). Obligatorio al preparar y crear videos nuevos. Conserva el mismo brandId en reintentos; si recuperas una generaci\xF3n hist\xF3rica aceptada sin este campo, om\xEDtelo como en la petici\xF3n original. status/cancel no lo necesitan."),
27619
+ websiteCaptureId: z123.string().uuid().optional().describe("ID de la captura preparada. Obligatorio para status/cancel/generate; no inventarlo."),
27620
+ generationRequestId: z123.string().uuid().optional().describe("Identidad opcional de una generaci\xF3n confirmada. Repite el mismo UUID al recuperar una respuesta perdida; usa otro \xFAnicamente cuando el usuario pida y confirme otro video, nunca por un error de transporte."),
27621
+ confirmed: z123.boolean().optional().describe("Solo true despu\xE9s de que el usuario confirme esta captura, formato, duraci\xF3n, idioma y precio. Obligatorio para generate; preparar no genera ni cobra."),
27457
27622
  // Plain text, not `.url()`: users type «cal.com», and the web accepts it.
27458
27623
  // normalizeWebAddress (shared with the web) adds https:// and refuses
27459
27624
  // anything that is not a public http(s) address.
27460
- landingUrl: z122.string().trim().min(1).optional().describe("Enlace p\xFAblico de la p\xE1gina del servicio, como lo dio el usuario (\xABcal.com\xBB o \xABhttps://cal.com\xBB). El video sale de lo que muestra esa p\xE1gina: su marca, colores y mensajes."),
27625
+ landingUrl: z123.string().trim().min(1).optional().describe("Enlace p\xFAblico de la p\xE1gina del servicio, como lo dio el usuario (\xABcal.com\xBB o \xABhttps://cal.com\xBB). El video sale de lo que muestra esa p\xE1gina: su marca, colores y mensajes."),
27461
27626
  format: MotionGraphicsFormatSchema.optional().describe('Formato: "vertical" (9:16, Reels/TikTok), "square" (1:1, feed) u "horizontal" (16:9, YouTube/web). Si el usuario no lo dijo, PREG\xDANTALE.'),
27462
27627
  durationSec: DurationInput.optional().describe(`Duraci\xF3n en segundos: ${MOTION_GRAPHICS_DURATIONS.join(", ")}. Fija el precio (ver la descripci\xF3n de la herramienta). Si el usuario no la dijo, PREG\xDANTALE.`),
27463
27628
  language: MotionGraphicsLanguageSchema.optional().describe('Idioma de los textos del video: "es", "en" o "pt".'),
27464
27629
  videoQuality: MotionGraphicsVideoQualitySchema.default(DEFAULT_MOTION_GRAPHICS_VIDEO_QUALITY).describe('Calidad IA: "economy" (econ\xF3mica) o "pro" (alta, por defecto). Afecta el precio de los clips IA.'),
27465
27630
  videoResolution: MotionGraphicsVideoResolutionSchema.default(DEFAULT_MOTION_GRAPHICS_VIDEO_RESOLUTION).describe('Resoluci\xF3n: "480p" (por defecto), "720p" o "1080p". 1080p solo est\xE1 disponible con videoQuality="pro".'),
27466
- notes: z122.string().trim().max(MOTION_GRAPHICS_NOTES_MAX_CHARS).optional().describe("Opcional. Idea creativa, escenarios, acciones, di\xE1logo, voz o m\xFAsica en lenguaje natural. El director puede hacer solo motion graphics, escenas reales o escenas imposibles seg\xFAn la idea; las frases gu\xEDan el guion sin garantizar reproducci\xF3n exacta."),
27631
+ notes: z123.string().trim().max(MOTION_GRAPHICS_NOTES_MAX_CHARS).optional().describe("Opcional. Idea creativa, escenarios, acciones, di\xE1logo, voz o m\xFAsica en lenguaje natural. El director puede hacer solo motion graphics, escenas reales o escenas imposibles seg\xFAn la idea; las frases gu\xEDan el guion sin garantizar reproducci\xF3n exacta."),
27467
27632
  hookVariants: MotionGraphicsHookVariantsSchema.optional().describe(`Opcional. Cantidad de videos independientes, de 1 a ${MOTION_GRAPHICS_HOOK_VARIANTS_MAX} (por defecto 1). Cada uno tiene su propio \xE1ngulo, guion y estilo visual, respetando notes, y reserva el precio completo de un video (ver la descripci\xF3n); \xFAsalo solo si el usuario lo pide.`),
27468
- music: z122.boolean().optional().describe("Opcional. M\xFAsica y efectos dirigidos seg\xFAn el negocio y el video (por defecto true), con una copia adicional solo con voces. false entrega solo voces, sin m\xFAsica ni efectos a\xF1adidos ni el cargo de m\xFAsica. \xDAsalo solo si el usuario lo pide.")
27633
+ music: z123.boolean().optional().describe("Opcional. M\xFAsica y efectos dirigidos seg\xFAn el negocio y el video (por defecto true), con una copia adicional solo con voces. false entrega solo voces, sin m\xFAsica ni efectos a\xF1adidos ni el cargo de m\xFAsica. \xDAsalo solo si el usuario lo pide.")
27469
27634
  }).strict();
27470
27635
  function captureNextAction(capture) {
27471
27636
  if (capture.status === "ready") return "Muestra la vista previa al usuario y confirma formato, duraci\xF3n, idioma, calidad IA, resoluci\xF3n y precio. Solo despu\xE9s llama create_animated_video con action=generate, este websiteCaptureId y confirmed=true.";
@@ -27518,33 +27683,33 @@ var FORMAT_LABELS = {
27518
27683
  square: "cuadrado 1:1",
27519
27684
  horizontal: "horizontal 16:9"
27520
27685
  };
27521
- var AnimatedVideoResultSchema = z122.object({
27522
- status: z122.enum([
27686
+ var AnimatedVideoResultSchema = z123.object({
27687
+ status: z123.enum([
27523
27688
  "pending",
27524
27689
  "done",
27525
27690
  "error"
27526
27691
  ]),
27527
- serviceMode: z122.literal("motion_graphics"),
27528
- finalMp4Url: z122.string().optional(),
27529
- adCopy: z122.string().optional(),
27530
- adCopies: z122.array(z122.string()).optional(),
27531
- error: z122.string().optional(),
27532
- motionGraphics: z122.object({
27692
+ serviceMode: z123.literal("motion_graphics"),
27693
+ finalMp4Url: z123.string().optional(),
27694
+ adCopy: z123.string().optional(),
27695
+ adCopies: z123.array(z123.string()).optional(),
27696
+ error: z123.string().optional(),
27697
+ motionGraphics: z123.object({
27533
27698
  stage: MotionGraphicsStageSchema,
27534
27699
  format: MotionGraphicsFormatSchema,
27535
- durationSec: z122.number(),
27536
- width: z122.number().optional(),
27537
- height: z122.number().optional(),
27700
+ durationSec: z123.number(),
27701
+ width: z123.number().optional(),
27702
+ height: z123.number().optional(),
27538
27703
  language: MotionGraphicsLanguageSchema.optional(),
27539
27704
  videoQuality: MotionGraphicsVideoQualitySchema.optional().catch(void 0),
27540
27705
  videoResolution: MotionGraphicsVideoResolutionSchema.optional().catch(void 0),
27541
- creativeBatch: z122.object({
27706
+ creativeBatch: z123.object({
27542
27707
  index: MotionGraphicsHookVariantsSchema,
27543
27708
  count: MotionGraphicsHookVariantsSchema,
27544
- tasks: z122.array(z122.object({
27545
- taskId: z122.string().uuid(),
27709
+ tasks: z123.array(z123.object({
27710
+ taskId: z123.string().uuid(),
27546
27711
  index: MotionGraphicsHookVariantsSchema,
27547
- status: z122.enum([
27712
+ status: z123.enum([
27548
27713
  "queued",
27549
27714
  "processing",
27550
27715
  "done",
@@ -27552,29 +27717,29 @@ var AnimatedVideoResultSchema = z122.object({
27552
27717
  ])
27553
27718
  })).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX)
27554
27719
  }).optional().catch(void 0),
27555
- queuedAt: z122.string().optional(),
27556
- jobsAhead: z122.number().int().nonnegative().optional(),
27557
- stageStartedAt: z122.string().optional(),
27558
- renderProgress: z122.number().optional(),
27720
+ queuedAt: z123.string().optional(),
27721
+ jobsAhead: z123.number().int().nonnegative().optional(),
27722
+ stageStartedAt: z123.string().optional(),
27723
+ renderProgress: z123.number().optional(),
27559
27724
  // AI clip fields (absent on a video paid before clips, or from an API
27560
27725
  // that predates them). Lenient: an unreadable value is dropped
27561
27726
  // instead of hiding the status.
27562
- clipCount: z122.number().int().nonnegative().optional().catch(void 0),
27563
- clipsUsed: z122.number().int().nonnegative().optional().catch(void 0),
27564
- clipPriceCents: z122.number().finite().nonnegative().optional().catch(void 0),
27565
- clipsRefunded: z122.number().int().nonnegative().optional().catch(void 0),
27727
+ clipCount: z123.number().int().nonnegative().optional().catch(void 0),
27728
+ clipsUsed: z123.number().int().nonnegative().optional().catch(void 0),
27729
+ clipPriceCents: z123.number().finite().nonnegative().optional().catch(void 0),
27730
+ clipsRefunded: z123.number().int().nonnegative().optional().catch(void 0),
27566
27731
  // Hook versions (absent from an API or a video before them): the
27567
27732
  // count ordered and, once done, the signed URLs of the EXTRA versions
27568
27733
  // (hook 2, hook 3); `finalMp4Url` is hook 1.
27569
- hookVariants: z122.number().int().min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).optional().catch(void 0),
27570
- cleanVideoUrl: z122.string().url().optional().catch(void 0),
27571
- cleanVariantUrls: z122.array(z122.string().url()).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
27572
- variantUrls: z122.array(z122.string().min(1)).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
27734
+ hookVariants: z123.number().int().min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).optional().catch(void 0),
27735
+ cleanVideoUrl: z123.string().url().optional().catch(void 0),
27736
+ cleanVariantUrls: z123.array(z123.string().url()).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
27737
+ variantUrls: z123.array(z123.string().min(1)).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
27573
27738
  // Extra hook versions given back, as the task recorded it once the
27574
27739
  // refunds landed (absent until then, and from an API before it).
27575
- variantsRefunded: z122.number().int().nonnegative().optional().catch(void 0),
27576
- activity: z122.array(MotionGraphicsActivitySchema).optional().catch(void 0),
27577
- previewUrl: z122.string().optional()
27740
+ variantsRefunded: z123.number().int().nonnegative().optional().catch(void 0),
27741
+ activity: z123.array(MotionGraphicsActivitySchema).optional().catch(void 0),
27742
+ previewUrl: z123.string().optional()
27578
27743
  }).passthrough()
27579
27744
  }).passthrough();
27580
27745
  function parseAnimatedVideoResult(value) {
@@ -27627,10 +27792,10 @@ function toAgentFacingAnimatedVideo(result) {
27627
27792
  ...hasSiteText && activity ? {
27628
27793
  activity: activity.map((item) => {
27629
27794
  if (!SITE_TEXT_CODES.has(item.code) || !item.text) return item;
27630
- const { text: text3, ...rest } = item;
27795
+ const { text: text4, ...rest } = item;
27631
27796
  return {
27632
27797
  ...rest,
27633
- untrustedSiteText: text3
27798
+ untrustedSiteText: text4
27634
27799
  };
27635
27800
  })
27636
27801
  } : {}
@@ -27853,7 +28018,7 @@ function registerAnimatedVideoTools(server, api) {
27853
28018
  nowMs: 0
27854
28019
  })
27855
28020
  });
27856
- const parsedTaskIds = z122.array(z122.string().uuid()).min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).safeParse(created.taskIds);
28021
+ const parsedTaskIds = z123.array(z123.string().uuid()).min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).safeParse(created.taskIds);
27857
28022
  const taskIds = parsedTaskIds.success && parsedTaskIds.data[0] === created.taskId ? parsedTaskIds.data : void 0;
27858
28023
  const receipt = {
27859
28024
  taskId: created.taskId,
@@ -27895,10 +28060,10 @@ function registerAnimatedVideoTools(server, api) {
27895
28060
  __name(registerAnimatedVideoTools, "registerAnimatedVideoTools");
27896
28061
 
27897
28062
  // src/tools/winning-product-image.ts
27898
- import { z as z123 } from "zod";
27899
- var WinnerReferenceInput = z123.object({
27900
- runId: z123.string().uuid(),
27901
- candidateSourceId: z123.string().trim().min(1).max(160)
28063
+ import { z as z124 } from "zod";
28064
+ var WinnerReferenceInput = z124.object({
28065
+ runId: z124.string().uuid(),
28066
+ candidateSourceId: z124.string().trim().min(1).max(160)
27902
28067
  }).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
27903
28068
  async function resolveWinnerImages(api, winnerReference, images) {
27904
28069
  if (!winnerReference) return images;
@@ -27909,9 +28074,9 @@ async function resolveWinnerImages(api, winnerReference, images) {
27909
28074
  },
27910
28075
  ...images ?? []
27911
28076
  ];
27912
- const unique = combined.filter((image, index, all) => all.findIndex((candidate) => candidate.assetId === image.assetId) === index);
28077
+ const unique = combined.filter((image2, index, all) => all.findIndex((candidate) => candidate.assetId === image2.assetId) === index);
27913
28078
  if (unique.length > 5) throw new Error("M\xE1ximo 5 fotos del producto en total.");
27914
- if (!unique.every((image) => Boolean(image.assetId))) {
28079
+ if (!unique.every((image2) => Boolean(image2.assetId))) {
27915
28080
  throw new Error("Cuando reutilizas la foto encontrada, carga las fotos adicionales con request_media_upload.");
27916
28081
  }
27917
28082
  return unique;
@@ -27935,62 +28100,62 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
27935
28100
  var CREATE_SERVICE_VIDEO_ON_MCP = PRODUCTMAKER_MCP_CAPABILITY_NAMES.includes("create_service_video");
27936
28101
  var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
27937
28102
  var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
27938
- var CreateProductTaskInput = z124.object({
28103
+ var CreateProductTaskInput = z125.object({
27939
28104
  images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
27940
28105
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
27941
- projectId: z124.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
27942
- productUrl: z124.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."),
28106
+ projectId: z125.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
28107
+ productUrl: z125.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."),
27943
28108
  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.'),
27944
28109
  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.'),
27945
- price: z124.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.'),
27946
- compareAtPrice: z124.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".'),
27947
- offer: z124.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.'),
27948
- paymentMethods: z124.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.'),
27949
- productContext: z124.string().max(PRODUCT_CONTEXT_MAX_CHARS).optional().describe("Opcional. Informacion adicional del producto que la IA debe usar como contexto prioritario: uso real, comprador, restricciones, diferenciadores o direccion creativa. No reemplaza la investigacion de competencia; si hay competencia, guia el primer angulo y los outputs no deben contradecirlo."),
27950
- productLabel: z124.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.'),
28110
+ price: z125.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.'),
28111
+ compareAtPrice: z125.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".'),
28112
+ offer: z125.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.'),
28113
+ paymentMethods: z125.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.'),
28114
+ productContext: z125.string().max(PRODUCT_CONTEXT_MAX_CHARS).optional().describe("Opcional. Informacion adicional del producto que la IA debe usar como contexto prioritario: uso real, comprador, restricciones, diferenciadores o direccion creativa. No reemplaza la investigacion de competencia; si hay competencia, guia el primer angulo y los outputs no deben contradecirlo."),
28115
+ productLabel: z125.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.'),
27951
28116
  videoPreset: VideoPresetEnum.default("auto").describe('Opcional. Tipo/narrativa del video \u2014 \xFAnico campo de "estilo" que el usuario controla. Default "auto" (la IA escoge tras analizar el producto). Todos los presets funcionan a 15s (single_call) y 30s (Multiescena); "problem_solution" en single_call abre sin el producto y el producto entra por referencia en su beat de soluci\xF3n. Opciones: "auto", "ugc_dynamic" (review con experiencia y prueba), "ugc_how_to" (tutorial con pasos y resultado visible), "ugc_unboxing_chaos" (apertura y primera prueba), "problem_solution" (problema concreto, producto como soluci\xF3n y CTA), "product_showcase" (producto ejecutando una funci\xF3n real), "wearable_showcase" (prenda o accesorio modelado), "cinematic" (TV spot con receta cinematogr\xE1fica), "wild_card" (idea imposible: un truco visual que en la vida real no podr\xEDa pasar, y al cierre la invitaci\xF3n a comprar), "pixar_problem" (problema animado 3D), "pixar_sassy" (producto que habla). Si el usuario pide algo fuera de esta lista, p\xEDdele una opci\xF3n v\xE1lida.'),
27952
28117
  animationStyle: AnimationStyleEnum.optional().describe('Opcional. Estilo visual SOLO para presets animados ("pixar_problem" o "pixar_sassy") \u2014 la API lo rechaza con cualquier otro preset. Opciones: "pixar_3d" (default, look 3D de pel\xEDcula animada), "claymation" (plastilina stop-motion artesanal), "wes_anderson" (tableau sim\xE9trico pastel), "sci_fi" (futurista con HUDs y ne\xF3n), "realista" (fotorrealista, fiel al producto). Si el usuario pide un look animado sin nombrar el estilo, omite el campo.'),
27953
- durationSeconds: z124.union([
27954
- z124.literal(15),
27955
- z124.literal(30)
28118
+ durationSeconds: z125.union([
28119
+ z125.literal(15),
28120
+ z125.literal(30)
27956
28121
  ]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
27957
- pauseForAngleReview: z124.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."),
27958
- aiDecidesAll: z124.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."),
28122
+ pauseForAngleReview: z125.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."),
28123
+ aiDecidesAll: z125.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."),
27959
28124
  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.'),
27960
28125
  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.'),
27961
28126
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
27962
28127
  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).'),
27963
- videoAngleCount: z124.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."),
28128
+ videoAngleCount: z125.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."),
27964
28129
  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.'),
27965
- outputs: z124.array(z124.enum([
28130
+ outputs: z125.array(z125.enum([
27966
28131
  "landing",
27967
28132
  "video",
27968
28133
  "image"
27969
28134
  ])).min(1).max(3).optional().describe(`Opcional. Qu\xE9 outputs generar. Default: todos ["landing","video","image"]. Para 2 outputs: ["landing","image"] (sin video), ["video","image"] (sin landing), ["landing","video"] (sin imagen). ${createProductTaskSingleOutputDescription}`),
27970
- includeInitialLandingGif: z124.boolean().optional().describe("Opcional. En nuevas landings cl\xE1sicas habilitadas, omitirlo incluye el primer GIF del producto y su coste en el total. Env\xEDa false si el usuario lo excluye: no se genera ni se reserva su coste. Conserva la elecci\xF3n al confirmar y al reintentar."),
27971
- competitorScanEnabled: z124.boolean().optional().describe("Opcional. Default false: omitirlo significa SIN estudio de mercado. Antes de crear, llama estimate_market_study_cost con kind=product_task, muestra al usuario el costo con y sin estudio y preg\xFAntale si lo quiere; env\xEDa true solo si lo acepta (o si solicita la narrativa an\xE1lisis de mercado). Si la tarea incluye video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico."),
28135
+ includeInitialLandingGif: z125.boolean().optional().describe("Opcional. En nuevas landings cl\xE1sicas habilitadas, omitirlo incluye el primer GIF del producto y su coste en el total. Env\xEDa false si el usuario lo excluye: no se genera ni se reserva su coste. Conserva la elecci\xF3n al confirmar y al reintentar."),
28136
+ competitorScanEnabled: z125.boolean().optional().describe("Opcional. Default false: omitirlo significa SIN estudio de mercado. Antes de crear, llama estimate_market_study_cost con kind=product_task, muestra al usuario el costo con y sin estudio y preg\xFAntale si lo quiere; env\xEDa true solo si lo acepta (o si solicita la narrativa an\xE1lisis de mercado). Si la tarea incluye video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico."),
27972
28137
  generateAiEdit: AiEditRequestSchema.optional().describe('Opcional. Pide la Edici\xF3n con IA: una pasada que a\xF1ade texto, efectos y m\xFAsica sobre cada video entregado (variante with_ai_edit; se cobra al entregar, por video). Nivel: "economy" (Econ\xF3mica, Sonnet 5.5, m\xE1s barata) o "pro" (Opus 5.5, mejor calidad, ~10 min). true equivale a "pro"; false/omitido = sin edici\xF3n.'),
27973
- replicateWinnerWhenFound: z124.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."),
27974
- brandId: z124.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."),
27975
- actorId: z124.string().trim().min(1).max(120).optional().describe("Opcional. ID de un personaje guardado (usa list_actors para verlos). Si lo env\xEDas, su foto y su voz mandan sobre la descripci\xF3n de texto."),
28138
+ replicateWinnerWhenFound: z125.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."),
28139
+ brandId: z125.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."),
28140
+ actorId: z125.string().trim().min(1).max(120).optional().describe("Opcional. ID de un personaje guardado (usa list_actors para verlos). Si lo env\xEDas, su foto y su voz mandan sobre la descripci\xF3n de texto."),
27976
28141
  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.'),
27977
- creativeDirection: z124.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.'),
27978
- headline: z124.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."),
27979
- subheadline: z124.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."),
28142
+ creativeDirection: z125.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.'),
28143
+ headline: z125.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."),
28144
+ subheadline: z125.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."),
27980
28145
  landingStrategy: LandingStrategyEnum.optional().describe('Opcional. Estructura de la landing cl\xE1sica cuando landing est\xE1 entre outputs: "classic" (estructura original probada y recomendada; default del primer rollout), "auto" (la IA decide; experimental), "pain_solution", "social_proof" (Landing Viral: UGC, WhatsApp, Instagram y evidencia social), "benefits_clarity", "offer_value" o "lifestyle_identity". Default "classic".'),
27981
28146
  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".')
27982
28147
  }).strict();
27983
- var CreateServiceVideoInput = z124.object({
27984
- landingUrl: z124.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
27985
- additionalContext: z124.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
28148
+ var CreateServiceVideoInput = z125.object({
28149
+ landingUrl: z125.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
28150
+ additionalContext: z125.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
27986
28151
  language: Lang.describe("Idioma del video: es, en o pt."),
27987
- voiceId: z124.string().trim().min(1).pipe(VoiceId).optional().describe('Opcional. Voz para toda la narraci\xF3n. Usa "auto" para que la IA la alinee con el presentador. Las voces del banco compartido fueron retiradas.'),
27988
- brandId: z124.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
27989
- reviewMode: z124.enum([
28152
+ voiceId: z125.string().trim().min(1).pipe(VoiceId).optional().describe('Opcional. Voz para toda la narraci\xF3n. Usa "auto" para que la IA la alinee con el presentador. Las voces del banco compartido fueron retiradas.'),
28153
+ brandId: z125.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
28154
+ reviewMode: z125.enum([
27990
28155
  "automatic",
27991
28156
  "guided"
27992
28157
  ]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
27993
- videoPreset: z124.enum([
28158
+ videoPreset: z125.enum([
27994
28159
  "auto",
27995
28160
  "ugc_dynamic",
27996
28161
  "ugc_how_to",
@@ -28000,128 +28165,128 @@ var CreateServiceVideoInput = z124.object({
28000
28165
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
28001
28166
  videoResolution: VideoResolutionEnum.default("480p").describe('Opcional. Resoluci\xF3n: "480p" o "720p". 720p cuesta m\xE1s por segundo y solo est\xE1 disponible en "economy" y "pro" (Medio = 768P). Default: 480p.')
28002
28167
  }).strict();
28003
- var GetTaskStatusInput = z124.object({
28004
- taskId: z124.string().min(1),
28005
- waitSeconds: z124.number().int().min(0).max(120).optional()
28168
+ var GetTaskStatusInput = z125.object({
28169
+ taskId: z125.string().min(1),
28170
+ waitSeconds: z125.number().int().min(0).max(120).optional()
28006
28171
  });
28007
- var ListTasksInput = z124.object({
28008
- limit: z124.number().int().min(1).max(50).optional(),
28009
- offset: z124.number().int().min(0).optional(),
28010
- search: z124.string().optional()
28172
+ var ListTasksInput = z125.object({
28173
+ limit: z125.number().int().min(1).max(50).optional(),
28174
+ offset: z125.number().int().min(0).optional(),
28175
+ search: z125.string().optional()
28011
28176
  });
28012
28177
  var MCP_REVIEW_LIST_FIELD_MAX = IMAGE_WIZARD_LIST_FIELD_MAX;
28013
28178
  var MCP_REVIEW_FEATURE_ITEM_MAX = IMAGE_FEATURE_ITEM_MAX;
28014
- var EditTaskDraftInput = z124.object({
28015
- taskId: z124.string().min(1),
28016
- angleIndex: z124.number().int().min(0),
28017
- angle: z124.object({
28018
- angle: z124.string().min(1).max(480),
28019
- buyerPersona: z124.string().min(1).max(360),
28020
- actor: z124.string().min(1).max(360).optional(),
28021
- actorId: z124.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."),
28022
- gender: z124.enum([
28179
+ var EditTaskDraftInput = z125.object({
28180
+ taskId: z125.string().min(1),
28181
+ angleIndex: z125.number().int().min(0),
28182
+ angle: z125.object({
28183
+ angle: z125.string().min(1).max(480),
28184
+ buyerPersona: z125.string().min(1).max(360),
28185
+ actor: z125.string().min(1).max(360).optional(),
28186
+ actorId: z125.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."),
28187
+ gender: z125.enum([
28023
28188
  "female",
28024
28189
  "male"
28025
28190
  ]).optional(),
28026
- scriptNotes: z124.string().max(2e3).optional()
28191
+ scriptNotes: z125.string().max(2e3).optional()
28027
28192
  })
28028
28193
  });
28029
- var PendingActionPayload = z124.discriminatedUnion("kind", [
28030
- z124.object({
28031
- kind: z124.literal("product_reference_set_approval"),
28194
+ var PendingActionPayload = z125.discriminatedUnion("kind", [
28195
+ z125.object({
28196
+ kind: z125.literal("product_reference_set_approval"),
28032
28197
  scope: ProductReferenceScopeEnum.optional(),
28033
- scopeKey: z124.string().min(1).max(120).optional(),
28034
- scopeSnapshotId: z124.string().uuid().optional(),
28035
- expectedScopeHash: z124.string().min(1).max(128).optional(),
28198
+ scopeKey: z125.string().min(1).max(120).optional(),
28199
+ scopeSnapshotId: z125.string().uuid().optional(),
28200
+ expectedScopeHash: z125.string().min(1).max(128).optional(),
28036
28201
  decision: ProductReferenceResolutionDecisionEnum,
28037
28202
  reason: ProductReferenceRejectionReasonEnum.optional(),
28038
- affectedRefKeys: z124.array(z124.string().min(1).max(200)).min(1).optional(),
28039
- affectedPhotoNumbers: z124.array(z124.number().int().positive()).min(1).optional(),
28040
- recoveryAction: z124.enum([
28203
+ affectedRefKeys: z125.array(z125.string().min(1).max(200)).min(1).optional(),
28204
+ affectedPhotoNumbers: z125.array(z125.number().int().positive()).min(1).optional(),
28205
+ recoveryAction: z125.enum([
28041
28206
  "remove",
28042
28207
  "replace",
28043
28208
  "upload",
28044
28209
  "return_to_selection"
28045
28210
  ]).optional()
28046
28211
  }),
28047
- z124.object({
28048
- kind: z124.literal("product_reference_confirmation"),
28049
- selectedPhotoNumbers: z124.array(z124.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."),
28212
+ z125.object({
28213
+ kind: z125.literal("product_reference_confirmation"),
28214
+ selectedPhotoNumbers: z125.array(z125.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."),
28050
28215
  userChoice: ProductReferenceUserChoiceEnum.optional(),
28051
- confirmedProductNames: z124.array(z124.string().min(1).max(120)).min(2).max(8).optional(),
28216
+ confirmedProductNames: z125.array(z125.string().min(1).max(120)).min(2).max(8).optional(),
28052
28217
  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."),
28053
28218
  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."),
28054
- useMultiSceneShowcase: z124.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
28219
+ useMultiSceneShowcase: z125.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
28055
28220
  }),
28056
- z124.object({
28057
- kind: z124.literal("angle_review_approval"),
28221
+ z125.object({
28222
+ kind: z125.literal("angle_review_approval"),
28058
28223
  // All edits are optional — empty action body just approves the
28059
28224
  // backend-generated draft as-is. Field shapes mirror the angle-review
28060
28225
  // request contracts in @packages/types/wizard.ts; the handler routes to
28061
28226
  // the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
28062
- customAngle: z124.string().min(1).max(480).optional(),
28227
+ customAngle: z125.string().min(1).max(480).optional(),
28063
28228
  // Keep the shared MCP action within the strictest downstream contract:
28064
28229
  // autopilot/image resume endpoints cap these fields at 1500 characters.
28065
- painPoints: z124.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
28066
- benefits: z124.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
28230
+ painPoints: z125.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
28231
+ benefits: z125.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
28067
28232
  // Same policy as the two fields above: the strictest downstream contract
28068
28233
  // wins. The image endpoint caps each feature at 240 while landing/video
28069
28234
  // accept 300, and this single action routes to whichever the task is — so
28070
28235
  // accepting 300 here turns a 250-character feature on an image task into
28071
28236
  // an opaque HTTP 400 after the model already believed it had been saved.
28072
- features: z124.array(z124.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
28073
- buyerPersona: z124.string().min(1).max(360).optional(),
28237
+ features: z125.array(z125.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
28238
+ buyerPersona: z125.string().min(1).max(360).optional(),
28074
28239
  narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n) funciona en ambos formatos \u2014 en Un solo clip abre sin producto y el producto entra por referencia en su beat. La familia storyteller ("animated_storyteller", "animated_inner_journey", "animated_object_soul", "animated_timeline") no est\xE1 disponible por ahora.'),
28075
- actor: z124.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."),
28076
- actorId: z124.string().max(120).nullable().optional(),
28077
- creativeDirection: z124.string().max(2e3).optional(),
28078
- selectedAngleNumbers: z124.array(z124.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."),
28079
- angleEdits: z124.array(z124.object({
28080
- angleNumber: z124.number().int().positive(),
28081
- narrativeSelection: z124.enum([
28240
+ actor: z125.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."),
28241
+ actorId: z125.string().max(120).nullable().optional(),
28242
+ creativeDirection: z125.string().max(2e3).optional(),
28243
+ selectedAngleNumbers: z125.array(z125.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."),
28244
+ angleEdits: z125.array(z125.object({
28245
+ angleNumber: z125.number().int().positive(),
28246
+ narrativeSelection: z125.enum([
28082
28247
  "market",
28083
28248
  "guided"
28084
28249
  ]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
28085
- angle: z124.string().min(1).max(480).optional(),
28086
- buyerPersona: z124.string().min(1).max(360).optional(),
28250
+ angle: z125.string().min(1).max(480).optional(),
28251
+ buyerPersona: z125.string().min(1).max(360).optional(),
28087
28252
  narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n) funciona en ambos formatos \u2014 en Un solo clip abre sin producto y el producto entra por referencia en su beat. La familia storyteller ("animated_storyteller", "animated_inner_journey", "animated_object_soul", "animated_timeline") no est\xE1 disponible por ahora.'),
28088
- actor: z124.string().min(1).max(360).optional(),
28089
- actorId: z124.string().max(120).nullable().optional(),
28090
- creativeDirection: z124.string().max(2e3).optional()
28253
+ actor: z125.string().min(1).max(360).optional(),
28254
+ actorId: z125.string().max(120).nullable().optional(),
28255
+ creativeDirection: z125.string().max(2e3).optional()
28091
28256
  }).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)."),
28092
- gapDurationSeconds: z124.union([
28093
- z124.literal(15),
28094
- z124.literal(30)
28257
+ gapDurationSeconds: z125.union([
28258
+ z125.literal(15),
28259
+ z125.literal(30)
28095
28260
  ]).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.")
28096
28261
  }),
28097
- z124.object({
28098
- kind: z124.literal("service_angle_approval"),
28099
- angleId: z124.string().uuid().optional(),
28100
- angleNumber: z124.number().int().positive().optional(),
28101
- content: z124.string().min(1).max(480).optional(),
28102
- creativeDirection: z124.string().min(1).max(1500).optional(),
28103
- actor: z124.string().min(1).max(360).optional()
28262
+ z125.object({
28263
+ kind: z125.literal("service_angle_approval"),
28264
+ angleId: z125.string().uuid().optional(),
28265
+ angleNumber: z125.number().int().positive().optional(),
28266
+ content: z125.string().min(1).max(480).optional(),
28267
+ creativeDirection: z125.string().min(1).max(1500).optional(),
28268
+ actor: z125.string().min(1).max(360).optional()
28104
28269
  }),
28105
- z124.object({
28106
- kind: z124.literal("service_script_approval"),
28107
- voiceovers: z124.record(z124.string(), z124.string().min(1).max(600)).optional(),
28108
- visualDirections: z124.record(z124.string(), z124.string().min(1).max(1200)).optional(),
28109
- voiceoversByScene: z124.record(z124.string(), z124.string().min(1).max(600)).optional(),
28110
- visualDirectionsByScene: z124.record(z124.string(), z124.string().min(1).max(1200)).optional()
28270
+ z125.object({
28271
+ kind: z125.literal("service_script_approval"),
28272
+ voiceovers: z125.record(z125.string(), z125.string().min(1).max(600)).optional(),
28273
+ visualDirections: z125.record(z125.string(), z125.string().min(1).max(1200)).optional(),
28274
+ voiceoversByScene: z125.record(z125.string(), z125.string().min(1).max(600)).optional(),
28275
+ visualDirectionsByScene: z125.record(z125.string(), z125.string().min(1).max(1200)).optional()
28111
28276
  })
28112
28277
  ]);
28113
- var ResolvePendingActionInput = z124.object({
28114
- taskId: z124.string().min(1),
28278
+ var ResolvePendingActionInput = z125.object({
28279
+ taskId: z125.string().min(1),
28115
28280
  action: PendingActionPayload
28116
28281
  }).strict();
28117
28282
  function resolveVariantConfirmVideoTier(action) {
28118
28283
  return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
28119
28284
  }
28120
28285
  __name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
28121
- var StatusForResolveSchema = z124.object({
28286
+ var StatusForResolveSchema = z125.object({
28122
28287
  // Metadata used to select the backend resume contract. Older API responses
28123
28288
  // may omit these fields, so the resolver keeps the generic fallback.
28124
- kind: z124.enum([
28289
+ kind: z125.enum([
28125
28290
  "autopilot",
28126
28291
  "video",
28127
28292
  "image",
@@ -28129,18 +28294,18 @@ var StatusForResolveSchema = z124.object({
28129
28294
  "mix",
28130
28295
  "service"
28131
28296
  ]).optional(),
28132
- selectedOutputs: z124.array(z124.enum([
28297
+ selectedOutputs: z125.array(z125.enum([
28133
28298
  "landing",
28134
28299
  "video",
28135
28300
  "image"
28136
28301
  ])).optional(),
28137
- videoAngleCount: z124.number().int().min(1).max(3).optional(),
28138
- ugcFormat: z124.enum([
28302
+ videoAngleCount: z125.number().int().min(1).max(3).optional(),
28303
+ ugcFormat: z125.enum([
28139
28304
  "single_8s",
28140
28305
  "single_15s",
28141
28306
  "double_30s"
28142
28307
  ]).optional(),
28143
- videoStyle: z124.enum([
28308
+ videoStyle: z125.enum([
28144
28309
  "ugc",
28145
28310
  "cartoon_3d",
28146
28311
  "product_only",
@@ -28150,13 +28315,13 @@ var StatusForResolveSchema = z124.object({
28150
28315
  videoQuality: VideoQualityEnum.optional(),
28151
28316
  videoRouteId: VideoRouteIdEnum.optional(),
28152
28317
  videoModel: TaskVideoModelEnum.optional(),
28153
- videoTier: z124.enum([
28318
+ videoTier: z125.enum([
28154
28319
  "legacy",
28155
28320
  "standard",
28156
28321
  "pro",
28157
28322
  "single_call"
28158
28323
  ]).optional(),
28159
- videoResolution: z124.enum([
28324
+ videoResolution: z125.enum([
28160
28325
  "480p",
28161
28326
  "720p"
28162
28327
  ]).optional(),
@@ -28164,60 +28329,60 @@ var StatusForResolveSchema = z124.object({
28164
28329
  // A task created before a narrative was blocked/hidden must still parse,
28165
28330
  // or resolve_pending_action could never approve it.
28166
28331
  narrativeStyle: NarrativeStyle.optional(),
28167
- pauseForVideoScriptReview: z124.boolean().optional(),
28168
- pendingUserAction: z124.object({
28169
- kind: z124.string(),
28170
- candidateGrouping: z124.string().optional(),
28171
- selectedImageUrls: z124.array(z124.string()).optional(),
28172
- proposedProductNames: z124.array(z124.string()).optional(),
28332
+ pauseForVideoScriptReview: z125.boolean().optional(),
28333
+ pendingUserAction: z125.object({
28334
+ kind: z125.string(),
28335
+ candidateGrouping: z125.string().optional(),
28336
+ selectedImageUrls: z125.array(z125.string()).optional(),
28337
+ proposedProductNames: z125.array(z125.string()).optional(),
28173
28338
  // Adaptive reference questions are server-owned. Echo only the evidence
28174
28339
  // identity and the choices shown by the current snapshot; never accept a
28175
28340
  // client-supplied reference set as authorization.
28176
- options: z124.array(ProductReferenceUserChoiceEnum).max(4).optional(),
28177
- mode: z124.enum([
28341
+ options: z125.array(ProductReferenceUserChoiceEnum).max(4).optional(),
28342
+ mode: z125.enum([
28178
28343
  "question",
28179
28344
  "visual_recovery"
28180
28345
  ]).optional(),
28181
28346
  /** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
28182
- canKeepSelection: z124.boolean().optional(),
28183
- decisionKey: z124.string().optional(),
28184
- questionOrdinal: z124.number().int().min(1).max(5).optional(),
28185
- questionCeiling: z124.union([
28186
- z124.literal(3),
28187
- z124.literal(5)
28347
+ canKeepSelection: z125.boolean().optional(),
28348
+ decisionKey: z125.string().optional(),
28349
+ questionOrdinal: z125.number().int().min(1).max(5).optional(),
28350
+ questionCeiling: z125.union([
28351
+ z125.literal(3),
28352
+ z125.literal(5)
28188
28353
  ]).optional(),
28189
- referenceEvidenceVersion: z124.number().int().positive().optional(),
28190
- expectedEvidenceHash: z124.string().optional(),
28191
- question: z124.object({
28192
- prompt: z124.string().min(1).max(240),
28193
- helpText: z124.string().min(1).max(300).optional(),
28194
- options: z124.array(z124.object({
28354
+ referenceEvidenceVersion: z125.number().int().positive().optional(),
28355
+ expectedEvidenceHash: z125.string().optional(),
28356
+ question: z125.object({
28357
+ prompt: z125.string().min(1).max(240),
28358
+ helpText: z125.string().min(1).max(300).optional(),
28359
+ options: z125.array(z125.object({
28195
28360
  value: ProductReferenceUserChoiceEnum,
28196
- label: z124.string().min(1).max(120),
28197
- description: z124.string().min(1).max(240).optional()
28361
+ label: z125.string().min(1).max(120),
28362
+ description: z125.string().min(1).max(240).optional()
28198
28363
  })).min(2).max(4)
28199
28364
  }).optional(),
28200
28365
  scope: ProductReferenceScopeEnum.optional(),
28201
- scopeKey: z124.string().optional(),
28202
- scopeSnapshotId: z124.string().uuid().optional(),
28203
- scopeHash: z124.string().optional(),
28204
- baseReferenceSetHash: z124.string().optional(),
28205
- phase: z124.enum([
28366
+ scopeKey: z125.string().optional(),
28367
+ scopeSnapshotId: z125.string().uuid().optional(),
28368
+ scopeHash: z125.string().optional(),
28369
+ baseReferenceSetHash: z125.string().optional(),
28370
+ phase: z125.enum([
28206
28371
  "preparation",
28207
28372
  "final"
28208
28373
  ]).optional(),
28209
- selectedRefKeys: z124.array(z124.string().min(1).max(200)).optional(),
28210
- allowedDecisions: z124.array(ProductReferenceResolutionDecisionEnum).optional(),
28211
- previews: z124.array(z124.object({
28212
- refKey: z124.string().min(1).max(200)
28374
+ selectedRefKeys: z125.array(z125.string().min(1).max(200)).optional(),
28375
+ allowedDecisions: z125.array(ProductReferenceResolutionDecisionEnum).optional(),
28376
+ previews: z125.array(z125.object({
28377
+ refKey: z125.string().min(1).max(200)
28213
28378
  }).passthrough()).optional(),
28214
- customAngleDraft: z124.string().optional(),
28215
- painPointsDraft: z124.string().optional(),
28216
- benefitsDraft: z124.string().optional(),
28217
- featuresDraft: z124.array(z124.string()).optional(),
28218
- angleOptions: z124.array(z124.object({
28219
- index: z124.number().int().nonnegative(),
28220
- angle: z124.string().min(1)
28379
+ customAngleDraft: z125.string().optional(),
28380
+ painPointsDraft: z125.string().optional(),
28381
+ benefitsDraft: z125.string().optional(),
28382
+ featuresDraft: z125.array(z125.string()).optional(),
28383
+ angleOptions: z125.array(z125.object({
28384
+ index: z125.number().int().nonnegative(),
28385
+ angle: z125.string().min(1)
28221
28386
  }).passthrough()).min(1).max(5).optional(),
28222
28387
  // Recommendation consumed only when the caller explicitly sends
28223
28388
  // gapDurationSeconds: 30 in the angle approval action.
@@ -28227,17 +28392,17 @@ var StatusForResolveSchema = z124.object({
28227
28392
  // keys. `actorId` (the saved custom actor the picker stored) was silently
28228
28393
  // dropped here, so the approval handler below could not echo it back on the
28229
28394
  // PATCH — the selection looked accepted and reached no render.
28230
- angles: z124.array(z124.object({
28231
- id: z124.string().uuid(),
28232
- content: z124.string(),
28233
- creativeDirection: z124.string(),
28234
- actor: z124.string(),
28235
- actorId: z124.string().nullable().optional()
28395
+ angles: z125.array(z125.object({
28396
+ id: z125.string().uuid(),
28397
+ content: z125.string(),
28398
+ creativeDirection: z125.string(),
28399
+ actor: z125.string(),
28400
+ actorId: z125.string().nullable().optional()
28236
28401
  }).passthrough()).optional(),
28237
- panels: z124.array(z124.object({
28238
- beatId: z124.string(),
28239
- voiceover: z124.string(),
28240
- visualDirection: z124.string()
28402
+ panels: z125.array(z125.object({
28403
+ beatId: z125.string(),
28404
+ voiceover: z125.string(),
28405
+ visualDirection: z125.string()
28241
28406
  }).passthrough()).optional()
28242
28407
  }).optional()
28243
28408
  }).passthrough();
@@ -28590,8 +28755,8 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
28590
28755
  server.registerTool("verify_landing_commerce", {
28591
28756
  description: getProductMakerCapabilityModelGuidance("verify_landing_commerce").summary + " Verifica una correcci\xF3n manual de precios, tachados o packs de una landing editable existente. Solo relee Shopify y los recibos externos; no cambia precios, inventario, SKU ni compra una edici\xF3n. Pasa taskId y editId de la edici\xF3n ya conocida; nunca inventes IDs ni pidas repetir el cambio. Devuelve el estado can\xF3nico por proveedor: conserva el aviso pendiente hasta confirmar los valores reales. Solo despu\xE9s de confirmar todos los valores, el servidor puede volver a habilitar la compra. Web guardada no demuestra publicaci\xF3n p\xFAblica ni checkout; muestra las correcciones y enlaces pendientes sin c\xF3digos t\xE9cnicos. La disponibilidad del editor conserva sus permisos actuales.",
28592
28757
  inputSchema: {
28593
- taskId: z124.string().uuid(),
28594
- editId: z124.string().uuid()
28758
+ taskId: z125.string().uuid(),
28759
+ editId: z125.string().uuid()
28595
28760
  },
28596
28761
  annotations: OVERWRITES_EXTERNAL
28597
28762
  }, async (input) => {
@@ -28783,15 +28948,15 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
28783
28948
  const rawOutputs = await fetchTaskOutputs(api, input.taskId, {
28784
28949
  signal
28785
28950
  });
28786
- const imageContent = await buildMcpGeneratedImageContent(rawOutputs.images.map((image, i) => ({
28787
- url: image.url,
28951
+ const imageContent = await buildMcpGeneratedImageContent(rawOutputs.images.map((image2, i) => ({
28952
+ url: image2.url,
28788
28953
  alt: `Imagen ${i + 1}`
28789
28954
  })), transport);
28790
28955
  const outputs = proxifyOutputs(rawOutputs, proxyBaseUrl);
28791
28956
  const media = {
28792
28957
  images: [
28793
- ...outputs.images.map((image, i) => ({
28794
- url: image.url,
28958
+ ...outputs.images.map((image2, i) => ({
28959
+ url: image2.url,
28795
28960
  alt: `Imagen ${i + 1}`
28796
28961
  })),
28797
28962
  ...outputs.landing.sections.map((section) => ({
@@ -28862,16 +29027,16 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
28862
29027
  if (input.search) qs.set("search", input.search);
28863
29028
  const path3 = `/v1/tasks${qs.toString() ? "?" + qs.toString() : ""}`;
28864
29029
  const r = await api.getJson(path3);
28865
- const page = z124.object({
28866
- items: z124.array(z124.unknown())
29030
+ const page = z125.object({
29031
+ items: z125.array(z125.unknown())
28867
29032
  }).passthrough().safeParse(r);
28868
29033
  if (!page.success) return asText(r);
28869
29034
  return asText({
28870
29035
  ...page.data,
28871
29036
  items: page.data.items.map((item) => {
28872
- const servicePage = z124.object({
28873
- taskId: z124.string().uuid(),
28874
- resourceType: z124.literal("service_page")
29037
+ const servicePage = z125.object({
29038
+ taskId: z125.string().uuid(),
29039
+ resourceType: z125.literal("service_page")
28875
29040
  }).passthrough().safeParse(item);
28876
29041
  if (!servicePage.success) return item;
28877
29042
  return {
@@ -29361,28 +29526,28 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
29361
29526
  __name(registerTaskTools, "registerTaskTools");
29362
29527
 
29363
29528
  // src/tools/brands.ts
29364
- import { z as z125 } from "zod";
29529
+ import { z as z126 } from "zod";
29365
29530
  var guidance2 = getProductMakerCapabilityModelGuidance("create_brand");
29366
29531
  var BRAND_START_REPLAY_WINDOW_MS = 15 * 60 * 1e3;
29367
29532
  var BRAND_NOTES_MAX_CHARS = 2e4;
29368
29533
  var BRAND_AMBIGUOUS_REQUEST_RETENTION_MS = 24 * 60 * 60 * 1e3;
29369
29534
  var BRAND_CREATION_REQUEST_LIMIT = 500;
29370
29535
  var brandCreationRequests = /* @__PURE__ */ new Map();
29371
- var CreateBrandInput = z125.object({
29372
- action: z125.enum([
29536
+ var CreateBrandInput = z126.object({
29537
+ action: z126.enum([
29373
29538
  "start",
29374
29539
  "status",
29375
29540
  "list"
29376
29541
  ]).default("start").describe("start cotiza (sin confirmed) o inicia (confirmed=true) el an\xE1lisis; status consulta brandId hasta ready o failed; list muestra las marcas que el usuario ya tiene."),
29377
- sourceUrl: z125.string().trim().min(1).max(BRAND_SOURCE_URL_MAX_LENGTH).optional().describe("Instagram, Facebook, TikTok o web p\xFAblica del negocio, como la dio el usuario (\xAB@sanlucasbarberia\xBB, \xABinstagram.com/sanlucasbarberia\xBB, \xABmibarberia.com\xBB). Obligatorio para start."),
29378
- businessNotes: z125.string().trim().max(BRAND_NOTES_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cuente de su negocio en el chat (servicios y precios, WhatsApp, ciudad o zona, horarios). Se guarda como documento del negocio y llega tal cual a la marca y a su landing. Copia sus palabras; no inventes datos."),
29379
- language: z125.enum([
29542
+ sourceUrl: z126.string().trim().min(1).max(BRAND_SOURCE_URL_MAX_LENGTH).optional().describe("Instagram, Facebook, TikTok o web p\xFAblica del negocio, como la dio el usuario (\xAB@sanlucasbarberia\xBB, \xABinstagram.com/sanlucasbarberia\xBB, \xABmibarberia.com\xBB). Obligatorio para start."),
29543
+ businessNotes: z126.string().trim().max(BRAND_NOTES_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cuente de su negocio en el chat (servicios y precios, WhatsApp, ciudad o zona, horarios). Se guarda como documento del negocio y llega tal cual a la marca y a su landing. Copia sus palabras; no inventes datos."),
29544
+ language: z126.enum([
29380
29545
  "es",
29381
29546
  "en",
29382
29547
  "pt"
29383
29548
  ]).optional().describe("Idioma de la conversaci\xF3n. Solo se usa si la p\xE1gina del negocio no deja claro su idioma."),
29384
- confirmed: z125.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, start solo cotiza y no cobra."),
29385
- brandId: z125.string().uuid().optional().describe("ID de la marca. Obligatorio para status; no lo inventes.")
29549
+ confirmed: z126.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, start solo cotiza y no cobra."),
29550
+ brandId: z126.string().uuid().optional().describe("ID de la marca. Obligatorio para status; no lo inventes.")
29386
29551
  }).strict();
29387
29552
  function normalizeBrandSourceUrl(raw) {
29388
29553
  const value = raw.trim();
@@ -29666,31 +29831,31 @@ __name(registerBrandTools, "registerBrandTools");
29666
29831
 
29667
29832
  // src/tools/service-landing.ts
29668
29833
  import { createHash as createHash3, randomUUID } from "crypto";
29669
- import { z as z126 } from "zod";
29834
+ import { z as z127 } from "zod";
29670
29835
  var guidance3 = getProductMakerCapabilityModelGuidance("create_service_landing");
29671
29836
  var SERVICE_LANDING_KEY_NAMESPACE = "6f1d8c2a-3b4e-5f60-8a7b-9c0d1e2f3a4b";
29672
29837
  var SERVICE_LANDING_INFO_MAX_CHARS = 2e4;
29673
- var CreateServiceLandingInput = z126.object({
29674
- action: z126.enum([
29838
+ var CreateServiceLandingInput = z127.object({
29839
+ action: z127.enum([
29675
29840
  "prepare",
29676
29841
  "build",
29677
29842
  "status",
29678
29843
  "publish"
29679
29844
  ]).default("prepare").describe("prepare (gratis) crea o retoma la landing de la marca y da el precio; build (pagado, confirmed=true) genera la p\xE1gina directamente con la marca y los datos guardados; status sigue el avance; publish la publica y devuelve su enlace."),
29680
- brandId: z126.string().uuid().optional().describe("ID de la marca (de create_brand). Obligatorio para prepare. Nunca un taskId de producto."),
29681
- servicePageId: z126.string().uuid().optional().describe("ID de la landing que devolvi\xF3 prepare. Obligatorio para build, status y publish."),
29682
- businessInfo: z126.string().trim().max(SERVICE_LANDING_INFO_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cont\xF3 del negocio y no estaba en su marca: servicios y precios, WhatsApp o tel\xE9fono, ciudad o zona, horarios. Copia sus palabras; no inventes datos."),
29683
- confirmed: z126.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio total y que el usuario acepte. Obligatorio para build."),
29684
- maxCredits: z126.number().int().positive().optional().describe("El total en cr\xE9ditos que el usuario acept\xF3 (el que devolvi\xF3 prepare). Obligatorio para build: ninguna etapa se inicia si su precio supera este total."),
29685
- operationId: z126.string().uuid().optional().describe("Opcional en status: la operaci\xF3n que devolvi\xF3 build."),
29686
- slug: z126.string().trim().toLowerCase().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).max(64).optional().describe("Opcional en publish: la direcci\xF3n corta de la p\xE1gina (ej. sanlucas-barberia). Si falta se usa la sugerida desde el nombre del negocio.")
29845
+ brandId: z127.string().uuid().optional().describe("ID de la marca (de create_brand). Obligatorio para prepare. Nunca un taskId de producto."),
29846
+ servicePageId: z127.string().uuid().optional().describe("ID de la landing que devolvi\xF3 prepare. Obligatorio para build, status y publish."),
29847
+ businessInfo: z127.string().trim().max(SERVICE_LANDING_INFO_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cont\xF3 del negocio y no estaba en su marca: servicios y precios, WhatsApp o tel\xE9fono, ciudad o zona, horarios. Copia sus palabras; no inventes datos."),
29848
+ confirmed: z127.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio total y que el usuario acepte. Obligatorio para build."),
29849
+ maxCredits: z127.number().int().positive().optional().describe("El total en cr\xE9ditos que el usuario acept\xF3 (el que devolvi\xF3 prepare). Obligatorio para build: ninguna etapa se inicia si su precio supera este total."),
29850
+ operationId: z127.string().uuid().optional().describe("Opcional en status: la operaci\xF3n que devolvi\xF3 build."),
29851
+ slug: z127.string().trim().toLowerCase().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).max(64).optional().describe("Opcional en publish: la direcci\xF3n corta de la p\xE1gina (ej. sanlucas-barberia). Si falta se usa la sugerida desde el nombre del negocio.")
29687
29852
  }).strict();
29688
29853
  function serviceKey(...parts) {
29689
29854
  return deriveUuidV5(parts.join(":"), SERVICE_LANDING_KEY_NAMESPACE);
29690
29855
  }
29691
29856
  __name(serviceKey, "serviceKey");
29692
- function textHash(text3) {
29693
- return createHash3("sha256").update(text3, "utf8").digest("hex").slice(0, 16);
29857
+ function textHash(text4) {
29858
+ return createHash3("sha256").update(text4, "utf8").digest("hex").slice(0, 16);
29694
29859
  }
29695
29860
  __name(textHash, "textHash");
29696
29861
  function quoteRange(quote) {
@@ -30058,7 +30223,7 @@ function registerServiceLandingTools(server, api) {
30058
30223
  __name(registerServiceLandingTools, "registerServiceLandingTools");
30059
30224
 
30060
30225
  // src/tools/service-images.ts
30061
- import { z as z127 } from "zod";
30226
+ import { z as z128 } from "zod";
30062
30227
  var guidance4 = getProductMakerCapabilityModelGuidance("create_service_images");
30063
30228
  var SERVICE_IMAGE_FORMATS = [
30064
30229
  "4:5",
@@ -30071,23 +30236,23 @@ var LANGUAGE_TAGS = {
30071
30236
  en: "en-US",
30072
30237
  pt: "pt-BR"
30073
30238
  };
30074
- var CreateServiceImagesInput = z127.object({
30075
- brandId: z127.string().uuid().optional().describe("ID de un servicio propio y listo (de create_brand), obligatorio para cotizar y crear im\xE1genes nuevas. En un retry hist\xF3rico ya confirmado que originalmente no ten\xEDa este campo, conserva la petici\xF3n original. Nunca un taskId de producto."),
30076
- instruction: z127.string().trim().max(4e3).optional().describe("Opcional. Qu\xE9 servicio o promoci\xF3n mostrar, con las palabras del usuario (ej. \xABcorte + barba a $35.000 los martes\xBB). Si se omite, la IA propone la imagen usando la informaci\xF3n del servicio."),
30077
- delegateToAi: z127.boolean().optional().describe("true si el usuario prefiere que la IA elija qu\xE9 mostrar a partir de su servicio. Tambi\xE9n se delega cuando instruction est\xE1 vac\xEDo."),
30078
- format: z127.enum(SERVICE_IMAGE_FORMATS).optional().describe('Formato: "4:5" (feed, por defecto), "9:16" (historias/reels) o "1:1" (cuadrado).'),
30079
- count: z127.number().int().min(1).max(SERVICE_IMAGE_MAX_COUNT).optional().describe("Cu\xE1ntas im\xE1genes, de 1 a 3 (por defecto 1)."),
30080
- quality: z127.enum([
30239
+ var CreateServiceImagesInput = z128.object({
30240
+ brandId: z128.string().uuid().optional().describe("ID de un servicio propio y listo (de create_brand), obligatorio para cotizar y crear im\xE1genes nuevas. En un retry hist\xF3rico ya confirmado que originalmente no ten\xEDa este campo, conserva la petici\xF3n original. Nunca un taskId de producto."),
30241
+ instruction: z128.string().trim().max(4e3).optional().describe("Opcional. Qu\xE9 servicio o promoci\xF3n mostrar, con las palabras del usuario (ej. \xABcorte + barba a $35.000 los martes\xBB). Si se omite, la IA propone la imagen usando la informaci\xF3n del servicio."),
30242
+ delegateToAi: z128.boolean().optional().describe("true si el usuario prefiere que la IA elija qu\xE9 mostrar a partir de su servicio. Tambi\xE9n se delega cuando instruction est\xE1 vac\xEDo."),
30243
+ format: z128.enum(SERVICE_IMAGE_FORMATS).optional().describe('Formato: "4:5" (feed, por defecto), "9:16" (historias/reels) o "1:1" (cuadrado).'),
30244
+ count: z128.number().int().min(1).max(SERVICE_IMAGE_MAX_COUNT).optional().describe("Cu\xE1ntas im\xE1genes, de 1 a 3 (por defecto 1)."),
30245
+ quality: z128.enum([
30081
30246
  "standard",
30082
30247
  "high"
30083
30248
  ]).optional().describe('Calidad: "standard" (por defecto) o "high" (m\xE1s cara; no disponible en 4:5).'),
30084
- language: z127.enum([
30249
+ language: z128.enum([
30085
30250
  "es",
30086
30251
  "en",
30087
30252
  "pt"
30088
30253
  ]).optional().describe("Idioma de los textos de la imagen (por defecto es)."),
30089
- adCopy: z127.boolean().optional().describe("Compatibilidad con clientes anteriores: el copy para publicar siempre est\xE1 incluido en cada imagen de servicios."),
30090
- confirmed: z127.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, solo cotiza y no cobra.")
30254
+ adCopy: z128.boolean().optional().describe("Compatibilidad con clientes anteriores: el copy para publicar siempre est\xE1 incluido en cada imagen de servicios."),
30255
+ confirmed: z128.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, solo cotiza y no cobra.")
30091
30256
  }).strict();
30092
30257
  function serviceImageModel(quality) {
30093
30258
  return quality === "high" ? AD_CREATIVE_MODELS.PREMIUM : AD_CREATIVE_MODELS.STANDARD;
@@ -30204,7 +30369,7 @@ function registerServiceImageTools(server, api, options = {}) {
30204
30369
  nextAction: "Dile al usuario que est\xE1s creando sus im\xE1genes. Llama get_task_status con este taskId (waitSeconds=45) hasta done (trae las im\xE1genes reales de ProductMaker) o error. Muestra los recursos de imagen devueltos directamente en el chat. Nunca generes ni recrees una imagen sustituta con otra herramienta. Si la vista previa falla, explica el fallo y conserva los enlaces protegidos devueltos."
30205
30370
  });
30206
30371
  } catch (error) {
30207
- if (error instanceof z127.ZodError) throw invalidInputFromZod(error);
30372
+ if (error instanceof z128.ZodError) throw invalidInputFromZod(error);
30208
30373
  throw translateError(error);
30209
30374
  }
30210
30375
  });
@@ -30212,7 +30377,7 @@ function registerServiceImageTools(server, api, options = {}) {
30212
30377
  __name(registerServiceImageTools, "registerServiceImageTools");
30213
30378
 
30214
30379
  // src/tools/creatives.ts
30215
- import { z as z128 } from "zod";
30380
+ import { z as z129 } from "zod";
30216
30381
  var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
30217
30382
  var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
30218
30383
  var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
@@ -30223,72 +30388,72 @@ var CreativeRefs = {
30223
30388
  images: ImagesInput,
30224
30389
  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.'),
30225
30390
  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.'),
30226
- price: z128.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.'),
30227
- offer: z128.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.'),
30228
- compareAtPrice: z128.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
30229
- productContext: z128.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."),
30230
- productLabel: z128.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.'),
30231
- buyerPersona: z128.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.'),
30232
- isCombo: z128.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
30233
- competitorScanEnabled: z128.boolean().optional().describe("Opcional. Default false: omitirlo significa SIN estudio de mercado. Antes de crear, llama estimate_market_study_cost, muestra al usuario el costo con y sin estudio y preg\xFAntale si lo quiere; env\xEDa true solo si lo acepta (o si solicita la narrativa an\xE1lisis de mercado). En video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico."),
30234
- brandId: z128.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.")
30391
+ price: z129.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.'),
30392
+ offer: z129.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.'),
30393
+ compareAtPrice: z129.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
30394
+ productContext: z129.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."),
30395
+ productLabel: z129.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.'),
30396
+ buyerPersona: z129.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.'),
30397
+ isCombo: z129.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
30398
+ competitorScanEnabled: z129.boolean().optional().describe("Opcional. Default false: omitirlo significa SIN estudio de mercado. Antes de crear, llama estimate_market_study_cost, muestra al usuario el costo con y sin estudio y preg\xFAntale si lo quiere; env\xEDa true solo si lo acepta (o si solicita la narrativa an\xE1lisis de mercado). En video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico."),
30399
+ brandId: z129.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.")
30235
30400
  };
30236
- var VideoPresenter = z128.discriminatedUnion("mode", [
30237
- z128.object({
30238
- mode: z128.literal("none")
30401
+ var VideoPresenter = z129.discriminatedUnion("mode", [
30402
+ z129.object({
30403
+ mode: z129.literal("none")
30239
30404
  }).strict(),
30240
- z128.object({
30241
- mode: z128.literal("saved_actor"),
30242
- actorId: z128.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
30405
+ z129.object({
30406
+ mode: z129.literal("saved_actor"),
30407
+ actorId: z129.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
30243
30408
  }).strict(),
30244
- z128.object({
30245
- mode: z128.literal("described"),
30246
- description: z128.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
30409
+ z129.object({
30410
+ mode: z129.literal("described"),
30411
+ description: z129.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
30247
30412
  }).strict()
30248
30413
  ]);
30249
- var VideoCreativeSetup = z128.discriminatedUnion("mode", [
30250
- z128.object({
30251
- mode: z128.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
30414
+ var VideoCreativeSetup = z129.discriminatedUnion("mode", [
30415
+ z129.object({
30416
+ mode: z129.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
30252
30417
  }).strict(),
30253
- z128.object({
30254
- mode: z128.literal("guided"),
30418
+ z129.object({
30419
+ mode: z129.literal("guided"),
30255
30420
  videoPreset: VideoPresetEnum.default("auto").describe('Narrativa opcional. Con estudio de mercado no la preguntes: se usa "auto" y el estudio define la estructura. Sin estudio conserva la elecci\xF3n del usuario. Todas las narrativas funcionan en Un solo clip y Multiescena.'),
30256
- buyerPersona: z128.string().trim().min(1).max(360),
30421
+ buyerPersona: z129.string().trim().min(1).max(360),
30257
30422
  animationStyle: AnimationStyleEnum.optional().describe('Opcional. Estilo visual SOLO para presets animados ("pixar_problem" o "pixar_sassy") \u2014 la API lo rechaza con cualquier otro preset. Opciones: "pixar_3d" (default, look 3D de pel\xEDcula animada), "claymation" (plastilina stop-motion artesanal), "wes_anderson" (tableau sim\xE9trico pastel), "sci_fi" (futurista con HUDs y ne\xF3n), "realista" (fotorrealista, fiel al producto). Si el usuario pide un look animado sin nombrar el estilo, omite el campo.'),
30258
30423
  presenter: VideoPresenter,
30259
- creativeDirection: z128.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
30424
+ creativeDirection: z129.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
30260
30425
  }).strict()
30261
30426
  ]);
30262
- var VideoInput = z128.object({
30427
+ var VideoInput = z129.object({
30263
30428
  images: CreativeRefs.images.optional(),
30264
30429
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
30265
- title: z128.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
30266
- primaryAngle: z128.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".'),
30430
+ title: z129.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
30431
+ primaryAngle: z129.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".'),
30267
30432
  language: CreativeRefs.language,
30268
30433
  country: CreativeRefs.country,
30269
- aspectRatio: z128.enum([
30434
+ aspectRatio: z129.enum([
30270
30435
  "9:16",
30271
30436
  "16:9",
30272
30437
  "Auto"
30273
30438
  ]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
30274
30439
  generateAiEdit: AiEditRequestSchema.optional().describe('Opcional. Pide la Edici\xF3n con IA: una pasada que a\xF1ade texto, efectos y m\xFAsica sobre cada video entregado (variante with_ai_edit; se cobra al entregar, por video). Nivel: "economy" (Econ\xF3mica, Sonnet 5.5, m\xE1s barata) o "pro" (Opus 5.5, mejor calidad, ~10 min). true equivale a "pro"; false/omitido = sin edici\xF3n.'),
30275
- durationSeconds: z128.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."),
30276
- videoAngleCount: z128.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."),
30440
+ durationSeconds: z129.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."),
30441
+ videoAngleCount: z129.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."),
30277
30442
  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.'),
30278
30443
  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."),
30279
30444
  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.'),
30280
30445
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
30281
30446
  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.'),
30282
- features: z128.array(z128.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
30447
+ features: z129.array(z129.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
30283
30448
  price: CreativeRefs.price,
30284
30449
  offer: CreativeRefs.offer,
30285
30450
  productContext: CreativeRefs.productContext,
30286
30451
  productLabel: CreativeRefs.productLabel,
30287
- cta: z128.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.'),
30288
- scriptNotes: z128.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.'),
30452
+ cta: z129.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.'),
30453
+ scriptNotes: z129.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.'),
30289
30454
  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.'),
30290
30455
  competitorScanEnabled: CreativeRefs.competitorScanEnabled,
30291
- replicateWinnerWhenFound: z128.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."),
30456
+ replicateWinnerWhenFound: z129.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."),
30292
30457
  brandId: CreativeRefs.brandId
30293
30458
  }).strict();
30294
30459
  var FreeVideoQualityEnum = VideoQualityEnum;
@@ -30306,7 +30471,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
30306
30471
  length: 29
30307
30472
  }, (_, index) => index + 2)
30308
30473
  };
30309
- var FreeVideoModelIdEnum = z128.enum([
30474
+ var FreeVideoModelIdEnum = z129.enum([
30310
30475
  "grok-imagine-video-1-5-preview",
30311
30476
  "minimax-h3/reference-to-video",
30312
30477
  "wan/3-0-video",
@@ -30317,66 +30482,66 @@ var FREE_SELECTABLE_MODEL_IDS = [
30317
30482
  "minimax-h3/reference-to-video",
30318
30483
  "wan/3-0-video"
30319
30484
  ];
30320
- var FreeVideoInput = z128.object({
30485
+ var FreeVideoInput = z129.object({
30321
30486
  images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
30322
- rawPrompt: z128.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."),
30487
+ rawPrompt: z129.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."),
30323
30488
  language: CreativeRefs.language,
30324
30489
  quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
30325
30490
  // Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
30326
30491
  // parsed ONLY so the handler can reject it with a message naming its
30327
30492
  // replacement — dropping it silently would turn a caller's explicit
30328
30493
  // Pro++ pick into a quiet fallback to Wan.
30329
- freeProModel: z128.enum([
30494
+ freeProModel: z129.enum([
30330
30495
  "wan",
30331
30496
  "seedance"
30332
30497
  ]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
30333
30498
  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.'),
30334
- durationSeconds: z128.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."),
30499
+ durationSeconds: z129.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."),
30335
30500
  videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
30336
- generateAiMusic: z128.boolean().default(false).describe('Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false. Equivale a generateAiEdit (nivel "pro"): la Edici\xF3n con IA trae su propia m\xFAsica.'),
30501
+ generateAiMusic: z129.boolean().default(false).describe('Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false. Equivale a generateAiEdit (nivel "pro"): la Edici\xF3n con IA trae su propia m\xFAsica.'),
30337
30502
  generateAiEdit: AiEditRequestSchema.optional().describe('Opcional. Pide la Edici\xF3n con IA: una pasada que a\xF1ade texto, gr\xE1ficos y m\xFAsica sobre el video ya entregado (variante with_ai_edit; se cobra al entregar). Nivel: "economy" (Econ\xF3mica, Sonnet 5.5, m\xE1s barata) o "pro" (Opus 5.5, mejor calidad, ~10 min). true equivale a "pro". Default sin edici\xF3n.'),
30338
- addSubtitles: z128.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
30339
- idempotencyKey: z128.string().uuid().optional().describe("Opcional. Se acepta por compatibilidad pero se ignora: la identidad del reintento se deriva autom\xE1ticamente de los argumentos sem\xE1nticos, as\xED que un retry con los mismos argumentos ya es idempotente sin este campo.")
30503
+ addSubtitles: z129.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
30504
+ idempotencyKey: z129.string().uuid().optional().describe("Opcional. Se acepta por compatibilidad pero se ignora: la identidad del reintento se deriva autom\xE1ticamente de los argumentos sem\xE1nticos, as\xED que un retry con los mismos argumentos ya es idempotente sin este campo.")
30340
30505
  }).strict();
30341
30506
  var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
30342
- var ImageCreativeSetup = z128.discriminatedUnion("mode", [
30343
- z128.object({
30344
- mode: z128.literal("automatic")
30507
+ var ImageCreativeSetup = z129.discriminatedUnion("mode", [
30508
+ z129.object({
30509
+ mode: z129.literal("automatic")
30345
30510
  }).strict(),
30346
- z128.object({
30347
- mode: z128.literal("guided"),
30348
- creativeArchetype: z128.union([
30511
+ z129.object({
30512
+ mode: z129.literal("guided"),
30513
+ creativeArchetype: z129.union([
30349
30514
  ImageCreativeArchetypeEnum,
30350
- z128.literal("ai_decides")
30515
+ z129.literal("ai_decides")
30351
30516
  ]),
30352
- visualTreatment: z128.union([
30517
+ visualTreatment: z129.union([
30353
30518
  ImageCreativeVisualTreatmentEnum,
30354
- z128.literal("ai_decides")
30519
+ z129.literal("ai_decides")
30355
30520
  ]),
30356
30521
  aspectRatio: ImageCreativeAspectRatioEnum,
30357
- nVariants: z128.union([
30358
- z128.literal(1),
30359
- z128.literal(2),
30360
- z128.literal(3),
30361
- z128.literal(4),
30362
- z128.literal(6)
30522
+ nVariants: z129.union([
30523
+ z129.literal(1),
30524
+ z129.literal(2),
30525
+ z129.literal(3),
30526
+ z129.literal(4),
30527
+ z129.literal(6)
30363
30528
  ]),
30364
- imageModel: z128.enum(PUBLIC_IMAGE_QUALITY_INPUTS).describe('Calidad: "image:1k" (Est\xE1ndar) o "image:2k" (Premium). Los tokens gpt-image-2-5:{1k,2k} y gpt-image-2:{1k,2k} se siguen aceptando.'),
30365
- styleMix: z128.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
30366
- generateAdCopy: z128.boolean(),
30367
- competitorScanEnabled: z128.boolean(),
30368
- productContext: z128.string().trim().min(1).max(3e3).nullable(),
30369
- creativeDirection: z128.string().trim().min(1).max(500).nullable(),
30370
- brandColors: z128.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.'),
30371
- headline: z128.string().trim().min(1).max(120).nullable(),
30372
- subheadline: z128.string().trim().min(1).max(160).nullable()
30529
+ imageModel: z129.enum(PUBLIC_IMAGE_QUALITY_INPUTS).describe('Calidad: "image:1k" (Est\xE1ndar) o "image:2k" (Premium). Los tokens gpt-image-2-5:{1k,2k} y gpt-image-2:{1k,2k} se siguen aceptando.'),
30530
+ styleMix: z129.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
30531
+ generateAdCopy: z129.boolean(),
30532
+ competitorScanEnabled: z129.boolean(),
30533
+ productContext: z129.string().trim().min(1).max(3e3).nullable(),
30534
+ creativeDirection: z129.string().trim().min(1).max(500).nullable(),
30535
+ brandColors: z129.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.'),
30536
+ headline: z129.string().trim().min(1).max(120).nullable(),
30537
+ subheadline: z129.string().trim().min(1).max(160).nullable()
30373
30538
  }).strict()
30374
30539
  ]).superRefine((setup, context) => {
30375
30540
  if (setup.mode !== "guided") return;
30376
30541
  const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
30377
30542
  if (needsStyleMix && setup.styleMix === null) {
30378
30543
  context.addIssue({
30379
- code: z128.ZodIssueCode.custom,
30544
+ code: z129.ZodIssueCode.custom,
30380
30545
  path: [
30381
30546
  "styleMix"
30382
30547
  ],
@@ -30385,7 +30550,7 @@ var ImageCreativeSetup = z128.discriminatedUnion("mode", [
30385
30550
  }
30386
30551
  if (!needsStyleMix && setup.styleMix !== null) {
30387
30552
  context.addIssue({
30388
- code: z128.ZodIssueCode.custom,
30553
+ code: z129.ZodIssueCode.custom,
30389
30554
  path: [
30390
30555
  "styleMix"
30391
30556
  ],
@@ -30394,7 +30559,7 @@ var ImageCreativeSetup = z128.discriminatedUnion("mode", [
30394
30559
  }
30395
30560
  if (imageResolutionOf(setup.imageModel) === "2k" && setup.aspectRatio === "4:5") {
30396
30561
  context.addIssue({
30397
- code: z128.ZodIssueCode.custom,
30562
+ code: z129.ZodIssueCode.custom,
30398
30563
  path: [
30399
30564
  "aspectRatio"
30400
30565
  ],
@@ -30402,55 +30567,55 @@ var ImageCreativeSetup = z128.discriminatedUnion("mode", [
30402
30567
  });
30403
30568
  }
30404
30569
  });
30405
- var LandingCreativeSetup = z128.discriminatedUnion("mode", [
30406
- z128.object({
30407
- mode: z128.literal("automatic")
30570
+ var LandingCreativeSetup = z129.discriminatedUnion("mode", [
30571
+ z129.object({
30572
+ mode: z129.literal("automatic")
30408
30573
  }).strict(),
30409
- z128.object({
30410
- mode: z128.literal("guided"),
30574
+ z129.object({
30575
+ mode: z129.literal("guided"),
30411
30576
  landingStrategy: LandingStrategyEnum,
30412
30577
  landingImageFormat: LandingImageFormatEnum,
30413
- competitorScanEnabled: z128.boolean(),
30414
- paymentMethods: z128.string().trim().min(1).max(240).nullable(),
30415
- productContext: z128.string().trim().min(1).max(3e3).nullable(),
30416
- creativeDirection: z128.string().trim().min(1).max(500).nullable(),
30417
- headline: z128.string().trim().min(1).max(120).nullable(),
30418
- subheadline: z128.string().trim().min(1).max(160).nullable()
30578
+ competitorScanEnabled: z129.boolean(),
30579
+ paymentMethods: z129.string().trim().min(1).max(240).nullable(),
30580
+ productContext: z129.string().trim().min(1).max(3e3).nullable(),
30581
+ creativeDirection: z129.string().trim().min(1).max(500).nullable(),
30582
+ headline: z129.string().trim().min(1).max(120).nullable(),
30583
+ subheadline: z129.string().trim().min(1).max(160).nullable()
30419
30584
  }).strict()
30420
30585
  ]);
30421
- var ImageInput = z128.object({
30586
+ var ImageInput = z129.object({
30422
30587
  images: CreativeRefs.images.optional(),
30423
30588
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
30424
- productTitle: z128.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
30425
- primaryAngle: z128.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.'),
30589
+ productTitle: z129.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
30590
+ primaryAngle: z129.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.'),
30426
30591
  buyerPersona: CreativeRefs.buyerPersona,
30427
30592
  language: CreativeRefs.language,
30428
30593
  country: CreativeRefs.country,
30429
30594
  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."),
30430
30595
  imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
30431
- features: z128.array(z128.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
30596
+ features: z129.array(z129.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
30432
30597
  price: CreativeRefs.price,
30433
- omitPrice: z128.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."),
30598
+ omitPrice: z129.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."),
30434
30599
  compareAtPrice: CreativeRefs.compareAtPrice,
30435
30600
  offer: CreativeRefs.offer,
30436
30601
  productLabel: CreativeRefs.productLabel,
30437
30602
  isCombo: CreativeRefs.isCombo,
30438
30603
  brandId: CreativeRefs.brandId
30439
30604
  });
30440
- var EditImageCreativeInput = z128.object({
30441
- taskId: z128.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
30442
- variantIndex: z128.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
30443
- clientRequestId: z128.string().min(1).max(160).optional().describe("Identidad estable de esta correcci\xF3n; reutil\xEDzala al reconciliar una respuesta perdida, no para otra instrucci\xF3n."),
30444
- instruction: z128.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".')
30605
+ var EditImageCreativeInput = z129.object({
30606
+ taskId: z129.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
30607
+ variantIndex: z129.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
30608
+ clientRequestId: z129.string().min(1).max(160).optional().describe("Identidad estable de esta correcci\xF3n; reutil\xEDzala al reconciliar una respuesta perdida, no para otra instrucci\xF3n."),
30609
+ instruction: z129.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".')
30445
30610
  });
30446
- var LandingInput = z128.object({
30447
- includeInitialLandingGif: z128.boolean().optional().describe("Opcional. En nuevas landings cl\xE1sicas habilitadas, omitirlo incluye el primer GIF del producto y su coste en el total. Env\xEDa false si el usuario lo excluye: no se genera ni se reserva su coste. Conserva la elecci\xF3n al confirmar y al reintentar."),
30611
+ var LandingInput = z129.object({
30612
+ includeInitialLandingGif: z129.boolean().optional().describe("Opcional. En nuevas landings cl\xE1sicas habilitadas, omitirlo incluye el primer GIF del producto y su coste en el total. Env\xEDa false si el usuario lo excluye: no se genera ni se reserva su coste. Conserva la elecci\xF3n al confirmar y al reintentar."),
30448
30613
  images: CreativeRefs.images.optional(),
30449
30614
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
30450
30615
  language: CreativeRefs.language,
30451
30616
  country: CreativeRefs.country,
30452
30617
  creativeSetup: LandingCreativeSetup.describe("Configuraci\xF3n obligatoria de landing cl\xE1sica equivalente al wizard web. No expone landing editable/code mientras siga siendo admin-only."),
30453
- salesAngle: z128.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.'),
30618
+ salesAngle: z129.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.'),
30454
30619
  buyerPersona: CreativeRefs.buyerPersona,
30455
30620
  price: CreativeRefs.price,
30456
30621
  compareAtPrice: CreativeRefs.compareAtPrice,
@@ -30732,8 +30897,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
30732
30897
  server.registerTool("get_image_edit_status", {
30733
30898
  description: imageEditStatusGuidance.summary,
30734
30899
  inputSchema: {
30735
- taskId: z128.string().uuid(),
30736
- operationId: z128.string().uuid()
30900
+ taskId: z129.string().uuid(),
30901
+ operationId: z129.string().uuid()
30737
30902
  },
30738
30903
  annotations: READS_INTERNAL
30739
30904
  }, async (input) => {
@@ -30790,10 +30955,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
30790
30955
  __name(registerCreativeTools, "registerCreativeTools");
30791
30956
 
30792
30957
  // src/tools/creative-variants.ts
30793
- import { z as z129 } from "zod";
30958
+ import { z as z130 } from "zod";
30794
30959
  var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
30795
30960
  var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
30796
- var LandingSectionKeyEnum = z129.enum([
30961
+ var LandingSectionKeyEnum = z130.enum([
30797
30962
  "problem_hook",
30798
30963
  "problem_cost",
30799
30964
  "solution_mechanism",
@@ -30833,24 +30998,24 @@ var LandingSectionKeyEnum = z129.enum([
30833
30998
  "lifestyle_fit",
30834
30999
  "join_lifestyle"
30835
31000
  ]);
30836
- var CreativeVariantKindEnum = z129.enum([
31001
+ var CreativeVariantKindEnum = z130.enum([
30837
31002
  "video",
30838
31003
  "image",
30839
31004
  "landing"
30840
31005
  ]);
30841
- var EstimateCreativeVariantInputBase = z129.object({
30842
- sourceTaskId: z129.string().uuid().describe("ID de la tarea original completada."),
31006
+ var EstimateCreativeVariantInputBase = z130.object({
31007
+ sourceTaskId: z130.string().uuid().describe("ID de la tarea original completada."),
30843
31008
  kind: CreativeVariantKindEnum,
30844
31009
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
30845
31010
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
30846
- nVariants: z129.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
31011
+ nVariants: z130.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
30847
31012
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
30848
- instructions: z129.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.")
31013
+ instructions: z130.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.")
30849
31014
  }).strict();
30850
31015
  var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
30851
31016
  if (input.kind === "video" && input.nVariants !== void 0) {
30852
31017
  ctx.addIssue({
30853
- code: z129.ZodIssueCode.custom,
31018
+ code: z130.ZodIssueCode.custom,
30854
31019
  path: [
30855
31020
  "nVariants"
30856
31021
  ],
@@ -30860,7 +31025,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
30860
31025
  if (input.kind !== "video") {
30861
31026
  if (input.videoPreset !== void 0) {
30862
31027
  ctx.addIssue({
30863
- code: z129.ZodIssueCode.custom,
31028
+ code: z130.ZodIssueCode.custom,
30864
31029
  path: [
30865
31030
  "videoPreset"
30866
31031
  ],
@@ -30869,7 +31034,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
30869
31034
  }
30870
31035
  if (input.videoResolution !== void 0) {
30871
31036
  ctx.addIssue({
30872
- code: z129.ZodIssueCode.custom,
31037
+ code: z130.ZodIssueCode.custom,
30873
31038
  path: [
30874
31039
  "videoResolution"
30875
31040
  ],
@@ -30879,7 +31044,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
30879
31044
  }
30880
31045
  if (input.kind !== "image" && input.nVariants !== void 0) {
30881
31046
  ctx.addIssue({
30882
- code: z129.ZodIssueCode.custom,
31047
+ code: z130.ZodIssueCode.custom,
30883
31048
  path: [
30884
31049
  "nVariants"
30885
31050
  ],
@@ -30889,7 +31054,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
30889
31054
  if (input.kind !== "landing") {
30890
31055
  if (input.sectionKey !== void 0) {
30891
31056
  ctx.addIssue({
30892
- code: z129.ZodIssueCode.custom,
31057
+ code: z130.ZodIssueCode.custom,
30893
31058
  path: [
30894
31059
  "sectionKey"
30895
31060
  ],
@@ -30898,7 +31063,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
30898
31063
  }
30899
31064
  if (input.instructions !== void 0) {
30900
31065
  ctx.addIssue({
30901
- code: z129.ZodIssueCode.custom,
31066
+ code: z130.ZodIssueCode.custom,
30902
31067
  path: [
30903
31068
  "instructions"
30904
31069
  ],
@@ -30907,31 +31072,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
30907
31072
  }
30908
31073
  }
30909
31074
  });
30910
- var CreateCreativeVariantInputBase = z129.object({
30911
- sourceTaskId: z129.string().uuid().describe("ID de la tarea original completada."),
31075
+ var CreateCreativeVariantInputBase = z130.object({
31076
+ sourceTaskId: z130.string().uuid().describe("ID de la tarea original completada."),
30912
31077
  kind: CreativeVariantKindEnum,
30913
- confirm: z129.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
30914
- clientRequestId: z129.string().uuid().describe("UUID estable para esta intenci\xF3n (obligatorio por compatibilidad de contrato; el servidor deriva la identidad real del request desde los argumentos sem\xE1nticos, as\xED que un UUID nuevo en un retry NO crea una variante duplicada). Si la API devuelve status=error, una nueva generaci\xF3n exige otra confirmaci\xF3n."),
30915
- angle: z129.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
30916
- buyerPersona: z129.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
30917
- scriptNotes: z129.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
30918
- creativeDirection: z129.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
31078
+ confirm: z130.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
31079
+ clientRequestId: z130.string().uuid().describe("UUID estable para esta intenci\xF3n (obligatorio por compatibilidad de contrato; el servidor deriva la identidad real del request desde los argumentos sem\xE1nticos, as\xED que un UUID nuevo en un retry NO crea una variante duplicada). Si la API devuelve status=error, una nueva generaci\xF3n exige otra confirmaci\xF3n."),
31080
+ angle: z130.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
31081
+ buyerPersona: z130.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
31082
+ scriptNotes: z130.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
31083
+ creativeDirection: z130.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
30919
31084
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
30920
31085
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
30921
- generateAiMusic: z129.boolean().optional().describe("Opcional para video."),
30922
- nVariants: z129.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
31086
+ generateAiMusic: z130.boolean().optional().describe("Opcional para video."),
31087
+ nVariants: z130.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
30923
31088
  imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
30924
31089
  creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
30925
31090
  visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
30926
31091
  aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
30927
- styleMix: z129.boolean().optional().describe("Opcional para imagen."),
31092
+ styleMix: z130.boolean().optional().describe("Opcional para imagen."),
30928
31093
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
30929
- instructions: z129.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.")
31094
+ instructions: z130.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.")
30930
31095
  }).strict();
30931
31096
  var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
30932
31097
  if ((input.kind === "video" || input.kind === "image") && !input.angle) {
30933
31098
  ctx.addIssue({
30934
- code: z129.ZodIssueCode.custom,
31099
+ code: z130.ZodIssueCode.custom,
30935
31100
  path: [
30936
31101
  "angle"
30937
31102
  ],
@@ -30940,7 +31105,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
30940
31105
  }
30941
31106
  if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
30942
31107
  ctx.addIssue({
30943
- code: z129.ZodIssueCode.custom,
31108
+ code: z130.ZodIssueCode.custom,
30944
31109
  path: [
30945
31110
  "instructions"
30946
31111
  ],
@@ -30986,7 +31151,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
30986
31151
  for (const field of fieldsByKind[input.kind]) {
30987
31152
  if (input[field] !== void 0) {
30988
31153
  ctx.addIssue({
30989
- code: z129.ZodIssueCode.custom,
31154
+ code: z130.ZodIssueCode.custom,
30990
31155
  path: [
30991
31156
  field
30992
31157
  ],
@@ -31144,13 +31309,13 @@ function registerCreativeVariantTools(server, api) {
31144
31309
  __name(registerCreativeVariantTools, "registerCreativeVariantTools");
31145
31310
 
31146
31311
  // src/tools/script-review.ts
31147
- import { z as z130 } from "zod";
31312
+ import { z as z131 } from "zod";
31148
31313
  var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
31149
31314
  var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
31150
31315
  var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
31151
- var GetVideoScriptInput = z130.object({
31152
- taskId: z130.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
31153
- angleKey: z130.string().min(1).optional().describe('Clave persistida del \xE1ngulo cuyo guion se quiere leer (formato "angle_0", "angle_1", ...). Usa exactamente el angleKey recibido en reviewNextAction.calls al aprobar \xE1ngulos, incluso si s\xF3lo elegiste uno. Si se omite, el backend resuelve a "angle_0" literal; elegir el segundo candidato no crea angle_0. No derives esta clave del n\xFAmero visible del candidato.')
31316
+ var GetVideoScriptInput = z131.object({
31317
+ taskId: z131.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
31318
+ angleKey: z131.string().min(1).optional().describe('Clave persistida del \xE1ngulo cuyo guion se quiere leer (formato "angle_0", "angle_1", ...). Usa exactamente el angleKey recibido en reviewNextAction.calls al aprobar \xE1ngulos, incluso si s\xF3lo elegiste uno. Si se omite, el backend resuelve a "angle_0" literal; elegir el segundo candidato no crea angle_0. No derives esta clave del n\xFAmero visible del candidato.')
31154
31319
  }).strict();
31155
31320
  var ApproveVideoScriptInput = ApproveVideoScriptCapabilityRequest;
31156
31321
  var RegenerateVideoScriptInput = RegenerateVideoScriptCapabilityRequest.extend({
@@ -31255,7 +31420,7 @@ Consulta get_task_status con esta tarea antes de reintentar. Si la tarea termin\
31255
31420
  __name(registerScriptReviewTools, "registerScriptReviewTools");
31256
31421
 
31257
31422
  // src/tools/connections.ts
31258
- import { z as z131 } from "zod";
31423
+ import { z as z132 } from "zod";
31259
31424
  var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
31260
31425
  var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
31261
31426
  var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
@@ -31264,7 +31429,7 @@ var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list
31264
31429
  function registerConnectionTools(server, api) {
31265
31430
  server.registerTool("list_shopify_shops", {
31266
31431
  description: listShopifyShopsGuidance.summary + " Si la lista est\xE1 vac\xEDa, dile al usuario que conecte una tienda en productmaker.app/integrations antes de intentar publicar.",
31267
- inputSchema: z131.object({}).shape,
31432
+ inputSchema: z132.object({}).shape,
31268
31433
  annotations: READS_INTERNAL
31269
31434
  }, async () => {
31270
31435
  try {
@@ -31276,10 +31441,10 @@ function registerConnectionTools(server, api) {
31276
31441
  });
31277
31442
  server.registerTool("list_shopify_products", {
31278
31443
  description: listShopifyProductsGuidance.summary + ' Usa el `id` devuelto junto con `publicationMode="existing"` en `publish_to_shopify`. Si `taskId` se proporciona, la respuesta tambi\xE9n indica el producto publicado actualmente para esa tarea y tienda. No modifica Shopify.',
31279
- inputSchema: z131.object({
31280
- shopDomain: z131.string().min(3).max(120),
31281
- query: z131.string().trim().max(120).optional(),
31282
- taskId: z131.string().uuid().optional()
31444
+ inputSchema: z132.object({
31445
+ shopDomain: z132.string().min(3).max(120),
31446
+ query: z132.string().trim().max(120).optional(),
31447
+ taskId: z132.string().uuid().optional()
31283
31448
  }).shape,
31284
31449
  annotations: READS_EXTERNAL
31285
31450
  }, async ({ shopDomain, query, taskId }) => {
@@ -31297,7 +31462,7 @@ function registerConnectionTools(server, api) {
31297
31462
  });
31298
31463
  server.registerTool("list_meta_ad_accounts", {
31299
31464
  description: listMetaAdAccountsGuidance.summary + " Para publicar, prefiere `list_meta_destinations`, que tambi\xE9n devuelve el portfolio y las p\xE1ginas disponibles. Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar Meta en productmaker.app/integrations.",
31300
- inputSchema: z131.object({}).shape,
31465
+ inputSchema: z132.object({}).shape,
31301
31466
  annotations: READS_EXTERNAL
31302
31467
  }, async () => {
31303
31468
  try {
@@ -31309,7 +31474,7 @@ function registerConnectionTools(server, api) {
31309
31474
  });
31310
31475
  server.registerTool("list_meta_destinations", {
31311
31476
  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.",
31312
- inputSchema: z131.object({}).shape,
31477
+ inputSchema: z132.object({}).shape,
31313
31478
  annotations: READS_EXTERNAL,
31314
31479
  _meta: {
31315
31480
  "openai/widgetAccessible": true
@@ -31324,7 +31489,7 @@ function registerConnectionTools(server, api) {
31324
31489
  });
31325
31490
  server.registerTool("list_tiktok_advertisers", {
31326
31491
  description: listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.",
31327
- inputSchema: z131.object({}).shape,
31492
+ inputSchema: z132.object({}).shape,
31328
31493
  annotations: READS_EXTERNAL
31329
31494
  }, async () => {
31330
31495
  try {
@@ -31338,7 +31503,7 @@ function registerConnectionTools(server, api) {
31338
31503
  __name(registerConnectionTools, "registerConnectionTools");
31339
31504
 
31340
31505
  // src/tools/actors.ts
31341
- import { z as z132 } from "zod";
31506
+ import { z as z133 } from "zod";
31342
31507
  var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
31343
31508
  var actorVoiceGuidance = {
31344
31509
  capabilities: getProductMakerCapabilityModelGuidance("get_actor_voice_capabilities"),
@@ -31378,7 +31543,7 @@ function sanitizeVoiceResult(value) {
31378
31543
  __name(sanitizeVoiceResult, "sanitizeVoiceResult");
31379
31544
  function registerActorTools(server, api) {
31380
31545
  const actor = {
31381
- actorId: z132.string().min(1).max(64)
31546
+ actorId: z133.string().min(1).max(64)
31382
31547
  };
31383
31548
  const safe = /* @__PURE__ */ __name(async (request) => {
31384
31549
  try {
@@ -31407,8 +31572,8 @@ function registerActorTools(server, api) {
31407
31572
  inputSchema: {
31408
31573
  ...actor,
31409
31574
  draft: ActorVoiceDraftSchema,
31410
- requestKey: z132.string().trim().min(1).max(128),
31411
- acceptedQuoteId: z132.string().trim().min(1).max(128)
31575
+ requestKey: z133.string().trim().min(1).max(128),
31576
+ acceptedQuoteId: z133.string().trim().min(1).max(128)
31412
31577
  },
31413
31578
  annotations: CREATES_PAID
31414
31579
  }, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/previews`, body)));
@@ -31416,7 +31581,7 @@ function registerActorTools(server, api) {
31416
31581
  description: actorVoiceGuidance.get.summary,
31417
31582
  inputSchema: {
31418
31583
  ...actor,
31419
- candidateId: z132.string().min(1).max(64)
31584
+ candidateId: z133.string().min(1).max(64)
31420
31585
  },
31421
31586
  // Polling can resume the first paid submission of an accepted quote.
31422
31587
  // The immutable candidate/operation key keeps recovery idempotent.
@@ -31429,16 +31594,16 @@ function registerActorTools(server, api) {
31429
31594
  description: actorVoiceGuidance.approve.summary,
31430
31595
  inputSchema: {
31431
31596
  ...actor,
31432
- candidateId: z132.string().min(1).max(64),
31433
- expectedRevision: z132.number().int().positive(),
31434
- expectedApprovedRevision: z132.number().int().positive().nullable().optional()
31597
+ candidateId: z133.string().min(1).max(64),
31598
+ expectedRevision: z133.number().int().positive(),
31599
+ expectedApprovedRevision: z133.number().int().positive().nullable().optional()
31435
31600
  },
31436
31601
  // Replaces the selected voice and withdraws the old catalog grants.
31437
31602
  annotations: OVERWRITES_INTERNAL
31438
31603
  }, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/approve`, body)));
31439
31604
  server.registerTool("list_actors", {
31440
31605
  description: listActorsGuidance.summary + " Devuelve id, nombre, descripci\xF3n, g\xE9nero y voz privada del personaje. Cuando el personaje tiene una voz personalizada, `voice.identityId` y `voice.revision` identifican la versi\xF3n aprobada \u2014 conserva la revisi\xF3n al llamar `approve_actor_voice` (expectedApprovedRevision) para reemplazarla. Los IDs de proveedor nunca se exponen por MCP. Usa el `id` como `actorId` al crear o editar una tarea. Solo aparecen los personajes listos para usar; si la lista est\xE1 vac\xEDa, dile al usuario que cree uno en productmaker.app antes de intentar asignarlo. No modifica nada.",
31441
- inputSchema: z132.object({}).shape,
31606
+ inputSchema: z133.object({}).shape,
31442
31607
  annotations: READS_INTERNAL
31443
31608
  }, async () => {
31444
31609
  try {
@@ -31471,7 +31636,7 @@ function registerActorTools(server, api) {
31471
31636
  __name(registerActorTools, "registerActorTools");
31472
31637
 
31473
31638
  // src/tools/publish.ts
31474
- import { z as z133 } from "zod";
31639
+ import { z as z134 } from "zod";
31475
31640
 
31476
31641
  // src/tools/meta-publish-attempt-id.ts
31477
31642
  var META_PUBLISH_NAMESPACE = "7b19c9ac-b4eb-4db1-970e-c2f24ce30b98";
@@ -31510,40 +31675,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
31510
31675
  var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
31511
31676
  var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
31512
31677
  var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
31513
- var ShopifyInput = z133.object({
31514
- taskId: z133.string().min(1),
31515
- shopDomain: z133.string().min(1),
31678
+ var ShopifyInput = z134.object({
31679
+ taskId: z134.string().min(1),
31680
+ shopDomain: z134.string().min(1),
31516
31681
  /** Override: number of landing images to include. Default = ALL images the
31517
31682
  * task generated (the MCP fetches /v1/results first to count). Bounded
31518
31683
  * generously here; the backend validates each index against
31519
31684
  * landing.images.length and rejects out-of-range. */
31520
- numLandingImages: z133.number().int().min(1).max(20).optional(),
31521
- variantIndex: z133.number().int().min(0).optional(),
31685
+ numLandingImages: z134.number().int().min(1).max(20).optional(),
31686
+ variantIndex: z134.number().int().min(0).optional(),
31522
31687
  /** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
31523
31688
  * When true, the landing renders variant-picker pills; when false, it ships
31524
31689
  * a single-option product page. Defaults to false. */
31525
- showVariantPicker: z133.boolean().optional(),
31690
+ showVariantPicker: z134.boolean().optional(),
31526
31691
  /** Default `auto` updates the product previously published for this task and
31527
31692
  * shop. Use `existing` with targetProductId to choose another product, or
31528
31693
  * `new` only when the user explicitly wants a duplicate/new listing. */
31529
- publicationMode: z133.enum([
31694
+ publicationMode: z134.enum([
31530
31695
  "auto",
31531
31696
  "existing",
31532
31697
  "new"
31533
31698
  ]).optional(),
31534
31699
  /** Shopify product GID, numeric id, or admin product URL. Required when
31535
31700
  * publicationMode is `existing`. */
31536
- targetProductId: z133.string().trim().min(1).max(300).optional(),
31701
+ targetProductId: z134.string().trim().min(1).max(300).optional(),
31537
31702
  /** Add an announcement bar text above add-to-cart (optional). */
31538
- announcementBarEnabled: z133.boolean().optional(),
31539
- announcementBarText: z133.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
31703
+ announcementBarEnabled: z134.boolean().optional(),
31704
+ announcementBarText: z134.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
31540
31705
  commerceCorrection: PublishCommerceCorrectionSchema.optional().describe("Complete seller-confirmed commerce values, with the revision and fingerprint returned in recovery. Never invent missing prices or convert currency."),
31541
- confirmed: z133.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
31706
+ confirmed: z134.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
31542
31707
  });
31543
31708
  var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
31544
31709
  if (value.commerceCorrection && value.confirmed !== true) {
31545
31710
  ctx.addIssue({
31546
- code: z133.ZodIssueCode.custom,
31711
+ code: z134.ZodIssueCode.custom,
31547
31712
  path: [
31548
31713
  "confirmed"
31549
31714
  ],
@@ -31552,7 +31717,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
31552
31717
  }
31553
31718
  if (value.announcementBarEnabled && !value.announcementBarText) {
31554
31719
  ctx.addIssue({
31555
- code: z133.ZodIssueCode.custom,
31720
+ code: z134.ZodIssueCode.custom,
31556
31721
  path: [
31557
31722
  "announcementBarText"
31558
31723
  ],
@@ -31561,7 +31726,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
31561
31726
  }
31562
31727
  if (!value.announcementBarEnabled && value.announcementBarText) {
31563
31728
  ctx.addIssue({
31564
- code: z133.ZodIssueCode.custom,
31729
+ code: z134.ZodIssueCode.custom,
31565
31730
  path: [
31566
31731
  "announcementBarText"
31567
31732
  ],
@@ -31575,90 +31740,90 @@ function parseShopifyInput(rawInput) {
31575
31740
  return parsed.data;
31576
31741
  }
31577
31742
  __name(parseShopifyInput, "parseShopifyInput");
31578
- var McpCampaignConfig = z133.object({
31743
+ var McpCampaignConfig = z134.object({
31579
31744
  /** Legacy USD amount. Meta retains its existing conversion; the TikTok
31580
31745
  * schema below restricts this input to USD advertiser accounts. */
31581
- dailyBudgetUsd: z133.number().positive().optional(),
31746
+ dailyBudgetUsd: z134.number().positive().optional(),
31582
31747
  /** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
31583
31748
  * normalizes at validation). Meta accepts max 1 (single-country ad set).
31584
31749
  * TikTok takes only the first entry. */
31585
- targetCountries: z133.array(CountryIso2Schema).max(1).optional(),
31586
- campaignName: z133.string().trim().min(1).max(100).optional()
31750
+ targetCountries: z134.array(CountryIso2Schema).max(1).optional(),
31751
+ campaignName: z134.string().trim().min(1).max(100).optional()
31587
31752
  });
31588
31753
  var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
31589
- var MetaInput = z133.object({
31590
- taskId: z133.string().min(1),
31754
+ var MetaInput = z134.object({
31755
+ taskId: z134.string().min(1),
31591
31756
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
31592
- portfolioId: z133.string().trim().min(1),
31757
+ portfolioId: z134.string().trim().min(1),
31593
31758
  /** Exact Facebook Page selected from `list_meta_destinations`. */
31594
- pageId: z133.string().trim().min(1),
31759
+ pageId: z134.string().trim().min(1),
31595
31760
  adAccountId: McpAdAccountId,
31596
- pixelId: z133.string().min(1).optional(),
31597
- landingUrl: z133.string().url().optional(),
31761
+ pixelId: z134.string().min(1).optional(),
31762
+ landingUrl: z134.string().url().optional(),
31598
31763
  /** Select which angles to publish by 0-based index. Omit to publish all
31599
31764
  * successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
31600
- angleIndexes: z133.array(z133.number().int().nonnegative()).optional(),
31765
+ angleIndexes: z134.array(z134.number().int().nonnegative()).optional(),
31601
31766
  campaignConfig: McpCampaignConfig.optional(),
31602
31767
  /** Override the ad's primary text (body copy). If omitted, ProductMaker
31603
31768
  * uses the auto-generated copy attached to the task. Capped at 500 chars
31604
31769
  * (Meta's primary-text limit). */
31605
- primaryText: z133.string().trim().min(1).max(500).optional(),
31770
+ primaryText: z134.string().trim().min(1).max(500).optional(),
31606
31771
  /** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
31607
31772
  * (wa.me) instead of a landing page. */
31608
- phoneNumber: z133.string().min(8).max(32).optional()
31773
+ phoneNumber: z134.string().min(8).max(32).optional()
31609
31774
  });
31610
- var GroupedTaskSource = z133.object({
31611
- type: z133.literal("task"),
31612
- taskId: z133.string().min(1),
31613
- angleIndex: z133.number().int().min(0).optional(),
31614
- videoVariant: z133.enum([
31775
+ var GroupedTaskSource = z134.object({
31776
+ type: z134.literal("task"),
31777
+ taskId: z134.string().min(1),
31778
+ angleIndex: z134.number().int().min(0).optional(),
31779
+ videoVariant: z134.enum([
31615
31780
  "with_subtitles",
31616
31781
  "without_subtitles"
31617
31782
  ]).optional(),
31618
- imageVariantIndex: z133.number().int().min(0).optional()
31619
- });
31620
- var GroupedMediaSource = z133.object({
31621
- type: z133.literal("media"),
31622
- url: z133.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
31623
- path: z133.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".'),
31624
- thumbnailUrl: z133.string().url().optional(),
31625
- thumbnailPath: z133.string().min(1).optional()
31783
+ imageVariantIndex: z134.number().int().min(0).optional()
31784
+ });
31785
+ var GroupedMediaSource = z134.object({
31786
+ type: z134.literal("media"),
31787
+ url: z134.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
31788
+ path: z134.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".'),
31789
+ thumbnailUrl: z134.string().url().optional(),
31790
+ thumbnailPath: z134.string().min(1).optional()
31626
31791
  }).refine((value) => Boolean(value.url) !== Boolean(value.path), {
31627
31792
  message: "media source needs exactly one of `url` or `path`"
31628
31793
  }).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
31629
31794
  message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
31630
31795
  });
31631
- var GroupedUploadedAssetSource = z133.object({
31632
- type: z133.literal("asset"),
31796
+ var GroupedUploadedAssetSource = z134.object({
31797
+ type: z134.literal("asset"),
31633
31798
  /** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
31634
- assetId: z133.string().uuid(),
31635
- thumbnailAssetId: z133.string().uuid().optional()
31799
+ assetId: z134.string().uuid(),
31800
+ thumbnailAssetId: z134.string().uuid().optional()
31636
31801
  });
31637
- var GroupedCreative = z133.object({
31638
- type: z133.enum([
31802
+ var GroupedCreative = z134.object({
31803
+ type: z134.enum([
31639
31804
  "image",
31640
31805
  "video"
31641
31806
  ]),
31642
- source: z133.union([
31807
+ source: z134.union([
31643
31808
  GroupedTaskSource,
31644
31809
  GroupedMediaSource,
31645
31810
  GroupedUploadedAssetSource
31646
31811
  ]),
31647
- title: z133.string().max(120).optional(),
31648
- description: z133.string().max(500).optional(),
31812
+ title: z134.string().max(120).optional(),
31813
+ description: z134.string().max(500).optional(),
31649
31814
  cta: MetaCtaType.optional(),
31650
- creativeId: z133.string().min(1).optional()
31815
+ creativeId: z134.string().min(1).optional()
31651
31816
  });
31652
- var GroupedCampaignConfigBase = z133.object({
31817
+ var GroupedCampaignConfigBase = z134.object({
31653
31818
  campaignType: MetaCampaignType.default("sales"),
31654
31819
  optimizationMode: MetaOptimizationMode.default("advantage_plus"),
31655
31820
  budgetMode: MetaBudgetMode.optional(),
31656
- campaignDailyBudget: z133.number().int().positive().optional(),
31657
- adSets: z133.array(z133.object({
31658
- tempId: z133.string().min(1).max(80),
31659
- name: z133.string().min(1).max(100),
31660
- dailyBudget: z133.number().int().positive().optional(),
31661
- creativeIds: z133.array(z133.string().min(1)).min(1)
31821
+ campaignDailyBudget: z134.number().int().positive().optional(),
31822
+ adSets: z134.array(z134.object({
31823
+ tempId: z134.string().min(1).max(80),
31824
+ name: z134.string().min(1).max(100),
31825
+ dailyBudget: z134.number().int().positive().optional(),
31826
+ creativeIds: z134.array(z134.string().min(1)).min(1)
31662
31827
  })).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
31663
31828
  /**
31664
31829
  * Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
@@ -31666,17 +31831,17 @@ var GroupedCampaignConfigBase = z133.object({
31666
31831
  * opaque `invalid_literal` and made the WhatsApp destination — supported by
31667
31832
  * the API since #849 — unreachable from this tool.
31668
31833
  */
31669
- destination: z133.discriminatedUnion("type", [
31670
- z133.object({
31671
- type: z133.literal("landing"),
31672
- landingUrl: z133.string().url()
31834
+ destination: z134.discriminatedUnion("type", [
31835
+ z134.object({
31836
+ type: z134.literal("landing"),
31837
+ landingUrl: z134.string().url()
31673
31838
  }),
31674
- z133.object({
31675
- type: z133.literal("whatsapp"),
31676
- phoneNumber: z133.string().min(8).max(32)
31839
+ z134.object({
31840
+ type: z134.literal("whatsapp"),
31841
+ phoneNumber: z134.string().min(8).max(32)
31677
31842
  })
31678
31843
  ]),
31679
- saveAsDefault: z133.boolean().default(false),
31844
+ saveAsDefault: z134.boolean().default(false),
31680
31845
  budgetPolicy: MetaBudgetPolicy.optional()
31681
31846
  });
31682
31847
  function resolveBudgetMode(value) {
@@ -31690,7 +31855,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
31690
31855
  const budgetMode = resolveBudgetMode(value);
31691
31856
  if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
31692
31857
  ctx.addIssue({
31693
- code: z133.ZodIssueCode.custom,
31858
+ code: z134.ZodIssueCode.custom,
31694
31859
  path: [
31695
31860
  "campaignDailyBudget"
31696
31861
  ],
@@ -31701,7 +31866,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
31701
31866
  value.adSets.forEach((adSet, index) => {
31702
31867
  if (adSet.dailyBudget === void 0) {
31703
31868
  ctx.addIssue({
31704
- code: z133.ZodIssueCode.custom,
31869
+ code: z134.ZodIssueCode.custom,
31705
31870
  path: [
31706
31871
  "adSets",
31707
31872
  index,
@@ -31716,25 +31881,25 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
31716
31881
  ...value,
31717
31882
  budgetMode: resolveBudgetMode(value)
31718
31883
  }));
31719
- var PublishCreativesToMetaInputBase = z133.object({
31720
- creatives: z133.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
31884
+ var PublishCreativesToMetaInputBase = z134.object({
31885
+ creatives: z134.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
31721
31886
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
31722
- portfolioId: z133.string().trim().min(1),
31887
+ portfolioId: z134.string().trim().min(1),
31723
31888
  /** Exact Facebook Page selected from `list_meta_destinations`. */
31724
- pageId: z133.string().trim().min(1),
31889
+ pageId: z134.string().trim().min(1),
31725
31890
  adAccountId: McpAdAccountId,
31726
- pixelId: z133.string().min(1).optional(),
31891
+ pixelId: z134.string().min(1).optional(),
31727
31892
  /** Required unless `campaignConfig.destination` is whatsapp or a creative
31728
31893
  * comes from a task (the API then lands on the published service landing
31729
31894
  * of its service tasks) — see the superRefine below. Mirrors the API's
31730
31895
  * `FacebookCreateCampaignFromTasksBodySchema`. */
31731
- landingUrl: z133.string().url().optional(),
31896
+ landingUrl: z134.string().url().optional(),
31732
31897
  /** ISO-2 code or resolvable country name — mirrors the API contract
31733
31898
  * (CountryIso2Schema), which normalizes names to alpha-2 at validation.
31734
31899
  * Omitted: the brand country of its service tasks (the API answers
31735
31900
  * META_NO_TARGET_COUNTRY when it has none); "US" for products. */
31736
31901
  targetCountry: CountryIso2Schema.optional(),
31737
- campaignName: z133.string().trim().min(1).max(100),
31902
+ campaignName: z134.string().trim().min(1).max(100),
31738
31903
  campaignConfig: GroupedCampaignConfig.optional()
31739
31904
  });
31740
31905
  var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
@@ -31742,7 +31907,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
31742
31907
  const hasTaskCreative = value.creatives.some((creative) => creative.source.type === "task");
31743
31908
  if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl && !hasTaskCreative) {
31744
31909
  ctx.addIssue({
31745
- code: z133.ZodIssueCode.custom,
31910
+ code: z134.ZodIssueCode.custom,
31746
31911
  path: [
31747
31912
  "landingUrl"
31748
31913
  ],
@@ -31751,7 +31916,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
31751
31916
  }
31752
31917
  if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
31753
31918
  ctx.addIssue({
31754
- code: z133.ZodIssueCode.custom,
31919
+ code: z134.ZodIssueCode.custom,
31755
31920
  path: [
31756
31921
  "campaignConfig",
31757
31922
  "destination",
@@ -31770,16 +31935,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
31770
31935
  }
31771
31936
  return value;
31772
31937
  });
31773
- var PresignUploadResponseSchema = z133.object({
31774
- uploadUrl: z133.string().url().refine((value) => {
31938
+ var PresignUploadResponseSchema = z134.object({
31939
+ uploadUrl: z134.string().url().refine((value) => {
31775
31940
  const url = new URL(value);
31776
31941
  return !url.username && !url.password && url.protocol === "https:";
31777
31942
  }, "presigned upload URL must be HTTPS without embedded credentials"),
31778
- publicUrl: z133.string().url().refine((value) => {
31943
+ publicUrl: z134.string().url().refine((value) => {
31779
31944
  const url = new URL(value);
31780
31945
  return !url.username && !url.password;
31781
31946
  }, "public media URL must not contain embedded credentials"),
31782
- stagingAssetId: z133.string().uuid()
31947
+ stagingAssetId: z134.string().uuid()
31783
31948
  });
31784
31949
  async function uploadResolvedMedia(api, media, assetRole) {
31785
31950
  if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
@@ -31805,14 +31970,14 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
31805
31970
  }
31806
31971
  __name(resolveAndUploadMedia, "resolveAndUploadMedia");
31807
31972
  var TikTokMcpCampaignConfig = McpCampaignConfig.extend({
31808
- dailyBudgetUsd: z133.number().finite().positive().optional().describe("Legacy USD amount, supported only for USD advertiser accounts. No FX conversion."),
31809
- dailyBudget: z133.number().finite().positive().optional().describe("Daily budget in the selected advertiser currency major units; pass budgetCurrency together."),
31973
+ dailyBudgetUsd: z134.number().finite().positive().optional().describe("Legacy USD amount, supported only for USD advertiser accounts. No FX conversion."),
31974
+ dailyBudget: z134.number().finite().positive().optional().describe("Daily budget in the selected advertiser currency major units; pass budgetCurrency together."),
31810
31975
  budgetCurrency: TikTokBudgetCurrencySchema.optional(),
31811
31976
  destination: TikTokCampaignDestinationSchema.optional()
31812
31977
  }).superRefine((value, ctx) => {
31813
31978
  if (value.dailyBudgetUsd !== void 0 && (value.dailyBudget !== void 0 || value.budgetCurrency !== void 0)) {
31814
31979
  ctx.addIssue({
31815
- code: z133.ZodIssueCode.custom,
31980
+ code: z134.ZodIssueCode.custom,
31816
31981
  path: [
31817
31982
  "dailyBudgetUsd"
31818
31983
  ],
@@ -31821,7 +31986,7 @@ var TikTokMcpCampaignConfig = McpCampaignConfig.extend({
31821
31986
  }
31822
31987
  if (value.dailyBudget !== void 0 !== (value.budgetCurrency !== void 0)) {
31823
31988
  ctx.addIssue({
31824
- code: z133.ZodIssueCode.custom,
31989
+ code: z134.ZodIssueCode.custom,
31825
31990
  path: [
31826
31991
  "budgetCurrency"
31827
31992
  ],
@@ -31829,16 +31994,16 @@ var TikTokMcpCampaignConfig = McpCampaignConfig.extend({
31829
31994
  });
31830
31995
  }
31831
31996
  });
31832
- var TikTokInput = z133.object({
31833
- taskId: z133.string().min(1),
31834
- advertiserId: z133.string().min(1),
31835
- pixelId: z133.string().min(1).optional(),
31836
- landingUrl: z133.string().url().optional(),
31837
- angleIndexes: z133.array(z133.number().int().nonnegative()).optional(),
31997
+ var TikTokInput = z134.object({
31998
+ taskId: z134.string().min(1),
31999
+ advertiserId: z134.string().min(1),
32000
+ pixelId: z134.string().min(1).optional(),
32001
+ landingUrl: z134.string().url().optional(),
32002
+ angleIndexes: z134.array(z134.number().int().nonnegative()).optional(),
31838
32003
  campaignConfig: TikTokMcpCampaignConfig.optional(),
31839
32004
  /** Override the ad's description (TikTok's body copy). If omitted,
31840
32005
  * ProductMaker uses the auto-generated copy attached to the task. */
31841
- primaryText: z133.string().trim().min(1).max(500).optional()
32006
+ primaryText: z134.string().trim().min(1).max(500).optional()
31842
32007
  });
31843
32008
  function registerPublishTools(server, api, opts = {}) {
31844
32009
  const transport = opts.transport ?? "http";
@@ -32197,39 +32362,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
32197
32362
 
32198
32363
  // src/tools/meta-upload.ts
32199
32364
  import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
32200
- import { z as z134 } from "zod";
32365
+ import { z as z135 } from "zod";
32201
32366
  var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
32202
- var UploadSessionInputBase = z134.object({
32203
- mediaKind: z134.enum([
32367
+ var UploadSessionInputBase = z135.object({
32368
+ mediaKind: z135.enum([
32204
32369
  "image",
32205
32370
  "video",
32206
32371
  "mixed"
32207
32372
  ]).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."),
32208
- assetRole: z134.enum([
32373
+ assetRole: z135.enum([
32209
32374
  "media",
32210
32375
  "thumbnail"
32211
32376
  ]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
32212
- uploadPurpose: z134.enum([
32377
+ uploadPurpose: z135.enum([
32213
32378
  "product_reference",
32214
32379
  "creative",
32215
32380
  "generic"
32216
32381
  ]).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."),
32217
- maxFiles: z134.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
32382
+ maxFiles: z135.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
32218
32383
  });
32219
- var OpenAiFileReference = z134.object({
32220
- download_url: z134.string().url().describe("Required by ChatGPT's openai/fileParams schema. The App prefers getFileDownloadUrl(file_id) for a fresh URL, and the server never fetches this value."),
32221
- file_id: z134.string().min(1),
32222
- mime_type: z134.string().min(1).optional(),
32223
- file_name: z134.string().min(1).optional()
32384
+ var OpenAiFileReference = z135.object({
32385
+ download_url: z135.string().url().describe("Required by ChatGPT's openai/fileParams schema. The App prefers getFileDownloadUrl(file_id) for a fresh URL, and the server never fetches this value."),
32386
+ file_id: z135.string().min(1),
32387
+ mime_type: z135.string().min(1).optional(),
32388
+ file_name: z135.string().min(1).optional()
32224
32389
  });
32225
32390
  var UploadSessionToolInputShape = {
32226
32391
  ...UploadSessionInputBase.shape,
32227
- files: z134.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.")
32392
+ files: z135.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.")
32228
32393
  };
32229
- var UploadSessionToolInput = z134.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
32394
+ var UploadSessionToolInput = z135.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
32230
32395
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
32231
32396
  ctx.addIssue({
32232
- code: z134.ZodIssueCode.custom,
32397
+ code: z135.ZodIssueCode.custom,
32233
32398
  path: [
32234
32399
  "mediaKind"
32235
32400
  ],
@@ -32238,7 +32403,7 @@ var UploadSessionToolInput = z134.object(UploadSessionToolInputShape).superRefin
32238
32403
  }
32239
32404
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
32240
32405
  ctx.addIssue({
32241
- code: z134.ZodIssueCode.custom,
32406
+ code: z135.ZodIssueCode.custom,
32242
32407
  path: [
32243
32408
  "maxFiles"
32244
32409
  ],
@@ -32247,7 +32412,7 @@ var UploadSessionToolInput = z134.object(UploadSessionToolInputShape).superRefin
32247
32412
  }
32248
32413
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
32249
32414
  ctx.addIssue({
32250
- code: z134.ZodIssueCode.custom,
32415
+ code: z135.ZodIssueCode.custom,
32251
32416
  path: [
32252
32417
  "maxFiles"
32253
32418
  ],
@@ -32255,38 +32420,38 @@ var UploadSessionToolInput = z134.object(UploadSessionToolInputShape).superRefin
32255
32420
  });
32256
32421
  }
32257
32422
  });
32258
- var UploadSessionResponse = z134.object({
32259
- sessionId: z134.string().uuid(),
32260
- uploadPageUrl: z134.string().url(),
32261
- mediaKind: z134.enum([
32423
+ var UploadSessionResponse = z135.object({
32424
+ sessionId: z135.string().uuid(),
32425
+ uploadPageUrl: z135.string().url(),
32426
+ mediaKind: z135.enum([
32262
32427
  "image",
32263
32428
  "video",
32264
32429
  "mixed"
32265
32430
  ]),
32266
- assetRole: z134.enum([
32431
+ assetRole: z135.enum([
32267
32432
  "media",
32268
32433
  "thumbnail"
32269
32434
  ]),
32270
- maxFiles: z134.number().int().positive(),
32271
- expiresAt: z134.string().datetime()
32435
+ maxFiles: z135.number().int().positive(),
32436
+ expiresAt: z135.string().datetime()
32272
32437
  });
32273
- var UploadStatusInput = z134.object({
32274
- sessionId: z134.string().uuid().describe("The sessionId returned by request_media_upload.")
32438
+ var UploadStatusInput = z135.object({
32439
+ sessionId: z135.string().uuid().describe("The sessionId returned by request_media_upload.")
32275
32440
  });
32276
- var UniversalUploadStatusResponse = z134.discriminatedUnion("status", [
32277
- z134.object({
32278
- status: z134.literal("pending"),
32279
- assets: z134.array(z134.never()).length(0)
32441
+ var UniversalUploadStatusResponse = z135.discriminatedUnion("status", [
32442
+ z135.object({
32443
+ status: z135.literal("pending"),
32444
+ assets: z135.array(z135.never()).length(0)
32280
32445
  }),
32281
- z134.object({
32282
- status: z134.literal("uploaded"),
32283
- assets: z134.array(z134.object({
32284
- assetId: z134.string().uuid(),
32285
- mediaKind: z134.enum([
32446
+ z135.object({
32447
+ status: z135.literal("uploaded"),
32448
+ assets: z135.array(z135.object({
32449
+ assetId: z135.string().uuid(),
32450
+ mediaKind: z135.enum([
32286
32451
  "image",
32287
32452
  "video"
32288
32453
  ]),
32289
- assetRole: z134.enum([
32454
+ assetRole: z135.enum([
32290
32455
  "media",
32291
32456
  "thumbnail"
32292
32457
  ])
@@ -32294,13 +32459,13 @@ var UniversalUploadStatusResponse = z134.discriminatedUnion("status", [
32294
32459
  })
32295
32460
  ]);
32296
32461
  var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
32297
- uploadPurpose: z134.enum([
32462
+ uploadPurpose: z135.enum([
32298
32463
  "product_reference",
32299
32464
  "creative",
32300
32465
  "generic"
32301
32466
  ]),
32302
- checkToolName: z134.literal("check_media_upload"),
32303
- resolveEndpoint: z134.string().url()
32467
+ checkToolName: z135.literal("check_media_upload"),
32468
+ resolveEndpoint: z135.string().url()
32304
32469
  });
32305
32470
  function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
32306
32471
  const url = new URL(uploadPageUrl);
@@ -32391,15 +32556,15 @@ function registerMediaUploadTools(server, api) {
32391
32556
  __name(registerMediaUploadTools, "registerMediaUploadTools");
32392
32557
 
32393
32558
  // src/tools/campaigns.ts
32394
- import { z as z135 } from "zod";
32559
+ import { z as z136 } from "zod";
32395
32560
  var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
32396
32561
  var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
32397
- var MetaStatusInput = z135.object({
32398
- campaignId: z135.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
32562
+ var MetaStatusInput = z136.object({
32563
+ campaignId: z136.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
32399
32564
  });
32400
- var TikTokStatusInput = z135.object({
32401
- campaignId: z135.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
32402
- advertiserId: z135.string().min(1).describe("The same advertiserId used to publish the campaign.")
32565
+ var TikTokStatusInput = z136.object({
32566
+ campaignId: z136.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
32567
+ advertiserId: z136.string().min(1).describe("The same advertiserId used to publish the campaign.")
32403
32568
  });
32404
32569
  function registerCampaignTools(server, api) {
32405
32570
  server.registerTool("get_meta_campaign_status", {
@@ -32504,10 +32669,10 @@ function renderTikTokStatusMarkdown(r) {
32504
32669
  __name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
32505
32670
 
32506
32671
  // ../../packages/product-economics/src/product-costing.ts
32507
- import { z as z137 } from "zod";
32672
+ import { z as z138 } from "zod";
32508
32673
 
32509
32674
  // ../../packages/product-economics/src/product-costing-countries.ts
32510
- import { z as z136 } from "zod";
32675
+ import { z as z137 } from "zod";
32511
32676
 
32512
32677
  // ../../packages/product-economics/src/product-costing-shipping-references.json
32513
32678
  var product_costing_shipping_references_default = {
@@ -32571,21 +32736,21 @@ var product_costing_shipping_references_default = {
32571
32736
  };
32572
32737
 
32573
32738
  // ../../packages/product-economics/src/product-costing-countries.ts
32574
- var ShippingReferenceSchema = z136.object({
32575
- reference: z136.number().positive(),
32576
- min: z136.number().nonnegative(),
32577
- max: z136.number().positive(),
32578
- updatedAt: z136.string().date(),
32579
- confidence: z136.enum([
32739
+ var ShippingReferenceSchema = z137.object({
32740
+ reference: z137.number().positive(),
32741
+ min: z137.number().nonnegative(),
32742
+ max: z137.number().positive(),
32743
+ updatedAt: z137.string().date(),
32744
+ confidence: z137.enum([
32580
32745
  "high",
32581
32746
  "medium",
32582
32747
  "medium-low"
32583
32748
  ]),
32584
- sources: z136.array(z136.string().url().startsWith("https://")).min(1).max(3)
32749
+ sources: z137.array(z137.string().url().startsWith("https://")).min(1).max(3)
32585
32750
  }).superRefine(({ reference, min, max }, context) => {
32586
32751
  if (min > reference || reference > max) {
32587
32752
  context.addIssue({
32588
- code: z136.ZodIssueCode.custom,
32753
+ code: z137.ZodIssueCode.custom,
32589
32754
  message: "shipping_reference_outside_range",
32590
32755
  path: [
32591
32756
  "reference"
@@ -32593,7 +32758,7 @@ var ShippingReferenceSchema = z136.object({
32593
32758
  });
32594
32759
  }
32595
32760
  });
32596
- var SHIPPING_REFERENCES = z136.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
32761
+ var SHIPPING_REFERENCES = z137.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
32597
32762
  var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
32598
32763
  var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
32599
32764
  "MX",
@@ -32775,18 +32940,18 @@ function getProductCostingCountryName(country) {
32775
32940
  __name(getProductCostingCountryName, "getProductCostingCountryName");
32776
32941
 
32777
32942
  // ../../packages/product-economics/src/product-costing.ts
32778
- var ProductCostingInputSchema = z137.object({
32779
- country: z137.string().refine(isProductCostingCountryCode, "unsupported_country"),
32780
- supplierCost: z137.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
32781
- shippingCost: z137.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
32782
- returnRate: z137.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
32783
- cancellationRate: z137.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
32784
- adsManagerCpa: z137.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
32785
- desiredMargin: z137.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
32943
+ var ProductCostingInputSchema = z138.object({
32944
+ country: z138.string().refine(isProductCostingCountryCode, "unsupported_country"),
32945
+ supplierCost: z138.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
32946
+ shippingCost: z138.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
32947
+ returnRate: z138.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
32948
+ cancellationRate: z138.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
32949
+ adsManagerCpa: z138.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
32950
+ desiredMargin: z138.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
32786
32951
  }).superRefine(({ returnRate, cancellationRate }, context) => {
32787
32952
  if (returnRate + cancellationRate >= 1) {
32788
32953
  context.addIssue({
32789
- code: z137.ZodIssueCode.custom,
32954
+ code: z138.ZodIssueCode.custom,
32790
32955
  message: "delivery_rate_positive",
32791
32956
  path: [
32792
32957
  "cancellationRate"
@@ -32883,15 +33048,15 @@ function calculateProductCosting(rawInput) {
32883
33048
  __name(calculateProductCosting, "calculateProductCosting");
32884
33049
 
32885
33050
  // src/tools/product-costing.ts
32886
- import { z as z138 } from "zod";
33051
+ import { z as z139 } from "zod";
32887
33052
  var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
32888
- var optionalAmount = /* @__PURE__ */ __name((description) => z138.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
32889
- var optionalPercent = /* @__PURE__ */ __name((description) => z138.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
32890
- var ProductCostingToolInput = z138.object({
32891
- country: z138.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
33053
+ var optionalAmount = /* @__PURE__ */ __name((description) => z139.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
33054
+ var optionalPercent = /* @__PURE__ */ __name((description) => z139.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
33055
+ var ProductCostingToolInput = z139.object({
33056
+ country: z139.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
32892
33057
  message: "Pa\xEDs no soportado por ProductMaker."
32893
33058
  }).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
32894
- supplierCost: z138.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."),
33059
+ supplierCost: z139.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."),
32895
33060
  supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
32896
33061
  shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
32897
33062
  shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
@@ -33054,7 +33219,7 @@ function formatPercent(value) {
33054
33219
  __name(formatPercent, "formatPercent");
33055
33220
 
33056
33221
  // src/tools/product-research.ts
33057
- import { z as z139 } from "zod";
33222
+ import { z as z140 } from "zod";
33058
33223
 
33059
33224
  // src/tools/product-research-idempotency.ts
33060
33225
  var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
@@ -33425,35 +33590,35 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
33425
33590
  ]);
33426
33591
  var POLL_INTERVAL_MS = 5e3;
33427
33592
  var MAX_WAIT_SECONDS = 120;
33428
- var FindInput = z139.object({
33593
+ var FindInput = z140.object({
33429
33594
  targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
33430
33595
  categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
33431
- confirmed: z139.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
33432
- waitSeconds: z139.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
33596
+ confirmed: z140.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
33597
+ waitSeconds: z140.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
33433
33598
  });
33434
- var GetInput = z139.object({
33435
- runId: z139.string().uuid().describe("ID del run devuelto por find_winning_products.")
33599
+ var GetInput = z140.object({
33600
+ runId: z140.string().uuid().describe("ID del run devuelto por find_winning_products.")
33436
33601
  });
33437
- var ListInput = z139.object({
33438
- limit: z139.number().int().min(1).max(20).default(10)
33602
+ var ListInput = z140.object({
33603
+ limit: z140.number().int().min(1).max(20).default(10)
33439
33604
  });
33440
- function textResult(text3) {
33605
+ function textResult(text4) {
33441
33606
  return {
33442
33607
  content: [
33443
33608
  {
33444
33609
  type: "text",
33445
- text: text3
33610
+ text: text4
33446
33611
  }
33447
33612
  ]
33448
33613
  };
33449
33614
  }
33450
33615
  __name(textResult, "textResult");
33451
- function researchResult(run, text3) {
33616
+ function researchResult(run, text4) {
33452
33617
  return {
33453
33618
  content: [
33454
33619
  {
33455
33620
  type: "text",
33456
- text: text3
33621
+ text: text4
33457
33622
  }
33458
33623
  ],
33459
33624
  structuredContent: run
@@ -33574,17 +33739,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
33574
33739
  __name(registerProductResearchTools, "registerProductResearchTools");
33575
33740
 
33576
33741
  // src/tools/dropshipping-projects.ts
33577
- import { z as z140 } from "zod";
33742
+ import { z as z141 } from "zod";
33578
33743
  var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
33579
33744
  var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
33580
33745
  var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
33581
- var ProjectId = z140.string().uuid();
33582
- var DropshippingProjectStatus = z140.enum([
33746
+ var ProjectId = z141.string().uuid();
33747
+ var DropshippingProjectStatus = z141.enum([
33583
33748
  "active",
33584
33749
  "completed",
33585
33750
  "archived"
33586
33751
  ]);
33587
- var DropshippingProjectPhase = z140.enum([
33752
+ var DropshippingProjectPhase = z141.enum([
33588
33753
  "research",
33589
33754
  "costing",
33590
33755
  "media",
@@ -33593,21 +33758,21 @@ var DropshippingProjectPhase = z140.enum([
33593
33758
  "advertising",
33594
33759
  "complete"
33595
33760
  ]);
33596
- var DropshippingRewardMilestone = z140.enum([
33761
+ var DropshippingRewardMilestone = z141.enum([
33597
33762
  "product_selected",
33598
33763
  "costing_saved",
33599
33764
  "product_media_ready",
33600
33765
  "creatives_completed",
33601
33766
  "campaign_created"
33602
33767
  ]);
33603
- var TargetCountry = z140.enum([
33768
+ var TargetCountry = z141.enum([
33604
33769
  "CO",
33605
33770
  "MX",
33606
33771
  "PE",
33607
33772
  "EC",
33608
33773
  "CL"
33609
33774
  ]);
33610
- var ResearchCategory = z140.enum([
33775
+ var ResearchCategory = z141.enum([
33611
33776
  "auto",
33612
33777
  "automotive",
33613
33778
  "kitchen",
@@ -33622,7 +33787,7 @@ var ResearchCategory = z140.enum([
33622
33787
  "garden",
33623
33788
  "cleaning"
33624
33789
  ]);
33625
- var HttpUrl3 = z140.string().url().max(2e3).refine((value) => {
33790
+ var HttpUrl3 = z141.string().url().max(2e3).refine((value) => {
33626
33791
  try {
33627
33792
  return [
33628
33793
  "http:",
@@ -33632,45 +33797,45 @@ var HttpUrl3 = z140.string().url().max(2e3).refine((value) => {
33632
33797
  return false;
33633
33798
  }
33634
33799
  }, "URL must use HTTP(S)");
33635
- var ResearchCandidateOrigin = z140.object({
33636
- type: z140.literal("research_candidate"),
33800
+ var ResearchCandidateOrigin = z141.object({
33801
+ type: z141.literal("research_candidate"),
33637
33802
  runId: ProjectId,
33638
- candidateSourceId: z140.string().min(1).max(160)
33803
+ candidateSourceId: z141.string().min(1).max(160)
33639
33804
  });
33640
- var TaskOrigin = z140.object({
33641
- type: z140.literal("task"),
33805
+ var TaskOrigin = z141.object({
33806
+ type: z141.literal("task"),
33642
33807
  taskId: ProjectId
33643
33808
  });
33644
- var ManualOrigin = z140.object({
33645
- type: z140.literal("manual"),
33809
+ var ManualOrigin = z141.object({
33810
+ type: z141.literal("manual"),
33646
33811
  clientRequestId: ProjectId,
33647
- country: z140.string().min(2).max(3).optional()
33812
+ country: z141.string().min(2).max(3).optional()
33648
33813
  });
33649
- var StartProjectInput = z140.object({
33650
- origin: z140.discriminatedUnion("type", [
33814
+ var StartProjectInput = z141.object({
33815
+ origin: z141.discriminatedUnion("type", [
33651
33816
  ResearchCandidateOrigin,
33652
33817
  TaskOrigin,
33653
33818
  ManualOrigin
33654
33819
  ]),
33655
- productName: z140.string().trim().min(1).max(240).optional(),
33820
+ productName: z141.string().trim().min(1).max(240).optional(),
33656
33821
  productUrl: HttpUrl3.optional(),
33657
- country: z140.string().min(2).max(3).optional(),
33658
- languageCode: z140.string().min(2).max(16).optional()
33822
+ country: z141.string().min(2).max(3).optional(),
33823
+ languageCode: z141.string().min(2).max(16).optional()
33659
33824
  }).strict();
33660
- var CostProjectInput = z140.object({
33825
+ var CostProjectInput = z141.object({
33661
33826
  projectId: ProjectId,
33662
- version: z140.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
33663
- country: z140.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
33827
+ version: z141.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
33828
+ country: z141.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
33664
33829
  message: "Pa\xEDs no soportado por ProductMaker."
33665
33830
  }).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
33666
- supplierCost: z140.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."),
33667
- shippingCost: z140.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
33668
- returnRate: z140.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."),
33669
- cancellationRate: z140.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."),
33670
- adsManagerCpa: z140.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
33671
- desiredMargin: z140.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
33672
- });
33673
- var GuideInput = z140.object({
33831
+ supplierCost: z141.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."),
33832
+ shippingCost: z141.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
33833
+ returnRate: z141.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."),
33834
+ cancellationRate: z141.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."),
33835
+ adsManagerCpa: z141.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
33836
+ desiredMargin: z141.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
33837
+ });
33838
+ var GuideInput = z141.object({
33674
33839
  projectId: ProjectId.optional()
33675
33840
  }).strict();
33676
33841
  var NEXT_ACTION_KINDS = [
@@ -33688,29 +33853,29 @@ var NEXT_ACTION_KINDS = [
33688
33853
  "repair_meta_campaign",
33689
33854
  "review_paused_campaign"
33690
33855
  ];
33691
- var DropshippingProjectNextAction = z140.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z140.object({
33692
- kind: z140.literal(kind),
33693
- href: z140.string().min(1)
33856
+ var DropshippingProjectNextAction = z141.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z141.object({
33857
+ kind: z141.literal(kind),
33858
+ href: z141.string().min(1)
33694
33859
  })));
33695
- var CostingInputSchema = z140.object({
33696
- country: z140.string().min(2).max(3),
33697
- supplierCost: z140.number().finite().positive(),
33698
- shippingCost: z140.number().finite().nonnegative(),
33699
- returnRate: z140.number().finite().min(0).lt(1),
33700
- cancellationRate: z140.number().finite().min(0).lt(1),
33701
- adsManagerCpa: z140.number().finite().nonnegative(),
33702
- desiredMargin: z140.number().finite().min(0).lt(1)
33860
+ var CostingInputSchema = z141.object({
33861
+ country: z141.string().min(2).max(3),
33862
+ supplierCost: z141.number().finite().positive(),
33863
+ shippingCost: z141.number().finite().nonnegative(),
33864
+ returnRate: z141.number().finite().min(0).lt(1),
33865
+ cancellationRate: z141.number().finite().min(0).lt(1),
33866
+ adsManagerCpa: z141.number().finite().nonnegative(),
33867
+ desiredMargin: z141.number().finite().min(0).lt(1)
33703
33868
  }).superRefine(({ returnRate, cancellationRate }, context) => {
33704
33869
  if (returnRate + cancellationRate >= 1) context.addIssue({
33705
- code: z140.ZodIssueCode.custom,
33870
+ code: z141.ZodIssueCode.custom,
33706
33871
  path: [
33707
33872
  "cancellationRate"
33708
33873
  ]
33709
33874
  });
33710
33875
  });
33711
- var FiniteCostingNumber = z140.number().finite();
33712
- var CostingResultSchema = z140.object({
33713
- country: z140.string().min(2).max(3),
33876
+ var FiniteCostingNumber = z141.number().finite();
33877
+ var CostingResultSchema = z141.object({
33878
+ country: z141.string().min(2).max(3),
33714
33879
  deliveryRate: FiniteCostingNumber,
33715
33880
  adjustedShippingCost: FiniteCostingNumber,
33716
33881
  adjustedCpa: FiniteCostingNumber,
@@ -33723,45 +33888,45 @@ var CostingResultSchema = z140.object({
33723
33888
  estimatedProfit: FiniteCostingNumber,
33724
33889
  actualMargin: FiniteCostingNumber,
33725
33890
  breakEvenAdsManagerCpa: FiniteCostingNumber,
33726
- wasPriceAutoAdjusted: z140.boolean(),
33727
- profitabilityStatus: z140.literal("healthy")
33728
- });
33729
- var RewardProgressSchema = z140.object({
33730
- campaignKey: z140.literal("dropshipping-launch-v1"),
33731
- totalCredits: z140.number().int().positive(),
33732
- earnedCredits: z140.number().int().nonnegative(),
33733
- milestones: z140.array(z140.object({
33891
+ wasPriceAutoAdjusted: z141.boolean(),
33892
+ profitabilityStatus: z141.literal("healthy")
33893
+ });
33894
+ var RewardProgressSchema = z141.object({
33895
+ campaignKey: z141.literal("dropshipping-launch-v1"),
33896
+ totalCredits: z141.number().int().positive(),
33897
+ earnedCredits: z141.number().int().nonnegative(),
33898
+ milestones: z141.array(z141.object({
33734
33899
  milestone: DropshippingRewardMilestone,
33735
- credits: z140.number().int().positive(),
33736
- available: z140.boolean().optional(),
33737
- earned: z140.boolean(),
33900
+ credits: z141.number().int().positive(),
33901
+ available: z141.boolean().optional(),
33902
+ earned: z141.boolean(),
33738
33903
  grantId: ProjectId.nullable(),
33739
- grantedAt: z140.string().datetime().nullable()
33904
+ grantedAt: z141.string().datetime().nullable()
33740
33905
  })).length(DropshippingRewardMilestone.options.length)
33741
33906
  });
33742
- var ProjectResponseSchema = z140.object({
33907
+ var ProjectResponseSchema = z141.object({
33743
33908
  id: ProjectId,
33744
33909
  taskId: ProjectId.nullable(),
33745
33910
  status: DropshippingProjectStatus,
33746
- originKey: z140.string().min(1),
33911
+ originKey: z141.string().min(1),
33747
33912
  researchRunId: ProjectId.nullable(),
33748
- candidateSourceId: z140.string().nullable(),
33749
- productName: z140.string().nullable(),
33913
+ candidateSourceId: z141.string().nullable(),
33914
+ productName: z141.string().nullable(),
33750
33915
  productUrl: HttpUrl3.nullable(),
33751
33916
  referenceImageUrl: HttpUrl3.nullable(),
33752
- targetCountry: z140.string().nullable(),
33753
- languageCode: z140.string().nullable(),
33754
- hasReferenceImage: z140.boolean(),
33755
- hasWinnerReferenceImage: z140.boolean(),
33917
+ targetCountry: z141.string().nullable(),
33918
+ languageCode: z141.string().nullable(),
33919
+ hasReferenceImage: z141.boolean(),
33920
+ hasWinnerReferenceImage: z141.boolean(),
33756
33921
  costingInput: CostingInputSchema.nullable(),
33757
33922
  costingResult: CostingResultSchema.nullable(),
33758
- costingVersion: z140.number().int().positive().nullable(),
33759
- version: z140.number().int().positive(),
33923
+ costingVersion: z141.number().int().positive().nullable(),
33924
+ version: z141.number().int().positive(),
33760
33925
  phase: DropshippingProjectPhase,
33761
33926
  nextAction: DropshippingProjectNextAction.nullable(),
33762
33927
  rewards: RewardProgressSchema,
33763
- createdAt: z140.string().datetime(),
33764
- updatedAt: z140.string().datetime()
33928
+ createdAt: z141.string().datetime(),
33929
+ updatedAt: z141.string().datetime()
33765
33930
  }).passthrough();
33766
33931
  var NEXT_ACTION_GUIDANCE = {
33767
33932
  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.",
@@ -33881,58 +34046,58 @@ function registerDropshippingProjectTools(server, api) {
33881
34046
  __name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
33882
34047
 
33883
34048
  // src/tools/daily-control.ts
33884
- import { z as z141 } from "zod";
34049
+ import { z as z142 } from "zod";
33885
34050
  var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
33886
34051
  var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
33887
34052
  var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
33888
- var ProviderCampaignIdentifier = z141.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
33889
- var DateOnly = z141.string().regex(/^\d{4}-\d{2}-\d{2}$/);
33890
- var DailyControlInput = z141.object({
34053
+ var ProviderCampaignIdentifier = z142.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
34054
+ var DateOnly = z142.string().regex(/^\d{4}-\d{2}-\d{2}$/);
34055
+ var DailyControlInput = z142.object({
33891
34056
  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."),
33892
- days: z141.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
33893
- projectId: z141.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
34057
+ days: z142.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
34058
+ projectId: z142.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
33894
34059
  }).strict();
33895
- var LinkCampaignInput = z141.object({
33896
- projectId: z141.string().uuid(),
33897
- provider: z141.enum([
34060
+ var LinkCampaignInput = z142.object({
34061
+ projectId: z142.string().uuid(),
34062
+ provider: z142.enum([
33898
34063
  "meta",
33899
34064
  "tiktok"
33900
34065
  ]),
33901
34066
  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."),
33902
34067
  campaignId: ProviderCampaignIdentifier
33903
34068
  }).strict();
33904
- var ReportReturnsInput = z141.object({
33905
- projectId: z141.string().uuid(),
34069
+ var ReportReturnsInput = z142.object({
34070
+ projectId: z142.string().uuid(),
33906
34071
  date: DateOnly,
33907
- returnedOrders: z141.number().int().min(0).max(1e5),
33908
- note: z141.string().trim().max(280).optional()
33909
- }).strict();
33910
- var DailyControlStatusMirror = DailyControlStatusEnum.or(z141.string());
33911
- var DailyControlLightMirror = DailyControlLightEnum.or(z141.string());
33912
- var DailyControlSourceMirror = DailyControlSourceEnum.or(z141.string());
33913
- var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z141.string());
33914
- var DailyControlDayMirror = z141.object({
33915
- date: z141.string(),
33916
- returnedOrders: z141.number(),
34072
+ returnedOrders: z142.number().int().min(0).max(1e5),
34073
+ note: z142.string().trim().max(280).optional()
34074
+ }).strict();
34075
+ var DailyControlStatusMirror = DailyControlStatusEnum.or(z142.string());
34076
+ var DailyControlLightMirror = DailyControlLightEnum.or(z142.string());
34077
+ var DailyControlSourceMirror = DailyControlSourceEnum.or(z142.string());
34078
+ var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z142.string());
34079
+ var DailyControlDayMirror = z142.object({
34080
+ date: z142.string(),
34081
+ returnedOrders: z142.number(),
33917
34082
  returnedSource: DailyControlSourceMirror,
33918
34083
  cancelledSource: DailyControlSourceMirror,
33919
- hasEstimates: z141.boolean(),
34084
+ hasEstimates: z142.boolean(),
33920
34085
  light: DailyControlLightMirror
33921
34086
  }).passthrough();
33922
- var DailyControlProductMirror = z141.object({
33923
- projectId: z141.string().uuid(),
33924
- productName: z141.string().nullable(),
34087
+ var DailyControlProductMirror = z142.object({
34088
+ projectId: z142.string().uuid(),
34089
+ productName: z142.string().nullable(),
33925
34090
  status: DailyControlStatusMirror,
33926
- statusMessage: z141.string().nullable(),
33927
- days: z141.array(DailyControlDayMirror),
34091
+ statusMessage: z142.string().nullable(),
34092
+ days: z142.array(DailyControlDayMirror),
33928
34093
  verdict: DailyControlVerdictMirror.nullable(),
33929
- rationale: z141.string().nullable()
34094
+ rationale: z142.string().nullable()
33930
34095
  }).passthrough();
33931
- var DailyControlResponseMirror = z141.object({
33932
- since: z141.string(),
33933
- until: z141.string(),
33934
- products: z141.array(DailyControlProductMirror),
33935
- archivedProjectSpend: z141.array(z141.unknown())
34096
+ var DailyControlResponseMirror = z142.object({
34097
+ since: z142.string(),
34098
+ until: z142.string(),
34099
+ products: z142.array(DailyControlProductMirror),
34100
+ archivedProjectSpend: z142.array(z142.unknown())
33936
34101
  }).passthrough();
33937
34102
  var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
33938
34103
  function withWarnings(response) {
@@ -34007,7 +34172,7 @@ __name(registerDailyControlTools, "registerDailyControlTools");
34007
34172
  // src/tools/product-control.ts
34008
34173
  import { readFile, stat } from "fs/promises";
34009
34174
  import { basename as basename2, isAbsolute, resolve as resolve3 } from "path";
34010
- import { z as z142 } from "zod";
34175
+ import { z as z143 } from "zod";
34011
34176
  var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
34012
34177
  var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
34013
34178
  var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
@@ -34020,36 +34185,36 @@ var createOperationGuidance = getProductMakerCapabilityModelGuidance("create_ope
34020
34185
  var mergeProductsGuidance = getProductMakerCapabilityModelGuidance("merge_products");
34021
34186
  var syncShopifyOrdersGuidance = getProductMakerCapabilityModelGuidance("sync_shopify_orders");
34022
34187
  var importOrdersFileGuidance = getProductMakerCapabilityModelGuidance("import_orders_file");
34023
- var DateOnly2 = z142.string().regex(/^\d{4}-\d{2}-\d{2}$/);
34188
+ var DateOnly2 = z143.string().regex(/^\d{4}-\d{2}-\d{2}$/);
34024
34189
  var IMPORT_BATCH_MAX2 = 50;
34025
- var ProductControlListInput = z142.object({
34026
- days: z142.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
34190
+ var ProductControlListInput = z143.object({
34191
+ days: z143.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
34027
34192
  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."),
34028
- shopDomain: z142.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
34193
+ shopDomain: z143.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
34029
34194
  }).strict();
34030
- var ImportableProductsInput = z142.object({
34031
- q: z142.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
34032
- after: z142.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
34033
- shopDomain: z142.string().min(1).optional()
34195
+ var ImportableProductsInput = z143.object({
34196
+ q: z143.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
34197
+ after: z143.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
34198
+ shopDomain: z143.string().min(1).optional()
34034
34199
  }).strict();
34035
- var ImportProductControlsInput = z142.object({
34036
- shopifyProductIds: z142.array(z142.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."),
34200
+ var ImportProductControlsInput = z143.object({
34201
+ shopifyProductIds: z143.array(z143.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."),
34037
34202
  // Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
34038
34203
  // sin decir a cuál archivaría el producto bajo la tienda equivocada.
34039
- shopDomain: z142.string().min(1)
34040
- }).strict();
34041
- var SetProductCostingInput = z142.object({
34042
- shopDomain: z142.string().min(1),
34043
- shopifyProductId: z142.string().min(1).max(64),
34044
- targetCountry: z142.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
34045
- supplierCost: z142.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
34046
- shippingCost: z142.number().finite().nonnegative(),
34047
- returnRate: z142.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
34048
- cancellationRate: z142.number().finite().min(0).lt(1)
34049
- }).strict();
34050
- var Count = z142.number().int().min(0).max(1e5).nullable().optional();
34051
- var ReportProductCountsInput = z142.object({
34052
- productControlId: z142.string().uuid().describe("El identificador que devuelve get_product_control."),
34204
+ shopDomain: z143.string().min(1)
34205
+ }).strict();
34206
+ var SetProductCostingInput = z143.object({
34207
+ shopDomain: z143.string().min(1),
34208
+ shopifyProductId: z143.string().min(1).max(64),
34209
+ targetCountry: z143.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
34210
+ supplierCost: z143.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
34211
+ shippingCost: z143.number().finite().nonnegative(),
34212
+ returnRate: z143.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
34213
+ cancellationRate: z143.number().finite().min(0).lt(1)
34214
+ }).strict();
34215
+ var Count = z143.number().int().min(0).max(1e5).nullable().optional();
34216
+ var ReportProductCountsInput = z143.object({
34217
+ productControlId: z143.string().uuid().describe("El identificador que devuelve get_product_control."),
34053
34218
  date: DateOnly2,
34054
34219
  orders: Count.describe("Pedidos que entraron ese d\xEDa."),
34055
34220
  cancelledOrders: Count,
@@ -34059,36 +34224,36 @@ var ReportProductCountsInput = z142.object({
34059
34224
  }).strict();
34060
34225
  var MAX_ORDERS_FILE_BYTES = 8 * 1024 * 1024;
34061
34226
  var SyncShopifyOrdersInput = SyncShopifyOrdersSchema;
34062
- var ImportOrdersFileInput = z142.object({
34227
+ var ImportOrdersFileInput = z143.object({
34063
34228
  /** Ruta ABSOLUTA en la máquina de quien usa el MCP. */
34064
- path: z142.string().min(1),
34065
- operationId: z142.string().uuid().optional(),
34229
+ path: z143.string().min(1),
34230
+ operationId: z143.string().uuid().optional(),
34066
34231
  /** Solo mirar: devuelve el resumen y no escribe nada. */
34067
- dryRun: z142.boolean().optional()
34232
+ dryRun: z143.boolean().optional()
34068
34233
  }).strict();
34069
- var CreateOperationInput = z142.object({
34070
- countryCode: z142.string().length(2),
34071
- label: z142.string().trim().min(1).max(60).optional()
34234
+ var CreateOperationInput = z143.object({
34235
+ countryCode: z143.string().length(2),
34236
+ label: z143.string().trim().min(1).max(60).optional()
34072
34237
  }).strict();
34073
- var MergeProductsInput = z142.object({
34074
- sourceId: z142.string().uuid(),
34075
- targetId: z142.string().uuid()
34238
+ var MergeProductsInput = z143.object({
34239
+ sourceId: z143.string().uuid(),
34240
+ targetId: z143.string().uuid()
34076
34241
  }).strict();
34077
- var SetMonthlyExpenseInput = z142.object({
34078
- month: z142.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
34242
+ var SetMonthlyExpenseInput = z143.object({
34243
+ month: z143.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
34079
34244
  label: SaveMonthlyExpenseSchema.shape.label,
34080
- amount: z142.number().finite().min(0),
34081
- operationId: z142.string().uuid().optional()
34245
+ amount: z143.number().finite().min(0),
34246
+ operationId: z143.string().uuid().optional()
34082
34247
  }).strict();
34083
- var SetAdSpendInput = z142.object({
34084
- month: z142.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
34085
- operationId: z142.string().uuid().optional(),
34248
+ var SetAdSpendInput = z143.object({
34249
+ month: z143.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
34250
+ operationId: z143.string().uuid().optional(),
34086
34251
  /** null RETIRA la corrección; cero afirma que no pautó. */
34087
- amount: z142.number().finite().min(0).nullable()
34252
+ amount: z143.number().finite().min(0).nullable()
34088
34253
  }).strict();
34089
- var GetFinancesInput = z142.object({
34090
- month: z142.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional().describe("Mes en YYYY-MM. Si se omite, el mes en curso. Solo mes calendario."),
34091
- operationId: z142.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
34254
+ var GetFinancesInput = z143.object({
34255
+ month: z143.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional().describe("Mes en YYYY-MM. Si se omite, el mes en curso. Solo mes calendario."),
34256
+ operationId: z143.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
34092
34257
  }).strict();
34093
34258
  function registerProductControlTools(server, api, { transport = "http" } = {}) {
34094
34259
  server.registerTool("get_product_control", {
@@ -34280,28 +34445,28 @@ function registerProductControlTools(server, api, { transport = "http" } = {}) {
34280
34445
  __name(registerProductControlTools, "registerProductControlTools");
34281
34446
 
34282
34447
  // src/tools/market-study-estimate.ts
34283
- import { z as z143 } from "zod";
34448
+ import { z as z144 } from "zod";
34284
34449
  var estimateMarketStudyGuidance = getProductMakerCapabilityModelGuidance("estimate_market_study_cost");
34285
- var ProductTaskOutputEnum = z143.enum([
34450
+ var ProductTaskOutputEnum = z144.enum([
34286
34451
  "landing",
34287
34452
  "video",
34288
34453
  "image"
34289
34454
  ]);
34290
- var EstimateMarketStudyInput = z143.object({
34291
- kind: z143.enum([
34455
+ var EstimateMarketStudyInput = z144.object({
34456
+ kind: z144.enum([
34292
34457
  "video",
34293
34458
  "product_task"
34294
34459
  ]).describe('"video" para generate_video_creative; "product_task" para create_product_task.'),
34295
- videoAngleCount: z143.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
34296
- durationSeconds: z143.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
34460
+ videoAngleCount: z144.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
34461
+ durationSeconds: z144.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
34297
34462
  videoStructure: VideoStructureEnum.default("single_take"),
34298
34463
  videoQuality: VideoQualityEnum.default("economy"),
34299
34464
  videoResolution: VideoResolutionEnum.default("480p"),
34300
- productImageCount: z143.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
34465
+ productImageCount: z144.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
34301
34466
  outputs: ProductTaskOutputEnum.array().min(1).max(3).optional().describe('Solo para kind="product_task": los mismos outputs de create_product_task. Default: todos.'),
34302
- generateAiMusic: z143.boolean().optional(),
34467
+ generateAiMusic: z144.boolean().optional(),
34303
34468
  generateAiEdit: AiEditRequestSchema.optional(),
34304
- replicateWinnerWhenFound: z143.boolean().optional().describe("La misma preferencia que enviar\xE1s al crear. false excluye la reserva de r\xE9plica del ganador de la cotizaci\xF3n con estudio.")
34469
+ replicateWinnerWhenFound: z144.boolean().optional().describe("La misma preferencia que enviar\xE1s al crear. false excluye la reserva de r\xE9plica del ganador de la cotizaci\xF3n con estudio.")
34305
34470
  }).strict();
34306
34471
  function buildMarketStudyEstimateRequests(input) {
34307
34472
  const quotesVideo = input.kind === "video" || (input.outputs ?? [