@productmaker/mcp 3.4.0 → 3.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/http.js +1012 -885
  2. package/dist/stdio.js +1000 -873
  3. package/package.json +1 -1
package/dist/stdio.js CHANGED
@@ -264,7 +264,7 @@ var ApiClient = class {
264
264
  };
265
265
 
266
266
  // src/index.ts
267
- var MCP_VERSION = "3.4.0";
267
+ var MCP_VERSION = "3.4.2";
268
268
 
269
269
  // src/meta-upload-app.ts
270
270
  import { readFileSync } from "fs";
@@ -336,7 +336,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
336
336
  __name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
337
337
 
338
338
  // src/tools/tasks.ts
339
- import { z as z48 } from "zod";
339
+ import { z as z49 } from "zod";
340
340
 
341
341
  // src/resolve-image.ts
342
342
  import { lookup as dnsLookup } from "dns/promises";
@@ -576,6 +576,7 @@ __name(resolveOne, "resolveOne");
576
576
 
577
577
  // src/status-poller.ts
578
578
  var TERMINAL = /* @__PURE__ */ new Set([
579
+ "done",
579
580
  "complete",
580
581
  "error"
581
582
  ]);
@@ -4313,6 +4314,32 @@ var StatusResponse = z24.object({
4313
4314
  requiresAction: z24.boolean().optional(),
4314
4315
  /** True when the task needs the user's attention rather than passive progress. */
4315
4316
  needsReview: z24.boolean().optional(),
4317
+ /**
4318
+ * THE answer to "does this task still owe the seller a question — now OR later
4319
+ * in this run?". The chat leaves for /tasks/:id only on an explicit `false`,
4320
+ * and /tasks/:id bounces her back on `true`. ONE field drives BOTH directions
4321
+ * on purpose: deciding them on two different facts is what looped
4322
+ * /tasks/:id ↔ wizard before (see apps/web/lib/task-routing.ts).
4323
+ *
4324
+ * STRICTLY WIDER THAN `needsReview`, and the difference is the whole point:
4325
+ * · `needsReview` answers "is a gate open RIGHT NOW", and it under-reports —
4326
+ * `buildPendingUserAction` only serves the reference-grouping question when
4327
+ * it is RENDERABLE, so an unconfirmed target reports `false` while
4328
+ * `angles.worker` will still pause at the END of the angles stage.
4329
+ * · this field adds the gates that are GUARANTEED to open: both pause flags,
4330
+ * plus that same worker prediction, through the one shared helper.
4331
+ *
4332
+ * Absent (undefined) means "an older API that cannot answer" — the client must
4333
+ * treat that as `true` and stay put. Uncertainty resolves to staying: a false
4334
+ * positive costs her a wait, a false negative strands her on a screen that
4335
+ * cannot render the gate (prod bd4d0bb1 / 52dc15a7, both refunded and
4336
+ * undelivered).
4337
+ *
4338
+ * ALWAYS false on a terminal task. `pauseForAngleReview` SURVIVES on completed
4339
+ * tasks, so without that guard a finished landing would report `true` forever
4340
+ * and get bounced into a chat with nothing left to ask.
4341
+ */
4342
+ willAskAgain: z24.boolean().optional(),
4316
4343
  /** True when an open gate exists that somebody can actually ANSWER. A strictly
4317
4344
  * narrower fact than `needsReview` — see the identical field on `TaskSummary`
4318
4345
  * below for why conflating the two produced a call to action that led nowhere. */
@@ -4447,6 +4474,9 @@ var CostEstimationType = z25.enum([
4447
4474
  "landing-regenerate",
4448
4475
  "landing-creative",
4449
4476
  "campaign-copy",
4477
+ "brand-extract",
4478
+ "persona-suggest",
4479
+ "chat-parse",
4450
4480
  "service-creative",
4451
4481
  "actor-grid"
4452
4482
  ]);
@@ -4612,11 +4642,14 @@ var LandingCreativeEstimationOptions = z25.object({
4612
4642
  landingStrategy: LandingStrategySchema.optional()
4613
4643
  });
4614
4644
  var CampaignCopyEstimationOptions = z25.object({
4615
- /** Number of creatives to generate copy for (1-4) */
4616
- nCreatives: z25.number().int().min(1).max(4),
4617
- /** Number of image creatives that will use vision analysis (0-4) */
4618
- nImages: z25.number().int().min(0).max(4).default(0)
4619
- });
4645
+ /** Number of creatives in the one copy-completion request (1-10). */
4646
+ nCreatives: z25.number().int().min(1).max(10),
4647
+ /** Number of image creatives that can each use one vision analysis (0-10). */
4648
+ nImages: z25.number().int().min(0).max(10).default(0)
4649
+ });
4650
+ var BrandExtractEstimationOptions = z25.object({}).strict();
4651
+ var PersonaSuggestEstimationOptions = z25.object({}).strict();
4652
+ var ChatParseEstimationOptions = z25.object({}).strict();
4620
4653
  var ServiceCreativeEstimationOptions = z25.object({
4621
4654
  mediaAssetCount: z25.number().int().min(0).max(8).optional(),
4622
4655
  uploadedVideoDurationSeconds: z25.number().min(0).max(240).optional()
@@ -4655,6 +4688,18 @@ var CostEstimationRequest = z25.discriminatedUnion("type", [
4655
4688
  type: z25.literal("campaign-copy"),
4656
4689
  options: CampaignCopyEstimationOptions
4657
4690
  }),
4691
+ z25.object({
4692
+ type: z25.literal("brand-extract"),
4693
+ options: BrandExtractEstimationOptions
4694
+ }),
4695
+ z25.object({
4696
+ type: z25.literal("persona-suggest"),
4697
+ options: PersonaSuggestEstimationOptions
4698
+ }),
4699
+ z25.object({
4700
+ type: z25.literal("chat-parse"),
4701
+ options: ChatParseEstimationOptions
4702
+ }),
4658
4703
  z25.object({
4659
4704
  type: z25.literal("service-creative"),
4660
4705
  options: ServiceCreativeEstimationOptions
@@ -5154,6 +5199,9 @@ var VideoMixQaJobSchema = z30.object({
5154
5199
  });
5155
5200
  var BrandExtractJobSchema = z30.object({
5156
5201
  brandId: z30.string().uuid(),
5202
+ // Generation is part of the durable paid-spend identity. Default 1 keeps
5203
+ // pre-migration BullMQ payloads parseable; their DB state fails safe.
5204
+ generation: z30.number().int().positive().default(1),
5157
5205
  url: z30.string().url().refine((value) => {
5158
5206
  const protocol = new URL(value).protocol;
5159
5207
  return protocol === "http:" || protocol === "https:";
@@ -6199,6 +6247,10 @@ var TikTokCreateCampaignResponseSchema = z35.object({
6199
6247
  adsManagerUrl: z35.string().optional()
6200
6248
  });
6201
6249
 
6250
+ // ../../packages/types/src/pricing-gemini-omni.ts
6251
+ var GEMINI_OMNI_FLAT_OUR_COST_CENTS = 84;
6252
+ var GEMINI_OMNI_FLAT_USER_PRICE_CENTS = 168;
6253
+
6202
6254
  // ../../packages/types/src/pricing.ts
6203
6255
  var CREDITS_PER_USD_CENT = 10;
6204
6256
  var CREDITS_PER_DOLLAR = 100 * CREDITS_PER_USD_CENT;
@@ -6607,6 +6659,18 @@ var DEFAULT_PRICING = {
6607
6659
  ourCostCents: 120,
6608
6660
  userPriceCents: 240
6609
6661
  },
6662
+ // Gemini Omni Video (gemini-omni-video) — Mix primary generator since
6663
+ // 2026-08-18. FLAT per generation: 168 KIE credits = $0.84, identical at
6664
+ // 720p and 1080p and independent of the 3.5-10s trim window. Do NOT add
6665
+ // per-second overrides for this key — resolveSuccessBilling bills it flat.
6666
+ //
6667
+ // Shares the constants with the pre-submit ESTIMATOR (mix-cost.ts) rather
6668
+ // than repeating the numbers: a literal here that drifted from the estimator
6669
+ // would quote one price and charge another on every mix.
6670
+ "kie:gemini-omni-video": {
6671
+ ourCostCents: GEMINI_OMNI_FLAT_OUR_COST_CENTS,
6672
+ userPriceCents: GEMINI_OMNI_FLAT_USER_PRICE_CENTS
6673
+ },
6610
6674
  "kie:video-lipsync-generation": {
6611
6675
  ourCostCents: 45,
6612
6676
  userPriceCents: 90
@@ -8570,7 +8634,57 @@ var FeatureSpec = z36.object({
8570
8634
  });
8571
8635
 
8572
8636
  // ../../packages/types/src/mix.ts
8637
+ import { z as z38 } from "zod";
8638
+
8639
+ // ../../packages/types/src/mix-degradation.ts
8573
8640
  import { z as z37 } from "zod";
8641
+ var MIX_DEGRADATION_REASONS = [
8642
+ /**
8643
+ * At least one scene the mix PLANNED is missing from the delivered video, so
8644
+ * the result is shorter than the source. Set at assemble time by comparing
8645
+ * the concat set against the planned scene set — the scene's own code (if it
8646
+ * had one) never reaches the mix-level rollup, which only sees scenes that
8647
+ * SUCCEEDED, and that is exactly how a live 17.00s-of-20.00s delivery
8648
+ * shipped with degradedReason NULL and no banner at all.
8649
+ *
8650
+ * ORDERING: FIRST, above every refusal code. A short delivery must never be
8651
+ * MASKED. It used to sit below the three content refusals on the theory that
8652
+ * a refusal names something the user can change AND explains the missing
8653
+ * scene — but it does neither reliably: in a 3-scene mix where scene 1 fails
8654
+ * outright and scene 2 ships through Wan after a reference refusal, the
8655
+ * refusal copy reads "we used a lower-quality alternative", a claim about
8656
+ * QUALITY that says nothing about the video being shorter than what was paid
8657
+ * for, and that is actively wrong about the dropped scene (for which we used
8658
+ * nothing). Every other code in this list describes a scene that DID ship.
8659
+ */
8660
+ "scenes_dropped",
8661
+ /** Google's safety filter rejected the user's reference photo. Deterministic. */
8662
+ "reference_rejected",
8663
+ /** Google refused the wording of the change description. */
8664
+ "prompt_rejected",
8665
+ /**
8666
+ * The provider refused the content but its message names neither the
8667
+ * reference nor the wording, so we cannot say which. Distinct from
8668
+ * 'provider_unavailable' on purpose: "unavailable" invites the user to retry
8669
+ * unchanged, which can never succeed against a content refusal and only
8670
+ * burns their credits. This code tells them something must change.
8671
+ */
8672
+ "content_rejected",
8673
+ /**
8674
+ * The scene's length fell outside Gemini's usable 3.5s-10s trim window —
8675
+ * EITHER bound. Deliberately ONE code for both: the user controls neither
8676
+ * (scene segmentation is entirely ours), so "too short" and "too long" are
8677
+ * not differently actionable, and one honest explanation beats two that
8678
+ * both amount to "our segmentation produced a length the primary generator
8679
+ * cannot take".
8680
+ */
8681
+ "scene_length_unsupported",
8682
+ /** Transient provider failures exhausted the budget. */
8683
+ "provider_unavailable"
8684
+ ];
8685
+ var MixDegradationReasonSchema = z37.enum(MIX_DEGRADATION_REASONS);
8686
+
8687
+ // ../../packages/types/src/mix.ts
8574
8688
  var MEDIA_TYPES = [
8575
8689
  "video",
8576
8690
  "image"
@@ -8608,38 +8722,38 @@ function isPublicHttpsUrl(raw) {
8608
8722
  return true;
8609
8723
  }
8610
8724
  __name(isPublicHttpsUrl, "isPublicHttpsUrl");
8611
- var PublicHttpsUrl = z37.string().url().refine(isPublicHttpsUrl, {
8725
+ var PublicHttpsUrl = z38.string().url().refine(isPublicHttpsUrl, {
8612
8726
  message: "must be a public HTTPS URL"
8613
8727
  });
8614
- var InternalAssetPath = z37.string().regex(/^\/(?:api|v1)\/assets\/[A-Za-z0-9._~%/-]+$/, "must be a public HTTPS URL or an internal asset path");
8615
- var MixImageUrl = z37.union([
8728
+ var InternalAssetPath = z38.string().regex(/^\/(?:api|v1)\/assets\/[A-Za-z0-9._~%/-]+$/, "must be a public HTTPS URL or an internal asset path");
8729
+ var MixImageUrl = z38.union([
8616
8730
  PublicHttpsUrl,
8617
8731
  InternalAssetPath
8618
8732
  ]);
8619
- var MixAxes = z37.object({
8620
- product: z37.boolean(),
8621
- person: z37.boolean(),
8622
- setting: z37.boolean()
8733
+ var MixAxes = z38.object({
8734
+ product: z38.boolean(),
8735
+ person: z38.boolean(),
8736
+ setting: z38.boolean()
8623
8737
  });
8624
- var MixReferences = z37.object({
8625
- product: z37.array(PublicHttpsUrl).max(3, "at most 3 product references"),
8626
- person: z37.array(PublicHttpsUrl).max(3, "at most 3 person references"),
8627
- setting: z37.array(PublicHttpsUrl).max(3, "at most 3 setting references")
8738
+ var MixReferences = z38.object({
8739
+ product: z38.array(PublicHttpsUrl).max(3, "at most 3 product references"),
8740
+ person: z38.array(PublicHttpsUrl).max(3, "at most 3 person references"),
8741
+ setting: z38.array(PublicHttpsUrl).max(3, "at most 3 setting references")
8628
8742
  });
8629
- var MixImageEdit = z37.object({
8630
- instruction: z37.string().min(1).max(600),
8631
- imageUrls: z37.array(MixImageUrl).min(1).max(3)
8743
+ var MixImageEdit = z38.object({
8744
+ instruction: z38.string().min(1).max(600),
8745
+ imageUrls: z38.array(MixImageUrl).min(1).max(3)
8632
8746
  });
8633
- var MixRequest = z37.object({
8634
- mediaType: z37.enum(MEDIA_TYPES),
8635
- originalUrl: z37.union([
8747
+ var MixRequest = z38.object({
8748
+ mediaType: z38.enum(MEDIA_TYPES),
8749
+ originalUrl: z38.union([
8636
8750
  PublicHttpsUrl,
8637
8751
  InternalAssetPath
8638
8752
  ]),
8639
8753
  axes: MixAxes,
8640
8754
  references: MixReferences,
8641
- personText: z37.string().max(500).optional(),
8642
- settingText: z37.string().max(500).optional(),
8755
+ personText: z38.string().max(500).optional(),
8756
+ settingText: z38.string().max(500).optional(),
8643
8757
  /**
8644
8758
  * Optional public URL of a user-uploaded audio file (mp3/wav). Wan Video
8645
8759
  * Edit has no audio input and the mix never lipsyncs: the Wan output is
@@ -8648,11 +8762,11 @@ var MixRequest = z37.object({
8648
8762
  * (mute + overlay). No per-scene slicing, no `reference_audio_urls`.
8649
8763
  */
8650
8764
  audioUrl: PublicHttpsUrl.optional(),
8651
- resolution: z37.enum(RESOLUTIONS).default("720p"),
8652
- originalDurationSec: z37.number().positive().max(600).optional(),
8765
+ resolution: z38.enum(RESOLUTIONS).default("720p"),
8766
+ originalDurationSec: z38.number().positive().max(600).optional(),
8653
8767
  image: MixImageEdit.optional(),
8654
- sourceTaskId: z37.string().max(64).optional(),
8655
- sourceCreativeId: z37.string().max(64).optional()
8768
+ sourceTaskId: z38.string().max(64).optional(),
8769
+ sourceCreativeId: z38.string().max(64).optional()
8656
8770
  }).superRefine((req, ctx) => {
8657
8771
  if (req.mediaType === "image") {
8658
8772
  if (!req.image) {
@@ -8686,18 +8800,18 @@ var MixRequest = z37.object({
8686
8800
  });
8687
8801
  }
8688
8802
  });
8689
- var ReferenceMap = z37.object({
8690
- product: z37.object({
8691
- start: z37.number().int(),
8692
- end: z37.number().int()
8803
+ var ReferenceMap = z38.object({
8804
+ product: z38.object({
8805
+ start: z38.number().int(),
8806
+ end: z38.number().int()
8693
8807
  }).optional(),
8694
- person: z37.object({
8695
- start: z37.number().int(),
8696
- end: z37.number().int()
8808
+ person: z38.object({
8809
+ start: z38.number().int(),
8810
+ end: z38.number().int()
8697
8811
  }).optional(),
8698
- setting: z37.object({
8699
- start: z37.number().int(),
8700
- end: z37.number().int()
8812
+ setting: z38.object({
8813
+ start: z38.number().int(),
8814
+ end: z38.number().int()
8701
8815
  }).optional()
8702
8816
  });
8703
8817
  var SCENE_CLIP_TYPES = [
@@ -8713,39 +8827,39 @@ var INSTANCE_CARDINALITIES = [
8713
8827
  "multiple_same",
8714
8828
  "multiple_distinct"
8715
8829
  ];
8716
- var SceneSegment = z37.object({
8717
- index: z37.number().int().positive(),
8718
- startTs: z37.number().nonnegative(),
8719
- endTs: z37.number().positive(),
8720
- seedanceDuration: z37.number().int().min(4).max(15),
8830
+ var SceneSegment = z38.object({
8831
+ index: z38.number().int().positive(),
8832
+ startTs: z38.number().nonnegative(),
8833
+ endTs: z38.number().positive(),
8834
+ seedanceDuration: z38.number().int().min(4).max(15),
8721
8835
  // Pass 1 / Pass 2 outputs (all optional — populated when the rich analyzer
8722
8836
  // runs and empty on fallback).
8723
- action: z37.string().optional(),
8724
- motion: z37.string().optional(),
8725
- clipType: z37.enum(SCENE_CLIP_TYPES).optional(),
8726
- hasCharacter: z37.boolean().optional(),
8727
- faceVisible: z37.boolean().optional(),
8837
+ action: z38.string().optional(),
8838
+ motion: z38.string().optional(),
8839
+ clipType: z38.enum(SCENE_CLIP_TYPES).optional(),
8840
+ hasCharacter: z38.boolean().optional(),
8841
+ faceVisible: z38.boolean().optional(),
8728
8842
  // Pass 2 refinement — rich per-scene metadata used by buildMixPrompt.
8729
- startState: z37.string().optional(),
8730
- endState: z37.string().optional(),
8731
- cameraMovement: z37.string().optional(),
8732
- emotion: z37.string().optional(),
8733
- productPlacement: z37.string().optional(),
8734
- productInteraction: z37.string().optional(),
8735
- settingDescription: z37.string().optional(),
8736
- dialogue: z37.string().optional(),
8843
+ startState: z38.string().optional(),
8844
+ endState: z38.string().optional(),
8845
+ cameraMovement: z38.string().optional(),
8846
+ emotion: z38.string().optional(),
8847
+ productPlacement: z38.string().optional(),
8848
+ productInteraction: z38.string().optional(),
8849
+ settingDescription: z38.string().optional(),
8850
+ dialogue: z38.string().optional(),
8737
8851
  // Main vs extras / noise (our addition on top of the script's schema).
8738
- mainPersonDescription: z37.string().optional(),
8739
- mainProductDescription: z37.string().optional(),
8740
- personInstances: z37.enum(INSTANCE_CARDINALITIES).optional(),
8741
- productInstances: z37.enum(INSTANCE_CARDINALITIES).optional(),
8852
+ mainPersonDescription: z38.string().optional(),
8853
+ mainProductDescription: z38.string().optional(),
8854
+ personInstances: z38.enum(INSTANCE_CARDINALITIES).optional(),
8855
+ productInstances: z38.enum(INSTANCE_CARDINALITIES).optional(),
8742
8856
  /**
8743
8857
  * Seconds of prev-clipType content absorbed at the start of this scene by
8744
8858
  * Pass 2.7's clipType boundary margin. When > 0 and the scene is a
8745
8859
  * pass-through (no Seedance), the concatenator prepends a held-still
8746
8860
  * preamble (nano-banana-swapped first frame) to hide the leak.
8747
8861
  */
8748
- absorbedMarginSec: z37.number().nonnegative().optional(),
8862
+ absorbedMarginSec: z38.number().nonnegative().optional(),
8749
8863
  /**
8750
8864
  * True when the scene shows post-production graphics baked into the frame:
8751
8865
  * caption/subtitle text, infographic overlay cards, or inset
@@ -8754,33 +8868,39 @@ var SceneSegment = z37.object({
8754
8868
  * (mentioning nonexistent overlays gives the generator license to
8755
8869
  * fabricate them).
8756
8870
  */
8757
- hasOverlayGraphics: z37.boolean().optional()
8871
+ hasOverlayGraphics: z38.boolean().optional()
8758
8872
  });
8759
- var MixSceneResult = z37.object({
8760
- index: z37.number().int().positive(),
8761
- status: z37.enum([
8873
+ var MixSceneResult = z38.object({
8874
+ index: z38.number().int().positive(),
8875
+ status: z38.enum([
8762
8876
  "queued",
8763
8877
  "submitted",
8764
8878
  "done",
8765
8879
  "failed"
8766
8880
  ]),
8767
- seedanceTaskId: z37.string().optional(),
8768
- videoUrl: z37.string().url().optional(),
8769
- error: z37.string().optional()
8770
- });
8771
- var MixResult = z37.object({
8772
- mixTaskId: z37.string().uuid(),
8773
- status: z37.enum([
8881
+ seedanceTaskId: z38.string().optional(),
8882
+ videoUrl: z38.string().url().optional(),
8883
+ error: z38.string().optional(),
8884
+ degradedReason: MixDegradationReasonSchema.optional()
8885
+ });
8886
+ var MixResult = z38.object({
8887
+ mixTaskId: z38.string().uuid(),
8888
+ status: z38.enum([
8774
8889
  "queued",
8775
8890
  "processing",
8776
8891
  "done",
8777
8892
  "error"
8778
8893
  ]),
8779
- resultUrl: z37.string().url().optional(),
8780
- scenes: z37.array(MixSceneResult).default([]),
8781
- failReason: z37.string().optional()
8894
+ resultUrl: z38.string().url().optional(),
8895
+ scenes: z38.array(MixSceneResult).default([]),
8896
+ failReason: z38.string().optional(),
8897
+ degradedReason: MixDegradationReasonSchema.optional()
8782
8898
  });
8783
8899
 
8900
+ // ../../packages/types/src/mix-cost.ts
8901
+ var MAX_QA_RETRIES_PER_SCENE_UPPER_BOUND = 1;
8902
+ var MAX_BILLABLE_GENERATIONS_PER_BLOCK = 1 + MAX_QA_RETRIES_PER_SCENE_UPPER_BOUND;
8903
+
8784
8904
  // ../../packages/types/src/product-delivery-format.ts
8785
8905
  var DELIVERY_FAMILIES = [
8786
8906
  "solid_dose",
@@ -8869,41 +8989,41 @@ var DECLARATION = DELIVERY_FAMILIES.map((family) => [
8869
8989
  ]);
8870
8990
 
8871
8991
  // ../../packages/types/src/task-type.ts
8872
- import { z as z38 } from "zod";
8873
- var TaskTypeSchema = z38.enum([
8992
+ import { z as z39 } from "zod";
8993
+ var TaskTypeSchema = z39.enum([
8874
8994
  "product",
8875
8995
  "service"
8876
8996
  ]);
8877
8997
 
8878
8998
  // ../../packages/types/src/landing-regeneration.ts
8879
- import { z as z39 } from "zod";
8880
- var LandingRegenerationStatus = z39.enum([
8999
+ import { z as z40 } from "zod";
9000
+ var LandingRegenerationStatus = z40.enum([
8881
9001
  "queued",
8882
9002
  "processing",
8883
9003
  "published",
8884
9004
  "failed"
8885
9005
  ]);
8886
- var RegenerateLandingRoleResponse = z39.object({
8887
- ok: z39.literal(true),
9006
+ var RegenerateLandingRoleResponse = z40.object({
9007
+ ok: z40.literal(true),
8888
9008
  role: LandingRole,
8889
- promptIndex: z39.number().int().nonnegative(),
8890
- operationId: z39.string().min(1)
9009
+ promptIndex: z40.number().int().nonnegative(),
9010
+ operationId: z40.string().min(1)
8891
9011
  });
8892
- var LandingRegenerationStatusResponse = z39.object({
8893
- ok: z39.literal(true),
8894
- operationId: z39.string().min(1),
9012
+ var LandingRegenerationStatusResponse = z40.object({
9013
+ ok: z40.literal(true),
9014
+ operationId: z40.string().min(1),
8895
9015
  role: LandingRole,
8896
9016
  status: LandingRegenerationStatus,
8897
- refunded: z39.boolean(),
8898
- failureReason: z39.string().nullable(),
8899
- publishedAssetKey: z39.string().nullable(),
8900
- updatedAt: z39.string().datetime()
9017
+ refunded: z40.boolean(),
9018
+ failureReason: z40.string().nullable(),
9019
+ publishedAssetKey: z40.string().nullable(),
9020
+ updatedAt: z40.string().datetime()
8901
9021
  });
8902
9022
 
8903
9023
  // ../../packages/types/src/video-edit.ts
8904
- import { z as z40 } from "zod";
9024
+ import { z as z41 } from "zod";
8905
9025
  var MAX_SEGMENT_SECONDS = 3;
8906
- var VideoEditStatusSchema = z40.enum([
9026
+ var VideoEditStatusSchema = z41.enum([
8907
9027
  "pending",
8908
9028
  "processing",
8909
9029
  "assembling",
@@ -8912,9 +9032,9 @@ var VideoEditStatusSchema = z40.enum([
8912
9032
  "discarded",
8913
9033
  "failed"
8914
9034
  ]);
8915
- var VideoEditTimeSectionSchema = z40.object({
8916
- startSec: z40.number().min(0),
8917
- endSec: z40.number().positive()
9035
+ var VideoEditTimeSectionSchema = z41.object({
9036
+ startSec: z41.number().min(0),
9037
+ endSec: z41.number().positive()
8918
9038
  }).refine((v) => v.endSec > v.startSec, {
8919
9039
  message: "endSec must be after startSec",
8920
9040
  path: [
@@ -8926,45 +9046,45 @@ var VideoEditTimeSectionSchema = z40.object({
8926
9046
  "endSec"
8927
9047
  ]
8928
9048
  });
8929
- var VideoEditRequestSchema = z40.object({
8930
- comment: z40.string().trim().min(1).max(2e3),
8931
- sections: z40.array(VideoEditTimeSectionSchema).min(1).optional()
9049
+ var VideoEditRequestSchema = z41.object({
9050
+ comment: z41.string().trim().min(1).max(2e3),
9051
+ sections: z41.array(VideoEditTimeSectionSchema).min(1).optional()
8932
9052
  });
8933
- var VideoEditModeSchema = z40.enum([
9053
+ var VideoEditModeSchema = z41.enum([
8934
9054
  "wan_edit",
8935
9055
  "regenerate"
8936
9056
  ]);
8937
- var VideoRegenerationEngineSchema = z40.enum([
9057
+ var VideoRegenerationEngineSchema = z41.enum([
8938
9058
  "free_text",
8939
9059
  "free_image",
8940
9060
  "single_call",
8941
9061
  "multi_shot"
8942
9062
  ]);
8943
- var VideoRegenerationRouteFingerprintSchema = z40.string().trim().min(1).max(128);
8944
- var RegenerateEditRequestSchema = z40.object({
8945
- angleKey: z40.string().min(1),
8946
- comment: z40.string().min(1).max(2e3)
9063
+ var VideoRegenerationRouteFingerprintSchema = z41.string().trim().min(1).max(128);
9064
+ var RegenerateEditRequestSchema = z41.object({
9065
+ angleKey: z41.string().min(1),
9066
+ comment: z41.string().min(1).max(2e3)
8947
9067
  });
8948
9068
 
8949
9069
  // ../../packages/types/src/uploaded-asset.ts
8950
- import { z as z41 } from "zod";
8951
- var UploadedAssetMediaKind = z41.enum([
9070
+ import { z as z42 } from "zod";
9071
+ var UploadedAssetMediaKind = z42.enum([
8952
9072
  "image",
8953
9073
  "video"
8954
9074
  ]);
8955
- var UploadedAssetSessionMediaKind = z41.enum([
9075
+ var UploadedAssetSessionMediaKind = z42.enum([
8956
9076
  "image",
8957
9077
  "video",
8958
9078
  "mixed"
8959
9079
  ]);
8960
- var UploadedAssetRole = z41.enum([
9080
+ var UploadedAssetRole = z42.enum([
8961
9081
  "media",
8962
9082
  "thumbnail"
8963
9083
  ]);
8964
9084
  var UPLOADED_ASSET_MAX_FILES = 10;
8965
9085
  var UPLOADED_ASSET_IMAGE_MAX_FILES = 5;
8966
- var UploadedAssetId = z41.string().uuid();
8967
- var HttpsUrl = z41.string().url().refine((value) => {
9086
+ var UploadedAssetId = z42.string().uuid();
9087
+ var HttpsUrl = z42.string().url().refine((value) => {
8968
9088
  try {
8969
9089
  const url = new URL(value);
8970
9090
  return url.protocol === "https:" && !url.username && !url.password;
@@ -8972,23 +9092,23 @@ var HttpsUrl = z41.string().url().refine((value) => {
8972
9092
  return false;
8973
9093
  }
8974
9094
  }, "URL must use https");
8975
- var UtcDateTime = z41.string().datetime().refine((value) => {
9095
+ var UtcDateTime = z42.string().datetime().refine((value) => {
8976
9096
  const parts = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?Z$/.exec(value);
8977
9097
  const timestamp = Date.parse(value);
8978
9098
  if (!parts || Number.isNaN(timestamp)) return false;
8979
9099
  const date = new Date(timestamp);
8980
9100
  return date.getUTCFullYear() === Number(parts[1]) && date.getUTCMonth() + 1 === Number(parts[2]) && date.getUTCDate() === Number(parts[3]) && date.getUTCHours() === Number(parts[4]) && date.getUTCMinutes() === Number(parts[5]) && date.getUTCSeconds() === Number(parts[6]);
8981
9101
  }, "datetime must be a valid UTC calendar instant");
8982
- var UploadedAssetRef = z41.object({
9102
+ var UploadedAssetRef = z42.object({
8983
9103
  assetId: UploadedAssetId
8984
9104
  }).strict();
8985
9105
  var UploadedAssetCompletion = UploadedAssetRef.extend({
8986
9106
  mediaKind: UploadedAssetMediaKind,
8987
9107
  assetRole: UploadedAssetRole
8988
9108
  }).strict();
8989
- var UploadedAssetMetadata = z41.object({
9109
+ var UploadedAssetMetadata = z42.object({
8990
9110
  assetId: UploadedAssetId,
8991
- ownerId: z41.string().min(1),
9111
+ ownerId: z42.string().min(1),
8992
9112
  mediaKind: UploadedAssetMediaKind,
8993
9113
  assetRole: UploadedAssetRole,
8994
9114
  createdAt: UtcDateTime,
@@ -8996,7 +9116,7 @@ var UploadedAssetMetadata = z41.object({
8996
9116
  }).strict().superRefine((value, ctx) => {
8997
9117
  if (Date.parse(value.expiresAt) <= Date.parse(value.createdAt)) {
8998
9118
  ctx.addIssue({
8999
- code: z41.ZodIssueCode.custom,
9119
+ code: z42.ZodIssueCode.custom,
9000
9120
  path: [
9001
9121
  "expiresAt"
9002
9122
  ],
@@ -9004,27 +9124,27 @@ var UploadedAssetMetadata = z41.object({
9004
9124
  });
9005
9125
  }
9006
9126
  });
9007
- var MediaSourceRef = z41.object({
9127
+ var MediaSourceRef = z42.object({
9008
9128
  url: HttpsUrl.optional(),
9009
- path: z41.string().min(1).optional(),
9129
+ path: z42.string().min(1).optional(),
9010
9130
  assetId: UploadedAssetId.optional()
9011
9131
  }).strict().superRefine((value, ctx) => {
9012
9132
  const sourceCount = Number(value.url !== void 0) + Number(value.path !== void 0) + Number(value.assetId !== void 0);
9013
9133
  if (sourceCount !== 1) {
9014
9134
  ctx.addIssue({
9015
- code: z41.ZodIssueCode.custom,
9135
+ code: z42.ZodIssueCode.custom,
9016
9136
  message: "media source needs exactly one of url, path, or assetId"
9017
9137
  });
9018
9138
  }
9019
9139
  });
9020
- var UploadedAssetSessionRequest = z41.object({
9140
+ var UploadedAssetSessionRequest = z42.object({
9021
9141
  mediaKind: UploadedAssetSessionMediaKind,
9022
9142
  assetRole: UploadedAssetRole.default("media"),
9023
- maxFiles: z41.number().int().min(1).max(UPLOADED_ASSET_MAX_FILES).optional()
9143
+ maxFiles: z42.number().int().min(1).max(UPLOADED_ASSET_MAX_FILES).optional()
9024
9144
  }).strict().superRefine((value, ctx) => {
9025
9145
  if (value.mediaKind === "mixed" && value.assetRole === "thumbnail") {
9026
9146
  ctx.addIssue({
9027
- code: z41.ZodIssueCode.custom,
9147
+ code: z42.ZodIssueCode.custom,
9028
9148
  path: [
9029
9149
  "mediaKind"
9030
9150
  ],
@@ -9033,7 +9153,7 @@ var UploadedAssetSessionRequest = z41.object({
9033
9153
  }
9034
9154
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
9035
9155
  ctx.addIssue({
9036
- code: z41.ZodIssueCode.custom,
9156
+ code: z42.ZodIssueCode.custom,
9037
9157
  path: [
9038
9158
  "maxFiles"
9039
9159
  ],
@@ -9042,7 +9162,7 @@ var UploadedAssetSessionRequest = z41.object({
9042
9162
  }
9043
9163
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > UPLOADED_ASSET_IMAGE_MAX_FILES) {
9044
9164
  ctx.addIssue({
9045
- code: z41.ZodIssueCode.custom,
9165
+ code: z42.ZodIssueCode.custom,
9046
9166
  path: [
9047
9167
  "maxFiles"
9048
9168
  ],
@@ -9051,7 +9171,7 @@ var UploadedAssetSessionRequest = z41.object({
9051
9171
  }
9052
9172
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
9053
9173
  ctx.addIssue({
9054
- code: z41.ZodIssueCode.custom,
9174
+ code: z42.ZodIssueCode.custom,
9055
9175
  path: [
9056
9176
  "mediaKind"
9057
9177
  ],
@@ -9059,32 +9179,32 @@ var UploadedAssetSessionRequest = z41.object({
9059
9179
  });
9060
9180
  }
9061
9181
  });
9062
- var UploadedAssetSessionStatus = z41.discriminatedUnion("status", [
9063
- z41.object({
9064
- status: z41.literal("pending"),
9065
- assets: z41.array(UploadedAssetCompletion).length(0)
9182
+ var UploadedAssetSessionStatus = z42.discriminatedUnion("status", [
9183
+ z42.object({
9184
+ status: z42.literal("pending"),
9185
+ assets: z42.array(UploadedAssetCompletion).length(0)
9066
9186
  }).strict(),
9067
- z41.object({
9068
- status: z41.literal("uploaded"),
9069
- assets: z41.array(UploadedAssetCompletion).min(1).max(UPLOADED_ASSET_MAX_FILES)
9187
+ z42.object({
9188
+ status: z42.literal("uploaded"),
9189
+ assets: z42.array(UploadedAssetCompletion).min(1).max(UPLOADED_ASSET_MAX_FILES)
9070
9190
  }).strict()
9071
9191
  ]);
9072
- var UploadedAssetAdoptionRequest = z41.object({
9192
+ var UploadedAssetAdoptionRequest = z42.object({
9073
9193
  assetId: UploadedAssetId,
9074
- ownerId: z41.string().min(1),
9075
- consumer: z41.string().min(1).max(100),
9076
- idempotencyKey: z41.string().min(1).max(255)
9194
+ ownerId: z42.string().min(1),
9195
+ consumer: z42.string().min(1).max(100),
9196
+ idempotencyKey: z42.string().min(1).max(255)
9077
9197
  }).strict();
9078
9198
 
9079
9199
  // ../../packages/types/src/dropshipping-project.ts
9080
- import { z as z42 } from "zod";
9081
- var DropshippingProjectStatusSchema = z42.enum([
9200
+ import { z as z43 } from "zod";
9201
+ var DropshippingProjectStatusSchema = z43.enum([
9082
9202
  "active",
9083
9203
  "completed",
9084
9204
  "archived"
9085
9205
  ]);
9086
9206
  var DROPSHIPPING_LAUNCH_REWARD_CAMPAIGN = "dropshipping-launch-v1";
9087
- var DropshippingRewardMilestoneSchema = z42.enum([
9207
+ var DropshippingRewardMilestoneSchema = z43.enum([
9088
9208
  "product_selected",
9089
9209
  "costing_saved",
9090
9210
  "product_media_ready",
@@ -9099,21 +9219,21 @@ var DROPSHIPPING_LAUNCH_REWARD_CREDITS = {
9099
9219
  campaign_created: 200
9100
9220
  };
9101
9221
  var DROPSHIPPING_LAUNCH_REWARD_TOTAL_CREDITS = Object.values(DROPSHIPPING_LAUNCH_REWARD_CREDITS).reduce((sum, credits) => sum + credits, 0);
9102
- var DropshippingProjectRewardMilestoneStateSchema = z42.object({
9222
+ var DropshippingProjectRewardMilestoneStateSchema = z43.object({
9103
9223
  milestone: DropshippingRewardMilestoneSchema,
9104
- credits: z42.number().int().positive(),
9105
- available: z42.boolean().optional(),
9106
- earned: z42.boolean(),
9107
- grantId: z42.string().uuid().nullable(),
9108
- grantedAt: z42.string().datetime().nullable()
9109
- });
9110
- var DropshippingProjectRewardProgressSchema = z42.object({
9111
- campaignKey: z42.literal(DROPSHIPPING_LAUNCH_REWARD_CAMPAIGN),
9112
- totalCredits: z42.number().int().positive(),
9113
- earnedCredits: z42.number().int().nonnegative(),
9114
- milestones: z42.array(DropshippingProjectRewardMilestoneStateSchema).length(DropshippingRewardMilestoneSchema.options.length)
9115
- });
9116
- var DropshippingProjectPhaseSchema = z42.enum([
9224
+ credits: z43.number().int().positive(),
9225
+ available: z43.boolean().optional(),
9226
+ earned: z43.boolean(),
9227
+ grantId: z43.string().uuid().nullable(),
9228
+ grantedAt: z43.string().datetime().nullable()
9229
+ });
9230
+ var DropshippingProjectRewardProgressSchema = z43.object({
9231
+ campaignKey: z43.literal(DROPSHIPPING_LAUNCH_REWARD_CAMPAIGN),
9232
+ totalCredits: z43.number().int().positive(),
9233
+ earnedCredits: z43.number().int().nonnegative(),
9234
+ milestones: z43.array(DropshippingProjectRewardMilestoneStateSchema).length(DropshippingRewardMilestoneSchema.options.length)
9235
+ });
9236
+ var DropshippingProjectPhaseSchema = z43.enum([
9117
9237
  "research",
9118
9238
  "costing",
9119
9239
  "media",
@@ -9122,18 +9242,18 @@ var DropshippingProjectPhaseSchema = z42.enum([
9122
9242
  "advertising",
9123
9243
  "complete"
9124
9244
  ]);
9125
- var DropshippingProjectCostingInputSchema = z42.object({
9126
- country: z42.string().min(2).max(3),
9127
- supplierCost: z42.number().finite().positive(),
9128
- shippingCost: z42.number().finite().nonnegative(),
9129
- returnRate: z42.number().finite().min(0).lt(1),
9130
- cancellationRate: z42.number().finite().min(0).lt(1),
9131
- adsManagerCpa: z42.number().finite().nonnegative(),
9132
- desiredMargin: z42.number().finite().min(0).lt(1)
9245
+ var DropshippingProjectCostingInputSchema = z43.object({
9246
+ country: z43.string().min(2).max(3),
9247
+ supplierCost: z43.number().finite().positive(),
9248
+ shippingCost: z43.number().finite().nonnegative(),
9249
+ returnRate: z43.number().finite().min(0).lt(1),
9250
+ cancellationRate: z43.number().finite().min(0).lt(1),
9251
+ adsManagerCpa: z43.number().finite().nonnegative(),
9252
+ desiredMargin: z43.number().finite().min(0).lt(1)
9133
9253
  }).superRefine(({ returnRate, cancellationRate }, context) => {
9134
9254
  if (returnRate + cancellationRate >= 1) {
9135
9255
  context.addIssue({
9136
- code: z42.ZodIssueCode.custom,
9256
+ code: z43.ZodIssueCode.custom,
9137
9257
  path: [
9138
9258
  "cancellationRate"
9139
9259
  ],
@@ -9141,24 +9261,24 @@ var DropshippingProjectCostingInputSchema = z42.object({
9141
9261
  });
9142
9262
  }
9143
9263
  });
9144
- var DropshippingProjectCostingResultSchema = z42.object({
9145
- country: z42.string().min(2).max(3),
9146
- deliveryRate: z42.number().finite(),
9147
- adjustedShippingCost: z42.number().finite(),
9148
- adjustedCpa: z42.number().finite(),
9149
- totalCost: z42.number().finite(),
9150
- suggestedPrice: z42.number().finite(),
9151
- baseCommercialPrice: z42.number().finite(),
9152
- minimumSafePrice: z42.number().finite(),
9153
- commercialPrice: z42.number().finite(),
9154
- comparisonPrice: z42.number().finite(),
9155
- estimatedProfit: z42.number().finite(),
9156
- actualMargin: z42.number().finite(),
9157
- breakEvenAdsManagerCpa: z42.number().finite(),
9158
- wasPriceAutoAdjusted: z42.boolean(),
9159
- profitabilityStatus: z42.literal("healthy")
9160
- });
9161
- var HttpUrlSchema = z42.string().url().max(2e3).refine((value) => {
9264
+ var DropshippingProjectCostingResultSchema = z43.object({
9265
+ country: z43.string().min(2).max(3),
9266
+ deliveryRate: z43.number().finite(),
9267
+ adjustedShippingCost: z43.number().finite(),
9268
+ adjustedCpa: z43.number().finite(),
9269
+ totalCost: z43.number().finite(),
9270
+ suggestedPrice: z43.number().finite(),
9271
+ baseCommercialPrice: z43.number().finite(),
9272
+ minimumSafePrice: z43.number().finite(),
9273
+ commercialPrice: z43.number().finite(),
9274
+ comparisonPrice: z43.number().finite(),
9275
+ estimatedProfit: z43.number().finite(),
9276
+ actualMargin: z43.number().finite(),
9277
+ breakEvenAdsManagerCpa: z43.number().finite(),
9278
+ wasPriceAutoAdjusted: z43.boolean(),
9279
+ profitabilityStatus: z43.literal("healthy")
9280
+ });
9281
+ var HttpUrlSchema = z43.string().url().max(2e3).refine((value) => {
9162
9282
  try {
9163
9283
  return [
9164
9284
  "http:",
@@ -9168,124 +9288,124 @@ var HttpUrlSchema = z42.string().url().max(2e3).refine((value) => {
9168
9288
  return false;
9169
9289
  }
9170
9290
  }, "Product URL must use HTTP(S)");
9171
- var ResearchCandidateOriginSchema = z42.object({
9172
- type: z42.literal("research_candidate"),
9173
- runId: z42.string().uuid(),
9174
- candidateSourceId: z42.string().min(1).max(160)
9175
- });
9176
- var TaskOriginSchema = z42.object({
9177
- type: z42.literal("task"),
9178
- taskId: z42.string().uuid()
9179
- });
9180
- var ManualOriginSchema = z42.object({
9181
- type: z42.literal("manual"),
9182
- clientRequestId: z42.string().uuid(),
9183
- country: z42.string().min(2).max(3).optional()
9184
- });
9185
- var CreateDropshippingProjectRequestSchema = z42.object({
9186
- origin: z42.discriminatedUnion("type", [
9291
+ var ResearchCandidateOriginSchema = z43.object({
9292
+ type: z43.literal("research_candidate"),
9293
+ runId: z43.string().uuid(),
9294
+ candidateSourceId: z43.string().min(1).max(160)
9295
+ });
9296
+ var TaskOriginSchema = z43.object({
9297
+ type: z43.literal("task"),
9298
+ taskId: z43.string().uuid()
9299
+ });
9300
+ var ManualOriginSchema = z43.object({
9301
+ type: z43.literal("manual"),
9302
+ clientRequestId: z43.string().uuid(),
9303
+ country: z43.string().min(2).max(3).optional()
9304
+ });
9305
+ var CreateDropshippingProjectRequestSchema = z43.object({
9306
+ origin: z43.discriminatedUnion("type", [
9187
9307
  ResearchCandidateOriginSchema,
9188
9308
  TaskOriginSchema,
9189
9309
  ManualOriginSchema
9190
9310
  ]),
9191
- productName: z42.string().trim().min(1).max(240).optional(),
9311
+ productName: z43.string().trim().min(1).max(240).optional(),
9192
9312
  productUrl: HttpUrlSchema.optional(),
9193
- country: z42.string().min(2).max(3).optional(),
9194
- languageCode: z42.string().min(2).max(16).optional()
9313
+ country: z43.string().min(2).max(3).optional(),
9314
+ languageCode: z43.string().min(2).max(16).optional()
9195
9315
  }).strict();
9196
- var SaveDropshippingProjectCostingRequestSchema = z42.object({
9316
+ var SaveDropshippingProjectCostingRequestSchema = z43.object({
9197
9317
  input: DropshippingProjectCostingInputSchema,
9198
- version: z42.number().int().positive()
9318
+ version: z43.number().int().positive()
9199
9319
  }).strict();
9200
- var DropshippingProjectNextActionSchema = z42.discriminatedUnion("kind", [
9201
- z42.object({
9202
- kind: z42.literal("cost_product"),
9203
- href: z42.string().min(1)
9320
+ var DropshippingProjectNextActionSchema = z43.discriminatedUnion("kind", [
9321
+ z43.object({
9322
+ kind: z43.literal("cost_product"),
9323
+ href: z43.string().min(1)
9204
9324
  }),
9205
- z42.object({
9206
- kind: z42.literal("provide_product_media"),
9207
- href: z42.string().min(1)
9325
+ z43.object({
9326
+ kind: z43.literal("provide_product_media"),
9327
+ href: z43.string().min(1)
9208
9328
  }),
9209
- z42.object({
9210
- kind: z42.literal("generate_creatives"),
9211
- href: z42.string().min(1)
9329
+ z43.object({
9330
+ kind: z43.literal("generate_creatives"),
9331
+ href: z43.string().min(1)
9212
9332
  }),
9213
- z42.object({
9214
- kind: z42.literal("wait_for_creatives"),
9215
- href: z42.string().min(1)
9333
+ z43.object({
9334
+ kind: z43.literal("wait_for_creatives"),
9335
+ href: z43.string().min(1)
9216
9336
  }),
9217
- z42.object({
9218
- kind: z42.literal("repair_creatives"),
9219
- href: z42.string().min(1)
9337
+ z43.object({
9338
+ kind: z43.literal("repair_creatives"),
9339
+ href: z43.string().min(1)
9220
9340
  }),
9221
- z42.object({
9222
- kind: z42.literal("complete_creative_set"),
9223
- href: z42.string().min(1)
9341
+ z43.object({
9342
+ kind: z43.literal("complete_creative_set"),
9343
+ href: z43.string().min(1)
9224
9344
  }),
9225
- z42.object({
9226
- kind: z42.literal("connect_shopify"),
9227
- href: z42.string().min(1)
9345
+ z43.object({
9346
+ kind: z43.literal("connect_shopify"),
9347
+ href: z43.string().min(1)
9228
9348
  }),
9229
- z42.object({
9230
- kind: z42.literal("publish_storefront"),
9231
- href: z42.string().min(1)
9349
+ z43.object({
9350
+ kind: z43.literal("publish_storefront"),
9351
+ href: z43.string().min(1)
9232
9352
  }),
9233
- z42.object({
9234
- kind: z42.literal("wait_for_storefront"),
9235
- href: z42.string().min(1)
9353
+ z43.object({
9354
+ kind: z43.literal("wait_for_storefront"),
9355
+ href: z43.string().min(1)
9236
9356
  }),
9237
- z42.object({
9238
- kind: z42.literal("connect_meta"),
9239
- href: z42.string().min(1)
9357
+ z43.object({
9358
+ kind: z43.literal("connect_meta"),
9359
+ href: z43.string().min(1)
9240
9360
  }),
9241
- z42.object({
9242
- kind: z42.literal("create_meta_campaign"),
9243
- href: z42.string().min(1)
9361
+ z43.object({
9362
+ kind: z43.literal("create_meta_campaign"),
9363
+ href: z43.string().min(1)
9244
9364
  }),
9245
- z42.object({
9246
- kind: z42.literal("repair_meta_campaign"),
9247
- href: z42.string().min(1)
9365
+ z43.object({
9366
+ kind: z43.literal("repair_meta_campaign"),
9367
+ href: z43.string().min(1)
9248
9368
  }),
9249
- z42.object({
9250
- kind: z42.literal("review_paused_campaign"),
9251
- href: z42.string().min(1)
9369
+ z43.object({
9370
+ kind: z43.literal("review_paused_campaign"),
9371
+ href: z43.string().min(1)
9252
9372
  })
9253
9373
  ]);
9254
- var DropshippingProjectResponseSchema = z42.object({
9255
- id: z42.string().uuid(),
9256
- taskId: z42.string().uuid().nullable(),
9374
+ var DropshippingProjectResponseSchema = z43.object({
9375
+ id: z43.string().uuid(),
9376
+ taskId: z43.string().uuid().nullable(),
9257
9377
  status: DropshippingProjectStatusSchema,
9258
- originKey: z42.string().min(1),
9259
- researchRunId: z42.string().uuid().nullable(),
9260
- candidateSourceId: z42.string().nullable(),
9261
- productName: z42.string().nullable(),
9378
+ originKey: z43.string().min(1),
9379
+ researchRunId: z43.string().uuid().nullable(),
9380
+ candidateSourceId: z43.string().nullable(),
9381
+ productName: z43.string().nullable(),
9262
9382
  productUrl: HttpUrlSchema.nullable(),
9263
- referenceImageUrl: z42.string().url().nullable(),
9264
- hasReferenceImage: z42.boolean(),
9265
- targetCountry: z42.string().nullable(),
9266
- languageCode: z42.string().nullable(),
9383
+ referenceImageUrl: z43.string().url().nullable(),
9384
+ hasReferenceImage: z43.boolean(),
9385
+ targetCountry: z43.string().nullable(),
9386
+ languageCode: z43.string().nullable(),
9267
9387
  costingInput: DropshippingProjectCostingInputSchema.nullable(),
9268
9388
  costingResult: DropshippingProjectCostingResultSchema.nullable(),
9269
- costingVersion: z42.number().int().positive().nullable(),
9270
- version: z42.number().int().positive(),
9389
+ costingVersion: z43.number().int().positive().nullable(),
9390
+ version: z43.number().int().positive(),
9271
9391
  phase: DropshippingProjectPhaseSchema,
9272
9392
  nextAction: DropshippingProjectNextActionSchema.nullable(),
9273
9393
  rewards: DropshippingProjectRewardProgressSchema,
9274
- createdAt: z42.string().datetime(),
9275
- updatedAt: z42.string().datetime()
9394
+ createdAt: z43.string().datetime(),
9395
+ updatedAt: z43.string().datetime()
9276
9396
  });
9277
9397
 
9278
9398
  // ../../packages/types/src/scene-subject-contract.ts
9279
- import { z as z43 } from "zod";
9280
- var SceneSubjectContractSchema = z43.object({
9281
- maxPeople: z43.number().int().min(1).max(10),
9282
- minPeople: z43.number().int().min(0).max(10),
9283
- minDistinctPeople: z43.number().int().min(0).max(10),
9284
- maxHands: z43.number().int().min(0).max(20)
9399
+ import { z as z44 } from "zod";
9400
+ var SceneSubjectContractSchema = z44.object({
9401
+ maxPeople: z44.number().int().min(1).max(10),
9402
+ minPeople: z44.number().int().min(0).max(10),
9403
+ minDistinctPeople: z44.number().int().min(0).max(10),
9404
+ maxHands: z44.number().int().min(0).max(20)
9285
9405
  }).superRefine((value, ctx) => {
9286
9406
  if (value.minPeople > value.maxPeople) {
9287
9407
  ctx.addIssue({
9288
- code: z43.ZodIssueCode.custom,
9408
+ code: z44.ZodIssueCode.custom,
9289
9409
  path: [
9290
9410
  "minPeople"
9291
9411
  ],
@@ -9294,7 +9414,7 @@ var SceneSubjectContractSchema = z43.object({
9294
9414
  }
9295
9415
  if (value.minDistinctPeople > value.maxPeople) {
9296
9416
  ctx.addIssue({
9297
- code: z43.ZodIssueCode.custom,
9417
+ code: z44.ZodIssueCode.custom,
9298
9418
  path: [
9299
9419
  "minDistinctPeople"
9300
9420
  ],
@@ -9303,7 +9423,7 @@ var SceneSubjectContractSchema = z43.object({
9303
9423
  }
9304
9424
  if (value.minDistinctPeople > value.minPeople) {
9305
9425
  ctx.addIssue({
9306
- code: z43.ZodIssueCode.custom,
9426
+ code: z44.ZodIssueCode.custom,
9307
9427
  path: [
9308
9428
  "minDistinctPeople"
9309
9429
  ],
@@ -9313,7 +9433,7 @@ var SceneSubjectContractSchema = z43.object({
9313
9433
  });
9314
9434
 
9315
9435
  // ../../packages/types/src/service-creative.ts
9316
- import { z as z44 } from "zod";
9436
+ import { z as z45 } from "zod";
9317
9437
  var SERVICE_CREATIVE_PUBLIC_PRESETS = [
9318
9438
  "auto",
9319
9439
  "ugc_dynamic",
@@ -9321,19 +9441,19 @@ var SERVICE_CREATIVE_PUBLIC_PRESETS = [
9321
9441
  "cinematic",
9322
9442
  "wild_card"
9323
9443
  ];
9324
- var ServiceCreativePresetSchema = z44.enum(SERVICE_CREATIVE_PUBLIC_PRESETS);
9444
+ var ServiceCreativePresetSchema = z45.enum(SERVICE_CREATIVE_PUBLIC_PRESETS);
9325
9445
  var SERVICE_REVIEW_MODES = [
9326
9446
  "automatic",
9327
9447
  "guided"
9328
9448
  ];
9329
- var ServiceReviewModeSchema = z44.enum(SERVICE_REVIEW_MODES);
9449
+ var ServiceReviewModeSchema = z45.enum(SERVICE_REVIEW_MODES);
9330
9450
  var SERVICE_HIGGSFIELD_MODES = [
9331
9451
  "product_review",
9332
9452
  "ugc_how_to",
9333
9453
  "tv_spot",
9334
9454
  "wild_card"
9335
9455
  ];
9336
- var ServiceHiggsfieldModeSchema = z44.enum(SERVICE_HIGGSFIELD_MODES);
9456
+ var ServiceHiggsfieldModeSchema = z45.enum(SERVICE_HIGGSFIELD_MODES);
9337
9457
  var SERVICE_MEDIA_ROLES = [
9338
9458
  "screen_demo",
9339
9459
  "ad_reference",
@@ -9341,20 +9461,20 @@ var SERVICE_MEDIA_ROLES = [
9341
9461
  "presenter_reference",
9342
9462
  "brand_asset"
9343
9463
  ];
9344
- var ServiceMediaRoleSchema = z44.enum(SERVICE_MEDIA_ROLES);
9345
- var ServiceMediaAssetSchema = z44.object({
9464
+ var ServiceMediaRoleSchema = z45.enum(SERVICE_MEDIA_ROLES);
9465
+ var ServiceMediaAssetSchema = z45.object({
9346
9466
  role: ServiceMediaRoleSchema,
9347
- s3Key: z44.string().min(1),
9467
+ s3Key: z45.string().min(1),
9348
9468
  /** HMAC ticket returned by the authenticated service-media presign route. */
9349
- uploadToken: z44.string().min(1).optional(),
9350
- mimeType: z44.string().min(1),
9351
- durationSec: z44.number().positive().max(30).optional(),
9352
- sourceName: z44.string().max(255).optional()
9469
+ uploadToken: z45.string().min(1).optional(),
9470
+ mimeType: z45.string().min(1),
9471
+ durationSec: z45.number().positive().max(30).optional(),
9472
+ sourceName: z45.string().max(255).optional()
9353
9473
  }).superRefine((asset, ctx) => {
9354
9474
  const isVideoRole = asset.role === "screen_demo" || asset.role === "ad_reference";
9355
9475
  if (isVideoRole && !asset.mimeType.startsWith("video/")) {
9356
9476
  ctx.addIssue({
9357
- code: z44.ZodIssueCode.custom,
9477
+ code: z45.ZodIssueCode.custom,
9358
9478
  message: `${asset.role} requires video media`,
9359
9479
  path: [
9360
9480
  "mimeType"
@@ -9363,7 +9483,7 @@ var ServiceMediaAssetSchema = z44.object({
9363
9483
  }
9364
9484
  if (isVideoRole && asset.durationSec === void 0) {
9365
9485
  ctx.addIssue({
9366
- code: z44.ZodIssueCode.custom,
9486
+ code: z45.ZodIssueCode.custom,
9367
9487
  message: `${asset.role} requires durationSec`,
9368
9488
  path: [
9369
9489
  "durationSec"
@@ -9372,7 +9492,7 @@ var ServiceMediaAssetSchema = z44.object({
9372
9492
  }
9373
9493
  if (!isVideoRole && !asset.mimeType.startsWith("image/")) {
9374
9494
  ctx.addIssue({
9375
- code: z44.ZodIssueCode.custom,
9495
+ code: z45.ZodIssueCode.custom,
9376
9496
  message: `${asset.role} requires image media`,
9377
9497
  path: [
9378
9498
  "mimeType"
@@ -9380,13 +9500,13 @@ var ServiceMediaAssetSchema = z44.object({
9380
9500
  });
9381
9501
  }
9382
9502
  });
9383
- var ServiceMediaBundleSchema = z44.object({
9384
- assets: z44.array(ServiceMediaAssetSchema).max(15).default([])
9503
+ var ServiceMediaBundleSchema = z45.object({
9504
+ assets: z45.array(ServiceMediaAssetSchema).max(15).default([])
9385
9505
  }).superRefine((bundle, ctx) => {
9386
9506
  const adReferences = bundle.assets.filter((asset) => asset.role === "ad_reference");
9387
9507
  if (adReferences.length > 5) {
9388
9508
  ctx.addIssue({
9389
- code: z44.ZodIssueCode.custom,
9509
+ code: z45.ZodIssueCode.custom,
9390
9510
  message: "A maximum of five ad_reference videos is allowed",
9391
9511
  path: [
9392
9512
  "assets"
@@ -9396,7 +9516,7 @@ var ServiceMediaBundleSchema = z44.object({
9396
9516
  const screenDemos = bundle.assets.filter((asset) => asset.role === "screen_demo");
9397
9517
  if (screenDemos.length > 3) {
9398
9518
  ctx.addIssue({
9399
- code: z44.ZodIssueCode.custom,
9519
+ code: z45.ZodIssueCode.custom,
9400
9520
  message: "A maximum of three screen_demo videos is allowed",
9401
9521
  path: [
9402
9522
  "assets"
@@ -9413,33 +9533,33 @@ var SERVICE_MEDIA_ANALYSIS_KINDS = [
9413
9533
  "product",
9414
9534
  "other"
9415
9535
  ];
9416
- var ServiceMediaAnalysisKindSchema = z44.enum(SERVICE_MEDIA_ANALYSIS_KINDS);
9417
- var ServiceMediaAnalysisItemSchema = z44.object({
9418
- assetIndex: z44.number().int().nonnegative(),
9419
- mediaType: z44.enum([
9536
+ var ServiceMediaAnalysisKindSchema = z45.enum(SERVICE_MEDIA_ANALYSIS_KINDS);
9537
+ var ServiceMediaAnalysisItemSchema = z45.object({
9538
+ assetIndex: z45.number().int().nonnegative(),
9539
+ mediaType: z45.enum([
9420
9540
  "image",
9421
9541
  "video"
9422
9542
  ]),
9423
9543
  kind: ServiceMediaAnalysisKindSchema,
9424
- description: z44.string().min(1).max(1200),
9425
- tags: z44.array(z44.string().min(1).max(80)).max(12),
9426
- suggestedRoles: z44.array(ServiceMediaRoleSchema).max(4),
9427
- visiblePeople: z44.number().int().nonnegative().max(20).optional(),
9428
- ocrText: z44.string().max(2e3).optional(),
9429
- speechSummary: z44.string().max(2e3).optional()
9430
- });
9431
- var ServiceMediaAnalysisSchema = z44.object({
9432
- version: z44.literal(1),
9433
- analyzedAt: z44.string().datetime(),
9434
- pricingAction: z44.literal("service-media-analysis"),
9435
- assetFingerprint: z44.string().regex(/^[a-f0-9]{64}$/),
9544
+ description: z45.string().min(1).max(1200),
9545
+ tags: z45.array(z45.string().min(1).max(80)).max(12),
9546
+ suggestedRoles: z45.array(ServiceMediaRoleSchema).max(4),
9547
+ visiblePeople: z45.number().int().nonnegative().max(20).optional(),
9548
+ ocrText: z45.string().max(2e3).optional(),
9549
+ speechSummary: z45.string().max(2e3).optional()
9550
+ });
9551
+ var ServiceMediaAnalysisSchema = z45.object({
9552
+ version: z45.literal(1),
9553
+ analyzedAt: z45.string().datetime(),
9554
+ pricingAction: z45.literal("service-media-analysis"),
9555
+ assetFingerprint: z45.string().regex(/^[a-f0-9]{64}$/),
9436
9556
  /** Language used for human-readable descriptions and tags. Optional for old checkpoints. */
9437
- language: z44.enum([
9557
+ language: z45.enum([
9438
9558
  "es",
9439
9559
  "en",
9440
9560
  "pt"
9441
9561
  ]).optional(),
9442
- items: z44.array(ServiceMediaAnalysisItemSchema).max(15)
9562
+ items: z45.array(ServiceMediaAnalysisItemSchema).max(15)
9443
9563
  });
9444
9564
 
9445
9565
  // ../../packages/types/src/productmaker-capability-registry.ts
@@ -9956,7 +10076,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
9956
10076
  ], [
9957
10077
  "creative"
9958
10078
  ]),
9959
- defineCapability("generate_landing", "75947c5a70d26305ca07ab8d7bc0be710e862eb9319010ee66dd43e64fab2050", "credit_consuming", "creative", [
10079
+ defineCapability("generate_landing", "67520417176396516cd5ad358dca39f70a5c4a74169eecd85987217226c12251", "credit_consuming", "creative", [
9960
10080
  "credit_consuming",
9961
10081
  "state_change"
9962
10082
  ], [
@@ -10001,12 +10121,14 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
10001
10121
  "competitorScanEnabled",
10002
10122
  "landingStrategy",
10003
10123
  "landingImageFormat",
10124
+ "pauseForAngleReview",
10004
10125
  // MCP-only, like create_product_task's aiDecidesAll.
10005
10126
  "aiDecidesAll"
10006
10127
  ], [
10007
10128
  "competitorScanEnabled",
10008
10129
  "landingStrategy",
10009
- "landingImageFormat"
10130
+ "landingImageFormat",
10131
+ "pauseForAngleReview"
10010
10132
  ])
10011
10133
  ], [
10012
10134
  "product_reference"
@@ -10522,8 +10644,8 @@ var PRODUCTMAKER_MCP_CAPABILITIES = toLegacyCapabilityCatalog(PRODUCTMAKER_MCP_C
10522
10644
  var PRODUCTMAKER_MCP_CAPABILITY_NAMES = PRODUCTMAKER_MCP_CAPABILITY_REGISTRY.map((capability) => capability.name);
10523
10645
 
10524
10646
  // ../../packages/types/src/actor.ts
10525
- import { z as z45 } from "zod";
10526
- var ActorStatusSchema = z45.enum([
10647
+ import { z as z46 } from "zod";
10648
+ var ActorStatusSchema = z46.enum([
10527
10649
  "draft",
10528
10650
  "generating",
10529
10651
  "ready",
@@ -10532,18 +10654,18 @@ var ActorStatusSchema = z45.enum([
10532
10654
  var ACTOR_NAME_MAX_CHARS = 60;
10533
10655
  var ACTOR_DESCRIPTION_MAX_CHARS = 600;
10534
10656
  var ACTOR_CANDIDATE_COUNT = 4;
10535
- var ActorGenderSchema = z45.enum([
10657
+ var ActorGenderSchema = z46.enum([
10536
10658
  "female",
10537
10659
  "male",
10538
10660
  "non_binary"
10539
10661
  ]);
10540
- var ActorSchema = z45.object({
10541
- id: z45.string(),
10542
- name: z45.string().min(1).max(ACTOR_NAME_MAX_CHARS),
10543
- description: z45.string().max(ACTOR_DESCRIPTION_MAX_CHARS),
10662
+ var ActorSchema = z46.object({
10663
+ id: z46.string(),
10664
+ name: z46.string().min(1).max(ACTOR_NAME_MAX_CHARS),
10665
+ description: z46.string().max(ACTOR_DESCRIPTION_MAX_CHARS),
10544
10666
  gender: ActorGenderSchema,
10545
- voiceId: z45.string().nullable().optional(),
10546
- brandId: z45.string().nullable().optional(),
10667
+ voiceId: z46.string().nullable().optional(),
10668
+ brandId: z46.string().nullable().optional(),
10547
10669
  status: ActorStatusSchema,
10548
10670
  /**
10549
10671
  * A candidate-grid run is in flight RIGHT NOW.
@@ -10555,36 +10677,36 @@ var ActorSchema = z45.object({
10555
10677
  * timestamp with a TTL, so an orphaned run reads as `false` instead of
10556
10678
  * pinning the personaje forever.
10557
10679
  */
10558
- generating: z45.boolean().optional(),
10559
- photoUrl: z45.string().url().nullable().optional(),
10560
- avatarUrl: z45.string().url().nullable().optional(),
10561
- candidateUrls: z45.array(z45.string().url()).optional(),
10680
+ generating: z46.boolean().optional(),
10681
+ photoUrl: z46.string().url().nullable().optional(),
10682
+ avatarUrl: z46.string().url().nullable().optional(),
10683
+ candidateUrls: z46.array(z46.string().url()).optional(),
10562
10684
  /** Indices of candidateUrls that failed the anatomy check (Task 6). */
10563
- flaggedCandidateIndices: z45.array(z45.number().int()).optional()
10685
+ flaggedCandidateIndices: z46.array(z46.number().int()).optional()
10564
10686
  });
10565
- var CreateActorRequest = z45.object({
10566
- name: z45.string().min(1).max(ACTOR_NAME_MAX_CHARS),
10567
- description: z45.string().max(ACTOR_DESCRIPTION_MAX_CHARS).default(""),
10687
+ var CreateActorRequest = z46.object({
10688
+ name: z46.string().min(1).max(ACTOR_NAME_MAX_CHARS),
10689
+ description: z46.string().max(ACTOR_DESCRIPTION_MAX_CHARS).default(""),
10568
10690
  gender: ActorGenderSchema,
10569
- voiceId: z45.string().optional(),
10570
- brandId: z45.string().optional(),
10571
- sourcePhotoKey: z45.string().optional()
10691
+ voiceId: z46.string().optional(),
10692
+ brandId: z46.string().optional(),
10693
+ sourcePhotoKey: z46.string().optional()
10572
10694
  }).refine((v) => v.description.trim().length > 0 || !!v.sourcePhotoKey, {
10573
10695
  message: "Se necesita una descripci\xF3n o una foto"
10574
10696
  });
10575
- var UpdateActorRequest = z45.object({
10576
- name: z45.string().min(1).max(ACTOR_NAME_MAX_CHARS).optional(),
10577
- description: z45.string().max(ACTOR_DESCRIPTION_MAX_CHARS).optional(),
10697
+ var UpdateActorRequest = z46.object({
10698
+ name: z46.string().min(1).max(ACTOR_NAME_MAX_CHARS).optional(),
10699
+ description: z46.string().max(ACTOR_DESCRIPTION_MAX_CHARS).optional(),
10578
10700
  gender: ActorGenderSchema.optional(),
10579
- voiceId: z45.string().nullable().optional(),
10580
- brandId: z45.string().nullable().optional()
10701
+ voiceId: z46.string().nullable().optional(),
10702
+ brandId: z46.string().nullable().optional()
10581
10703
  });
10582
- var ApproveActorRequest = z45.object({
10583
- candidateIndex: z45.number().int().min(0).max(ACTOR_CANDIDATE_COUNT - 1)
10704
+ var ApproveActorRequest = z46.object({
10705
+ candidateIndex: z46.number().int().min(0).max(ACTOR_CANDIDATE_COUNT - 1)
10584
10706
  });
10585
10707
 
10586
10708
  // ../../packages/types/src/referral-dashboard.ts
10587
- import { z as z46 } from "zod";
10709
+ import { z as z47 } from "zod";
10588
10710
  var REFERRAL_DASHBOARD_RAW_STATUSES = [
10589
10711
  "ACTIVE",
10590
10712
  "PENDING",
@@ -10603,66 +10725,66 @@ var REFERRAL_DASHBOARD_PLAN_KINDS = [
10603
10725
  "last",
10604
10726
  "none"
10605
10727
  ];
10606
- var ReferralDashboardRawStatusSchema = z46.enum(REFERRAL_DASHBOARD_RAW_STATUSES);
10607
- var ReferralDashboardStateSchema = z46.enum(REFERRAL_DASHBOARD_STATES);
10608
- var ReferralDashboardPlanKindSchema = z46.enum(REFERRAL_DASHBOARD_PLAN_KINDS);
10609
- var ReferralDashboardStatusSchema = z46.enum([
10728
+ var ReferralDashboardRawStatusSchema = z47.enum(REFERRAL_DASHBOARD_RAW_STATUSES);
10729
+ var ReferralDashboardStateSchema = z47.enum(REFERRAL_DASHBOARD_STATES);
10730
+ var ReferralDashboardPlanKindSchema = z47.enum(REFERRAL_DASHBOARD_PLAN_KINDS);
10731
+ var ReferralDashboardStatusSchema = z47.enum([
10610
10732
  "all",
10611
10733
  "active",
10612
10734
  "pending",
10613
10735
  "inactive"
10614
10736
  ]).default("all");
10615
- var ReferralDashboardPlanSchema = z46.string().trim().min(1).max(100).optional();
10616
- var ReferralDashboardFiltersSchema = z46.object({
10737
+ var ReferralDashboardPlanSchema = z47.string().trim().min(1).max(100).optional();
10738
+ var ReferralDashboardFiltersSchema = z47.object({
10617
10739
  status: ReferralDashboardStatusSchema,
10618
10740
  plan: ReferralDashboardPlanSchema
10619
10741
  });
10620
- var ReferralDashboardSubscriptionSchema = z46.object({
10621
- planName: z46.string().nullable(),
10742
+ var ReferralDashboardSubscriptionSchema = z47.object({
10743
+ planName: z47.string().nullable(),
10622
10744
  planKind: ReferralDashboardPlanKindSchema,
10623
10745
  rawStatus: ReferralDashboardRawStatusSchema.nullable(),
10624
10746
  state: ReferralDashboardStateSchema,
10625
- currentPeriodEnd: z46.string().datetime({
10747
+ currentPeriodEnd: z47.string().datetime({
10626
10748
  offset: true
10627
10749
  }).nullable(),
10628
- cancelAtPeriodEnd: z46.boolean()
10750
+ cancelAtPeriodEnd: z47.boolean()
10629
10751
  });
10630
- var ReferralDashboardReferralSchema = z46.object({
10631
- id: z46.string().min(1),
10632
- registeredAt: z46.string().datetime({
10752
+ var ReferralDashboardReferralSchema = z47.object({
10753
+ id: z47.string().min(1),
10754
+ registeredAt: z47.string().datetime({
10633
10755
  offset: true
10634
10756
  }),
10635
10757
  // Kept in the response for compatibility with existing referral API clients.
10636
10758
  // The referrer dashboard intentionally does not render these legacy fields.
10637
- expiresAt: z46.string().datetime({
10759
+ expiresAt: z47.string().datetime({
10638
10760
  offset: true
10639
10761
  }).nullable().optional(),
10640
- status: z46.string().min(1).optional(),
10641
- referredUser: z46.object({
10642
- email: z46.string().nullable()
10762
+ status: z47.string().min(1).optional(),
10763
+ referredUser: z47.object({
10764
+ email: z47.string().nullable()
10643
10765
  }),
10644
10766
  subscription: ReferralDashboardSubscriptionSchema
10645
10767
  });
10646
- var ReferralDashboardReferralsPageSchema = z46.object({
10647
- referrals: z46.array(ReferralDashboardReferralSchema),
10648
- total: z46.number().int().nonnegative()
10768
+ var ReferralDashboardReferralsPageSchema = z47.object({
10769
+ referrals: z47.array(ReferralDashboardReferralSchema),
10770
+ total: z47.number().int().nonnegative()
10649
10771
  });
10650
- var ReferralDashboardPlanBreakdownSchema = z46.object({
10651
- planName: z46.string().nullable(),
10652
- count: z46.number().int().nonnegative()
10772
+ var ReferralDashboardPlanBreakdownSchema = z47.object({
10773
+ planName: z47.string().nullable(),
10774
+ count: z47.number().int().nonnegative()
10653
10775
  });
10654
- var ReferralDashboardMonthlyRegistrationSchema = z46.object({
10655
- month: z46.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/),
10656
- count: z46.number().int().nonnegative()
10776
+ var ReferralDashboardMonthlyRegistrationSchema = z47.object({
10777
+ month: z47.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/),
10778
+ count: z47.number().int().nonnegative()
10657
10779
  });
10658
- var ReferralDashboardOverviewSchema = z46.object({
10659
- totalReferredUsers: z46.number().int().nonnegative(),
10660
- activeUsers: z46.number().int().nonnegative(),
10661
- pendingUsers: z46.number().int().nonnegative(),
10662
- inactiveUsers: z46.number().int().nonnegative(),
10663
- noPlanUsers: z46.number().int().nonnegative(),
10664
- planBreakdown: z46.array(ReferralDashboardPlanBreakdownSchema),
10665
- monthlyRegistrations: z46.array(ReferralDashboardMonthlyRegistrationSchema).refine((months) => months.length === 6, "Expected six monthly registration buckets")
10780
+ var ReferralDashboardOverviewSchema = z47.object({
10781
+ totalReferredUsers: z47.number().int().nonnegative(),
10782
+ activeUsers: z47.number().int().nonnegative(),
10783
+ pendingUsers: z47.number().int().nonnegative(),
10784
+ inactiveUsers: z47.number().int().nonnegative(),
10785
+ noPlanUsers: z47.number().int().nonnegative(),
10786
+ planBreakdown: z47.array(ReferralDashboardPlanBreakdownSchema),
10787
+ monthlyRegistrations: z47.array(ReferralDashboardMonthlyRegistrationSchema).refine((months) => months.length === 6, "Expected six monthly registration buckets")
10666
10788
  });
10667
10789
 
10668
10790
  // src/resolve-media.ts
@@ -10905,10 +11027,10 @@ async function resolveMediaRef(ref, opts) {
10905
11027
  __name(resolveMediaRef, "resolveMediaRef");
10906
11028
 
10907
11029
  // src/tools/shared.ts
10908
- import { z as z47 } from "zod";
10909
- var Lang = z47.string().min(2).max(10);
10910
- var Country = z47.string().min(2).max(3);
10911
- var LandingStrategyEnum = z47.enum([
11030
+ import { z as z48 } from "zod";
11031
+ var Lang = z48.string().min(2).max(10);
11032
+ var Country = z48.string().min(2).max(3);
11033
+ var LandingStrategyEnum = z48.enum([
10912
11034
  "auto",
10913
11035
  "classic",
10914
11036
  "pain_solution",
@@ -10917,12 +11039,12 @@ var LandingStrategyEnum = z47.enum([
10917
11039
  "offer_value",
10918
11040
  "lifestyle_identity"
10919
11041
  ]);
10920
- var LandingImageFormatEnum = z47.enum([
11042
+ var LandingImageFormatEnum = z48.enum([
10921
11043
  "9:16",
10922
11044
  "4:5",
10923
11045
  "1:1"
10924
11046
  ]);
10925
- var VideoPresetEnum = z47.enum([
11047
+ var VideoPresetEnum = z48.enum([
10926
11048
  "auto",
10927
11049
  "ugc_dynamic",
10928
11050
  "ugc_how_to",
@@ -10935,7 +11057,7 @@ var VideoPresetEnum = z47.enum([
10935
11057
  "pixar_problem",
10936
11058
  "pixar_sassy"
10937
11059
  ]);
10938
- var TaskCreativeVariantVideoPresetEnum = z47.enum([
11060
+ var TaskCreativeVariantVideoPresetEnum = z48.enum([
10939
11061
  "auto",
10940
11062
  "ugc_dynamic",
10941
11063
  "ugc_how_to",
@@ -11006,7 +11128,7 @@ function resolveVideoPreset(preset) {
11006
11128
  return VIDEO_PRESET_RESOLUTION[preset] ?? null;
11007
11129
  }
11008
11130
  __name(resolveVideoPreset, "resolveVideoPreset");
11009
- var VideoTierEnum = z47.enum([
11131
+ var VideoTierEnum = z48.enum([
11010
11132
  "basic"
11011
11133
  ]);
11012
11134
  function resolveVideoTier(_tier) {
@@ -11021,17 +11143,17 @@ function resolveVideoFormatForDuration(durationSeconds) {
11021
11143
  return durationSeconds === 30 ? "double_30s" : "single_15s";
11022
11144
  }
11023
11145
  __name(resolveVideoFormatForDuration, "resolveVideoFormatForDuration");
11024
- var VideoResolutionEnum = z47.enum([
11146
+ var VideoResolutionEnum = z48.enum([
11025
11147
  "480p",
11026
11148
  "720p"
11027
11149
  ]);
11028
- var VideoStyleEnum = z47.enum([
11150
+ var VideoStyleEnum = z48.enum([
11029
11151
  "ugc",
11030
11152
  "cartoon_3d",
11031
11153
  "product_only",
11032
11154
  "ai_dynamic"
11033
11155
  ]);
11034
- var NarrativeStyleEnum = z47.enum([
11156
+ var NarrativeStyleEnum = z48.enum([
11035
11157
  "review",
11036
11158
  "ugc_how_to",
11037
11159
  "problem_product_cta",
@@ -11048,7 +11170,7 @@ var NarrativeStyleEnum = z47.enum([
11048
11170
  "ugc_skeptic_confession",
11049
11171
  "ugc_demo_review"
11050
11172
  ]);
11051
- var PublicNarrativeStyleEnum = z47.enum([
11173
+ var PublicNarrativeStyleEnum = z48.enum([
11052
11174
  "review",
11053
11175
  "ugc_how_to",
11054
11176
  "ugc_unboxing_chaos",
@@ -11060,7 +11182,7 @@ var PublicNarrativeStyleEnum = z47.enum([
11060
11182
  "animated_problem_pixar",
11061
11183
  "sassy_product_pixar"
11062
11184
  ]);
11063
- var VideoModelEnum = z47.enum([
11185
+ var VideoModelEnum = z48.enum([
11064
11186
  "veo",
11065
11187
  "wan",
11066
11188
  "bytedance",
@@ -11068,29 +11190,29 @@ var VideoModelEnum = z47.enum([
11068
11190
  "grok",
11069
11191
  "kling"
11070
11192
  ]);
11071
- var ProductReferenceUserChoiceEnum = z47.enum([
11193
+ var ProductReferenceUserChoiceEnum = z48.enum([
11072
11194
  "same_product",
11073
11195
  "variants",
11074
11196
  "different_products",
11075
11197
  "combo_distinct"
11076
11198
  ]);
11077
- var ProductReferenceCandidateGroupingEnum = z47.enum([
11199
+ var ProductReferenceCandidateGroupingEnum = z48.enum([
11078
11200
  "same_product_same_variant",
11079
11201
  "same_product_different_variants",
11080
11202
  "different_products",
11081
11203
  "unclear"
11082
11204
  ]);
11083
- var ProductReferenceScopeEnum = z47.enum([
11205
+ var ProductReferenceScopeEnum = z48.enum([
11084
11206
  "base",
11085
11207
  "video_view_pack"
11086
11208
  ]);
11087
- var ProductReferenceResolutionDecisionEnum = z47.enum([
11209
+ var ProductReferenceResolutionDecisionEnum = z48.enum([
11088
11210
  "approve",
11089
11211
  "reject",
11090
11212
  "observed_only",
11091
11213
  "correct_view"
11092
11214
  ]);
11093
- var ProductReferenceRejectionReasonEnum = z47.enum([
11215
+ var ProductReferenceRejectionReasonEnum = z48.enum([
11094
11216
  "replacement_requested",
11095
11217
  "wrong_product_identity",
11096
11218
  "wrong_variant",
@@ -11101,13 +11223,13 @@ var ProductReferenceRejectionReasonEnum = z47.enum([
11101
11223
  "not_a_product_photo",
11102
11224
  "other"
11103
11225
  ]);
11104
- var GapDurationChoiceMirror = z47.object({
11105
- angleIndex: z47.number().int().nonnegative(),
11106
- recommendedSec: z47.union([
11107
- z47.literal(15),
11108
- z47.literal(30)
11226
+ var GapDurationChoiceMirror = z48.object({
11227
+ angleIndex: z48.number().int().nonnegative(),
11228
+ recommendedSec: z48.union([
11229
+ z48.literal(15),
11230
+ z48.literal(30)
11109
11231
  ]),
11110
- estimatedDeltaCredits: z47.number().int().nonnegative().optional()
11232
+ estimatedDeltaCredits: z48.number().int().nonnegative().optional()
11111
11233
  });
11112
11234
  function buildSelectedImageUrlsHash(urls) {
11113
11235
  const input = [
@@ -11117,13 +11239,13 @@ function buildSelectedImageUrlsHash(urls) {
11117
11239
  return `fnv1a:${hash.toString(16).padStart(8, "0")}:${urls.length}`;
11118
11240
  }
11119
11241
  __name(buildSelectedImageUrlsHash, "buildSelectedImageUrlsHash");
11120
- var ImageCreativeStyleEnum = z47.enum([
11242
+ var ImageCreativeStyleEnum = z48.enum([
11121
11243
  "studio",
11122
11244
  "floating",
11123
11245
  "ingredients",
11124
11246
  "in_use"
11125
11247
  ]);
11126
- var ImageCreativeArchetypeEnum = z47.enum([
11248
+ var ImageCreativeArchetypeEnum = z48.enum([
11127
11249
  "direct_response_product_ad",
11128
11250
  "hero_outcome",
11129
11251
  "offer_value_prop",
@@ -11132,20 +11254,20 @@ var ImageCreativeArchetypeEnum = z47.enum([
11132
11254
  "problem_solution",
11133
11255
  "lifestyle_identity"
11134
11256
  ]);
11135
- var ImageCreativeVisualTreatmentEnum = z47.enum([
11257
+ var ImageCreativeVisualTreatmentEnum = z48.enum([
11136
11258
  "performance_product_ad",
11137
11259
  "premium_dtc_carousel"
11138
11260
  ]);
11139
- var ImageCreativeAspectRatioEnum = z47.enum([
11261
+ var ImageCreativeAspectRatioEnum = z48.enum([
11140
11262
  "1:1",
11141
11263
  "4:5",
11142
11264
  "9:16",
11143
11265
  "16:9"
11144
11266
  ]);
11145
- var ImageRefSchema = z47.object({
11146
- url: z47.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.'),
11147
- path: z47.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`.'),
11148
- assetId: z47.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.")
11267
+ var ImageRefSchema = z48.object({
11268
+ url: z48.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.'),
11269
+ path: z48.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`.'),
11270
+ assetId: z48.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.")
11149
11271
  }).refine((v) => [
11150
11272
  v.url,
11151
11273
  v.path,
@@ -11153,11 +11275,11 @@ var ImageRefSchema = z47.object({
11153
11275
  ].filter(Boolean).length === 1, {
11154
11276
  message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
11155
11277
  });
11156
- var ImagesInput = z47.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
11278
+ var ImagesInput = z48.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
11157
11279
  const assetCount = images.filter((image) => Boolean(image.assetId)).length;
11158
11280
  if (assetCount > 0 && assetCount !== images.length) {
11159
11281
  ctx.addIssue({
11160
- code: z47.ZodIssueCode.custom,
11282
+ code: z48.ZodIssueCode.custom,
11161
11283
  message: "all image entries must use assetId, or all must use URL/path sources"
11162
11284
  });
11163
11285
  }
@@ -11227,14 +11349,14 @@ async function submitCreative(api, opts) {
11227
11349
  });
11228
11350
  }
11229
11351
  __name(submitCreative, "submitCreative");
11230
- var ResearchTargetCountryEnum = z47.enum([
11352
+ var ResearchTargetCountryEnum = z48.enum([
11231
11353
  "CO",
11232
11354
  "MX",
11233
11355
  "PE",
11234
11356
  "EC",
11235
11357
  "CL"
11236
11358
  ]);
11237
- var ResearchCategoryEnum = z47.enum([
11359
+ var ResearchCategoryEnum = z48.enum([
11238
11360
  "auto",
11239
11361
  "automotive",
11240
11362
  "kitchen",
@@ -11293,6 +11415,7 @@ var McpErrorCode = {
11293
11415
  REVOKED_API_KEY: "REVOKED_API_KEY",
11294
11416
  // Rate limit / quota
11295
11417
  RATE_LIMITED: "RATE_LIMITED",
11418
+ CREDIT_ADMISSION_UNAVAILABLE: "CREDIT_ADMISSION_UNAVAILABLE",
11296
11419
  // Input
11297
11420
  INVALID_INPUT: "INVALID_INPUT",
11298
11421
  INSUFFICIENT_CREDITS: "INSUFFICIENT_CREDITS",
@@ -11481,6 +11604,7 @@ var CODE_MESSAGES = {
11481
11604
  REVOKED_API_KEY: "API key revoked. Generate a new one at https://productmaker.app/account/api-keys.",
11482
11605
  // Rate
11483
11606
  RATE_LIMITED: "Too many requests. Wait a few seconds.",
11607
+ CREDIT_ADMISSION_UNAVAILABLE: "Credit admission is temporarily unavailable. Do not retry a paid action until ProductMaker can verify the balance.",
11484
11608
  INSUFFICIENT_CREDITS: "Insufficient credits for this action. Check your balance and add credits at https://productmaker.app before retrying.",
11485
11609
  TASK_QUOTA_EXCEEDED: "You reached the active-task limit. Wait for a task to finish before creating another variant.",
11486
11610
  // Generic
@@ -11575,6 +11699,7 @@ var INVALID_PARAM_CODES = /* @__PURE__ */ new Set([
11575
11699
  McpErrorCode.NO_META_AD_ACCOUNTS
11576
11700
  ]);
11577
11701
  var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
11702
+ McpErrorCode.CREDIT_ADMISSION_UNAVAILABLE,
11578
11703
  McpErrorCode.INSUFFICIENT_CREDITS,
11579
11704
  McpErrorCode.TASK_QUOTA_EXCEEDED,
11580
11705
  McpErrorCode.DROPSHIPPING_PROJECT_NOT_FOUND,
@@ -11673,6 +11798,7 @@ __name(looksLikeMeaningfulBackendMessage, "looksLikeMeaningfulBackendMessage");
11673
11798
  function resolveMessage(code, backendMessage) {
11674
11799
  const mapped = CODE_MESSAGES[code];
11675
11800
  const backend = typeof backendMessage === "string" ? backendMessage.trim() : "";
11801
+ if (code === McpErrorCode.CREDIT_ADMISSION_UNAVAILABLE && mapped) return mapped;
11676
11802
  if (mapped && backend && looksLikeMeaningfulBackendMessage(backend, mapped)) {
11677
11803
  return `${mapped} (Detail: ${backend})`;
11678
11804
  }
@@ -11935,54 +12061,54 @@ function renderOutputsMarkdown(outputs) {
11935
12061
  __name(renderOutputsMarkdown, "renderOutputsMarkdown");
11936
12062
 
11937
12063
  // src/tools/tasks.ts
11938
- var CreateProductTaskInput = z48.object({
12064
+ var CreateProductTaskInput = z49.object({
11939
12065
  images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
11940
- projectId: z48.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
11941
- productUrl: z48.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."),
12066
+ projectId: z49.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
12067
+ productUrl: z49.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."),
11942
12068
  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.'),
11943
12069
  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.'),
11944
- price: z48.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.'),
11945
- compareAtPrice: z48.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".'),
11946
- offer: z48.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.'),
11947
- paymentMethods: z48.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.'),
11948
- productContext: z48.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."),
11949
- productLabel: z48.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.'),
12070
+ price: z49.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.'),
12071
+ compareAtPrice: z49.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".'),
12072
+ offer: z49.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.'),
12073
+ paymentMethods: z49.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.'),
12074
+ productContext: z49.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."),
12075
+ productLabel: z49.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.'),
11950
12076
  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). 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" (una regla visual experimental original), "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.'),
11951
- durationSeconds: z48.union([
11952
- z48.literal(15),
11953
- z48.literal(30)
12077
+ durationSeconds: z49.union([
12078
+ z49.literal(15),
12079
+ z49.literal(30)
11954
12080
  ]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
11955
- pauseForAngleReview: z48.boolean().optional().describe("Opcional. Si true, pausa despu\xE9s de generar el \xE1ngulo para que el usuario lo confirme o edite antes del render. \xDAsalo si quiere decidir 15/30s cuando aparezca un winner. Default false."),
11956
- aiDecidesAll: z48.boolean().optional().describe("Opcional. Si true, ProductMaker decide TODO y no vuelve a interrumpir al usuario: resuelve solo las confirmaciones de referencias del producto y no abre gates de aprobaci\xF3n, as\xED que `pendingUserAction` no deber\xEDa aparecer. Act\xEDvalo \xFAnicamente cuando el usuario pida expl\xEDcitamente que la IA decida todo o que no le pregunten m\xE1s. Default false."),
12081
+ pauseForAngleReview: z49.boolean().optional().describe("Opcional. Si true, pausa despu\xE9s de generar el \xE1ngulo para que el usuario lo confirme o edite antes del render. \xDAsalo si quiere decidir 15/30s cuando aparezca un winner. Default false."),
12082
+ aiDecidesAll: z49.boolean().optional().describe("Opcional. Si true, ProductMaker decide TODO y no vuelve a interrumpir al usuario: resuelve solo las confirmaciones de referencias del producto y no abre gates de aprobaci\xF3n, as\xED que `pendingUserAction` no deber\xEDa aparecer. Act\xEDvalo \xFAnicamente cuando el usuario pida expl\xEDcitamente que la IA decida todo o que no le pregunten m\xE1s. Default false."),
11957
12083
  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.'),
11958
12084
  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).'),
11959
- multiAngleVideos: z48.boolean().optional().describe("Opcional. Si true, genera m\xFAltiples \xE1ngulos de venta en paralelo (3-5 videos). Si false/omitido, genera 1 video del \xE1ngulo principal. Default false."),
12085
+ multiAngleVideos: z49.boolean().optional().describe("Opcional. Si true, genera m\xFAltiples \xE1ngulos de venta en paralelo (3-5 videos). Si false/omitido, genera 1 video del \xE1ngulo principal. Default false."),
11960
12086
  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". angleNarratives[i] fuerza la narrativa del \xE1ngulo i; las posiciones restantes las elige la IA. Requiere multiAngleVideos:true para varios \xE1ngulos.'),
11961
- outputs: z48.array(z48.enum([
12087
+ outputs: z49.array(z49.enum([
11962
12088
  "landing",
11963
12089
  "video",
11964
12090
  "image"
11965
12091
  ])).min(2).max(3).optional().describe('Opcional. Qu\xE9 outputs generar. Default: todos ["landing","video","image"]. Para 2 outputs: ["landing","image"] (sin video), ["video","image"] (sin landing), ["landing","video"] (sin imagen). Para 1 solo output, usa generate_landing / generate_video_creative / generate_image_creatives.'),
11966
- competitorScanEnabled: z48.boolean().optional().describe("Opcional. Si true (default), el sistema analiza ads de competencia en Meta Ad Library y enriquece los \xE1ngulos generados con hooks y painPoints validados por el mercado (\u2248$0.20-0.48 extra por task \u2014 var\xEDa con cu\xE1ntas transcripciones de video se capturen). Si false, el pipeline genera \xE1ngulos sin esa se\xF1al \u2014 usa esto SOLO si el usuario ya tiene su propia investigaci\xF3n de mercado o quiere ahorrar costos en productos muy nicho sin presencia en Meta. Default true."),
11967
- brandId: z48.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."),
11968
- actorId: z48.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."),
11969
- creativeDirection: z48.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.'),
11970
- headline: z48.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."),
11971
- subheadline: z48.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."),
12092
+ competitorScanEnabled: z49.boolean().optional().describe("Opcional. Si true (default), el sistema analiza ads de competencia en Meta Ad Library y enriquece los \xE1ngulos generados con hooks y painPoints validados por el mercado (\u2248$0.20-0.48 extra por task \u2014 var\xEDa con cu\xE1ntas transcripciones de video se capturen). Si false, el pipeline genera \xE1ngulos sin esa se\xF1al \u2014 usa esto SOLO si el usuario ya tiene su propia investigaci\xF3n de mercado o quiere ahorrar costos en productos muy nicho sin presencia en Meta. Default true."),
12093
+ brandId: z49.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."),
12094
+ actorId: z49.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."),
12095
+ creativeDirection: z49.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.'),
12096
+ headline: z49.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."),
12097
+ subheadline: z49.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."),
11972
12098
  landingStrategy: LandingStrategyEnum.default("classic").describe('Opcional. Estructura de la landing cl\xE1sica cuando landing est\xE1 entre outputs: "classic" (estructura original probada y recomendada; default del primer rollout), "auto" (la IA decide; experimental), "pain_solution", "social_proof" (Landing Viral: UGC, WhatsApp, Instagram y evidencia social), "benefits_clarity", "offer_value" o "lifestyle_identity". Default "classic".'),
11973
12099
  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".')
11974
12100
  }).strict();
11975
- var CreateServiceVideoInput = z48.object({
11976
- landingUrl: z48.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
11977
- additionalContext: z48.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
12101
+ var CreateServiceVideoInput = z49.object({
12102
+ landingUrl: z49.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
12103
+ additionalContext: z49.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
11978
12104
  language: Lang.describe("Idioma del video: es, en o pt."),
11979
- voiceId: z48.string().trim().min(1).optional().describe('Opcional. Voz de ElevenLabs para toda la narraci\xF3n. Usa "auto" para que la IA la alinee con el presentador o env\xEDa un ID concreto de la lista de voces de la web.'),
11980
- brandId: z48.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
11981
- reviewMode: z48.enum([
12105
+ voiceId: z49.string().trim().min(1).optional().describe('Opcional. Voz de ElevenLabs para toda la narraci\xF3n. Usa "auto" para que la IA la alinee con el presentador o env\xEDa un ID concreto de la lista de voces de la web.'),
12106
+ brandId: z49.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
12107
+ reviewMode: z49.enum([
11982
12108
  "automatic",
11983
12109
  "guided"
11984
12110
  ]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
11985
- videoPreset: z48.enum([
12111
+ videoPreset: z49.enum([
11986
12112
  "auto",
11987
12113
  "ugc_dynamic",
11988
12114
  "ugc_how_to",
@@ -11990,51 +12116,51 @@ var CreateServiceVideoInput = z48.object({
11990
12116
  "wild_card"
11991
12117
  ]).default("auto")
11992
12118
  }).strict();
11993
- var GetTaskStatusInput = z48.object({
11994
- taskId: z48.string().min(1),
11995
- waitSeconds: z48.number().int().min(0).max(120).optional()
11996
- });
11997
- var ListTasksInput = z48.object({
11998
- limit: z48.number().int().min(1).max(50).optional(),
11999
- offset: z48.number().int().min(0).optional(),
12000
- search: z48.string().optional()
12001
- });
12002
- var EditTaskDraftInput = z48.object({
12003
- taskId: z48.string().min(1),
12004
- angleIndex: z48.number().int().min(0),
12005
- angle: z48.object({
12006
- angle: z48.string().min(1).max(480),
12007
- buyerPersona: z48.string().min(1).max(360),
12008
- actor: z48.string().min(1).max(360).optional(),
12009
- actorId: z48.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."),
12010
- gender: z48.enum([
12119
+ var GetTaskStatusInput = z49.object({
12120
+ taskId: z49.string().min(1),
12121
+ waitSeconds: z49.number().int().min(0).max(120).optional()
12122
+ });
12123
+ var ListTasksInput = z49.object({
12124
+ limit: z49.number().int().min(1).max(50).optional(),
12125
+ offset: z49.number().int().min(0).optional(),
12126
+ search: z49.string().optional()
12127
+ });
12128
+ var EditTaskDraftInput = z49.object({
12129
+ taskId: z49.string().min(1),
12130
+ angleIndex: z49.number().int().min(0),
12131
+ angle: z49.object({
12132
+ angle: z49.string().min(1).max(480),
12133
+ buyerPersona: z49.string().min(1).max(360),
12134
+ actor: z49.string().min(1).max(360).optional(),
12135
+ actorId: z49.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."),
12136
+ gender: z49.enum([
12011
12137
  "female",
12012
12138
  "male"
12013
12139
  ]).optional(),
12014
- scriptNotes: z48.string().max(2e3).optional()
12140
+ scriptNotes: z49.string().max(2e3).optional()
12015
12141
  })
12016
12142
  });
12017
- var PendingActionPayload = z48.discriminatedUnion("kind", [
12018
- z48.object({
12019
- kind: z48.literal("product_reference_set_approval"),
12143
+ var PendingActionPayload = z49.discriminatedUnion("kind", [
12144
+ z49.object({
12145
+ kind: z49.literal("product_reference_set_approval"),
12020
12146
  scope: ProductReferenceScopeEnum,
12021
- scopeKey: z48.string().min(1).max(120),
12022
- scopeSnapshotId: z48.string().uuid(),
12023
- expectedScopeHash: z48.string().min(1).max(128),
12147
+ scopeKey: z49.string().min(1).max(120),
12148
+ scopeSnapshotId: z49.string().uuid(),
12149
+ expectedScopeHash: z49.string().min(1).max(128),
12024
12150
  decision: ProductReferenceResolutionDecisionEnum,
12025
12151
  reason: ProductReferenceRejectionReasonEnum.optional(),
12026
- affectedRefKeys: z48.array(z48.string().min(1).max(200)).min(1).optional(),
12027
- recoveryAction: z48.enum([
12152
+ affectedRefKeys: z49.array(z49.string().min(1).max(200)).min(1).optional(),
12153
+ recoveryAction: z49.enum([
12028
12154
  "remove",
12029
12155
  "replace",
12030
12156
  "upload",
12031
12157
  "return_to_selection"
12032
12158
  ]).optional()
12033
12159
  }),
12034
- z48.object({
12035
- kind: z48.literal("product_reference_confirmation"),
12160
+ z49.object({
12161
+ kind: z49.literal("product_reference_confirmation"),
12036
12162
  userChoice: ProductReferenceUserChoiceEnum.optional(),
12037
- confirmedProductNames: z48.array(z48.string().min(1).max(120)).min(2).max(8).optional(),
12163
+ confirmedProductNames: z49.array(z49.string().min(1).max(120)).min(2).max(8).optional(),
12038
12164
  // SCOPED multi-scene opt-in — the ONLY way STANDARD ("Multiescena") is
12039
12165
  // reachable via MCP. Valid ONLY together with userChoice='variants' (same
12040
12166
  // product in several colors): renders one shot per color and stitches them,
@@ -12045,50 +12171,50 @@ var PendingActionPayload = z48.discriminatedUnion("kind", [
12045
12171
  // safe because multi-scene IS the intended render for a color variant set,
12046
12172
  // not a blind quality upsell. Maps to `videoTier: 'standard'` on the
12047
12173
  // confirm call; the backend re-gates it (variants + variant_set only).
12048
- useMultiSceneShowcase: z48.boolean().optional().describe('Opcional (SOLO con userChoice="variants"). true = render Multiescena: una toma por color, mostrando todas las variantes, hasta 30s. Se factura POR ESCENA (m\xE1s caro que el render normal de una sola toma) \u2014 AV\xCDSALE del mayor costo al usuario antes de activarlo. Omitir = render est\xE1ndar de una sola toma. Se ignora si userChoice no es "variants".')
12174
+ useMultiSceneShowcase: z49.boolean().optional().describe('Opcional (SOLO con userChoice="variants"). true = render Multiescena: una toma por color, mostrando todas las variantes, hasta 30s. Se factura POR ESCENA (m\xE1s caro que el render normal de una sola toma) \u2014 AV\xCDSALE del mayor costo al usuario antes de activarlo. Omitir = render est\xE1ndar de una sola toma. Se ignora si userChoice no es "variants".')
12049
12175
  }),
12050
- z48.object({
12051
- kind: z48.literal("angle_review_approval"),
12176
+ z49.object({
12177
+ kind: z49.literal("angle_review_approval"),
12052
12178
  // All edits are optional — empty action body just approves the
12053
12179
  // backend-generated draft as-is. Field shapes mirror the angle-review
12054
12180
  // request contracts in @packages/types/wizard.ts; the handler routes to
12055
12181
  // the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
12056
- customAngle: z48.string().min(1).max(480).optional(),
12182
+ customAngle: z49.string().min(1).max(480).optional(),
12057
12183
  // Keep the shared MCP action within the strictest downstream contract:
12058
12184
  // autopilot/image resume endpoints cap these fields at 1500 characters.
12059
- painPoints: z48.string().max(1500).optional(),
12060
- benefits: z48.string().max(1500).optional(),
12061
- features: z48.array(z48.string().min(1).max(300)).max(10).optional(),
12062
- gapDurationSeconds: z48.union([
12063
- z48.literal(15),
12064
- z48.literal(30)
12185
+ painPoints: z49.string().max(1500).optional(),
12186
+ benefits: z49.string().max(1500).optional(),
12187
+ features: z49.array(z49.string().min(1).max(300)).max(10).optional(),
12188
+ gapDurationSeconds: z49.union([
12189
+ z49.literal(15),
12190
+ z49.literal(30)
12065
12191
  ]).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.")
12066
12192
  }),
12067
- z48.object({
12068
- kind: z48.literal("service_angle_approval"),
12069
- angleId: z48.string().uuid(),
12070
- content: z48.string().min(1).max(480).optional(),
12071
- creativeDirection: z48.string().min(1).max(1500).optional(),
12072
- actor: z48.string().min(1).max(360).optional()
12193
+ z49.object({
12194
+ kind: z49.literal("service_angle_approval"),
12195
+ angleId: z49.string().uuid(),
12196
+ content: z49.string().min(1).max(480).optional(),
12197
+ creativeDirection: z49.string().min(1).max(1500).optional(),
12198
+ actor: z49.string().min(1).max(360).optional()
12073
12199
  }),
12074
- z48.object({
12075
- kind: z48.literal("service_script_approval"),
12076
- voiceovers: z48.record(z48.string(), z48.string().min(1).max(600)).optional(),
12077
- visualDirections: z48.record(z48.string(), z48.string().min(1).max(1200)).optional()
12200
+ z49.object({
12201
+ kind: z49.literal("service_script_approval"),
12202
+ voiceovers: z49.record(z49.string(), z49.string().min(1).max(600)).optional(),
12203
+ visualDirections: z49.record(z49.string(), z49.string().min(1).max(1200)).optional()
12078
12204
  })
12079
12205
  ]);
12080
- var ResolvePendingActionInput = z48.object({
12081
- taskId: z48.string().min(1),
12206
+ var ResolvePendingActionInput = z49.object({
12207
+ taskId: z49.string().min(1),
12082
12208
  action: PendingActionPayload
12083
12209
  }).strict();
12084
12210
  function resolveVariantConfirmVideoTier(action) {
12085
12211
  return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
12086
12212
  }
12087
12213
  __name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
12088
- var StatusForResolveSchema = z48.object({
12214
+ var StatusForResolveSchema = z49.object({
12089
12215
  // Metadata used to select the backend resume contract. Older API responses
12090
12216
  // may omit these fields, so the resolver keeps the generic fallback.
12091
- kind: z48.enum([
12217
+ kind: z49.enum([
12092
12218
  "autopilot",
12093
12219
  "video",
12094
12220
  "image",
@@ -12096,24 +12222,24 @@ var StatusForResolveSchema = z48.object({
12096
12222
  "mix",
12097
12223
  "service"
12098
12224
  ]).optional(),
12099
- selectedOutputs: z48.array(z48.enum([
12225
+ selectedOutputs: z49.array(z49.enum([
12100
12226
  "landing",
12101
12227
  "video",
12102
12228
  "image"
12103
12229
  ])).optional(),
12104
- videoAngleCount: z48.number().int().min(1).max(3).optional(),
12105
- ugcFormat: z48.enum([
12230
+ videoAngleCount: z49.number().int().min(1).max(3).optional(),
12231
+ ugcFormat: z49.enum([
12106
12232
  "single_8s",
12107
12233
  "single_15s",
12108
12234
  "double_30s"
12109
12235
  ]).optional(),
12110
- videoStyle: z48.enum([
12236
+ videoStyle: z49.enum([
12111
12237
  "ugc",
12112
12238
  "cartoon_3d",
12113
12239
  "product_only",
12114
12240
  "ai_dynamic"
12115
12241
  ]).optional(),
12116
- videoModel: z48.enum([
12242
+ videoModel: z49.enum([
12117
12243
  "veo",
12118
12244
  "wan",
12119
12245
  "bytedance",
@@ -12121,62 +12247,62 @@ var StatusForResolveSchema = z48.object({
12121
12247
  "grok",
12122
12248
  "kling"
12123
12249
  ]).optional(),
12124
- videoTier: z48.enum([
12250
+ videoTier: z49.enum([
12125
12251
  "legacy",
12126
12252
  "standard",
12127
12253
  "pro",
12128
12254
  "single_call"
12129
12255
  ]).optional(),
12130
- videoResolution: z48.enum([
12256
+ videoResolution: z49.enum([
12131
12257
  "480p",
12132
12258
  "720p"
12133
12259
  ]).optional(),
12134
12260
  narrativeStyle: NarrativeStyleEnum.optional(),
12135
- pendingUserAction: z48.object({
12136
- kind: z48.string(),
12137
- candidateGrouping: z48.string().optional(),
12138
- selectedImageUrls: z48.array(z48.string()).optional(),
12139
- proposedProductNames: z48.array(z48.string()).optional(),
12261
+ pendingUserAction: z49.object({
12262
+ kind: z49.string(),
12263
+ candidateGrouping: z49.string().optional(),
12264
+ selectedImageUrls: z49.array(z49.string()).optional(),
12265
+ proposedProductNames: z49.array(z49.string()).optional(),
12140
12266
  // Adaptive reference questions are server-owned. Echo only the evidence
12141
12267
  // identity and the choices shown by the current snapshot; never accept a
12142
12268
  // client-supplied reference set as authorization.
12143
- options: z48.array(ProductReferenceUserChoiceEnum).max(4).optional(),
12144
- mode: z48.enum([
12269
+ options: z49.array(ProductReferenceUserChoiceEnum).max(4).optional(),
12270
+ mode: z49.enum([
12145
12271
  "question",
12146
12272
  "visual_recovery"
12147
12273
  ]).optional(),
12148
- decisionKey: z48.string().optional(),
12149
- questionOrdinal: z48.number().int().min(1).max(5).optional(),
12150
- questionCeiling: z48.union([
12151
- z48.literal(3),
12152
- z48.literal(5)
12274
+ decisionKey: z49.string().optional(),
12275
+ questionOrdinal: z49.number().int().min(1).max(5).optional(),
12276
+ questionCeiling: z49.union([
12277
+ z49.literal(3),
12278
+ z49.literal(5)
12153
12279
  ]).optional(),
12154
- referenceEvidenceVersion: z48.number().int().positive().optional(),
12155
- expectedEvidenceHash: z48.string().optional(),
12156
- question: z48.object({
12157
- prompt: z48.string().min(1).max(240),
12158
- helpText: z48.string().min(1).max(300).optional(),
12159
- options: z48.array(z48.object({
12280
+ referenceEvidenceVersion: z49.number().int().positive().optional(),
12281
+ expectedEvidenceHash: z49.string().optional(),
12282
+ question: z49.object({
12283
+ prompt: z49.string().min(1).max(240),
12284
+ helpText: z49.string().min(1).max(300).optional(),
12285
+ options: z49.array(z49.object({
12160
12286
  value: ProductReferenceUserChoiceEnum,
12161
- label: z48.string().min(1).max(120),
12162
- description: z48.string().min(1).max(240).optional()
12287
+ label: z49.string().min(1).max(120),
12288
+ description: z49.string().min(1).max(240).optional()
12163
12289
  })).min(2).max(4)
12164
12290
  }).optional(),
12165
12291
  scope: ProductReferenceScopeEnum.optional(),
12166
- scopeKey: z48.string().optional(),
12167
- scopeSnapshotId: z48.string().uuid().optional(),
12168
- scopeHash: z48.string().optional(),
12169
- baseReferenceSetHash: z48.string().optional(),
12170
- phase: z48.enum([
12292
+ scopeKey: z49.string().optional(),
12293
+ scopeSnapshotId: z49.string().uuid().optional(),
12294
+ scopeHash: z49.string().optional(),
12295
+ baseReferenceSetHash: z49.string().optional(),
12296
+ phase: z49.enum([
12171
12297
  "preparation",
12172
12298
  "final"
12173
12299
  ]).optional(),
12174
- selectedRefKeys: z48.array(z48.string().min(1).max(200)).optional(),
12175
- allowedDecisions: z48.array(ProductReferenceResolutionDecisionEnum).optional(),
12176
- customAngleDraft: z48.string().optional(),
12177
- painPointsDraft: z48.string().optional(),
12178
- benefitsDraft: z48.string().optional(),
12179
- featuresDraft: z48.array(z48.string()).optional(),
12300
+ selectedRefKeys: z49.array(z49.string().min(1).max(200)).optional(),
12301
+ allowedDecisions: z49.array(ProductReferenceResolutionDecisionEnum).optional(),
12302
+ customAngleDraft: z49.string().optional(),
12303
+ painPointsDraft: z49.string().optional(),
12304
+ benefitsDraft: z49.string().optional(),
12305
+ featuresDraft: z49.array(z49.string()).optional(),
12180
12306
  // Recommendation consumed only when the caller explicitly sends
12181
12307
  // gapDurationSeconds: 30 in the angle approval action.
12182
12308
  gapDurationChoice: GapDurationChoiceMirror.optional(),
@@ -12185,17 +12311,17 @@ var StatusForResolveSchema = z48.object({
12185
12311
  // keys. `actorId` (the saved custom actor the picker stored) was silently
12186
12312
  // dropped here, so the approval handler below could not echo it back on the
12187
12313
  // PATCH — the selection looked accepted and reached no render.
12188
- angles: z48.array(z48.object({
12189
- id: z48.string().uuid(),
12190
- content: z48.string(),
12191
- creativeDirection: z48.string(),
12192
- actor: z48.string(),
12193
- actorId: z48.string().nullable().optional()
12314
+ angles: z49.array(z49.object({
12315
+ id: z49.string().uuid(),
12316
+ content: z49.string(),
12317
+ creativeDirection: z49.string(),
12318
+ actor: z49.string(),
12319
+ actorId: z49.string().nullable().optional()
12194
12320
  }).passthrough()).optional(),
12195
- panels: z48.array(z48.object({
12196
- beatId: z48.string(),
12197
- voiceover: z48.string(),
12198
- visualDirection: z48.string()
12321
+ panels: z49.array(z49.object({
12322
+ beatId: z49.string(),
12323
+ voiceover: z49.string(),
12324
+ visualDirection: z49.string()
12199
12325
  }).passthrough()).optional()
12200
12326
  }).optional()
12201
12327
  }).passthrough();
@@ -12708,59 +12834,59 @@ __name(registerTaskTools, "registerTaskTools");
12708
12834
 
12709
12835
  // src/tools/creatives.ts
12710
12836
  import { randomUUID } from "crypto";
12711
- import { z as z49 } from "zod";
12837
+ import { z as z50 } from "zod";
12712
12838
  var CreativeRefs = {
12713
12839
  images: ImagesInput,
12714
12840
  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.'),
12715
12841
  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.'),
12716
- price: z49.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.'),
12717
- offer: z49.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.'),
12718
- compareAtPrice: z49.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
12719
- paymentMethods: z49.string().min(1).max(240).optional().describe('Opcional. M\xE9todos de pago a mostrar. Ej. "Tarjeta, PSE, Nequi, Contraentrega". Si se omite, la landing no muestra m\xE9todos de pago.'),
12720
- productContext: z49.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."),
12721
- productLabel: z49.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.'),
12722
- buyerPersona: z49.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.'),
12723
- isCombo: z49.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
12724
- competitorScanEnabled: z49.boolean().optional().describe("Opcional. Si true (default), el sistema analiza ads de competencia en Meta Ad Library y enriquece los \xE1ngulos generados con hooks y painPoints validados por el mercado (\u2248$0.20-0.48 extra por task \u2014 var\xEDa con cu\xE1ntas transcripciones de video se capturen). Si false, el pipeline genera \xE1ngulos sin esa se\xF1al \u2014 usa esto SOLO si el usuario ya tiene su propia investigaci\xF3n de mercado o quiere ahorrar costos en productos muy nicho sin presencia en Meta. Default true."),
12725
- brandId: z49.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."),
12726
- projectId: z49.string().uuid().optional().describe("Opcional. ID de un proyecto guiado de dropshipping activo del usuario. Enlaza esta generaci\xF3n con su progreso y recompensas."),
12727
- creativeDirection: z49.string().max(500).optional().describe('Opcional. Direcci\xF3n creativa en texto libre (colores, mood, estilo). M\xC1XIMA PRIORIDAD: anula marca, colores y estilo por defecto. Aplica SOLO a im\xE1genes y landing. Ej. im\xE1genes: "amarillo, azul y rojo, minimalista"; landing: "elegante, paleta fr\xEDa". Para video usa scriptNotes (ambiente/escenario). M\xE1x 500 caracteres.'),
12728
- headline: z49.string().max(120).optional().describe("Opcional. Titular EXACTO a renderizar en la imagen (o en la portada de la landing). Se imprime tal cual: la IA no lo reescribe, no lo acorta y no lo traduce. \xDAsalo cuando el copy es de marca y no es negociable. M\xE1x 120 caracteres. Si lo omites, la IA escribe el titular."),
12729
- subheadline: z49.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.")
12842
+ price: z50.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.'),
12843
+ offer: z50.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.'),
12844
+ compareAtPrice: z50.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
12845
+ paymentMethods: z50.string().min(1).max(240).optional().describe('Opcional. M\xE9todos de pago a mostrar. Ej. "Tarjeta, PSE, Nequi, Contraentrega". Si se omite, la landing no muestra m\xE9todos de pago.'),
12846
+ productContext: z50.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."),
12847
+ productLabel: z50.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.'),
12848
+ buyerPersona: z50.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.'),
12849
+ isCombo: z50.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
12850
+ competitorScanEnabled: z50.boolean().optional().describe("Opcional. Si true (default), el sistema analiza ads de competencia en Meta Ad Library y enriquece los \xE1ngulos generados con hooks y painPoints validados por el mercado (\u2248$0.20-0.48 extra por task \u2014 var\xEDa con cu\xE1ntas transcripciones de video se capturen). Si false, el pipeline genera \xE1ngulos sin esa se\xF1al \u2014 usa esto SOLO si el usuario ya tiene su propia investigaci\xF3n de mercado o quiere ahorrar costos en productos muy nicho sin presencia en Meta. Default true."),
12851
+ brandId: z50.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."),
12852
+ projectId: z50.string().uuid().optional().describe("Opcional. ID de un proyecto guiado de dropshipping activo del usuario. Enlaza esta generaci\xF3n con su progreso y recompensas."),
12853
+ creativeDirection: z50.string().max(500).optional().describe('Opcional. Direcci\xF3n creativa en texto libre (colores, mood, estilo). M\xC1XIMA PRIORIDAD: anula marca, colores y estilo por defecto. Aplica SOLO a im\xE1genes y landing. Ej. im\xE1genes: "amarillo, azul y rojo, minimalista"; landing: "elegante, paleta fr\xEDa". Para video usa scriptNotes (ambiente/escenario). M\xE1x 500 caracteres.'),
12854
+ headline: z50.string().max(120).optional().describe("Opcional. Titular EXACTO a renderizar en la imagen (o en la portada de la landing). Se imprime tal cual: la IA no lo reescribe, no lo acorta y no lo traduce. \xDAsalo cuando el copy es de marca y no es negociable. M\xE1x 120 caracteres. Si lo omites, la IA escribe el titular."),
12855
+ subheadline: z50.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.")
12730
12856
  };
12731
- var VideoInput = z49.object({
12857
+ var VideoInput = z50.object({
12732
12858
  images: CreativeRefs.images,
12733
- title: z49.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
12734
- primaryAngle: z49.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".'),
12859
+ title: z50.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
12860
+ primaryAngle: z50.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".'),
12735
12861
  language: CreativeRefs.language,
12736
12862
  country: CreativeRefs.country,
12737
- aspectRatio: z49.enum([
12863
+ aspectRatio: z50.enum([
12738
12864
  "9:16",
12739
12865
  "16:9",
12740
12866
  "Auto"
12741
12867
  ]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
12742
- durationSeconds: z49.union([
12743
- z49.literal(15),
12744
- z49.literal(30)
12868
+ durationSeconds: z50.union([
12869
+ z50.literal(15),
12870
+ z50.literal(30)
12745
12871
  ]).default(15).describe("Opcional. Duraci\xF3n objetivo: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
12746
12872
  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). 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" (una regla visual experimental original), "pixar_problem" (problema animado 3D), "pixar_sassy" (producto que habla).'),
12747
12873
  videoTier: VideoTierEnum.optional().describe('Opcional. Estilo del video. "basic" = "Realista"; para durationSeconds=30 el sistema selecciona internamente Multiescena. No se expone el tier interno directamente.'),
12748
12874
  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).'),
12749
- features: z49.array(z49.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
12875
+ features: z50.array(z50.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
12750
12876
  price: CreativeRefs.price,
12751
12877
  offer: CreativeRefs.offer,
12752
12878
  productContext: CreativeRefs.productContext,
12753
12879
  productLabel: CreativeRefs.productLabel,
12754
- cta: z49.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.'),
12755
- scriptNotes: z49.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 \u2014 para editar el guion palabra-por-palabra, pasa `pauseForVideoScriptReview: true` y usa get_video_script / approve_video_script tras la pausa.'),
12756
- pauseForVideoScriptReview: z49.boolean().optional().describe("Opcional. Si true, la tarea pausa despu\xE9s de generar el guion y antes de renderizar. \xDAsalo cuando el usuario quiera editar el guion antes de gastar cr\xE9ditos en el video. Tras la pausa: get_video_script para leerlo, approve_video_script para aprobar (con o sin ediciones). Default false."),
12757
- pauseForAngleReview: z49.boolean().optional().describe("Opcional. Si true, pausa despu\xE9s de generar el \xE1ngulo para que el usuario lo confirme o edite antes del render. Default false."),
12758
- aiDecidesAll: z49.boolean().optional().describe("Opcional. Si true, ProductMaker decide TODO y no vuelve a interrumpir al usuario: resuelve solo las confirmaciones de referencias del producto y no abre gates de aprobaci\xF3n. Act\xEDvalo \xFAnicamente cuando el usuario pida expl\xEDcitamente que la IA decida todo o que no le pregunten m\xE1s. Default false."),
12880
+ cta: z50.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.'),
12881
+ scriptNotes: z50.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 \u2014 para editar el guion palabra-por-palabra, pasa `pauseForVideoScriptReview: true` y usa get_video_script / approve_video_script tras la pausa.'),
12882
+ pauseForVideoScriptReview: z50.boolean().optional().describe("Opcional. Si true, la tarea pausa despu\xE9s de generar el guion y antes de renderizar. \xDAsalo cuando el usuario quiera editar el guion antes de gastar cr\xE9ditos en el video. Tras la pausa: get_video_script para leerlo, approve_video_script para aprobar (con o sin ediciones). Default false."),
12883
+ pauseForAngleReview: z50.boolean().optional().describe("Opcional. Si true, pausa despu\xE9s de generar el \xE1ngulo para que el usuario lo confirme o edite antes del render. Default false."),
12884
+ aiDecidesAll: z50.boolean().optional().describe("Opcional. Si true, ProductMaker decide TODO y no vuelve a interrumpir al usuario: resuelve solo las confirmaciones de referencias del producto y no abre gates de aprobaci\xF3n. Act\xEDvalo \xFAnicamente cuando el usuario pida expl\xEDcitamente que la IA decida todo o que no le pregunten m\xE1s. Default false."),
12759
12885
  competitorScanEnabled: CreativeRefs.competitorScanEnabled,
12760
12886
  brandId: CreativeRefs.brandId,
12761
12887
  projectId: CreativeRefs.projectId
12762
12888
  }).strict();
12763
- var FreeVideoQualityEnum = z49.enum([
12889
+ var FreeVideoQualityEnum = z50.enum([
12764
12890
  "economical",
12765
12891
  "high_detail"
12766
12892
  ]);
@@ -12782,38 +12908,38 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
12782
12908
  15
12783
12909
  ]
12784
12910
  };
12785
- var FreeVideoInput = z49.object({
12911
+ var FreeVideoInput = z50.object({
12786
12912
  images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Si el usuario adjunt\xF3 o mencion\xF3 fotos locales y no existe un assetId reutilizable, llama primero request_media_upload con mediaKind=image y usa los assetId devueltos; no pidas rutas ni URLs. Om\xEDtelo para generar desde texto puro."),
12787
- rawPrompt: z49.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."),
12913
+ rawPrompt: z50.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."),
12788
12914
  quality: FreeVideoQualityEnum.describe('Calidad del video: "economical" = Econ\xF3mico o "high_detail" = Alto detalle.'),
12789
- durationSeconds: z49.number().int().min(1).max(15).describe("Duraci\xF3n exacta. Econ\xF3mico permite 6, 8, 10 o 15s; Alto detalle permite 4, 8, 12 o 15s."),
12915
+ durationSeconds: z50.number().int().min(1).max(15).describe("Duraci\xF3n exacta. Econ\xF3mico permite 6, 8, 10 o 15s; Alto detalle permite 4, 8, 12 o 15s."),
12790
12916
  videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
12791
- generateAiMusic: z49.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
12792
- addSubtitles: z49.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
12793
- idempotencyKey: z49.string().uuid().optional().describe("Opcional. UUID para reintentar exactamente esta misma solicitud sin crear ni cobrar otro video. Reutiliza el mismo valor si el cliente no recibi\xF3 la respuesta.")
12917
+ generateAiMusic: z50.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
12918
+ addSubtitles: z50.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
12919
+ idempotencyKey: z50.string().uuid().optional().describe("Opcional. UUID para reintentar exactamente esta misma solicitud sin crear ni cobrar otro video. Reutiliza el mismo valor si el cliente no recibi\xF3 la respuesta.")
12794
12920
  }).strict();
12795
12921
  var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
12796
12922
  var archetypeList = ImageCreativeArchetypeEnum.options.join(" | ");
12797
12923
  var visualTreatmentList = ImageCreativeVisualTreatmentEnum.options.join(" | ");
12798
12924
  var aspectRatioList = ImageCreativeAspectRatioEnum.options.join(" | ");
12799
- var ImageInput = z49.object({
12925
+ var ImageInput = z50.object({
12800
12926
  images: CreativeRefs.images,
12801
- productTitle: z49.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
12802
- primaryAngle: z49.string().min(1).describe('\xC1ngulo de venta principal. Ej. "Reduce arrugas en 14 d\xEDas".'),
12927
+ productTitle: z50.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
12928
+ primaryAngle: z50.string().min(1).describe('\xC1ngulo de venta principal. Ej. "Reduce arrugas en 14 d\xEDas".'),
12803
12929
  buyerPersona: CreativeRefs.buyerPersona,
12804
12930
  language: CreativeRefs.language,
12805
12931
  country: CreativeRefs.country,
12806
- nVariants: z49.number().int().min(1).max(6).optional().describe("Opcional. N\xFAmero de variantes a generar (1-6). Default 3."),
12807
- imageModel: z49.string().optional().describe('Opcional. Modelo de imagen. Ej. "gpt-image-2", "nano-banana-2". Om\xEDtelo para usar el default optimizado por costo/calidad.'),
12932
+ nVariants: z50.number().int().min(1).max(6).optional().describe("Opcional. N\xFAmero de variantes a generar (1-6). Default 3."),
12933
+ imageModel: z50.string().optional().describe('Opcional. Modelo de imagen. Ej. "gpt-image-2", "nano-banana-2". Om\xEDtelo para usar el default optimizado por costo/calidad.'),
12808
12934
  imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
12809
12935
  creativeArchetype: ImageCreativeArchetypeEnum.optional().describe(`Opcional. Arquetipo CRO de la composici\xF3n. Valores: ${archetypeList}. Si se omite, la IA escoge seg\xFAn \xE1ngulo+oferta (ej. "offer_value_prop" cuando hay descuento, "social_proof_trust" cuando el \xE1ngulo es testimonial).`),
12810
12936
  visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe(`Opcional. Tratamiento gr\xE1fico. Valores: ${visualTreatmentList} ("performance_product_ad" = dealer-style alto CTR para Meta/TikTok ads; "premium_dtc_carousel" = fotograf\xEDa limpia estilo Allbirds/Glossier). Si se omite, la IA escoge.`),
12811
- styleMix: z49.boolean().optional().describe("Opcional. Si true, las N variantes mezclan distintos imageStyle para A/B test. Si false/omitido, todas comparten estilo. Default false."),
12937
+ styleMix: z50.boolean().optional().describe("Opcional. Si true, las N variantes mezclan distintos imageStyle para A/B test. Si false/omitido, todas comparten estilo. Default false."),
12812
12938
  aspectRatio: ImageCreativeAspectRatioEnum.optional().describe(`Opcional. Relaci\xF3n de aspecto. Valores: ${aspectRatioList}. Default "4:5" (vertical Instagram feed).`),
12813
- generateAdCopy: z49.boolean().optional().describe("Opcional. Si true, tambi\xE9n genera headline/body/CTA para el ad. Default false."),
12814
- pauseForAngleReview: z49.boolean().optional().describe("Opcional. Si true, pausa despu\xE9s de generar el \xE1ngulo y antes de las im\xE1genes para que el usuario edite v\xEDa edit_task_draft. Default false."),
12815
- features: z49.array(z49.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
12816
- brandColors: z49.array(z49.string()).optional().describe('Opcional. Paleta de marca en hex. Ej. ["#FF6B35", "#004E89"]. Si se omite, la IA elige seg\xFAn el producto.'),
12939
+ generateAdCopy: z50.boolean().optional().describe("Opcional. Si true, tambi\xE9n genera headline/body/CTA para el ad. Default false."),
12940
+ pauseForAngleReview: z50.boolean().optional().describe("Opcional. Si true, pausa despu\xE9s de generar el \xE1ngulo y antes de las im\xE1genes para que el usuario edite v\xEDa edit_task_draft. Default false."),
12941
+ features: z50.array(z50.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
12942
+ brandColors: z50.array(z50.string()).optional().describe('Opcional. Paleta de marca en hex. Ej. ["#FF6B35", "#004E89"]. Si se omite, la IA elige seg\xFAn el producto.'),
12817
12943
  price: CreativeRefs.price,
12818
12944
  compareAtPrice: CreativeRefs.compareAtPrice,
12819
12945
  offer: CreativeRefs.offer,
@@ -12827,17 +12953,17 @@ var ImageInput = z49.object({
12827
12953
  headline: CreativeRefs.headline,
12828
12954
  subheadline: CreativeRefs.subheadline
12829
12955
  });
12830
- var EditImageCreativeInput = z49.object({
12831
- taskId: z49.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
12832
- variantIndex: z49.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
12833
- instruction: z49.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".')
12956
+ var EditImageCreativeInput = z50.object({
12957
+ taskId: z50.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
12958
+ variantIndex: z50.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
12959
+ instruction: z50.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".')
12834
12960
  });
12835
- var LandingInput = z49.object({
12836
- aiDecidesAll: z49.boolean().optional().describe("Opcional. Si true, ProductMaker decide TODO y no vuelve a interrumpir al usuario: resuelve solo las confirmaciones de referencias del producto y no abre gates de aprobaci\xF3n. Act\xEDvalo \xFAnicamente cuando el usuario pida expl\xEDcitamente que la IA decida todo o que no le pregunten m\xE1s. Default false."),
12961
+ var LandingInput = z50.object({
12962
+ aiDecidesAll: z50.boolean().optional().describe("Opcional. Si true, ProductMaker decide TODO y no vuelve a interrumpir al usuario: resuelve solo las confirmaciones de referencias del producto y no abre gates de aprobaci\xF3n. Act\xEDvalo \xFAnicamente cuando el usuario pida expl\xEDcitamente que la IA decida todo o que no le pregunten m\xE1s. Default false."),
12837
12963
  images: CreativeRefs.images,
12838
12964
  language: CreativeRefs.language,
12839
12965
  country: CreativeRefs.country,
12840
- salesAngle: z49.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.'),
12966
+ salesAngle: z50.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.'),
12841
12967
  buyerPersona: CreativeRefs.buyerPersona,
12842
12968
  price: CreativeRefs.price,
12843
12969
  compareAtPrice: CreativeRefs.compareAtPrice,
@@ -12852,6 +12978,7 @@ var LandingInput = z49.object({
12852
12978
  creativeDirection: CreativeRefs.creativeDirection,
12853
12979
  landingStrategy: LandingStrategyEnum.default("classic").describe('Opcional. Estructura de la landing cl\xE1sica: "classic" (estructura original probada y recomendada; default del primer rollout), "auto" (la IA decide; experimental), "pain_solution" (problema\u2192soluci\xF3n), "social_proof" (Landing Viral: UGC, WhatsApp, Instagram y evidencia social), "benefits_clarity" (beneficios claros), "offer_value" (promoci\xF3n/valor) o "lifestyle_identity" (estilo de vida). Default "classic".'),
12854
12980
  landingImageFormat: LandingImageFormatEnum.default("9:16").describe('Opcional. Formato/relaci\xF3n de aspecto de las im\xE1genes de la landing cl\xE1sica: "9:16" (vertical, por defecto), "4:5" (vertical compacto para feed) o "1:1" (cuadrado). Default "9:16".'),
12981
+ pauseForAngleReview: z50.boolean().optional().describe("Opcional. Si true, pausa despu\xE9s de generar el \xE1ngulo para que el usuario lo confirme o edite antes de la creaci\xF3n de la landing. Default false."),
12855
12982
  headline: CreativeRefs.headline,
12856
12983
  subheadline: CreativeRefs.subheadline
12857
12984
  });
@@ -12962,8 +13089,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
12962
13089
  __name(registerCreativeTools, "registerCreativeTools");
12963
13090
 
12964
13091
  // src/tools/creative-variants.ts
12965
- import { z as z50 } from "zod";
12966
- var LandingSectionKeyEnum = z50.enum([
13092
+ import { z as z51 } from "zod";
13093
+ var LandingSectionKeyEnum = z51.enum([
12967
13094
  "problem_hook",
12968
13095
  "problem_cost",
12969
13096
  "solution_mechanism",
@@ -13003,24 +13130,24 @@ var LandingSectionKeyEnum = z50.enum([
13003
13130
  "lifestyle_fit",
13004
13131
  "join_lifestyle"
13005
13132
  ]);
13006
- var CreativeVariantKindEnum = z50.enum([
13133
+ var CreativeVariantKindEnum = z51.enum([
13007
13134
  "video",
13008
13135
  "image",
13009
13136
  "landing"
13010
13137
  ]);
13011
- var EstimateCreativeVariantInputBase = z50.object({
13012
- sourceTaskId: z50.string().uuid().describe("ID de la tarea original completada."),
13138
+ var EstimateCreativeVariantInputBase = z51.object({
13139
+ sourceTaskId: z51.string().uuid().describe("ID de la tarea original completada."),
13013
13140
  kind: CreativeVariantKindEnum,
13014
13141
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
13015
13142
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
13016
- nVariants: z50.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
13143
+ nVariants: z51.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
13017
13144
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
13018
- instructions: z50.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.")
13145
+ instructions: z51.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.")
13019
13146
  }).strict();
13020
13147
  var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
13021
13148
  if (input.kind === "video" && input.nVariants !== void 0) {
13022
13149
  ctx.addIssue({
13023
- code: z50.ZodIssueCode.custom,
13150
+ code: z51.ZodIssueCode.custom,
13024
13151
  path: [
13025
13152
  "nVariants"
13026
13153
  ],
@@ -13030,7 +13157,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
13030
13157
  if (input.kind !== "video") {
13031
13158
  if (input.videoPreset !== void 0) {
13032
13159
  ctx.addIssue({
13033
- code: z50.ZodIssueCode.custom,
13160
+ code: z51.ZodIssueCode.custom,
13034
13161
  path: [
13035
13162
  "videoPreset"
13036
13163
  ],
@@ -13039,7 +13166,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
13039
13166
  }
13040
13167
  if (input.videoResolution !== void 0) {
13041
13168
  ctx.addIssue({
13042
- code: z50.ZodIssueCode.custom,
13169
+ code: z51.ZodIssueCode.custom,
13043
13170
  path: [
13044
13171
  "videoResolution"
13045
13172
  ],
@@ -13049,7 +13176,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
13049
13176
  }
13050
13177
  if (input.kind !== "image" && input.nVariants !== void 0) {
13051
13178
  ctx.addIssue({
13052
- code: z50.ZodIssueCode.custom,
13179
+ code: z51.ZodIssueCode.custom,
13053
13180
  path: [
13054
13181
  "nVariants"
13055
13182
  ],
@@ -13059,7 +13186,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
13059
13186
  if (input.kind !== "landing") {
13060
13187
  if (input.sectionKey !== void 0) {
13061
13188
  ctx.addIssue({
13062
- code: z50.ZodIssueCode.custom,
13189
+ code: z51.ZodIssueCode.custom,
13063
13190
  path: [
13064
13191
  "sectionKey"
13065
13192
  ],
@@ -13068,7 +13195,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
13068
13195
  }
13069
13196
  if (input.instructions !== void 0) {
13070
13197
  ctx.addIssue({
13071
- code: z50.ZodIssueCode.custom,
13198
+ code: z51.ZodIssueCode.custom,
13072
13199
  path: [
13073
13200
  "instructions"
13074
13201
  ],
@@ -13077,31 +13204,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
13077
13204
  }
13078
13205
  }
13079
13206
  });
13080
- var CreateCreativeVariantInputBase = z50.object({
13081
- sourceTaskId: z50.string().uuid().describe("ID de la tarea original completada."),
13207
+ var CreateCreativeVariantInputBase = z51.object({
13208
+ sourceTaskId: z51.string().uuid().describe("ID de la tarea original completada."),
13082
13209
  kind: CreativeVariantKindEnum,
13083
- confirm: z50.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
13084
- clientRequestId: z50.string().uuid().describe("UUID estable y obligatorio para esta intenci\xF3n. Reutil\xEDzalo ante timeouts o transporte ambiguo. Si la API devuelve status=error, una nueva generaci\xF3n exige otra confirmaci\xF3n y un UUID nuevo."),
13085
- angle: z50.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
13086
- buyerPersona: z50.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
13087
- scriptNotes: z50.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
13088
- creativeDirection: z50.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
13210
+ confirm: z51.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
13211
+ clientRequestId: z51.string().uuid().describe("UUID estable y obligatorio para esta intenci\xF3n. Reutil\xEDzalo ante timeouts o transporte ambiguo. Si la API devuelve status=error, una nueva generaci\xF3n exige otra confirmaci\xF3n y un UUID nuevo."),
13212
+ angle: z51.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
13213
+ buyerPersona: z51.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
13214
+ scriptNotes: z51.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
13215
+ creativeDirection: z51.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
13089
13216
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
13090
13217
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
13091
- generateAiMusic: z50.boolean().optional().describe("Opcional para video."),
13092
- nVariants: z50.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
13218
+ generateAiMusic: z51.boolean().optional().describe("Opcional para video."),
13219
+ nVariants: z51.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
13093
13220
  imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
13094
13221
  creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
13095
13222
  visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
13096
13223
  aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
13097
- styleMix: z50.boolean().optional().describe("Opcional para imagen."),
13224
+ styleMix: z51.boolean().optional().describe("Opcional para imagen."),
13098
13225
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
13099
- instructions: z50.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.")
13226
+ instructions: z51.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.")
13100
13227
  }).strict();
13101
13228
  var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
13102
13229
  if ((input.kind === "video" || input.kind === "image") && !input.angle) {
13103
13230
  ctx.addIssue({
13104
- code: z50.ZodIssueCode.custom,
13231
+ code: z51.ZodIssueCode.custom,
13105
13232
  path: [
13106
13233
  "angle"
13107
13234
  ],
@@ -13110,7 +13237,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
13110
13237
  }
13111
13238
  if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
13112
13239
  ctx.addIssue({
13113
- code: z50.ZodIssueCode.custom,
13240
+ code: z51.ZodIssueCode.custom,
13114
13241
  path: [
13115
13242
  "instructions"
13116
13243
  ],
@@ -13156,7 +13283,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
13156
13283
  for (const field of fieldsByKind[input.kind]) {
13157
13284
  if (input[field] !== void 0) {
13158
13285
  ctx.addIssue({
13159
- code: z50.ZodIssueCode.custom,
13286
+ code: z51.ZodIssueCode.custom,
13160
13287
  path: [
13161
13288
  field
13162
13289
  ],
@@ -13273,27 +13400,27 @@ function registerCreativeVariantTools(server, api) {
13273
13400
  __name(registerCreativeVariantTools, "registerCreativeVariantTools");
13274
13401
 
13275
13402
  // src/tools/script-review.ts
13276
- import { z as z51 } from "zod";
13277
- var GetVideoScriptInput = z51.object({
13278
- taskId: z51.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
13279
- angleKey: z51.string().min(1).optional().describe('Clave del \xE1ngulo cuyo guion se quiere leer (formato "angle_0", "angle_1", ...). REQUERIDO para tareas multi-angle: si se omite, el backend resuelve a "angle_0" LITERAL (no "el primer pendiente"), as\xED que en multi-angle donde angle_0 ya est\xE9 aprobado/saltado obtendr\xEDas status="approved" y nunca alcanzar\xEDas el \xE1ngulo realmente pendiente. Para single-angle puede omitirse.')
13403
+ import { z as z52 } from "zod";
13404
+ var GetVideoScriptInput = z52.object({
13405
+ taskId: z52.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
13406
+ angleKey: z52.string().min(1).optional().describe('Clave del \xE1ngulo cuyo guion se quiere leer (formato "angle_0", "angle_1", ...). REQUERIDO para tareas multi-angle: si se omite, el backend resuelve a "angle_0" LITERAL (no "el primer pendiente"), as\xED que en multi-angle donde angle_0 ya est\xE9 aprobado/saltado obtendr\xEDas status="approved" y nunca alcanzar\xEDas el \xE1ngulo realmente pendiente. Para single-angle puede omitirse.')
13280
13407
  }).strict();
13281
13408
  var VIDEO_SCRIPT_APPROVAL_MAX_SCENES2 = 50;
13282
13409
  var VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2 = 2e3;
13283
- var ApproveSceneEdit = z51.object({
13284
- index: z51.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
13285
- dialogue: z51.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
13410
+ var ApproveSceneEdit = z52.object({
13411
+ index: z52.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
13412
+ dialogue: z52.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
13286
13413
  message: "dialogue no puede ser s\xF3lo espacios"
13287
13414
  }).describe("Di\xE1logo final de la escena. NO puede estar vac\xEDo ni ser s\xF3lo espacios. Puede ser el original sin cambios o la edici\xF3n del usuario.")
13288
13415
  }).strict();
13289
- var ApproveVideoScriptInput = z51.object({
13290
- taskId: z51.string().min(1).describe("ID de la tarea."),
13291
- angleKey: z51.string().trim().min(1).max(120).optional().describe('Mismo angleKey usado en get_video_script. REQUERIDO en multi-angle (si se omite el backend resuelve a "angle_0" literal). En single-angle puede omitirse.'),
13292
- scenes: z51.array(ApproveSceneEdit).min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_SCENES2).describe("Escenas con los di\xE1logos finales. El backend mergea por `index` \u2014 las escenas NO incluidas conservan el di\xE1logo original. Debe haber entre 1 y 50 entradas. Para cada entrada que mandes con un dialogue distinto del original, el backend valida minWords \u2264 words \u2264 maxWords y rechaza con 400 si te sales del rango.")
13416
+ var ApproveVideoScriptInput = z52.object({
13417
+ taskId: z52.string().min(1).describe("ID de la tarea."),
13418
+ angleKey: z52.string().trim().min(1).max(120).optional().describe('Mismo angleKey usado en get_video_script. REQUERIDO en multi-angle (si se omite el backend resuelve a "angle_0" literal). En single-angle puede omitirse.'),
13419
+ scenes: z52.array(ApproveSceneEdit).min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_SCENES2).describe("Escenas con los di\xE1logos finales. El backend mergea por `index` \u2014 las escenas NO incluidas conservan el di\xE1logo original. Debe haber entre 1 y 50 entradas. Para cada entrada que mandes con un dialogue distinto del original, el backend valida minWords \u2264 words \u2264 maxWords y rechaza con 400 si te sales del rango.")
13293
13420
  }).strict();
13294
- var RegenerateVideoScriptInput = z51.object({
13295
- taskId: z51.string().min(1).describe("ID de la tarea."),
13296
- angleKey: z51.string().min(1).describe('Clave del \xE1ngulo a regenerar. Single-angle: pasa "angle_0". Multi-angle: el mismo que devuelve get_video_script. NO se puede omitir \u2014 el backend lo exige siempre.'),
13421
+ var RegenerateVideoScriptInput = z52.object({
13422
+ taskId: z52.string().min(1).describe("ID de la tarea."),
13423
+ angleKey: z52.string().min(1).describe('Clave del \xE1ngulo a regenerar. Single-angle: pasa "angle_0". Multi-angle: el mismo que devuelve get_video_script. NO se puede omitir \u2014 el backend lo exige siempre.'),
13297
13424
  narrativeStyle: NarrativeStyleEnum.describe('Narrativa para el nuevo guion. Incluye valores hist\xF3ricos porque esta herramienta tambi\xE9n regenera tareas antiguas. REQUERIDO \u2014 el backend NO acepta "mantener la actual"; siempre tienes que elegir una. Si el usuario quiere re-rolear con la misma narrativa, pasa la que ya tiene el \xE1ngulo (la ves en get_video_script o en get_task_status).')
13298
13425
  }).strict();
13299
13426
  function registerScriptReviewTools(server, api) {
@@ -13344,9 +13471,9 @@ function registerScriptReviewTools(server, api) {
13344
13471
  __name(registerScriptReviewTools, "registerScriptReviewTools");
13345
13472
 
13346
13473
  // src/tools/connections.ts
13347
- import { z as z52 } from "zod";
13474
+ import { z as z53 } from "zod";
13348
13475
  function registerConnectionTools(server, api) {
13349
- server.tool("list_shopify_shops", "Lista las tiendas Shopify conectadas por este usuario. Si la lista est\xE1 vac\xEDa, dile al usuario que conecte una tienda en productmaker.app/integrations antes de intentar publicar.", z52.object({}).shape, READS_INTERNAL, async () => {
13476
+ server.tool("list_shopify_shops", "Lista las tiendas Shopify conectadas por este usuario. Si la lista est\xE1 vac\xEDa, dile al usuario que conecte una tienda en productmaker.app/integrations antes de intentar publicar.", z53.object({}).shape, READS_INTERNAL, async () => {
13350
13477
  try {
13351
13478
  const r = await api.getJson("/v1/shopify/shops");
13352
13479
  return asText(r);
@@ -13354,10 +13481,10 @@ function registerConnectionTools(server, api) {
13354
13481
  throw translateError(e);
13355
13482
  }
13356
13483
  });
13357
- server.tool("list_shopify_products", 'Busca productos en una tienda Shopify conectada para elegir el target de una republicaci\xF3n. 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.', z52.object({
13358
- shopDomain: z52.string().min(3).max(120),
13359
- query: z52.string().trim().max(120).optional(),
13360
- taskId: z52.string().uuid().optional()
13484
+ server.tool("list_shopify_products", 'Busca productos en una tienda Shopify conectada para elegir el target de una republicaci\xF3n. 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.', z53.object({
13485
+ shopDomain: z53.string().min(3).max(120),
13486
+ query: z53.string().trim().max(120).optional(),
13487
+ taskId: z53.string().uuid().optional()
13361
13488
  }).shape, READS_EXTERNAL, async ({ shopDomain, query, taskId }) => {
13362
13489
  try {
13363
13490
  const params = new URLSearchParams({
@@ -13371,7 +13498,7 @@ function registerConnectionTools(server, api) {
13371
13498
  throw translateError(e);
13372
13499
  }
13373
13500
  });
13374
- server.tool("list_meta_ad_accounts", "Lista las cuentas publicitarias de Meta conectadas. 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.", z52.object({}).shape, READS_EXTERNAL, async () => {
13501
+ server.tool("list_meta_ad_accounts", "Lista las cuentas publicitarias de Meta conectadas. 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.", z53.object({}).shape, READS_EXTERNAL, async () => {
13375
13502
  try {
13376
13503
  const r = await api.getJson("/v1/facebook/ad-accounts");
13377
13504
  return asText(r);
@@ -13381,7 +13508,7 @@ function registerConnectionTools(server, api) {
13381
13508
  });
13382
13509
  server.registerTool("list_meta_destinations", {
13383
13510
  description: "Lista los destinos de publicaci\xF3n de Meta del usuario: Business portfolios, cuentas publicitarias dentro de cada portfolio y Facebook Pages disponibles. 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.",
13384
- inputSchema: z52.object({}).shape,
13511
+ inputSchema: z53.object({}).shape,
13385
13512
  annotations: READS_EXTERNAL,
13386
13513
  _meta: {
13387
13514
  "openai/widgetAccessible": true
@@ -13394,7 +13521,7 @@ function registerConnectionTools(server, api) {
13394
13521
  throw translateError(e);
13395
13522
  }
13396
13523
  });
13397
- server.tool("list_tiktok_advertisers", "Lista las cuentas de TikTok Ads conectadas. Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.", z52.object({}).shape, READS_EXTERNAL, async () => {
13524
+ server.tool("list_tiktok_advertisers", "Lista las cuentas de TikTok Ads conectadas. Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.", z53.object({}).shape, READS_EXTERNAL, async () => {
13398
13525
  try {
13399
13526
  const r = await api.getJson("/v1/tiktok/advertisers");
13400
13527
  return asText(r);
@@ -13406,9 +13533,9 @@ function registerConnectionTools(server, api) {
13406
13533
  __name(registerConnectionTools, "registerConnectionTools");
13407
13534
 
13408
13535
  // src/tools/actors.ts
13409
- import { z as z53 } from "zod";
13536
+ import { z as z54 } from "zod";
13410
13537
  function registerActorTools(server, api) {
13411
- server.tool("list_actors", "Lista los personajes guardados del usuario (personas creadas con IA que pueden protagonizar los videos e im\xE1genes). Devuelve id, nombre, descripci\xF3n, g\xE9nero y voz. Usa el `id` como `actorId` al crear o editar una tarea. Solo aparecen los personajes listos para usar; si la lista est\xE1 vac\xEDa, dile al usuario que cree uno en productmaker.app antes de intentar asignarlo. No modifica nada.", z53.object({}).shape, READS_INTERNAL, async () => {
13538
+ server.tool("list_actors", "Lista los personajes guardados del usuario (personas creadas con IA que pueden protagonizar los videos e im\xE1genes). Devuelve id, nombre, descripci\xF3n, g\xE9nero y voz. Usa el `id` como `actorId` al crear o editar una tarea. Solo aparecen los personajes listos para usar; si la lista est\xE1 vac\xEDa, dile al usuario que cree uno en productmaker.app antes de intentar asignarlo. No modifica nada.", z54.object({}).shape, READS_INTERNAL, async () => {
13412
13539
  try {
13413
13540
  const rows = await api.getJson("/v1/actors");
13414
13541
  const actors = (Array.isArray(rows) ? rows : []).filter((actor) => actor.status === "ready").map(({ id, name, description, gender, voiceId }) => ({
@@ -13429,39 +13556,39 @@ function registerActorTools(server, api) {
13429
13556
  __name(registerActorTools, "registerActorTools");
13430
13557
 
13431
13558
  // src/tools/publish.ts
13432
- import { z as z54 } from "zod";
13433
- var ShopifyInput = z54.object({
13434
- taskId: z54.string().min(1),
13435
- shopDomain: z54.string().min(1),
13559
+ import { z as z55 } from "zod";
13560
+ var ShopifyInput = z55.object({
13561
+ taskId: z55.string().min(1),
13562
+ shopDomain: z55.string().min(1),
13436
13563
  /** Override: number of landing images to include. Default = ALL images the
13437
13564
  * task generated (the MCP fetches /v1/results first to count). Bounded
13438
13565
  * generously here; the backend validates each index against
13439
13566
  * landing.images.length and rejects out-of-range. */
13440
- numLandingImages: z54.number().int().min(1).max(20).optional(),
13441
- variantIndex: z54.number().int().min(0).optional(),
13567
+ numLandingImages: z55.number().int().min(1).max(20).optional(),
13568
+ variantIndex: z55.number().int().min(0).optional(),
13442
13569
  /** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
13443
13570
  * When true, the landing renders variant-picker pills; when false, it ships
13444
13571
  * a single-option product page. Defaults to false. */
13445
- showVariantPicker: z54.boolean().optional(),
13572
+ showVariantPicker: z55.boolean().optional(),
13446
13573
  /** Default `auto` updates the product previously published for this task and
13447
13574
  * shop. Use `existing` with targetProductId to choose another product, or
13448
13575
  * `new` only when the user explicitly wants a duplicate/new listing. */
13449
- publicationMode: z54.enum([
13576
+ publicationMode: z55.enum([
13450
13577
  "auto",
13451
13578
  "existing",
13452
13579
  "new"
13453
13580
  ]).optional(),
13454
13581
  /** Shopify product GID, numeric id, or admin product URL. Required when
13455
13582
  * publicationMode is `existing`. */
13456
- targetProductId: z54.string().trim().min(1).max(300).optional(),
13583
+ targetProductId: z55.string().trim().min(1).max(300).optional(),
13457
13584
  /** Add an announcement bar text above add-to-cart (optional). */
13458
- announcementBarEnabled: z54.boolean().optional(),
13459
- announcementBarText: z54.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional()
13585
+ announcementBarEnabled: z55.boolean().optional(),
13586
+ announcementBarText: z55.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional()
13460
13587
  });
13461
13588
  var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
13462
13589
  if (value.announcementBarEnabled && !value.announcementBarText) {
13463
13590
  ctx.addIssue({
13464
- code: z54.ZodIssueCode.custom,
13591
+ code: z55.ZodIssueCode.custom,
13465
13592
  path: [
13466
13593
  "announcementBarText"
13467
13594
  ],
@@ -13470,7 +13597,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
13470
13597
  }
13471
13598
  if (!value.announcementBarEnabled && value.announcementBarText) {
13472
13599
  ctx.addIssue({
13473
- code: z54.ZodIssueCode.custom,
13600
+ code: z55.ZodIssueCode.custom,
13474
13601
  path: [
13475
13602
  "announcementBarText"
13476
13603
  ],
@@ -13484,90 +13611,90 @@ function parseShopifyInput(rawInput) {
13484
13611
  return parsed.data;
13485
13612
  }
13486
13613
  __name(parseShopifyInput, "parseShopifyInput");
13487
- var McpCampaignConfig = z54.object({
13614
+ var McpCampaignConfig = z55.object({
13488
13615
  /** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
13489
13616
  * converts to the account currency server-side. Do NOT pre-convert: on a COP
13490
13617
  * account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
13491
- dailyBudgetUsd: z54.number().positive().optional(),
13618
+ dailyBudgetUsd: z55.number().positive().optional(),
13492
13619
  /** ISO-3166-1 alpha-2 country codes. Meta accepts max 1 (single-country
13493
13620
  * ad set). TikTok takes only the first entry. */
13494
- targetCountries: z54.array(z54.string().length(2)).max(1).optional(),
13495
- campaignName: z54.string().trim().min(1).max(100).optional()
13621
+ targetCountries: z55.array(z55.string().length(2)).max(1).optional(),
13622
+ campaignName: z55.string().trim().min(1).max(100).optional()
13496
13623
  });
13497
13624
  var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
13498
- var MetaInput = z54.object({
13499
- taskId: z54.string().min(1),
13625
+ var MetaInput = z55.object({
13626
+ taskId: z55.string().min(1),
13500
13627
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
13501
- portfolioId: z54.string().trim().min(1),
13628
+ portfolioId: z55.string().trim().min(1),
13502
13629
  /** Exact Facebook Page selected from `list_meta_destinations`. */
13503
- pageId: z54.string().trim().min(1),
13630
+ pageId: z55.string().trim().min(1),
13504
13631
  adAccountId: McpAdAccountId,
13505
- pixelId: z54.string().min(1).optional(),
13506
- landingUrl: z54.string().url().optional(),
13632
+ pixelId: z55.string().min(1).optional(),
13633
+ landingUrl: z55.string().url().optional(),
13507
13634
  /** Select which angles to publish by 0-based index. Omit to publish all
13508
13635
  * successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
13509
- angleIndexes: z54.array(z54.number().int().nonnegative()).optional(),
13636
+ angleIndexes: z55.array(z55.number().int().nonnegative()).optional(),
13510
13637
  campaignConfig: McpCampaignConfig.optional(),
13511
13638
  /** Override the ad's primary text (body copy). If omitted, ProductMaker
13512
13639
  * uses the auto-generated copy attached to the task. Capped at 500 chars
13513
13640
  * (Meta's primary-text limit). */
13514
- primaryText: z54.string().trim().min(1).max(500).optional(),
13641
+ primaryText: z55.string().trim().min(1).max(500).optional(),
13515
13642
  /** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
13516
13643
  * (wa.me) instead of a landing page. */
13517
- phoneNumber: z54.string().min(8).max(32).optional()
13644
+ phoneNumber: z55.string().min(8).max(32).optional()
13518
13645
  });
13519
- var GroupedTaskSource = z54.object({
13520
- type: z54.literal("task"),
13521
- taskId: z54.string().min(1),
13522
- angleIndex: z54.number().int().min(0).optional(),
13523
- videoVariant: z54.enum([
13646
+ var GroupedTaskSource = z55.object({
13647
+ type: z55.literal("task"),
13648
+ taskId: z55.string().min(1),
13649
+ angleIndex: z55.number().int().min(0).optional(),
13650
+ videoVariant: z55.enum([
13524
13651
  "with_subtitles",
13525
13652
  "without_subtitles"
13526
13653
  ]).optional(),
13527
- imageVariantIndex: z54.number().int().min(0).optional()
13528
- });
13529
- var GroupedMediaSource = z54.object({
13530
- type: z54.literal("media"),
13531
- url: z54.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
13532
- path: z54.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".'),
13533
- thumbnailUrl: z54.string().url().optional(),
13534
- thumbnailPath: z54.string().min(1).optional()
13654
+ imageVariantIndex: z55.number().int().min(0).optional()
13655
+ });
13656
+ var GroupedMediaSource = z55.object({
13657
+ type: z55.literal("media"),
13658
+ url: z55.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
13659
+ path: z55.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".'),
13660
+ thumbnailUrl: z55.string().url().optional(),
13661
+ thumbnailPath: z55.string().min(1).optional()
13535
13662
  }).refine((value) => Boolean(value.url) !== Boolean(value.path), {
13536
13663
  message: "media source needs exactly one of `url` or `path`"
13537
13664
  }).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
13538
13665
  message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
13539
13666
  });
13540
- var GroupedUploadedAssetSource = z54.object({
13541
- type: z54.literal("asset"),
13667
+ var GroupedUploadedAssetSource = z55.object({
13668
+ type: z55.literal("asset"),
13542
13669
  /** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
13543
- assetId: z54.string().uuid(),
13544
- thumbnailAssetId: z54.string().uuid().optional()
13670
+ assetId: z55.string().uuid(),
13671
+ thumbnailAssetId: z55.string().uuid().optional()
13545
13672
  });
13546
- var GroupedCreative = z54.object({
13547
- type: z54.enum([
13673
+ var GroupedCreative = z55.object({
13674
+ type: z55.enum([
13548
13675
  "image",
13549
13676
  "video"
13550
13677
  ]),
13551
- source: z54.union([
13678
+ source: z55.union([
13552
13679
  GroupedTaskSource,
13553
13680
  GroupedMediaSource,
13554
13681
  GroupedUploadedAssetSource
13555
13682
  ]),
13556
- title: z54.string().max(120).optional(),
13557
- description: z54.string().max(500).optional(),
13683
+ title: z55.string().max(120).optional(),
13684
+ description: z55.string().max(500).optional(),
13558
13685
  cta: MetaCtaType.optional(),
13559
- creativeId: z54.string().min(1).optional()
13686
+ creativeId: z55.string().min(1).optional()
13560
13687
  });
13561
- var GroupedCampaignConfigBase = z54.object({
13688
+ var GroupedCampaignConfigBase = z55.object({
13562
13689
  campaignType: MetaCampaignType.default("sales"),
13563
13690
  optimizationMode: MetaOptimizationMode.default("advantage_plus"),
13564
13691
  budgetMode: MetaBudgetMode.optional(),
13565
- campaignDailyBudget: z54.number().int().positive().optional(),
13566
- adSets: z54.array(z54.object({
13567
- tempId: z54.string().min(1).max(80),
13568
- name: z54.string().min(1).max(100),
13569
- dailyBudget: z54.number().int().positive().optional(),
13570
- creativeIds: z54.array(z54.string().min(1)).min(1)
13692
+ campaignDailyBudget: z55.number().int().positive().optional(),
13693
+ adSets: z55.array(z55.object({
13694
+ tempId: z55.string().min(1).max(80),
13695
+ name: z55.string().min(1).max(100),
13696
+ dailyBudget: z55.number().int().positive().optional(),
13697
+ creativeIds: z55.array(z55.string().min(1)).min(1)
13571
13698
  })).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
13572
13699
  /**
13573
13700
  * Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
@@ -13575,17 +13702,17 @@ var GroupedCampaignConfigBase = z54.object({
13575
13702
  * opaque `invalid_literal` and made the WhatsApp destination — supported by
13576
13703
  * the API since #849 — unreachable from this tool.
13577
13704
  */
13578
- destination: z54.discriminatedUnion("type", [
13579
- z54.object({
13580
- type: z54.literal("landing"),
13581
- landingUrl: z54.string().url()
13705
+ destination: z55.discriminatedUnion("type", [
13706
+ z55.object({
13707
+ type: z55.literal("landing"),
13708
+ landingUrl: z55.string().url()
13582
13709
  }),
13583
- z54.object({
13584
- type: z54.literal("whatsapp"),
13585
- phoneNumber: z54.string().min(8).max(32)
13710
+ z55.object({
13711
+ type: z55.literal("whatsapp"),
13712
+ phoneNumber: z55.string().min(8).max(32)
13586
13713
  })
13587
13714
  ]),
13588
- saveAsDefault: z54.boolean().default(false),
13715
+ saveAsDefault: z55.boolean().default(false),
13589
13716
  budgetPolicy: MetaBudgetPolicy.optional()
13590
13717
  });
13591
13718
  function resolveBudgetMode(value) {
@@ -13599,7 +13726,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
13599
13726
  const budgetMode = resolveBudgetMode(value);
13600
13727
  if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
13601
13728
  ctx.addIssue({
13602
- code: z54.ZodIssueCode.custom,
13729
+ code: z55.ZodIssueCode.custom,
13603
13730
  path: [
13604
13731
  "campaignDailyBudget"
13605
13732
  ],
@@ -13610,7 +13737,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
13610
13737
  value.adSets.forEach((adSet, index) => {
13611
13738
  if (adSet.dailyBudget === void 0) {
13612
13739
  ctx.addIssue({
13613
- code: z54.ZodIssueCode.custom,
13740
+ code: z55.ZodIssueCode.custom,
13614
13741
  path: [
13615
13742
  "adSets",
13616
13743
  index,
@@ -13625,26 +13752,26 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
13625
13752
  ...value,
13626
13753
  budgetMode: resolveBudgetMode(value)
13627
13754
  }));
13628
- var PublishCreativesToMetaInputBase = z54.object({
13629
- creatives: z54.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
13755
+ var PublishCreativesToMetaInputBase = z55.object({
13756
+ creatives: z55.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
13630
13757
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
13631
- portfolioId: z54.string().trim().min(1),
13758
+ portfolioId: z55.string().trim().min(1),
13632
13759
  /** Exact Facebook Page selected from `list_meta_destinations`. */
13633
- pageId: z54.string().trim().min(1),
13760
+ pageId: z55.string().trim().min(1),
13634
13761
  adAccountId: McpAdAccountId,
13635
- pixelId: z54.string().min(1).optional(),
13762
+ pixelId: z55.string().min(1).optional(),
13636
13763
  /** Required unless `campaignConfig.destination` is whatsapp — see the
13637
13764
  * superRefine below. Mirrors the API's `UploadToMetaRequest`. */
13638
- landingUrl: z54.string().url().optional(),
13639
- targetCountry: z54.string().length(2),
13640
- campaignName: z54.string().trim().min(1).max(100),
13765
+ landingUrl: z55.string().url().optional(),
13766
+ targetCountry: z55.string().length(2),
13767
+ campaignName: z55.string().trim().min(1).max(100),
13641
13768
  campaignConfig: GroupedCampaignConfig.optional()
13642
13769
  });
13643
13770
  var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
13644
13771
  const destination = value.campaignConfig?.destination;
13645
13772
  if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
13646
13773
  ctx.addIssue({
13647
- code: z54.ZodIssueCode.custom,
13774
+ code: z55.ZodIssueCode.custom,
13648
13775
  path: [
13649
13776
  "landingUrl"
13650
13777
  ],
@@ -13653,7 +13780,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
13653
13780
  }
13654
13781
  if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
13655
13782
  ctx.addIssue({
13656
- code: z54.ZodIssueCode.custom,
13783
+ code: z55.ZodIssueCode.custom,
13657
13784
  path: [
13658
13785
  "campaignConfig",
13659
13786
  "destination",
@@ -13672,16 +13799,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
13672
13799
  }
13673
13800
  return value;
13674
13801
  });
13675
- var PresignUploadResponseSchema = z54.object({
13676
- uploadUrl: z54.string().url().refine((value) => {
13802
+ var PresignUploadResponseSchema = z55.object({
13803
+ uploadUrl: z55.string().url().refine((value) => {
13677
13804
  const url = new URL(value);
13678
13805
  return !url.username && !url.password && url.protocol === "https:";
13679
13806
  }, "presigned upload URL must be HTTPS without embedded credentials"),
13680
- publicUrl: z54.string().url().refine((value) => {
13807
+ publicUrl: z55.string().url().refine((value) => {
13681
13808
  const url = new URL(value);
13682
13809
  return !url.username && !url.password;
13683
13810
  }, "public media URL must not contain embedded credentials"),
13684
- stagingAssetId: z54.string().uuid()
13811
+ stagingAssetId: z55.string().uuid()
13685
13812
  });
13686
13813
  async function uploadResolvedMedia(api, media, assetRole) {
13687
13814
  if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
@@ -13706,16 +13833,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
13706
13833
  return uploadResolvedMedia(api, media, assetRole);
13707
13834
  }
13708
13835
  __name(resolveAndUploadMedia, "resolveAndUploadMedia");
13709
- var TikTokInput = z54.object({
13710
- taskId: z54.string().min(1),
13711
- advertiserId: z54.string().min(1),
13712
- pixelId: z54.string().min(1).optional(),
13713
- landingUrl: z54.string().url().optional(),
13714
- angleIndexes: z54.array(z54.number().int().nonnegative()).optional(),
13836
+ var TikTokInput = z55.object({
13837
+ taskId: z55.string().min(1),
13838
+ advertiserId: z55.string().min(1),
13839
+ pixelId: z55.string().min(1).optional(),
13840
+ landingUrl: z55.string().url().optional(),
13841
+ angleIndexes: z55.array(z55.number().int().nonnegative()).optional(),
13715
13842
  campaignConfig: McpCampaignConfig.optional(),
13716
13843
  /** Override the ad's description (TikTok's body copy). If omitted,
13717
13844
  * ProductMaker uses the auto-generated copy attached to the task. */
13718
- primaryText: z54.string().trim().min(1).max(500).optional()
13845
+ primaryText: z55.string().trim().min(1).max(500).optional()
13719
13846
  });
13720
13847
  function registerPublishTools(server, api, opts = {}) {
13721
13848
  const transport = opts.transport ?? "http";
@@ -13965,38 +14092,38 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
13965
14092
 
13966
14093
  // src/tools/meta-upload.ts
13967
14094
  import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
13968
- import { z as z55 } from "zod";
13969
- var UploadSessionInputBase = z55.object({
13970
- mediaKind: z55.enum([
14095
+ import { z as z56 } from "zod";
14096
+ var UploadSessionInputBase = z56.object({
14097
+ mediaKind: z56.enum([
13971
14098
  "image",
13972
14099
  "video",
13973
14100
  "mixed"
13974
14101
  ]).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."),
13975
- assetRole: z55.enum([
14102
+ assetRole: z56.enum([
13976
14103
  "media",
13977
14104
  "thumbnail"
13978
14105
  ]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
13979
- uploadPurpose: z55.enum([
14106
+ uploadPurpose: z56.enum([
13980
14107
  "product_reference",
13981
14108
  "creative",
13982
14109
  "generic"
13983
14110
  ]).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."),
13984
- maxFiles: z55.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
14111
+ maxFiles: z56.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
13985
14112
  });
13986
- var OpenAiFileReference = z55.object({
13987
- download_url: z55.string().url().optional().describe("Optional host-provided download URL. The App prefers getFileDownloadUrl(file_id) and the server never fetches this URL."),
13988
- file_id: z55.string().min(1),
13989
- mime_type: z55.string().min(1).optional(),
13990
- file_name: z55.string().min(1).optional()
14113
+ var OpenAiFileReference = z56.object({
14114
+ download_url: z56.string().url().optional().describe("Optional host-provided download URL. The App prefers getFileDownloadUrl(file_id) and the server never fetches this URL."),
14115
+ file_id: z56.string().min(1),
14116
+ mime_type: z56.string().min(1).optional(),
14117
+ file_name: z56.string().min(1).optional()
13991
14118
  });
13992
14119
  var UploadSessionToolInputShape = {
13993
14120
  ...UploadSessionInputBase.shape,
13994
- files: z55.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.")
14121
+ files: z56.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.")
13995
14122
  };
13996
- var UploadSessionToolInput = z55.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
14123
+ var UploadSessionToolInput = z56.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
13997
14124
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
13998
14125
  ctx.addIssue({
13999
- code: z55.ZodIssueCode.custom,
14126
+ code: z56.ZodIssueCode.custom,
14000
14127
  path: [
14001
14128
  "mediaKind"
14002
14129
  ],
@@ -14005,7 +14132,7 @@ var UploadSessionToolInput = z55.object(UploadSessionToolInputShape).superRefine
14005
14132
  }
14006
14133
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
14007
14134
  ctx.addIssue({
14008
- code: z55.ZodIssueCode.custom,
14135
+ code: z56.ZodIssueCode.custom,
14009
14136
  path: [
14010
14137
  "maxFiles"
14011
14138
  ],
@@ -14014,7 +14141,7 @@ var UploadSessionToolInput = z55.object(UploadSessionToolInputShape).superRefine
14014
14141
  }
14015
14142
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
14016
14143
  ctx.addIssue({
14017
- code: z55.ZodIssueCode.custom,
14144
+ code: z56.ZodIssueCode.custom,
14018
14145
  path: [
14019
14146
  "maxFiles"
14020
14147
  ],
@@ -14022,38 +14149,38 @@ var UploadSessionToolInput = z55.object(UploadSessionToolInputShape).superRefine
14022
14149
  });
14023
14150
  }
14024
14151
  });
14025
- var UploadSessionResponse = z55.object({
14026
- sessionId: z55.string().uuid(),
14027
- uploadPageUrl: z55.string().url(),
14028
- mediaKind: z55.enum([
14152
+ var UploadSessionResponse = z56.object({
14153
+ sessionId: z56.string().uuid(),
14154
+ uploadPageUrl: z56.string().url(),
14155
+ mediaKind: z56.enum([
14029
14156
  "image",
14030
14157
  "video",
14031
14158
  "mixed"
14032
14159
  ]),
14033
- assetRole: z55.enum([
14160
+ assetRole: z56.enum([
14034
14161
  "media",
14035
14162
  "thumbnail"
14036
14163
  ]),
14037
- maxFiles: z55.number().int().positive(),
14038
- expiresAt: z55.string().datetime()
14164
+ maxFiles: z56.number().int().positive(),
14165
+ expiresAt: z56.string().datetime()
14039
14166
  });
14040
- var UploadStatusInput = z55.object({
14041
- sessionId: z55.string().uuid().describe("The sessionId returned by request_media_upload.")
14167
+ var UploadStatusInput = z56.object({
14168
+ sessionId: z56.string().uuid().describe("The sessionId returned by request_media_upload.")
14042
14169
  });
14043
- var UniversalUploadStatusResponse = z55.discriminatedUnion("status", [
14044
- z55.object({
14045
- status: z55.literal("pending"),
14046
- assets: z55.array(z55.never()).length(0)
14170
+ var UniversalUploadStatusResponse = z56.discriminatedUnion("status", [
14171
+ z56.object({
14172
+ status: z56.literal("pending"),
14173
+ assets: z56.array(z56.never()).length(0)
14047
14174
  }),
14048
- z55.object({
14049
- status: z55.literal("uploaded"),
14050
- assets: z55.array(z55.object({
14051
- assetId: z55.string().uuid(),
14052
- mediaKind: z55.enum([
14175
+ z56.object({
14176
+ status: z56.literal("uploaded"),
14177
+ assets: z56.array(z56.object({
14178
+ assetId: z56.string().uuid(),
14179
+ mediaKind: z56.enum([
14053
14180
  "image",
14054
14181
  "video"
14055
14182
  ]),
14056
- assetRole: z55.enum([
14183
+ assetRole: z56.enum([
14057
14184
  "media",
14058
14185
  "thumbnail"
14059
14186
  ])
@@ -14061,13 +14188,13 @@ var UniversalUploadStatusResponse = z55.discriminatedUnion("status", [
14061
14188
  })
14062
14189
  ]);
14063
14190
  var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
14064
- uploadPurpose: z55.enum([
14191
+ uploadPurpose: z56.enum([
14065
14192
  "product_reference",
14066
14193
  "creative",
14067
14194
  "generic"
14068
14195
  ]),
14069
- checkToolName: z55.literal("check_media_upload"),
14070
- resolveEndpoint: z55.string().url()
14196
+ checkToolName: z56.literal("check_media_upload"),
14197
+ resolveEndpoint: z56.string().url()
14071
14198
  });
14072
14199
  function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
14073
14200
  const url = new URL(uploadPageUrl);
@@ -14158,13 +14285,13 @@ function registerMediaUploadTools(server, api) {
14158
14285
  __name(registerMediaUploadTools, "registerMediaUploadTools");
14159
14286
 
14160
14287
  // src/tools/campaigns.ts
14161
- import { z as z56 } from "zod";
14162
- var MetaStatusInput = z56.object({
14163
- campaignId: z56.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
14288
+ import { z as z57 } from "zod";
14289
+ var MetaStatusInput = z57.object({
14290
+ campaignId: z57.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
14164
14291
  });
14165
- var TikTokStatusInput = z56.object({
14166
- campaignId: z56.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
14167
- advertiserId: z56.string().min(1).describe("The same advertiserId used to publish the campaign.")
14292
+ var TikTokStatusInput = z57.object({
14293
+ campaignId: z57.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
14294
+ advertiserId: z57.string().min(1).describe("The same advertiserId used to publish the campaign.")
14168
14295
  });
14169
14296
  function registerCampaignTools(server, api) {
14170
14297
  server.tool("get_meta_campaign_status", "Consulta el estado actual + m\xE9tricas lifetime (spend, impressions, clicks, reach) de una campa\xF1a Meta publicada. Llama esto DESPU\xC9S de `publish_to_meta` para confirmar que la campa\xF1a se cre\xF3 correctamente y para reportar performance al usuario. Es read-only \u2014 no modifica nada en Meta Ads Manager.", MetaStatusInput.shape, READS_EXTERNAL, async (input) => {
@@ -14261,10 +14388,10 @@ function renderTikTokStatusMarkdown(r) {
14261
14388
  __name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
14262
14389
 
14263
14390
  // ../../packages/product-economics/src/product-costing.ts
14264
- import { z as z58 } from "zod";
14391
+ import { z as z59 } from "zod";
14265
14392
 
14266
14393
  // ../../packages/product-economics/src/product-costing-countries.ts
14267
- import { z as z57 } from "zod";
14394
+ import { z as z58 } from "zod";
14268
14395
 
14269
14396
  // ../../packages/product-economics/src/product-costing-shipping-references.json
14270
14397
  var product_costing_shipping_references_default = {
@@ -14328,21 +14455,21 @@ var product_costing_shipping_references_default = {
14328
14455
  };
14329
14456
 
14330
14457
  // ../../packages/product-economics/src/product-costing-countries.ts
14331
- var ShippingReferenceSchema = z57.object({
14332
- reference: z57.number().positive(),
14333
- min: z57.number().nonnegative(),
14334
- max: z57.number().positive(),
14335
- updatedAt: z57.string().date(),
14336
- confidence: z57.enum([
14458
+ var ShippingReferenceSchema = z58.object({
14459
+ reference: z58.number().positive(),
14460
+ min: z58.number().nonnegative(),
14461
+ max: z58.number().positive(),
14462
+ updatedAt: z58.string().date(),
14463
+ confidence: z58.enum([
14337
14464
  "high",
14338
14465
  "medium",
14339
14466
  "medium-low"
14340
14467
  ]),
14341
- sources: z57.array(z57.string().url().startsWith("https://")).min(1).max(3)
14468
+ sources: z58.array(z58.string().url().startsWith("https://")).min(1).max(3)
14342
14469
  }).superRefine(({ reference, min, max }, context) => {
14343
14470
  if (min > reference || reference > max) {
14344
14471
  context.addIssue({
14345
- code: z57.ZodIssueCode.custom,
14472
+ code: z58.ZodIssueCode.custom,
14346
14473
  message: "shipping_reference_outside_range",
14347
14474
  path: [
14348
14475
  "reference"
@@ -14350,7 +14477,7 @@ var ShippingReferenceSchema = z57.object({
14350
14477
  });
14351
14478
  }
14352
14479
  });
14353
- var SHIPPING_REFERENCES = z57.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
14480
+ var SHIPPING_REFERENCES = z58.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
14354
14481
  var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
14355
14482
  var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
14356
14483
  "MX",
@@ -14532,18 +14659,18 @@ function getProductCostingCountryName(country) {
14532
14659
  __name(getProductCostingCountryName, "getProductCostingCountryName");
14533
14660
 
14534
14661
  // ../../packages/product-economics/src/product-costing.ts
14535
- var ProductCostingInputSchema = z58.object({
14536
- country: z58.string().refine(isProductCostingCountryCode, "unsupported_country"),
14537
- supplierCost: z58.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
14538
- shippingCost: z58.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
14539
- returnRate: z58.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
14540
- cancellationRate: z58.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
14541
- adsManagerCpa: z58.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
14542
- desiredMargin: z58.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
14662
+ var ProductCostingInputSchema = z59.object({
14663
+ country: z59.string().refine(isProductCostingCountryCode, "unsupported_country"),
14664
+ supplierCost: z59.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
14665
+ shippingCost: z59.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
14666
+ returnRate: z59.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
14667
+ cancellationRate: z59.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
14668
+ adsManagerCpa: z59.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
14669
+ desiredMargin: z59.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
14543
14670
  }).superRefine(({ returnRate, cancellationRate }, context) => {
14544
14671
  if (returnRate + cancellationRate >= 1) {
14545
14672
  context.addIssue({
14546
- code: z58.ZodIssueCode.custom,
14673
+ code: z59.ZodIssueCode.custom,
14547
14674
  message: "delivery_rate_positive",
14548
14675
  path: [
14549
14676
  "cancellationRate"
@@ -14610,14 +14737,14 @@ function calculateProductCosting(rawInput) {
14610
14737
  __name(calculateProductCosting, "calculateProductCosting");
14611
14738
 
14612
14739
  // src/tools/product-costing.ts
14613
- import { z as z59 } from "zod";
14614
- var optionalAmount = /* @__PURE__ */ __name((description) => z59.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
14615
- var optionalPercent = /* @__PURE__ */ __name((description) => z59.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
14616
- var ProductCostingToolInput = z59.object({
14617
- country: z59.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
14740
+ import { z as z60 } from "zod";
14741
+ var optionalAmount = /* @__PURE__ */ __name((description) => z60.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
14742
+ var optionalPercent = /* @__PURE__ */ __name((description) => z60.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
14743
+ var ProductCostingToolInput = z60.object({
14744
+ country: z60.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
14618
14745
  message: "Pa\xEDs no soportado por ProductMaker."
14619
14746
  }).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
14620
- supplierCost: z59.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."),
14747
+ supplierCost: z60.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."),
14621
14748
  supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
14622
14749
  shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
14623
14750
  shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
@@ -14749,7 +14876,7 @@ function formatPercent(value) {
14749
14876
  __name(formatPercent, "formatPercent");
14750
14877
 
14751
14878
  // src/tools/product-research.ts
14752
- import { z as z60 } from "zod";
14879
+ import { z as z61 } from "zod";
14753
14880
 
14754
14881
  // src/tools/product-research-idempotency.ts
14755
14882
  import { createHash as createHash2 } from "crypto";
@@ -14865,17 +14992,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
14865
14992
  ]);
14866
14993
  var POLL_INTERVAL_MS = 5e3;
14867
14994
  var MAX_WAIT_SECONDS = 120;
14868
- var FindInput = z60.object({
14995
+ var FindInput = z61.object({
14869
14996
  targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
14870
14997
  categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
14871
- confirmed: z60.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
14872
- waitSeconds: z60.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
14998
+ confirmed: z61.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
14999
+ waitSeconds: z61.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
14873
15000
  });
14874
- var GetInput = z60.object({
14875
- runId: z60.string().uuid().describe("ID del run devuelto por find_winning_products.")
15001
+ var GetInput = z61.object({
15002
+ runId: z61.string().uuid().describe("ID del run devuelto por find_winning_products.")
14876
15003
  });
14877
- var ListInput = z60.object({
14878
- limit: z60.number().int().min(1).max(20).default(10)
15004
+ var ListInput = z61.object({
15005
+ limit: z61.number().int().min(1).max(20).default(10)
14879
15006
  });
14880
15007
  function textResult(text) {
14881
15008
  return {
@@ -14967,14 +15094,14 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
14967
15094
  __name(registerProductResearchTools, "registerProductResearchTools");
14968
15095
 
14969
15096
  // src/tools/dropshipping-projects.ts
14970
- import { z as z61 } from "zod";
14971
- var ProjectId = z61.string().uuid();
14972
- var DropshippingProjectStatus = z61.enum([
15097
+ import { z as z62 } from "zod";
15098
+ var ProjectId = z62.string().uuid();
15099
+ var DropshippingProjectStatus = z62.enum([
14973
15100
  "active",
14974
15101
  "completed",
14975
15102
  "archived"
14976
15103
  ]);
14977
- var DropshippingProjectPhase = z61.enum([
15104
+ var DropshippingProjectPhase = z62.enum([
14978
15105
  "research",
14979
15106
  "costing",
14980
15107
  "media",
@@ -14983,21 +15110,21 @@ var DropshippingProjectPhase = z61.enum([
14983
15110
  "advertising",
14984
15111
  "complete"
14985
15112
  ]);
14986
- var DropshippingRewardMilestone = z61.enum([
15113
+ var DropshippingRewardMilestone = z62.enum([
14987
15114
  "product_selected",
14988
15115
  "costing_saved",
14989
15116
  "product_media_ready",
14990
15117
  "creatives_completed",
14991
15118
  "campaign_created"
14992
15119
  ]);
14993
- var TargetCountry = z61.enum([
15120
+ var TargetCountry = z62.enum([
14994
15121
  "CO",
14995
15122
  "MX",
14996
15123
  "PE",
14997
15124
  "EC",
14998
15125
  "CL"
14999
15126
  ]);
15000
- var ResearchCategory = z61.enum([
15127
+ var ResearchCategory = z62.enum([
15001
15128
  "auto",
15002
15129
  "automotive",
15003
15130
  "kitchen",
@@ -15012,7 +15139,7 @@ var ResearchCategory = z61.enum([
15012
15139
  "garden",
15013
15140
  "cleaning"
15014
15141
  ]);
15015
- var HttpUrl3 = z61.string().url().max(2e3).refine((value) => {
15142
+ var HttpUrl3 = z62.string().url().max(2e3).refine((value) => {
15016
15143
  try {
15017
15144
  return [
15018
15145
  "http:",
@@ -15022,43 +15149,43 @@ var HttpUrl3 = z61.string().url().max(2e3).refine((value) => {
15022
15149
  return false;
15023
15150
  }
15024
15151
  }, "URL must use HTTP(S)");
15025
- var ResearchCandidateOrigin = z61.object({
15026
- type: z61.literal("research_candidate"),
15152
+ var ResearchCandidateOrigin = z62.object({
15153
+ type: z62.literal("research_candidate"),
15027
15154
  runId: ProjectId,
15028
- candidateSourceId: z61.string().min(1).max(160)
15155
+ candidateSourceId: z62.string().min(1).max(160)
15029
15156
  });
15030
- var TaskOrigin = z61.object({
15031
- type: z61.literal("task"),
15157
+ var TaskOrigin = z62.object({
15158
+ type: z62.literal("task"),
15032
15159
  taskId: ProjectId
15033
15160
  });
15034
- var ManualOrigin = z61.object({
15035
- type: z61.literal("manual"),
15161
+ var ManualOrigin = z62.object({
15162
+ type: z62.literal("manual"),
15036
15163
  clientRequestId: ProjectId,
15037
- country: z61.string().min(2).max(3).optional()
15164
+ country: z62.string().min(2).max(3).optional()
15038
15165
  });
15039
- var StartProjectInput = z61.object({
15040
- origin: z61.discriminatedUnion("type", [
15166
+ var StartProjectInput = z62.object({
15167
+ origin: z62.discriminatedUnion("type", [
15041
15168
  ResearchCandidateOrigin,
15042
15169
  TaskOrigin,
15043
15170
  ManualOrigin
15044
15171
  ]),
15045
- productName: z61.string().trim().min(1).max(240).optional(),
15172
+ productName: z62.string().trim().min(1).max(240).optional(),
15046
15173
  productUrl: HttpUrl3.optional(),
15047
- country: z61.string().min(2).max(3).optional(),
15048
- languageCode: z61.string().min(2).max(16).optional()
15174
+ country: z62.string().min(2).max(3).optional(),
15175
+ languageCode: z62.string().min(2).max(16).optional()
15049
15176
  }).strict();
15050
- var CostProjectInput = z61.object({
15177
+ var CostProjectInput = z62.object({
15051
15178
  projectId: ProjectId,
15052
- version: z61.number().int().positive(),
15053
- country: z61.string().trim().min(2).max(3),
15054
- supplierCost: z61.number().finite().positive(),
15055
- shippingCost: z61.number().finite().nonnegative(),
15056
- returnRate: z61.number().finite().min(0).lt(1),
15057
- cancellationRate: z61.number().finite().min(0).lt(1),
15058
- adsManagerCpa: z61.number().finite().nonnegative(),
15059
- desiredMargin: z61.number().finite().min(0).lt(1)
15060
- });
15061
- var GuideInput = z61.object({
15179
+ version: z62.number().int().positive(),
15180
+ country: z62.string().trim().min(2).max(3),
15181
+ supplierCost: z62.number().finite().positive(),
15182
+ shippingCost: z62.number().finite().nonnegative(),
15183
+ returnRate: z62.number().finite().min(0).lt(1),
15184
+ cancellationRate: z62.number().finite().min(0).lt(1),
15185
+ adsManagerCpa: z62.number().finite().nonnegative(),
15186
+ desiredMargin: z62.number().finite().min(0).lt(1)
15187
+ });
15188
+ var GuideInput = z62.object({
15062
15189
  projectId: ProjectId.optional()
15063
15190
  }).strict();
15064
15191
  var NEXT_ACTION_KINDS = [
@@ -15076,29 +15203,29 @@ var NEXT_ACTION_KINDS = [
15076
15203
  "repair_meta_campaign",
15077
15204
  "review_paused_campaign"
15078
15205
  ];
15079
- var DropshippingProjectNextAction = z61.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z61.object({
15080
- kind: z61.literal(kind),
15081
- href: z61.string().min(1)
15206
+ var DropshippingProjectNextAction = z62.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z62.object({
15207
+ kind: z62.literal(kind),
15208
+ href: z62.string().min(1)
15082
15209
  })));
15083
- var CostingInputSchema = z61.object({
15084
- country: z61.string().min(2).max(3),
15085
- supplierCost: z61.number().finite().positive(),
15086
- shippingCost: z61.number().finite().nonnegative(),
15087
- returnRate: z61.number().finite().min(0).lt(1),
15088
- cancellationRate: z61.number().finite().min(0).lt(1),
15089
- adsManagerCpa: z61.number().finite().nonnegative(),
15090
- desiredMargin: z61.number().finite().min(0).lt(1)
15210
+ var CostingInputSchema = z62.object({
15211
+ country: z62.string().min(2).max(3),
15212
+ supplierCost: z62.number().finite().positive(),
15213
+ shippingCost: z62.number().finite().nonnegative(),
15214
+ returnRate: z62.number().finite().min(0).lt(1),
15215
+ cancellationRate: z62.number().finite().min(0).lt(1),
15216
+ adsManagerCpa: z62.number().finite().nonnegative(),
15217
+ desiredMargin: z62.number().finite().min(0).lt(1)
15091
15218
  }).superRefine(({ returnRate, cancellationRate }, context) => {
15092
15219
  if (returnRate + cancellationRate >= 1) context.addIssue({
15093
- code: z61.ZodIssueCode.custom,
15220
+ code: z62.ZodIssueCode.custom,
15094
15221
  path: [
15095
15222
  "cancellationRate"
15096
15223
  ]
15097
15224
  });
15098
15225
  });
15099
- var FiniteCostingNumber = z61.number().finite();
15100
- var CostingResultSchema = z61.object({
15101
- country: z61.string().min(2).max(3),
15226
+ var FiniteCostingNumber = z62.number().finite();
15227
+ var CostingResultSchema = z62.object({
15228
+ country: z62.string().min(2).max(3),
15102
15229
  deliveryRate: FiniteCostingNumber,
15103
15230
  adjustedShippingCost: FiniteCostingNumber,
15104
15231
  adjustedCpa: FiniteCostingNumber,
@@ -15111,44 +15238,44 @@ var CostingResultSchema = z61.object({
15111
15238
  estimatedProfit: FiniteCostingNumber,
15112
15239
  actualMargin: FiniteCostingNumber,
15113
15240
  breakEvenAdsManagerCpa: FiniteCostingNumber,
15114
- wasPriceAutoAdjusted: z61.boolean(),
15115
- profitabilityStatus: z61.literal("healthy")
15116
- });
15117
- var RewardProgressSchema = z61.object({
15118
- campaignKey: z61.literal("dropshipping-launch-v1"),
15119
- totalCredits: z61.number().int().positive(),
15120
- earnedCredits: z61.number().int().nonnegative(),
15121
- milestones: z61.array(z61.object({
15241
+ wasPriceAutoAdjusted: z62.boolean(),
15242
+ profitabilityStatus: z62.literal("healthy")
15243
+ });
15244
+ var RewardProgressSchema = z62.object({
15245
+ campaignKey: z62.literal("dropshipping-launch-v1"),
15246
+ totalCredits: z62.number().int().positive(),
15247
+ earnedCredits: z62.number().int().nonnegative(),
15248
+ milestones: z62.array(z62.object({
15122
15249
  milestone: DropshippingRewardMilestone,
15123
- credits: z61.number().int().positive(),
15124
- available: z61.boolean().optional(),
15125
- earned: z61.boolean(),
15250
+ credits: z62.number().int().positive(),
15251
+ available: z62.boolean().optional(),
15252
+ earned: z62.boolean(),
15126
15253
  grantId: ProjectId.nullable(),
15127
- grantedAt: z61.string().datetime().nullable()
15254
+ grantedAt: z62.string().datetime().nullable()
15128
15255
  })).length(DropshippingRewardMilestone.options.length)
15129
15256
  });
15130
- var ProjectResponseSchema = z61.object({
15257
+ var ProjectResponseSchema = z62.object({
15131
15258
  id: ProjectId,
15132
15259
  taskId: ProjectId.nullable(),
15133
15260
  status: DropshippingProjectStatus,
15134
- originKey: z61.string().min(1),
15261
+ originKey: z62.string().min(1),
15135
15262
  researchRunId: ProjectId.nullable(),
15136
- candidateSourceId: z61.string().nullable(),
15137
- productName: z61.string().nullable(),
15263
+ candidateSourceId: z62.string().nullable(),
15264
+ productName: z62.string().nullable(),
15138
15265
  productUrl: HttpUrl3.nullable(),
15139
15266
  referenceImageUrl: HttpUrl3.nullable(),
15140
- targetCountry: z61.string().nullable(),
15141
- languageCode: z61.string().nullable(),
15142
- hasReferenceImage: z61.boolean(),
15267
+ targetCountry: z62.string().nullable(),
15268
+ languageCode: z62.string().nullable(),
15269
+ hasReferenceImage: z62.boolean(),
15143
15270
  costingInput: CostingInputSchema.nullable(),
15144
15271
  costingResult: CostingResultSchema.nullable(),
15145
- costingVersion: z61.number().int().positive().nullable(),
15146
- version: z61.number().int().positive(),
15272
+ costingVersion: z62.number().int().positive().nullable(),
15273
+ version: z62.number().int().positive(),
15147
15274
  phase: DropshippingProjectPhase,
15148
15275
  nextAction: DropshippingProjectNextAction.nullable(),
15149
15276
  rewards: RewardProgressSchema,
15150
- createdAt: z61.string().datetime(),
15151
- updatedAt: z61.string().datetime()
15277
+ createdAt: z62.string().datetime(),
15278
+ updatedAt: z62.string().datetime()
15152
15279
  }).passthrough();
15153
15280
  var NEXT_ACTION_GUIDANCE = {
15154
15281
  cost_product: "Llama `cost_dropshipping_project` con el costo real del proveedor. Nunca lo inventes: p\xEDdeselo al usuario.",