@productmaker/mcp 3.4.0 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/http.js +955 -880
  2. package/dist/stdio.js +943 -868
  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.1";
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";
@@ -6199,6 +6199,10 @@ var TikTokCreateCampaignResponseSchema = z35.object({
6199
6199
  adsManagerUrl: z35.string().optional()
6200
6200
  });
6201
6201
 
6202
+ // ../../packages/types/src/pricing-gemini-omni.ts
6203
+ var GEMINI_OMNI_FLAT_OUR_COST_CENTS = 84;
6204
+ var GEMINI_OMNI_FLAT_USER_PRICE_CENTS = 168;
6205
+
6202
6206
  // ../../packages/types/src/pricing.ts
6203
6207
  var CREDITS_PER_USD_CENT = 10;
6204
6208
  var CREDITS_PER_DOLLAR = 100 * CREDITS_PER_USD_CENT;
@@ -6607,6 +6611,18 @@ var DEFAULT_PRICING = {
6607
6611
  ourCostCents: 120,
6608
6612
  userPriceCents: 240
6609
6613
  },
6614
+ // Gemini Omni Video (gemini-omni-video) — Mix primary generator since
6615
+ // 2026-08-18. FLAT per generation: 168 KIE credits = $0.84, identical at
6616
+ // 720p and 1080p and independent of the 3.5-10s trim window. Do NOT add
6617
+ // per-second overrides for this key — resolveSuccessBilling bills it flat.
6618
+ //
6619
+ // Shares the constants with the pre-submit ESTIMATOR (mix-cost.ts) rather
6620
+ // than repeating the numbers: a literal here that drifted from the estimator
6621
+ // would quote one price and charge another on every mix.
6622
+ "kie:gemini-omni-video": {
6623
+ ourCostCents: GEMINI_OMNI_FLAT_OUR_COST_CENTS,
6624
+ userPriceCents: GEMINI_OMNI_FLAT_USER_PRICE_CENTS
6625
+ },
6610
6626
  "kie:video-lipsync-generation": {
6611
6627
  ourCostCents: 45,
6612
6628
  userPriceCents: 90
@@ -8570,7 +8586,57 @@ var FeatureSpec = z36.object({
8570
8586
  });
8571
8587
 
8572
8588
  // ../../packages/types/src/mix.ts
8589
+ import { z as z38 } from "zod";
8590
+
8591
+ // ../../packages/types/src/mix-degradation.ts
8573
8592
  import { z as z37 } from "zod";
8593
+ var MIX_DEGRADATION_REASONS = [
8594
+ /**
8595
+ * At least one scene the mix PLANNED is missing from the delivered video, so
8596
+ * the result is shorter than the source. Set at assemble time by comparing
8597
+ * the concat set against the planned scene set — the scene's own code (if it
8598
+ * had one) never reaches the mix-level rollup, which only sees scenes that
8599
+ * SUCCEEDED, and that is exactly how a live 17.00s-of-20.00s delivery
8600
+ * shipped with degradedReason NULL and no banner at all.
8601
+ *
8602
+ * ORDERING: FIRST, above every refusal code. A short delivery must never be
8603
+ * MASKED. It used to sit below the three content refusals on the theory that
8604
+ * a refusal names something the user can change AND explains the missing
8605
+ * scene — but it does neither reliably: in a 3-scene mix where scene 1 fails
8606
+ * outright and scene 2 ships through Wan after a reference refusal, the
8607
+ * refusal copy reads "we used a lower-quality alternative", a claim about
8608
+ * QUALITY that says nothing about the video being shorter than what was paid
8609
+ * for, and that is actively wrong about the dropped scene (for which we used
8610
+ * nothing). Every other code in this list describes a scene that DID ship.
8611
+ */
8612
+ "scenes_dropped",
8613
+ /** Google's safety filter rejected the user's reference photo. Deterministic. */
8614
+ "reference_rejected",
8615
+ /** Google refused the wording of the change description. */
8616
+ "prompt_rejected",
8617
+ /**
8618
+ * The provider refused the content but its message names neither the
8619
+ * reference nor the wording, so we cannot say which. Distinct from
8620
+ * 'provider_unavailable' on purpose: "unavailable" invites the user to retry
8621
+ * unchanged, which can never succeed against a content refusal and only
8622
+ * burns their credits. This code tells them something must change.
8623
+ */
8624
+ "content_rejected",
8625
+ /**
8626
+ * The scene's length fell outside Gemini's usable 3.5s-10s trim window —
8627
+ * EITHER bound. Deliberately ONE code for both: the user controls neither
8628
+ * (scene segmentation is entirely ours), so "too short" and "too long" are
8629
+ * not differently actionable, and one honest explanation beats two that
8630
+ * both amount to "our segmentation produced a length the primary generator
8631
+ * cannot take".
8632
+ */
8633
+ "scene_length_unsupported",
8634
+ /** Transient provider failures exhausted the budget. */
8635
+ "provider_unavailable"
8636
+ ];
8637
+ var MixDegradationReasonSchema = z37.enum(MIX_DEGRADATION_REASONS);
8638
+
8639
+ // ../../packages/types/src/mix.ts
8574
8640
  var MEDIA_TYPES = [
8575
8641
  "video",
8576
8642
  "image"
@@ -8608,38 +8674,38 @@ function isPublicHttpsUrl(raw) {
8608
8674
  return true;
8609
8675
  }
8610
8676
  __name(isPublicHttpsUrl, "isPublicHttpsUrl");
8611
- var PublicHttpsUrl = z37.string().url().refine(isPublicHttpsUrl, {
8677
+ var PublicHttpsUrl = z38.string().url().refine(isPublicHttpsUrl, {
8612
8678
  message: "must be a public HTTPS URL"
8613
8679
  });
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([
8680
+ var InternalAssetPath = z38.string().regex(/^\/(?:api|v1)\/assets\/[A-Za-z0-9._~%/-]+$/, "must be a public HTTPS URL or an internal asset path");
8681
+ var MixImageUrl = z38.union([
8616
8682
  PublicHttpsUrl,
8617
8683
  InternalAssetPath
8618
8684
  ]);
8619
- var MixAxes = z37.object({
8620
- product: z37.boolean(),
8621
- person: z37.boolean(),
8622
- setting: z37.boolean()
8685
+ var MixAxes = z38.object({
8686
+ product: z38.boolean(),
8687
+ person: z38.boolean(),
8688
+ setting: z38.boolean()
8623
8689
  });
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")
8690
+ var MixReferences = z38.object({
8691
+ product: z38.array(PublicHttpsUrl).max(3, "at most 3 product references"),
8692
+ person: z38.array(PublicHttpsUrl).max(3, "at most 3 person references"),
8693
+ setting: z38.array(PublicHttpsUrl).max(3, "at most 3 setting references")
8628
8694
  });
8629
- var MixImageEdit = z37.object({
8630
- instruction: z37.string().min(1).max(600),
8631
- imageUrls: z37.array(MixImageUrl).min(1).max(3)
8695
+ var MixImageEdit = z38.object({
8696
+ instruction: z38.string().min(1).max(600),
8697
+ imageUrls: z38.array(MixImageUrl).min(1).max(3)
8632
8698
  });
8633
- var MixRequest = z37.object({
8634
- mediaType: z37.enum(MEDIA_TYPES),
8635
- originalUrl: z37.union([
8699
+ var MixRequest = z38.object({
8700
+ mediaType: z38.enum(MEDIA_TYPES),
8701
+ originalUrl: z38.union([
8636
8702
  PublicHttpsUrl,
8637
8703
  InternalAssetPath
8638
8704
  ]),
8639
8705
  axes: MixAxes,
8640
8706
  references: MixReferences,
8641
- personText: z37.string().max(500).optional(),
8642
- settingText: z37.string().max(500).optional(),
8707
+ personText: z38.string().max(500).optional(),
8708
+ settingText: z38.string().max(500).optional(),
8643
8709
  /**
8644
8710
  * Optional public URL of a user-uploaded audio file (mp3/wav). Wan Video
8645
8711
  * Edit has no audio input and the mix never lipsyncs: the Wan output is
@@ -8648,11 +8714,11 @@ var MixRequest = z37.object({
8648
8714
  * (mute + overlay). No per-scene slicing, no `reference_audio_urls`.
8649
8715
  */
8650
8716
  audioUrl: PublicHttpsUrl.optional(),
8651
- resolution: z37.enum(RESOLUTIONS).default("720p"),
8652
- originalDurationSec: z37.number().positive().max(600).optional(),
8717
+ resolution: z38.enum(RESOLUTIONS).default("720p"),
8718
+ originalDurationSec: z38.number().positive().max(600).optional(),
8653
8719
  image: MixImageEdit.optional(),
8654
- sourceTaskId: z37.string().max(64).optional(),
8655
- sourceCreativeId: z37.string().max(64).optional()
8720
+ sourceTaskId: z38.string().max(64).optional(),
8721
+ sourceCreativeId: z38.string().max(64).optional()
8656
8722
  }).superRefine((req, ctx) => {
8657
8723
  if (req.mediaType === "image") {
8658
8724
  if (!req.image) {
@@ -8686,18 +8752,18 @@ var MixRequest = z37.object({
8686
8752
  });
8687
8753
  }
8688
8754
  });
8689
- var ReferenceMap = z37.object({
8690
- product: z37.object({
8691
- start: z37.number().int(),
8692
- end: z37.number().int()
8755
+ var ReferenceMap = z38.object({
8756
+ product: z38.object({
8757
+ start: z38.number().int(),
8758
+ end: z38.number().int()
8693
8759
  }).optional(),
8694
- person: z37.object({
8695
- start: z37.number().int(),
8696
- end: z37.number().int()
8760
+ person: z38.object({
8761
+ start: z38.number().int(),
8762
+ end: z38.number().int()
8697
8763
  }).optional(),
8698
- setting: z37.object({
8699
- start: z37.number().int(),
8700
- end: z37.number().int()
8764
+ setting: z38.object({
8765
+ start: z38.number().int(),
8766
+ end: z38.number().int()
8701
8767
  }).optional()
8702
8768
  });
8703
8769
  var SCENE_CLIP_TYPES = [
@@ -8713,39 +8779,39 @@ var INSTANCE_CARDINALITIES = [
8713
8779
  "multiple_same",
8714
8780
  "multiple_distinct"
8715
8781
  ];
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),
8782
+ var SceneSegment = z38.object({
8783
+ index: z38.number().int().positive(),
8784
+ startTs: z38.number().nonnegative(),
8785
+ endTs: z38.number().positive(),
8786
+ seedanceDuration: z38.number().int().min(4).max(15),
8721
8787
  // Pass 1 / Pass 2 outputs (all optional — populated when the rich analyzer
8722
8788
  // 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(),
8789
+ action: z38.string().optional(),
8790
+ motion: z38.string().optional(),
8791
+ clipType: z38.enum(SCENE_CLIP_TYPES).optional(),
8792
+ hasCharacter: z38.boolean().optional(),
8793
+ faceVisible: z38.boolean().optional(),
8728
8794
  // 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(),
8795
+ startState: z38.string().optional(),
8796
+ endState: z38.string().optional(),
8797
+ cameraMovement: z38.string().optional(),
8798
+ emotion: z38.string().optional(),
8799
+ productPlacement: z38.string().optional(),
8800
+ productInteraction: z38.string().optional(),
8801
+ settingDescription: z38.string().optional(),
8802
+ dialogue: z38.string().optional(),
8737
8803
  // 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(),
8804
+ mainPersonDescription: z38.string().optional(),
8805
+ mainProductDescription: z38.string().optional(),
8806
+ personInstances: z38.enum(INSTANCE_CARDINALITIES).optional(),
8807
+ productInstances: z38.enum(INSTANCE_CARDINALITIES).optional(),
8742
8808
  /**
8743
8809
  * Seconds of prev-clipType content absorbed at the start of this scene by
8744
8810
  * Pass 2.7's clipType boundary margin. When > 0 and the scene is a
8745
8811
  * pass-through (no Seedance), the concatenator prepends a held-still
8746
8812
  * preamble (nano-banana-swapped first frame) to hide the leak.
8747
8813
  */
8748
- absorbedMarginSec: z37.number().nonnegative().optional(),
8814
+ absorbedMarginSec: z38.number().nonnegative().optional(),
8749
8815
  /**
8750
8816
  * True when the scene shows post-production graphics baked into the frame:
8751
8817
  * caption/subtitle text, infographic overlay cards, or inset
@@ -8754,33 +8820,39 @@ var SceneSegment = z37.object({
8754
8820
  * (mentioning nonexistent overlays gives the generator license to
8755
8821
  * fabricate them).
8756
8822
  */
8757
- hasOverlayGraphics: z37.boolean().optional()
8823
+ hasOverlayGraphics: z38.boolean().optional()
8758
8824
  });
8759
- var MixSceneResult = z37.object({
8760
- index: z37.number().int().positive(),
8761
- status: z37.enum([
8825
+ var MixSceneResult = z38.object({
8826
+ index: z38.number().int().positive(),
8827
+ status: z38.enum([
8762
8828
  "queued",
8763
8829
  "submitted",
8764
8830
  "done",
8765
8831
  "failed"
8766
8832
  ]),
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([
8833
+ seedanceTaskId: z38.string().optional(),
8834
+ videoUrl: z38.string().url().optional(),
8835
+ error: z38.string().optional(),
8836
+ degradedReason: MixDegradationReasonSchema.optional()
8837
+ });
8838
+ var MixResult = z38.object({
8839
+ mixTaskId: z38.string().uuid(),
8840
+ status: z38.enum([
8774
8841
  "queued",
8775
8842
  "processing",
8776
8843
  "done",
8777
8844
  "error"
8778
8845
  ]),
8779
- resultUrl: z37.string().url().optional(),
8780
- scenes: z37.array(MixSceneResult).default([]),
8781
- failReason: z37.string().optional()
8846
+ resultUrl: z38.string().url().optional(),
8847
+ scenes: z38.array(MixSceneResult).default([]),
8848
+ failReason: z38.string().optional(),
8849
+ degradedReason: MixDegradationReasonSchema.optional()
8782
8850
  });
8783
8851
 
8852
+ // ../../packages/types/src/mix-cost.ts
8853
+ var MAX_QA_RETRIES_PER_SCENE_UPPER_BOUND = 1;
8854
+ var MAX_BILLABLE_GENERATIONS_PER_BLOCK = 1 + MAX_QA_RETRIES_PER_SCENE_UPPER_BOUND;
8855
+
8784
8856
  // ../../packages/types/src/product-delivery-format.ts
8785
8857
  var DELIVERY_FAMILIES = [
8786
8858
  "solid_dose",
@@ -8869,41 +8941,41 @@ var DECLARATION = DELIVERY_FAMILIES.map((family) => [
8869
8941
  ]);
8870
8942
 
8871
8943
  // ../../packages/types/src/task-type.ts
8872
- import { z as z38 } from "zod";
8873
- var TaskTypeSchema = z38.enum([
8944
+ import { z as z39 } from "zod";
8945
+ var TaskTypeSchema = z39.enum([
8874
8946
  "product",
8875
8947
  "service"
8876
8948
  ]);
8877
8949
 
8878
8950
  // ../../packages/types/src/landing-regeneration.ts
8879
- import { z as z39 } from "zod";
8880
- var LandingRegenerationStatus = z39.enum([
8951
+ import { z as z40 } from "zod";
8952
+ var LandingRegenerationStatus = z40.enum([
8881
8953
  "queued",
8882
8954
  "processing",
8883
8955
  "published",
8884
8956
  "failed"
8885
8957
  ]);
8886
- var RegenerateLandingRoleResponse = z39.object({
8887
- ok: z39.literal(true),
8958
+ var RegenerateLandingRoleResponse = z40.object({
8959
+ ok: z40.literal(true),
8888
8960
  role: LandingRole,
8889
- promptIndex: z39.number().int().nonnegative(),
8890
- operationId: z39.string().min(1)
8961
+ promptIndex: z40.number().int().nonnegative(),
8962
+ operationId: z40.string().min(1)
8891
8963
  });
8892
- var LandingRegenerationStatusResponse = z39.object({
8893
- ok: z39.literal(true),
8894
- operationId: z39.string().min(1),
8964
+ var LandingRegenerationStatusResponse = z40.object({
8965
+ ok: z40.literal(true),
8966
+ operationId: z40.string().min(1),
8895
8967
  role: LandingRole,
8896
8968
  status: LandingRegenerationStatus,
8897
- refunded: z39.boolean(),
8898
- failureReason: z39.string().nullable(),
8899
- publishedAssetKey: z39.string().nullable(),
8900
- updatedAt: z39.string().datetime()
8969
+ refunded: z40.boolean(),
8970
+ failureReason: z40.string().nullable(),
8971
+ publishedAssetKey: z40.string().nullable(),
8972
+ updatedAt: z40.string().datetime()
8901
8973
  });
8902
8974
 
8903
8975
  // ../../packages/types/src/video-edit.ts
8904
- import { z as z40 } from "zod";
8976
+ import { z as z41 } from "zod";
8905
8977
  var MAX_SEGMENT_SECONDS = 3;
8906
- var VideoEditStatusSchema = z40.enum([
8978
+ var VideoEditStatusSchema = z41.enum([
8907
8979
  "pending",
8908
8980
  "processing",
8909
8981
  "assembling",
@@ -8912,9 +8984,9 @@ var VideoEditStatusSchema = z40.enum([
8912
8984
  "discarded",
8913
8985
  "failed"
8914
8986
  ]);
8915
- var VideoEditTimeSectionSchema = z40.object({
8916
- startSec: z40.number().min(0),
8917
- endSec: z40.number().positive()
8987
+ var VideoEditTimeSectionSchema = z41.object({
8988
+ startSec: z41.number().min(0),
8989
+ endSec: z41.number().positive()
8918
8990
  }).refine((v) => v.endSec > v.startSec, {
8919
8991
  message: "endSec must be after startSec",
8920
8992
  path: [
@@ -8926,45 +8998,45 @@ var VideoEditTimeSectionSchema = z40.object({
8926
8998
  "endSec"
8927
8999
  ]
8928
9000
  });
8929
- var VideoEditRequestSchema = z40.object({
8930
- comment: z40.string().trim().min(1).max(2e3),
8931
- sections: z40.array(VideoEditTimeSectionSchema).min(1).optional()
9001
+ var VideoEditRequestSchema = z41.object({
9002
+ comment: z41.string().trim().min(1).max(2e3),
9003
+ sections: z41.array(VideoEditTimeSectionSchema).min(1).optional()
8932
9004
  });
8933
- var VideoEditModeSchema = z40.enum([
9005
+ var VideoEditModeSchema = z41.enum([
8934
9006
  "wan_edit",
8935
9007
  "regenerate"
8936
9008
  ]);
8937
- var VideoRegenerationEngineSchema = z40.enum([
9009
+ var VideoRegenerationEngineSchema = z41.enum([
8938
9010
  "free_text",
8939
9011
  "free_image",
8940
9012
  "single_call",
8941
9013
  "multi_shot"
8942
9014
  ]);
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)
9015
+ var VideoRegenerationRouteFingerprintSchema = z41.string().trim().min(1).max(128);
9016
+ var RegenerateEditRequestSchema = z41.object({
9017
+ angleKey: z41.string().min(1),
9018
+ comment: z41.string().min(1).max(2e3)
8947
9019
  });
8948
9020
 
8949
9021
  // ../../packages/types/src/uploaded-asset.ts
8950
- import { z as z41 } from "zod";
8951
- var UploadedAssetMediaKind = z41.enum([
9022
+ import { z as z42 } from "zod";
9023
+ var UploadedAssetMediaKind = z42.enum([
8952
9024
  "image",
8953
9025
  "video"
8954
9026
  ]);
8955
- var UploadedAssetSessionMediaKind = z41.enum([
9027
+ var UploadedAssetSessionMediaKind = z42.enum([
8956
9028
  "image",
8957
9029
  "video",
8958
9030
  "mixed"
8959
9031
  ]);
8960
- var UploadedAssetRole = z41.enum([
9032
+ var UploadedAssetRole = z42.enum([
8961
9033
  "media",
8962
9034
  "thumbnail"
8963
9035
  ]);
8964
9036
  var UPLOADED_ASSET_MAX_FILES = 10;
8965
9037
  var UPLOADED_ASSET_IMAGE_MAX_FILES = 5;
8966
- var UploadedAssetId = z41.string().uuid();
8967
- var HttpsUrl = z41.string().url().refine((value) => {
9038
+ var UploadedAssetId = z42.string().uuid();
9039
+ var HttpsUrl = z42.string().url().refine((value) => {
8968
9040
  try {
8969
9041
  const url = new URL(value);
8970
9042
  return url.protocol === "https:" && !url.username && !url.password;
@@ -8972,23 +9044,23 @@ var HttpsUrl = z41.string().url().refine((value) => {
8972
9044
  return false;
8973
9045
  }
8974
9046
  }, "URL must use https");
8975
- var UtcDateTime = z41.string().datetime().refine((value) => {
9047
+ var UtcDateTime = z42.string().datetime().refine((value) => {
8976
9048
  const parts = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?Z$/.exec(value);
8977
9049
  const timestamp = Date.parse(value);
8978
9050
  if (!parts || Number.isNaN(timestamp)) return false;
8979
9051
  const date = new Date(timestamp);
8980
9052
  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
9053
  }, "datetime must be a valid UTC calendar instant");
8982
- var UploadedAssetRef = z41.object({
9054
+ var UploadedAssetRef = z42.object({
8983
9055
  assetId: UploadedAssetId
8984
9056
  }).strict();
8985
9057
  var UploadedAssetCompletion = UploadedAssetRef.extend({
8986
9058
  mediaKind: UploadedAssetMediaKind,
8987
9059
  assetRole: UploadedAssetRole
8988
9060
  }).strict();
8989
- var UploadedAssetMetadata = z41.object({
9061
+ var UploadedAssetMetadata = z42.object({
8990
9062
  assetId: UploadedAssetId,
8991
- ownerId: z41.string().min(1),
9063
+ ownerId: z42.string().min(1),
8992
9064
  mediaKind: UploadedAssetMediaKind,
8993
9065
  assetRole: UploadedAssetRole,
8994
9066
  createdAt: UtcDateTime,
@@ -8996,7 +9068,7 @@ var UploadedAssetMetadata = z41.object({
8996
9068
  }).strict().superRefine((value, ctx) => {
8997
9069
  if (Date.parse(value.expiresAt) <= Date.parse(value.createdAt)) {
8998
9070
  ctx.addIssue({
8999
- code: z41.ZodIssueCode.custom,
9071
+ code: z42.ZodIssueCode.custom,
9000
9072
  path: [
9001
9073
  "expiresAt"
9002
9074
  ],
@@ -9004,27 +9076,27 @@ var UploadedAssetMetadata = z41.object({
9004
9076
  });
9005
9077
  }
9006
9078
  });
9007
- var MediaSourceRef = z41.object({
9079
+ var MediaSourceRef = z42.object({
9008
9080
  url: HttpsUrl.optional(),
9009
- path: z41.string().min(1).optional(),
9081
+ path: z42.string().min(1).optional(),
9010
9082
  assetId: UploadedAssetId.optional()
9011
9083
  }).strict().superRefine((value, ctx) => {
9012
9084
  const sourceCount = Number(value.url !== void 0) + Number(value.path !== void 0) + Number(value.assetId !== void 0);
9013
9085
  if (sourceCount !== 1) {
9014
9086
  ctx.addIssue({
9015
- code: z41.ZodIssueCode.custom,
9087
+ code: z42.ZodIssueCode.custom,
9016
9088
  message: "media source needs exactly one of url, path, or assetId"
9017
9089
  });
9018
9090
  }
9019
9091
  });
9020
- var UploadedAssetSessionRequest = z41.object({
9092
+ var UploadedAssetSessionRequest = z42.object({
9021
9093
  mediaKind: UploadedAssetSessionMediaKind,
9022
9094
  assetRole: UploadedAssetRole.default("media"),
9023
- maxFiles: z41.number().int().min(1).max(UPLOADED_ASSET_MAX_FILES).optional()
9095
+ maxFiles: z42.number().int().min(1).max(UPLOADED_ASSET_MAX_FILES).optional()
9024
9096
  }).strict().superRefine((value, ctx) => {
9025
9097
  if (value.mediaKind === "mixed" && value.assetRole === "thumbnail") {
9026
9098
  ctx.addIssue({
9027
- code: z41.ZodIssueCode.custom,
9099
+ code: z42.ZodIssueCode.custom,
9028
9100
  path: [
9029
9101
  "mediaKind"
9030
9102
  ],
@@ -9033,7 +9105,7 @@ var UploadedAssetSessionRequest = z41.object({
9033
9105
  }
9034
9106
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
9035
9107
  ctx.addIssue({
9036
- code: z41.ZodIssueCode.custom,
9108
+ code: z42.ZodIssueCode.custom,
9037
9109
  path: [
9038
9110
  "maxFiles"
9039
9111
  ],
@@ -9042,7 +9114,7 @@ var UploadedAssetSessionRequest = z41.object({
9042
9114
  }
9043
9115
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > UPLOADED_ASSET_IMAGE_MAX_FILES) {
9044
9116
  ctx.addIssue({
9045
- code: z41.ZodIssueCode.custom,
9117
+ code: z42.ZodIssueCode.custom,
9046
9118
  path: [
9047
9119
  "maxFiles"
9048
9120
  ],
@@ -9051,7 +9123,7 @@ var UploadedAssetSessionRequest = z41.object({
9051
9123
  }
9052
9124
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
9053
9125
  ctx.addIssue({
9054
- code: z41.ZodIssueCode.custom,
9126
+ code: z42.ZodIssueCode.custom,
9055
9127
  path: [
9056
9128
  "mediaKind"
9057
9129
  ],
@@ -9059,32 +9131,32 @@ var UploadedAssetSessionRequest = z41.object({
9059
9131
  });
9060
9132
  }
9061
9133
  });
9062
- var UploadedAssetSessionStatus = z41.discriminatedUnion("status", [
9063
- z41.object({
9064
- status: z41.literal("pending"),
9065
- assets: z41.array(UploadedAssetCompletion).length(0)
9134
+ var UploadedAssetSessionStatus = z42.discriminatedUnion("status", [
9135
+ z42.object({
9136
+ status: z42.literal("pending"),
9137
+ assets: z42.array(UploadedAssetCompletion).length(0)
9066
9138
  }).strict(),
9067
- z41.object({
9068
- status: z41.literal("uploaded"),
9069
- assets: z41.array(UploadedAssetCompletion).min(1).max(UPLOADED_ASSET_MAX_FILES)
9139
+ z42.object({
9140
+ status: z42.literal("uploaded"),
9141
+ assets: z42.array(UploadedAssetCompletion).min(1).max(UPLOADED_ASSET_MAX_FILES)
9070
9142
  }).strict()
9071
9143
  ]);
9072
- var UploadedAssetAdoptionRequest = z41.object({
9144
+ var UploadedAssetAdoptionRequest = z42.object({
9073
9145
  assetId: UploadedAssetId,
9074
- ownerId: z41.string().min(1),
9075
- consumer: z41.string().min(1).max(100),
9076
- idempotencyKey: z41.string().min(1).max(255)
9146
+ ownerId: z42.string().min(1),
9147
+ consumer: z42.string().min(1).max(100),
9148
+ idempotencyKey: z42.string().min(1).max(255)
9077
9149
  }).strict();
9078
9150
 
9079
9151
  // ../../packages/types/src/dropshipping-project.ts
9080
- import { z as z42 } from "zod";
9081
- var DropshippingProjectStatusSchema = z42.enum([
9152
+ import { z as z43 } from "zod";
9153
+ var DropshippingProjectStatusSchema = z43.enum([
9082
9154
  "active",
9083
9155
  "completed",
9084
9156
  "archived"
9085
9157
  ]);
9086
9158
  var DROPSHIPPING_LAUNCH_REWARD_CAMPAIGN = "dropshipping-launch-v1";
9087
- var DropshippingRewardMilestoneSchema = z42.enum([
9159
+ var DropshippingRewardMilestoneSchema = z43.enum([
9088
9160
  "product_selected",
9089
9161
  "costing_saved",
9090
9162
  "product_media_ready",
@@ -9099,21 +9171,21 @@ var DROPSHIPPING_LAUNCH_REWARD_CREDITS = {
9099
9171
  campaign_created: 200
9100
9172
  };
9101
9173
  var DROPSHIPPING_LAUNCH_REWARD_TOTAL_CREDITS = Object.values(DROPSHIPPING_LAUNCH_REWARD_CREDITS).reduce((sum, credits) => sum + credits, 0);
9102
- var DropshippingProjectRewardMilestoneStateSchema = z42.object({
9174
+ var DropshippingProjectRewardMilestoneStateSchema = z43.object({
9103
9175
  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([
9176
+ credits: z43.number().int().positive(),
9177
+ available: z43.boolean().optional(),
9178
+ earned: z43.boolean(),
9179
+ grantId: z43.string().uuid().nullable(),
9180
+ grantedAt: z43.string().datetime().nullable()
9181
+ });
9182
+ var DropshippingProjectRewardProgressSchema = z43.object({
9183
+ campaignKey: z43.literal(DROPSHIPPING_LAUNCH_REWARD_CAMPAIGN),
9184
+ totalCredits: z43.number().int().positive(),
9185
+ earnedCredits: z43.number().int().nonnegative(),
9186
+ milestones: z43.array(DropshippingProjectRewardMilestoneStateSchema).length(DropshippingRewardMilestoneSchema.options.length)
9187
+ });
9188
+ var DropshippingProjectPhaseSchema = z43.enum([
9117
9189
  "research",
9118
9190
  "costing",
9119
9191
  "media",
@@ -9122,18 +9194,18 @@ var DropshippingProjectPhaseSchema = z42.enum([
9122
9194
  "advertising",
9123
9195
  "complete"
9124
9196
  ]);
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)
9197
+ var DropshippingProjectCostingInputSchema = z43.object({
9198
+ country: z43.string().min(2).max(3),
9199
+ supplierCost: z43.number().finite().positive(),
9200
+ shippingCost: z43.number().finite().nonnegative(),
9201
+ returnRate: z43.number().finite().min(0).lt(1),
9202
+ cancellationRate: z43.number().finite().min(0).lt(1),
9203
+ adsManagerCpa: z43.number().finite().nonnegative(),
9204
+ desiredMargin: z43.number().finite().min(0).lt(1)
9133
9205
  }).superRefine(({ returnRate, cancellationRate }, context) => {
9134
9206
  if (returnRate + cancellationRate >= 1) {
9135
9207
  context.addIssue({
9136
- code: z42.ZodIssueCode.custom,
9208
+ code: z43.ZodIssueCode.custom,
9137
9209
  path: [
9138
9210
  "cancellationRate"
9139
9211
  ],
@@ -9141,24 +9213,24 @@ var DropshippingProjectCostingInputSchema = z42.object({
9141
9213
  });
9142
9214
  }
9143
9215
  });
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) => {
9216
+ var DropshippingProjectCostingResultSchema = z43.object({
9217
+ country: z43.string().min(2).max(3),
9218
+ deliveryRate: z43.number().finite(),
9219
+ adjustedShippingCost: z43.number().finite(),
9220
+ adjustedCpa: z43.number().finite(),
9221
+ totalCost: z43.number().finite(),
9222
+ suggestedPrice: z43.number().finite(),
9223
+ baseCommercialPrice: z43.number().finite(),
9224
+ minimumSafePrice: z43.number().finite(),
9225
+ commercialPrice: z43.number().finite(),
9226
+ comparisonPrice: z43.number().finite(),
9227
+ estimatedProfit: z43.number().finite(),
9228
+ actualMargin: z43.number().finite(),
9229
+ breakEvenAdsManagerCpa: z43.number().finite(),
9230
+ wasPriceAutoAdjusted: z43.boolean(),
9231
+ profitabilityStatus: z43.literal("healthy")
9232
+ });
9233
+ var HttpUrlSchema = z43.string().url().max(2e3).refine((value) => {
9162
9234
  try {
9163
9235
  return [
9164
9236
  "http:",
@@ -9168,124 +9240,124 @@ var HttpUrlSchema = z42.string().url().max(2e3).refine((value) => {
9168
9240
  return false;
9169
9241
  }
9170
9242
  }, "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", [
9243
+ var ResearchCandidateOriginSchema = z43.object({
9244
+ type: z43.literal("research_candidate"),
9245
+ runId: z43.string().uuid(),
9246
+ candidateSourceId: z43.string().min(1).max(160)
9247
+ });
9248
+ var TaskOriginSchema = z43.object({
9249
+ type: z43.literal("task"),
9250
+ taskId: z43.string().uuid()
9251
+ });
9252
+ var ManualOriginSchema = z43.object({
9253
+ type: z43.literal("manual"),
9254
+ clientRequestId: z43.string().uuid(),
9255
+ country: z43.string().min(2).max(3).optional()
9256
+ });
9257
+ var CreateDropshippingProjectRequestSchema = z43.object({
9258
+ origin: z43.discriminatedUnion("type", [
9187
9259
  ResearchCandidateOriginSchema,
9188
9260
  TaskOriginSchema,
9189
9261
  ManualOriginSchema
9190
9262
  ]),
9191
- productName: z42.string().trim().min(1).max(240).optional(),
9263
+ productName: z43.string().trim().min(1).max(240).optional(),
9192
9264
  productUrl: HttpUrlSchema.optional(),
9193
- country: z42.string().min(2).max(3).optional(),
9194
- languageCode: z42.string().min(2).max(16).optional()
9265
+ country: z43.string().min(2).max(3).optional(),
9266
+ languageCode: z43.string().min(2).max(16).optional()
9195
9267
  }).strict();
9196
- var SaveDropshippingProjectCostingRequestSchema = z42.object({
9268
+ var SaveDropshippingProjectCostingRequestSchema = z43.object({
9197
9269
  input: DropshippingProjectCostingInputSchema,
9198
- version: z42.number().int().positive()
9270
+ version: z43.number().int().positive()
9199
9271
  }).strict();
9200
- var DropshippingProjectNextActionSchema = z42.discriminatedUnion("kind", [
9201
- z42.object({
9202
- kind: z42.literal("cost_product"),
9203
- href: z42.string().min(1)
9272
+ var DropshippingProjectNextActionSchema = z43.discriminatedUnion("kind", [
9273
+ z43.object({
9274
+ kind: z43.literal("cost_product"),
9275
+ href: z43.string().min(1)
9204
9276
  }),
9205
- z42.object({
9206
- kind: z42.literal("provide_product_media"),
9207
- href: z42.string().min(1)
9277
+ z43.object({
9278
+ kind: z43.literal("provide_product_media"),
9279
+ href: z43.string().min(1)
9208
9280
  }),
9209
- z42.object({
9210
- kind: z42.literal("generate_creatives"),
9211
- href: z42.string().min(1)
9281
+ z43.object({
9282
+ kind: z43.literal("generate_creatives"),
9283
+ href: z43.string().min(1)
9212
9284
  }),
9213
- z42.object({
9214
- kind: z42.literal("wait_for_creatives"),
9215
- href: z42.string().min(1)
9285
+ z43.object({
9286
+ kind: z43.literal("wait_for_creatives"),
9287
+ href: z43.string().min(1)
9216
9288
  }),
9217
- z42.object({
9218
- kind: z42.literal("repair_creatives"),
9219
- href: z42.string().min(1)
9289
+ z43.object({
9290
+ kind: z43.literal("repair_creatives"),
9291
+ href: z43.string().min(1)
9220
9292
  }),
9221
- z42.object({
9222
- kind: z42.literal("complete_creative_set"),
9223
- href: z42.string().min(1)
9293
+ z43.object({
9294
+ kind: z43.literal("complete_creative_set"),
9295
+ href: z43.string().min(1)
9224
9296
  }),
9225
- z42.object({
9226
- kind: z42.literal("connect_shopify"),
9227
- href: z42.string().min(1)
9297
+ z43.object({
9298
+ kind: z43.literal("connect_shopify"),
9299
+ href: z43.string().min(1)
9228
9300
  }),
9229
- z42.object({
9230
- kind: z42.literal("publish_storefront"),
9231
- href: z42.string().min(1)
9301
+ z43.object({
9302
+ kind: z43.literal("publish_storefront"),
9303
+ href: z43.string().min(1)
9232
9304
  }),
9233
- z42.object({
9234
- kind: z42.literal("wait_for_storefront"),
9235
- href: z42.string().min(1)
9305
+ z43.object({
9306
+ kind: z43.literal("wait_for_storefront"),
9307
+ href: z43.string().min(1)
9236
9308
  }),
9237
- z42.object({
9238
- kind: z42.literal("connect_meta"),
9239
- href: z42.string().min(1)
9309
+ z43.object({
9310
+ kind: z43.literal("connect_meta"),
9311
+ href: z43.string().min(1)
9240
9312
  }),
9241
- z42.object({
9242
- kind: z42.literal("create_meta_campaign"),
9243
- href: z42.string().min(1)
9313
+ z43.object({
9314
+ kind: z43.literal("create_meta_campaign"),
9315
+ href: z43.string().min(1)
9244
9316
  }),
9245
- z42.object({
9246
- kind: z42.literal("repair_meta_campaign"),
9247
- href: z42.string().min(1)
9317
+ z43.object({
9318
+ kind: z43.literal("repair_meta_campaign"),
9319
+ href: z43.string().min(1)
9248
9320
  }),
9249
- z42.object({
9250
- kind: z42.literal("review_paused_campaign"),
9251
- href: z42.string().min(1)
9321
+ z43.object({
9322
+ kind: z43.literal("review_paused_campaign"),
9323
+ href: z43.string().min(1)
9252
9324
  })
9253
9325
  ]);
9254
- var DropshippingProjectResponseSchema = z42.object({
9255
- id: z42.string().uuid(),
9256
- taskId: z42.string().uuid().nullable(),
9326
+ var DropshippingProjectResponseSchema = z43.object({
9327
+ id: z43.string().uuid(),
9328
+ taskId: z43.string().uuid().nullable(),
9257
9329
  status: DropshippingProjectStatusSchema,
9258
- originKey: z42.string().min(1),
9259
- researchRunId: z42.string().uuid().nullable(),
9260
- candidateSourceId: z42.string().nullable(),
9261
- productName: z42.string().nullable(),
9330
+ originKey: z43.string().min(1),
9331
+ researchRunId: z43.string().uuid().nullable(),
9332
+ candidateSourceId: z43.string().nullable(),
9333
+ productName: z43.string().nullable(),
9262
9334
  productUrl: HttpUrlSchema.nullable(),
9263
- referenceImageUrl: z42.string().url().nullable(),
9264
- hasReferenceImage: z42.boolean(),
9265
- targetCountry: z42.string().nullable(),
9266
- languageCode: z42.string().nullable(),
9335
+ referenceImageUrl: z43.string().url().nullable(),
9336
+ hasReferenceImage: z43.boolean(),
9337
+ targetCountry: z43.string().nullable(),
9338
+ languageCode: z43.string().nullable(),
9267
9339
  costingInput: DropshippingProjectCostingInputSchema.nullable(),
9268
9340
  costingResult: DropshippingProjectCostingResultSchema.nullable(),
9269
- costingVersion: z42.number().int().positive().nullable(),
9270
- version: z42.number().int().positive(),
9341
+ costingVersion: z43.number().int().positive().nullable(),
9342
+ version: z43.number().int().positive(),
9271
9343
  phase: DropshippingProjectPhaseSchema,
9272
9344
  nextAction: DropshippingProjectNextActionSchema.nullable(),
9273
9345
  rewards: DropshippingProjectRewardProgressSchema,
9274
- createdAt: z42.string().datetime(),
9275
- updatedAt: z42.string().datetime()
9346
+ createdAt: z43.string().datetime(),
9347
+ updatedAt: z43.string().datetime()
9276
9348
  });
9277
9349
 
9278
9350
  // ../../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)
9351
+ import { z as z44 } from "zod";
9352
+ var SceneSubjectContractSchema = z44.object({
9353
+ maxPeople: z44.number().int().min(1).max(10),
9354
+ minPeople: z44.number().int().min(0).max(10),
9355
+ minDistinctPeople: z44.number().int().min(0).max(10),
9356
+ maxHands: z44.number().int().min(0).max(20)
9285
9357
  }).superRefine((value, ctx) => {
9286
9358
  if (value.minPeople > value.maxPeople) {
9287
9359
  ctx.addIssue({
9288
- code: z43.ZodIssueCode.custom,
9360
+ code: z44.ZodIssueCode.custom,
9289
9361
  path: [
9290
9362
  "minPeople"
9291
9363
  ],
@@ -9294,7 +9366,7 @@ var SceneSubjectContractSchema = z43.object({
9294
9366
  }
9295
9367
  if (value.minDistinctPeople > value.maxPeople) {
9296
9368
  ctx.addIssue({
9297
- code: z43.ZodIssueCode.custom,
9369
+ code: z44.ZodIssueCode.custom,
9298
9370
  path: [
9299
9371
  "minDistinctPeople"
9300
9372
  ],
@@ -9303,7 +9375,7 @@ var SceneSubjectContractSchema = z43.object({
9303
9375
  }
9304
9376
  if (value.minDistinctPeople > value.minPeople) {
9305
9377
  ctx.addIssue({
9306
- code: z43.ZodIssueCode.custom,
9378
+ code: z44.ZodIssueCode.custom,
9307
9379
  path: [
9308
9380
  "minDistinctPeople"
9309
9381
  ],
@@ -9313,7 +9385,7 @@ var SceneSubjectContractSchema = z43.object({
9313
9385
  });
9314
9386
 
9315
9387
  // ../../packages/types/src/service-creative.ts
9316
- import { z as z44 } from "zod";
9388
+ import { z as z45 } from "zod";
9317
9389
  var SERVICE_CREATIVE_PUBLIC_PRESETS = [
9318
9390
  "auto",
9319
9391
  "ugc_dynamic",
@@ -9321,19 +9393,19 @@ var SERVICE_CREATIVE_PUBLIC_PRESETS = [
9321
9393
  "cinematic",
9322
9394
  "wild_card"
9323
9395
  ];
9324
- var ServiceCreativePresetSchema = z44.enum(SERVICE_CREATIVE_PUBLIC_PRESETS);
9396
+ var ServiceCreativePresetSchema = z45.enum(SERVICE_CREATIVE_PUBLIC_PRESETS);
9325
9397
  var SERVICE_REVIEW_MODES = [
9326
9398
  "automatic",
9327
9399
  "guided"
9328
9400
  ];
9329
- var ServiceReviewModeSchema = z44.enum(SERVICE_REVIEW_MODES);
9401
+ var ServiceReviewModeSchema = z45.enum(SERVICE_REVIEW_MODES);
9330
9402
  var SERVICE_HIGGSFIELD_MODES = [
9331
9403
  "product_review",
9332
9404
  "ugc_how_to",
9333
9405
  "tv_spot",
9334
9406
  "wild_card"
9335
9407
  ];
9336
- var ServiceHiggsfieldModeSchema = z44.enum(SERVICE_HIGGSFIELD_MODES);
9408
+ var ServiceHiggsfieldModeSchema = z45.enum(SERVICE_HIGGSFIELD_MODES);
9337
9409
  var SERVICE_MEDIA_ROLES = [
9338
9410
  "screen_demo",
9339
9411
  "ad_reference",
@@ -9341,20 +9413,20 @@ var SERVICE_MEDIA_ROLES = [
9341
9413
  "presenter_reference",
9342
9414
  "brand_asset"
9343
9415
  ];
9344
- var ServiceMediaRoleSchema = z44.enum(SERVICE_MEDIA_ROLES);
9345
- var ServiceMediaAssetSchema = z44.object({
9416
+ var ServiceMediaRoleSchema = z45.enum(SERVICE_MEDIA_ROLES);
9417
+ var ServiceMediaAssetSchema = z45.object({
9346
9418
  role: ServiceMediaRoleSchema,
9347
- s3Key: z44.string().min(1),
9419
+ s3Key: z45.string().min(1),
9348
9420
  /** 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()
9421
+ uploadToken: z45.string().min(1).optional(),
9422
+ mimeType: z45.string().min(1),
9423
+ durationSec: z45.number().positive().max(30).optional(),
9424
+ sourceName: z45.string().max(255).optional()
9353
9425
  }).superRefine((asset, ctx) => {
9354
9426
  const isVideoRole = asset.role === "screen_demo" || asset.role === "ad_reference";
9355
9427
  if (isVideoRole && !asset.mimeType.startsWith("video/")) {
9356
9428
  ctx.addIssue({
9357
- code: z44.ZodIssueCode.custom,
9429
+ code: z45.ZodIssueCode.custom,
9358
9430
  message: `${asset.role} requires video media`,
9359
9431
  path: [
9360
9432
  "mimeType"
@@ -9363,7 +9435,7 @@ var ServiceMediaAssetSchema = z44.object({
9363
9435
  }
9364
9436
  if (isVideoRole && asset.durationSec === void 0) {
9365
9437
  ctx.addIssue({
9366
- code: z44.ZodIssueCode.custom,
9438
+ code: z45.ZodIssueCode.custom,
9367
9439
  message: `${asset.role} requires durationSec`,
9368
9440
  path: [
9369
9441
  "durationSec"
@@ -9372,7 +9444,7 @@ var ServiceMediaAssetSchema = z44.object({
9372
9444
  }
9373
9445
  if (!isVideoRole && !asset.mimeType.startsWith("image/")) {
9374
9446
  ctx.addIssue({
9375
- code: z44.ZodIssueCode.custom,
9447
+ code: z45.ZodIssueCode.custom,
9376
9448
  message: `${asset.role} requires image media`,
9377
9449
  path: [
9378
9450
  "mimeType"
@@ -9380,13 +9452,13 @@ var ServiceMediaAssetSchema = z44.object({
9380
9452
  });
9381
9453
  }
9382
9454
  });
9383
- var ServiceMediaBundleSchema = z44.object({
9384
- assets: z44.array(ServiceMediaAssetSchema).max(15).default([])
9455
+ var ServiceMediaBundleSchema = z45.object({
9456
+ assets: z45.array(ServiceMediaAssetSchema).max(15).default([])
9385
9457
  }).superRefine((bundle, ctx) => {
9386
9458
  const adReferences = bundle.assets.filter((asset) => asset.role === "ad_reference");
9387
9459
  if (adReferences.length > 5) {
9388
9460
  ctx.addIssue({
9389
- code: z44.ZodIssueCode.custom,
9461
+ code: z45.ZodIssueCode.custom,
9390
9462
  message: "A maximum of five ad_reference videos is allowed",
9391
9463
  path: [
9392
9464
  "assets"
@@ -9396,7 +9468,7 @@ var ServiceMediaBundleSchema = z44.object({
9396
9468
  const screenDemos = bundle.assets.filter((asset) => asset.role === "screen_demo");
9397
9469
  if (screenDemos.length > 3) {
9398
9470
  ctx.addIssue({
9399
- code: z44.ZodIssueCode.custom,
9471
+ code: z45.ZodIssueCode.custom,
9400
9472
  message: "A maximum of three screen_demo videos is allowed",
9401
9473
  path: [
9402
9474
  "assets"
@@ -9413,33 +9485,33 @@ var SERVICE_MEDIA_ANALYSIS_KINDS = [
9413
9485
  "product",
9414
9486
  "other"
9415
9487
  ];
9416
- var ServiceMediaAnalysisKindSchema = z44.enum(SERVICE_MEDIA_ANALYSIS_KINDS);
9417
- var ServiceMediaAnalysisItemSchema = z44.object({
9418
- assetIndex: z44.number().int().nonnegative(),
9419
- mediaType: z44.enum([
9488
+ var ServiceMediaAnalysisKindSchema = z45.enum(SERVICE_MEDIA_ANALYSIS_KINDS);
9489
+ var ServiceMediaAnalysisItemSchema = z45.object({
9490
+ assetIndex: z45.number().int().nonnegative(),
9491
+ mediaType: z45.enum([
9420
9492
  "image",
9421
9493
  "video"
9422
9494
  ]),
9423
9495
  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}$/),
9496
+ description: z45.string().min(1).max(1200),
9497
+ tags: z45.array(z45.string().min(1).max(80)).max(12),
9498
+ suggestedRoles: z45.array(ServiceMediaRoleSchema).max(4),
9499
+ visiblePeople: z45.number().int().nonnegative().max(20).optional(),
9500
+ ocrText: z45.string().max(2e3).optional(),
9501
+ speechSummary: z45.string().max(2e3).optional()
9502
+ });
9503
+ var ServiceMediaAnalysisSchema = z45.object({
9504
+ version: z45.literal(1),
9505
+ analyzedAt: z45.string().datetime(),
9506
+ pricingAction: z45.literal("service-media-analysis"),
9507
+ assetFingerprint: z45.string().regex(/^[a-f0-9]{64}$/),
9436
9508
  /** Language used for human-readable descriptions and tags. Optional for old checkpoints. */
9437
- language: z44.enum([
9509
+ language: z45.enum([
9438
9510
  "es",
9439
9511
  "en",
9440
9512
  "pt"
9441
9513
  ]).optional(),
9442
- items: z44.array(ServiceMediaAnalysisItemSchema).max(15)
9514
+ items: z45.array(ServiceMediaAnalysisItemSchema).max(15)
9443
9515
  });
9444
9516
 
9445
9517
  // ../../packages/types/src/productmaker-capability-registry.ts
@@ -9956,7 +10028,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
9956
10028
  ], [
9957
10029
  "creative"
9958
10030
  ]),
9959
- defineCapability("generate_landing", "75947c5a70d26305ca07ab8d7bc0be710e862eb9319010ee66dd43e64fab2050", "credit_consuming", "creative", [
10031
+ defineCapability("generate_landing", "67520417176396516cd5ad358dca39f70a5c4a74169eecd85987217226c12251", "credit_consuming", "creative", [
9960
10032
  "credit_consuming",
9961
10033
  "state_change"
9962
10034
  ], [
@@ -10001,12 +10073,14 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
10001
10073
  "competitorScanEnabled",
10002
10074
  "landingStrategy",
10003
10075
  "landingImageFormat",
10076
+ "pauseForAngleReview",
10004
10077
  // MCP-only, like create_product_task's aiDecidesAll.
10005
10078
  "aiDecidesAll"
10006
10079
  ], [
10007
10080
  "competitorScanEnabled",
10008
10081
  "landingStrategy",
10009
- "landingImageFormat"
10082
+ "landingImageFormat",
10083
+ "pauseForAngleReview"
10010
10084
  ])
10011
10085
  ], [
10012
10086
  "product_reference"
@@ -10522,8 +10596,8 @@ var PRODUCTMAKER_MCP_CAPABILITIES = toLegacyCapabilityCatalog(PRODUCTMAKER_MCP_C
10522
10596
  var PRODUCTMAKER_MCP_CAPABILITY_NAMES = PRODUCTMAKER_MCP_CAPABILITY_REGISTRY.map((capability) => capability.name);
10523
10597
 
10524
10598
  // ../../packages/types/src/actor.ts
10525
- import { z as z45 } from "zod";
10526
- var ActorStatusSchema = z45.enum([
10599
+ import { z as z46 } from "zod";
10600
+ var ActorStatusSchema = z46.enum([
10527
10601
  "draft",
10528
10602
  "generating",
10529
10603
  "ready",
@@ -10532,18 +10606,18 @@ var ActorStatusSchema = z45.enum([
10532
10606
  var ACTOR_NAME_MAX_CHARS = 60;
10533
10607
  var ACTOR_DESCRIPTION_MAX_CHARS = 600;
10534
10608
  var ACTOR_CANDIDATE_COUNT = 4;
10535
- var ActorGenderSchema = z45.enum([
10609
+ var ActorGenderSchema = z46.enum([
10536
10610
  "female",
10537
10611
  "male",
10538
10612
  "non_binary"
10539
10613
  ]);
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),
10614
+ var ActorSchema = z46.object({
10615
+ id: z46.string(),
10616
+ name: z46.string().min(1).max(ACTOR_NAME_MAX_CHARS),
10617
+ description: z46.string().max(ACTOR_DESCRIPTION_MAX_CHARS),
10544
10618
  gender: ActorGenderSchema,
10545
- voiceId: z45.string().nullable().optional(),
10546
- brandId: z45.string().nullable().optional(),
10619
+ voiceId: z46.string().nullable().optional(),
10620
+ brandId: z46.string().nullable().optional(),
10547
10621
  status: ActorStatusSchema,
10548
10622
  /**
10549
10623
  * A candidate-grid run is in flight RIGHT NOW.
@@ -10555,36 +10629,36 @@ var ActorSchema = z45.object({
10555
10629
  * timestamp with a TTL, so an orphaned run reads as `false` instead of
10556
10630
  * pinning the personaje forever.
10557
10631
  */
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(),
10632
+ generating: z46.boolean().optional(),
10633
+ photoUrl: z46.string().url().nullable().optional(),
10634
+ avatarUrl: z46.string().url().nullable().optional(),
10635
+ candidateUrls: z46.array(z46.string().url()).optional(),
10562
10636
  /** Indices of candidateUrls that failed the anatomy check (Task 6). */
10563
- flaggedCandidateIndices: z45.array(z45.number().int()).optional()
10637
+ flaggedCandidateIndices: z46.array(z46.number().int()).optional()
10564
10638
  });
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(""),
10639
+ var CreateActorRequest = z46.object({
10640
+ name: z46.string().min(1).max(ACTOR_NAME_MAX_CHARS),
10641
+ description: z46.string().max(ACTOR_DESCRIPTION_MAX_CHARS).default(""),
10568
10642
  gender: ActorGenderSchema,
10569
- voiceId: z45.string().optional(),
10570
- brandId: z45.string().optional(),
10571
- sourcePhotoKey: z45.string().optional()
10643
+ voiceId: z46.string().optional(),
10644
+ brandId: z46.string().optional(),
10645
+ sourcePhotoKey: z46.string().optional()
10572
10646
  }).refine((v) => v.description.trim().length > 0 || !!v.sourcePhotoKey, {
10573
10647
  message: "Se necesita una descripci\xF3n o una foto"
10574
10648
  });
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(),
10649
+ var UpdateActorRequest = z46.object({
10650
+ name: z46.string().min(1).max(ACTOR_NAME_MAX_CHARS).optional(),
10651
+ description: z46.string().max(ACTOR_DESCRIPTION_MAX_CHARS).optional(),
10578
10652
  gender: ActorGenderSchema.optional(),
10579
- voiceId: z45.string().nullable().optional(),
10580
- brandId: z45.string().nullable().optional()
10653
+ voiceId: z46.string().nullable().optional(),
10654
+ brandId: z46.string().nullable().optional()
10581
10655
  });
10582
- var ApproveActorRequest = z45.object({
10583
- candidateIndex: z45.number().int().min(0).max(ACTOR_CANDIDATE_COUNT - 1)
10656
+ var ApproveActorRequest = z46.object({
10657
+ candidateIndex: z46.number().int().min(0).max(ACTOR_CANDIDATE_COUNT - 1)
10584
10658
  });
10585
10659
 
10586
10660
  // ../../packages/types/src/referral-dashboard.ts
10587
- import { z as z46 } from "zod";
10661
+ import { z as z47 } from "zod";
10588
10662
  var REFERRAL_DASHBOARD_RAW_STATUSES = [
10589
10663
  "ACTIVE",
10590
10664
  "PENDING",
@@ -10603,66 +10677,66 @@ var REFERRAL_DASHBOARD_PLAN_KINDS = [
10603
10677
  "last",
10604
10678
  "none"
10605
10679
  ];
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([
10680
+ var ReferralDashboardRawStatusSchema = z47.enum(REFERRAL_DASHBOARD_RAW_STATUSES);
10681
+ var ReferralDashboardStateSchema = z47.enum(REFERRAL_DASHBOARD_STATES);
10682
+ var ReferralDashboardPlanKindSchema = z47.enum(REFERRAL_DASHBOARD_PLAN_KINDS);
10683
+ var ReferralDashboardStatusSchema = z47.enum([
10610
10684
  "all",
10611
10685
  "active",
10612
10686
  "pending",
10613
10687
  "inactive"
10614
10688
  ]).default("all");
10615
- var ReferralDashboardPlanSchema = z46.string().trim().min(1).max(100).optional();
10616
- var ReferralDashboardFiltersSchema = z46.object({
10689
+ var ReferralDashboardPlanSchema = z47.string().trim().min(1).max(100).optional();
10690
+ var ReferralDashboardFiltersSchema = z47.object({
10617
10691
  status: ReferralDashboardStatusSchema,
10618
10692
  plan: ReferralDashboardPlanSchema
10619
10693
  });
10620
- var ReferralDashboardSubscriptionSchema = z46.object({
10621
- planName: z46.string().nullable(),
10694
+ var ReferralDashboardSubscriptionSchema = z47.object({
10695
+ planName: z47.string().nullable(),
10622
10696
  planKind: ReferralDashboardPlanKindSchema,
10623
10697
  rawStatus: ReferralDashboardRawStatusSchema.nullable(),
10624
10698
  state: ReferralDashboardStateSchema,
10625
- currentPeriodEnd: z46.string().datetime({
10699
+ currentPeriodEnd: z47.string().datetime({
10626
10700
  offset: true
10627
10701
  }).nullable(),
10628
- cancelAtPeriodEnd: z46.boolean()
10702
+ cancelAtPeriodEnd: z47.boolean()
10629
10703
  });
10630
- var ReferralDashboardReferralSchema = z46.object({
10631
- id: z46.string().min(1),
10632
- registeredAt: z46.string().datetime({
10704
+ var ReferralDashboardReferralSchema = z47.object({
10705
+ id: z47.string().min(1),
10706
+ registeredAt: z47.string().datetime({
10633
10707
  offset: true
10634
10708
  }),
10635
10709
  // Kept in the response for compatibility with existing referral API clients.
10636
10710
  // The referrer dashboard intentionally does not render these legacy fields.
10637
- expiresAt: z46.string().datetime({
10711
+ expiresAt: z47.string().datetime({
10638
10712
  offset: true
10639
10713
  }).nullable().optional(),
10640
- status: z46.string().min(1).optional(),
10641
- referredUser: z46.object({
10642
- email: z46.string().nullable()
10714
+ status: z47.string().min(1).optional(),
10715
+ referredUser: z47.object({
10716
+ email: z47.string().nullable()
10643
10717
  }),
10644
10718
  subscription: ReferralDashboardSubscriptionSchema
10645
10719
  });
10646
- var ReferralDashboardReferralsPageSchema = z46.object({
10647
- referrals: z46.array(ReferralDashboardReferralSchema),
10648
- total: z46.number().int().nonnegative()
10720
+ var ReferralDashboardReferralsPageSchema = z47.object({
10721
+ referrals: z47.array(ReferralDashboardReferralSchema),
10722
+ total: z47.number().int().nonnegative()
10649
10723
  });
10650
- var ReferralDashboardPlanBreakdownSchema = z46.object({
10651
- planName: z46.string().nullable(),
10652
- count: z46.number().int().nonnegative()
10724
+ var ReferralDashboardPlanBreakdownSchema = z47.object({
10725
+ planName: z47.string().nullable(),
10726
+ count: z47.number().int().nonnegative()
10653
10727
  });
10654
- var ReferralDashboardMonthlyRegistrationSchema = z46.object({
10655
- month: z46.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/),
10656
- count: z46.number().int().nonnegative()
10728
+ var ReferralDashboardMonthlyRegistrationSchema = z47.object({
10729
+ month: z47.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/),
10730
+ count: z47.number().int().nonnegative()
10657
10731
  });
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")
10732
+ var ReferralDashboardOverviewSchema = z47.object({
10733
+ totalReferredUsers: z47.number().int().nonnegative(),
10734
+ activeUsers: z47.number().int().nonnegative(),
10735
+ pendingUsers: z47.number().int().nonnegative(),
10736
+ inactiveUsers: z47.number().int().nonnegative(),
10737
+ noPlanUsers: z47.number().int().nonnegative(),
10738
+ planBreakdown: z47.array(ReferralDashboardPlanBreakdownSchema),
10739
+ monthlyRegistrations: z47.array(ReferralDashboardMonthlyRegistrationSchema).refine((months) => months.length === 6, "Expected six monthly registration buckets")
10666
10740
  });
10667
10741
 
10668
10742
  // src/resolve-media.ts
@@ -10905,10 +10979,10 @@ async function resolveMediaRef(ref, opts) {
10905
10979
  __name(resolveMediaRef, "resolveMediaRef");
10906
10980
 
10907
10981
  // 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([
10982
+ import { z as z48 } from "zod";
10983
+ var Lang = z48.string().min(2).max(10);
10984
+ var Country = z48.string().min(2).max(3);
10985
+ var LandingStrategyEnum = z48.enum([
10912
10986
  "auto",
10913
10987
  "classic",
10914
10988
  "pain_solution",
@@ -10917,12 +10991,12 @@ var LandingStrategyEnum = z47.enum([
10917
10991
  "offer_value",
10918
10992
  "lifestyle_identity"
10919
10993
  ]);
10920
- var LandingImageFormatEnum = z47.enum([
10994
+ var LandingImageFormatEnum = z48.enum([
10921
10995
  "9:16",
10922
10996
  "4:5",
10923
10997
  "1:1"
10924
10998
  ]);
10925
- var VideoPresetEnum = z47.enum([
10999
+ var VideoPresetEnum = z48.enum([
10926
11000
  "auto",
10927
11001
  "ugc_dynamic",
10928
11002
  "ugc_how_to",
@@ -10935,7 +11009,7 @@ var VideoPresetEnum = z47.enum([
10935
11009
  "pixar_problem",
10936
11010
  "pixar_sassy"
10937
11011
  ]);
10938
- var TaskCreativeVariantVideoPresetEnum = z47.enum([
11012
+ var TaskCreativeVariantVideoPresetEnum = z48.enum([
10939
11013
  "auto",
10940
11014
  "ugc_dynamic",
10941
11015
  "ugc_how_to",
@@ -11006,7 +11080,7 @@ function resolveVideoPreset(preset) {
11006
11080
  return VIDEO_PRESET_RESOLUTION[preset] ?? null;
11007
11081
  }
11008
11082
  __name(resolveVideoPreset, "resolveVideoPreset");
11009
- var VideoTierEnum = z47.enum([
11083
+ var VideoTierEnum = z48.enum([
11010
11084
  "basic"
11011
11085
  ]);
11012
11086
  function resolveVideoTier(_tier) {
@@ -11021,17 +11095,17 @@ function resolveVideoFormatForDuration(durationSeconds) {
11021
11095
  return durationSeconds === 30 ? "double_30s" : "single_15s";
11022
11096
  }
11023
11097
  __name(resolveVideoFormatForDuration, "resolveVideoFormatForDuration");
11024
- var VideoResolutionEnum = z47.enum([
11098
+ var VideoResolutionEnum = z48.enum([
11025
11099
  "480p",
11026
11100
  "720p"
11027
11101
  ]);
11028
- var VideoStyleEnum = z47.enum([
11102
+ var VideoStyleEnum = z48.enum([
11029
11103
  "ugc",
11030
11104
  "cartoon_3d",
11031
11105
  "product_only",
11032
11106
  "ai_dynamic"
11033
11107
  ]);
11034
- var NarrativeStyleEnum = z47.enum([
11108
+ var NarrativeStyleEnum = z48.enum([
11035
11109
  "review",
11036
11110
  "ugc_how_to",
11037
11111
  "problem_product_cta",
@@ -11048,7 +11122,7 @@ var NarrativeStyleEnum = z47.enum([
11048
11122
  "ugc_skeptic_confession",
11049
11123
  "ugc_demo_review"
11050
11124
  ]);
11051
- var PublicNarrativeStyleEnum = z47.enum([
11125
+ var PublicNarrativeStyleEnum = z48.enum([
11052
11126
  "review",
11053
11127
  "ugc_how_to",
11054
11128
  "ugc_unboxing_chaos",
@@ -11060,7 +11134,7 @@ var PublicNarrativeStyleEnum = z47.enum([
11060
11134
  "animated_problem_pixar",
11061
11135
  "sassy_product_pixar"
11062
11136
  ]);
11063
- var VideoModelEnum = z47.enum([
11137
+ var VideoModelEnum = z48.enum([
11064
11138
  "veo",
11065
11139
  "wan",
11066
11140
  "bytedance",
@@ -11068,29 +11142,29 @@ var VideoModelEnum = z47.enum([
11068
11142
  "grok",
11069
11143
  "kling"
11070
11144
  ]);
11071
- var ProductReferenceUserChoiceEnum = z47.enum([
11145
+ var ProductReferenceUserChoiceEnum = z48.enum([
11072
11146
  "same_product",
11073
11147
  "variants",
11074
11148
  "different_products",
11075
11149
  "combo_distinct"
11076
11150
  ]);
11077
- var ProductReferenceCandidateGroupingEnum = z47.enum([
11151
+ var ProductReferenceCandidateGroupingEnum = z48.enum([
11078
11152
  "same_product_same_variant",
11079
11153
  "same_product_different_variants",
11080
11154
  "different_products",
11081
11155
  "unclear"
11082
11156
  ]);
11083
- var ProductReferenceScopeEnum = z47.enum([
11157
+ var ProductReferenceScopeEnum = z48.enum([
11084
11158
  "base",
11085
11159
  "video_view_pack"
11086
11160
  ]);
11087
- var ProductReferenceResolutionDecisionEnum = z47.enum([
11161
+ var ProductReferenceResolutionDecisionEnum = z48.enum([
11088
11162
  "approve",
11089
11163
  "reject",
11090
11164
  "observed_only",
11091
11165
  "correct_view"
11092
11166
  ]);
11093
- var ProductReferenceRejectionReasonEnum = z47.enum([
11167
+ var ProductReferenceRejectionReasonEnum = z48.enum([
11094
11168
  "replacement_requested",
11095
11169
  "wrong_product_identity",
11096
11170
  "wrong_variant",
@@ -11101,13 +11175,13 @@ var ProductReferenceRejectionReasonEnum = z47.enum([
11101
11175
  "not_a_product_photo",
11102
11176
  "other"
11103
11177
  ]);
11104
- var GapDurationChoiceMirror = z47.object({
11105
- angleIndex: z47.number().int().nonnegative(),
11106
- recommendedSec: z47.union([
11107
- z47.literal(15),
11108
- z47.literal(30)
11178
+ var GapDurationChoiceMirror = z48.object({
11179
+ angleIndex: z48.number().int().nonnegative(),
11180
+ recommendedSec: z48.union([
11181
+ z48.literal(15),
11182
+ z48.literal(30)
11109
11183
  ]),
11110
- estimatedDeltaCredits: z47.number().int().nonnegative().optional()
11184
+ estimatedDeltaCredits: z48.number().int().nonnegative().optional()
11111
11185
  });
11112
11186
  function buildSelectedImageUrlsHash(urls) {
11113
11187
  const input = [
@@ -11117,13 +11191,13 @@ function buildSelectedImageUrlsHash(urls) {
11117
11191
  return `fnv1a:${hash.toString(16).padStart(8, "0")}:${urls.length}`;
11118
11192
  }
11119
11193
  __name(buildSelectedImageUrlsHash, "buildSelectedImageUrlsHash");
11120
- var ImageCreativeStyleEnum = z47.enum([
11194
+ var ImageCreativeStyleEnum = z48.enum([
11121
11195
  "studio",
11122
11196
  "floating",
11123
11197
  "ingredients",
11124
11198
  "in_use"
11125
11199
  ]);
11126
- var ImageCreativeArchetypeEnum = z47.enum([
11200
+ var ImageCreativeArchetypeEnum = z48.enum([
11127
11201
  "direct_response_product_ad",
11128
11202
  "hero_outcome",
11129
11203
  "offer_value_prop",
@@ -11132,20 +11206,20 @@ var ImageCreativeArchetypeEnum = z47.enum([
11132
11206
  "problem_solution",
11133
11207
  "lifestyle_identity"
11134
11208
  ]);
11135
- var ImageCreativeVisualTreatmentEnum = z47.enum([
11209
+ var ImageCreativeVisualTreatmentEnum = z48.enum([
11136
11210
  "performance_product_ad",
11137
11211
  "premium_dtc_carousel"
11138
11212
  ]);
11139
- var ImageCreativeAspectRatioEnum = z47.enum([
11213
+ var ImageCreativeAspectRatioEnum = z48.enum([
11140
11214
  "1:1",
11141
11215
  "4:5",
11142
11216
  "9:16",
11143
11217
  "16:9"
11144
11218
  ]);
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.")
11219
+ var ImageRefSchema = z48.object({
11220
+ 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.'),
11221
+ 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`.'),
11222
+ 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
11223
  }).refine((v) => [
11150
11224
  v.url,
11151
11225
  v.path,
@@ -11153,11 +11227,11 @@ var ImageRefSchema = z47.object({
11153
11227
  ].filter(Boolean).length === 1, {
11154
11228
  message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
11155
11229
  });
11156
- var ImagesInput = z47.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
11230
+ var ImagesInput = z48.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
11157
11231
  const assetCount = images.filter((image) => Boolean(image.assetId)).length;
11158
11232
  if (assetCount > 0 && assetCount !== images.length) {
11159
11233
  ctx.addIssue({
11160
- code: z47.ZodIssueCode.custom,
11234
+ code: z48.ZodIssueCode.custom,
11161
11235
  message: "all image entries must use assetId, or all must use URL/path sources"
11162
11236
  });
11163
11237
  }
@@ -11227,14 +11301,14 @@ async function submitCreative(api, opts) {
11227
11301
  });
11228
11302
  }
11229
11303
  __name(submitCreative, "submitCreative");
11230
- var ResearchTargetCountryEnum = z47.enum([
11304
+ var ResearchTargetCountryEnum = z48.enum([
11231
11305
  "CO",
11232
11306
  "MX",
11233
11307
  "PE",
11234
11308
  "EC",
11235
11309
  "CL"
11236
11310
  ]);
11237
- var ResearchCategoryEnum = z47.enum([
11311
+ var ResearchCategoryEnum = z48.enum([
11238
11312
  "auto",
11239
11313
  "automotive",
11240
11314
  "kitchen",
@@ -11935,54 +12009,54 @@ function renderOutputsMarkdown(outputs) {
11935
12009
  __name(renderOutputsMarkdown, "renderOutputsMarkdown");
11936
12010
 
11937
12011
  // src/tools/tasks.ts
11938
- var CreateProductTaskInput = z48.object({
12012
+ var CreateProductTaskInput = z49.object({
11939
12013
  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."),
12014
+ 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."),
12015
+ 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
12016
  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
12017
  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.'),
12018
+ 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.'),
12019
+ 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".'),
12020
+ 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.'),
12021
+ 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.'),
12022
+ 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."),
12023
+ 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
12024
  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)
12025
+ durationSeconds: z49.union([
12026
+ z49.literal(15),
12027
+ z49.literal(30)
11954
12028
  ]).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."),
12029
+ 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."),
12030
+ 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
12031
  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
12032
  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."),
12033
+ 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
12034
  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([
12035
+ outputs: z49.array(z49.enum([
11962
12036
  "landing",
11963
12037
  "video",
11964
12038
  "image"
11965
12039
  ])).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."),
12040
+ 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."),
12041
+ 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."),
12042
+ 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."),
12043
+ 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.'),
12044
+ 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."),
12045
+ 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
12046
  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
12047
  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
12048
  }).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.'),
12049
+ var CreateServiceVideoInput = z49.object({
12050
+ 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."),
12051
+ 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
12052
  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([
12053
+ 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.'),
12054
+ brandId: z49.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
12055
+ reviewMode: z49.enum([
11982
12056
  "automatic",
11983
12057
  "guided"
11984
12058
  ]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
11985
- videoPreset: z48.enum([
12059
+ videoPreset: z49.enum([
11986
12060
  "auto",
11987
12061
  "ugc_dynamic",
11988
12062
  "ugc_how_to",
@@ -11990,51 +12064,51 @@ var CreateServiceVideoInput = z48.object({
11990
12064
  "wild_card"
11991
12065
  ]).default("auto")
11992
12066
  }).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([
12067
+ var GetTaskStatusInput = z49.object({
12068
+ taskId: z49.string().min(1),
12069
+ waitSeconds: z49.number().int().min(0).max(120).optional()
12070
+ });
12071
+ var ListTasksInput = z49.object({
12072
+ limit: z49.number().int().min(1).max(50).optional(),
12073
+ offset: z49.number().int().min(0).optional(),
12074
+ search: z49.string().optional()
12075
+ });
12076
+ var EditTaskDraftInput = z49.object({
12077
+ taskId: z49.string().min(1),
12078
+ angleIndex: z49.number().int().min(0),
12079
+ angle: z49.object({
12080
+ angle: z49.string().min(1).max(480),
12081
+ buyerPersona: z49.string().min(1).max(360),
12082
+ actor: z49.string().min(1).max(360).optional(),
12083
+ 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."),
12084
+ gender: z49.enum([
12011
12085
  "female",
12012
12086
  "male"
12013
12087
  ]).optional(),
12014
- scriptNotes: z48.string().max(2e3).optional()
12088
+ scriptNotes: z49.string().max(2e3).optional()
12015
12089
  })
12016
12090
  });
12017
- var PendingActionPayload = z48.discriminatedUnion("kind", [
12018
- z48.object({
12019
- kind: z48.literal("product_reference_set_approval"),
12091
+ var PendingActionPayload = z49.discriminatedUnion("kind", [
12092
+ z49.object({
12093
+ kind: z49.literal("product_reference_set_approval"),
12020
12094
  scope: ProductReferenceScopeEnum,
12021
- scopeKey: z48.string().min(1).max(120),
12022
- scopeSnapshotId: z48.string().uuid(),
12023
- expectedScopeHash: z48.string().min(1).max(128),
12095
+ scopeKey: z49.string().min(1).max(120),
12096
+ scopeSnapshotId: z49.string().uuid(),
12097
+ expectedScopeHash: z49.string().min(1).max(128),
12024
12098
  decision: ProductReferenceResolutionDecisionEnum,
12025
12099
  reason: ProductReferenceRejectionReasonEnum.optional(),
12026
- affectedRefKeys: z48.array(z48.string().min(1).max(200)).min(1).optional(),
12027
- recoveryAction: z48.enum([
12100
+ affectedRefKeys: z49.array(z49.string().min(1).max(200)).min(1).optional(),
12101
+ recoveryAction: z49.enum([
12028
12102
  "remove",
12029
12103
  "replace",
12030
12104
  "upload",
12031
12105
  "return_to_selection"
12032
12106
  ]).optional()
12033
12107
  }),
12034
- z48.object({
12035
- kind: z48.literal("product_reference_confirmation"),
12108
+ z49.object({
12109
+ kind: z49.literal("product_reference_confirmation"),
12036
12110
  userChoice: ProductReferenceUserChoiceEnum.optional(),
12037
- confirmedProductNames: z48.array(z48.string().min(1).max(120)).min(2).max(8).optional(),
12111
+ confirmedProductNames: z49.array(z49.string().min(1).max(120)).min(2).max(8).optional(),
12038
12112
  // SCOPED multi-scene opt-in — the ONLY way STANDARD ("Multiescena") is
12039
12113
  // reachable via MCP. Valid ONLY together with userChoice='variants' (same
12040
12114
  // product in several colors): renders one shot per color and stitches them,
@@ -12045,50 +12119,50 @@ var PendingActionPayload = z48.discriminatedUnion("kind", [
12045
12119
  // safe because multi-scene IS the intended render for a color variant set,
12046
12120
  // not a blind quality upsell. Maps to `videoTier: 'standard'` on the
12047
12121
  // 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".')
12122
+ 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
12123
  }),
12050
- z48.object({
12051
- kind: z48.literal("angle_review_approval"),
12124
+ z49.object({
12125
+ kind: z49.literal("angle_review_approval"),
12052
12126
  // All edits are optional — empty action body just approves the
12053
12127
  // backend-generated draft as-is. Field shapes mirror the angle-review
12054
12128
  // request contracts in @packages/types/wizard.ts; the handler routes to
12055
12129
  // the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
12056
- customAngle: z48.string().min(1).max(480).optional(),
12130
+ customAngle: z49.string().min(1).max(480).optional(),
12057
12131
  // Keep the shared MCP action within the strictest downstream contract:
12058
12132
  // 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)
12133
+ painPoints: z49.string().max(1500).optional(),
12134
+ benefits: z49.string().max(1500).optional(),
12135
+ features: z49.array(z49.string().min(1).max(300)).max(10).optional(),
12136
+ gapDurationSeconds: z49.union([
12137
+ z49.literal(15),
12138
+ z49.literal(30)
12065
12139
  ]).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
12140
  }),
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()
12141
+ z49.object({
12142
+ kind: z49.literal("service_angle_approval"),
12143
+ angleId: z49.string().uuid(),
12144
+ content: z49.string().min(1).max(480).optional(),
12145
+ creativeDirection: z49.string().min(1).max(1500).optional(),
12146
+ actor: z49.string().min(1).max(360).optional()
12073
12147
  }),
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()
12148
+ z49.object({
12149
+ kind: z49.literal("service_script_approval"),
12150
+ voiceovers: z49.record(z49.string(), z49.string().min(1).max(600)).optional(),
12151
+ visualDirections: z49.record(z49.string(), z49.string().min(1).max(1200)).optional()
12078
12152
  })
12079
12153
  ]);
12080
- var ResolvePendingActionInput = z48.object({
12081
- taskId: z48.string().min(1),
12154
+ var ResolvePendingActionInput = z49.object({
12155
+ taskId: z49.string().min(1),
12082
12156
  action: PendingActionPayload
12083
12157
  }).strict();
12084
12158
  function resolveVariantConfirmVideoTier(action) {
12085
12159
  return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
12086
12160
  }
12087
12161
  __name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
12088
- var StatusForResolveSchema = z48.object({
12162
+ var StatusForResolveSchema = z49.object({
12089
12163
  // Metadata used to select the backend resume contract. Older API responses
12090
12164
  // may omit these fields, so the resolver keeps the generic fallback.
12091
- kind: z48.enum([
12165
+ kind: z49.enum([
12092
12166
  "autopilot",
12093
12167
  "video",
12094
12168
  "image",
@@ -12096,24 +12170,24 @@ var StatusForResolveSchema = z48.object({
12096
12170
  "mix",
12097
12171
  "service"
12098
12172
  ]).optional(),
12099
- selectedOutputs: z48.array(z48.enum([
12173
+ selectedOutputs: z49.array(z49.enum([
12100
12174
  "landing",
12101
12175
  "video",
12102
12176
  "image"
12103
12177
  ])).optional(),
12104
- videoAngleCount: z48.number().int().min(1).max(3).optional(),
12105
- ugcFormat: z48.enum([
12178
+ videoAngleCount: z49.number().int().min(1).max(3).optional(),
12179
+ ugcFormat: z49.enum([
12106
12180
  "single_8s",
12107
12181
  "single_15s",
12108
12182
  "double_30s"
12109
12183
  ]).optional(),
12110
- videoStyle: z48.enum([
12184
+ videoStyle: z49.enum([
12111
12185
  "ugc",
12112
12186
  "cartoon_3d",
12113
12187
  "product_only",
12114
12188
  "ai_dynamic"
12115
12189
  ]).optional(),
12116
- videoModel: z48.enum([
12190
+ videoModel: z49.enum([
12117
12191
  "veo",
12118
12192
  "wan",
12119
12193
  "bytedance",
@@ -12121,62 +12195,62 @@ var StatusForResolveSchema = z48.object({
12121
12195
  "grok",
12122
12196
  "kling"
12123
12197
  ]).optional(),
12124
- videoTier: z48.enum([
12198
+ videoTier: z49.enum([
12125
12199
  "legacy",
12126
12200
  "standard",
12127
12201
  "pro",
12128
12202
  "single_call"
12129
12203
  ]).optional(),
12130
- videoResolution: z48.enum([
12204
+ videoResolution: z49.enum([
12131
12205
  "480p",
12132
12206
  "720p"
12133
12207
  ]).optional(),
12134
12208
  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(),
12209
+ pendingUserAction: z49.object({
12210
+ kind: z49.string(),
12211
+ candidateGrouping: z49.string().optional(),
12212
+ selectedImageUrls: z49.array(z49.string()).optional(),
12213
+ proposedProductNames: z49.array(z49.string()).optional(),
12140
12214
  // Adaptive reference questions are server-owned. Echo only the evidence
12141
12215
  // identity and the choices shown by the current snapshot; never accept a
12142
12216
  // client-supplied reference set as authorization.
12143
- options: z48.array(ProductReferenceUserChoiceEnum).max(4).optional(),
12144
- mode: z48.enum([
12217
+ options: z49.array(ProductReferenceUserChoiceEnum).max(4).optional(),
12218
+ mode: z49.enum([
12145
12219
  "question",
12146
12220
  "visual_recovery"
12147
12221
  ]).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)
12222
+ decisionKey: z49.string().optional(),
12223
+ questionOrdinal: z49.number().int().min(1).max(5).optional(),
12224
+ questionCeiling: z49.union([
12225
+ z49.literal(3),
12226
+ z49.literal(5)
12153
12227
  ]).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({
12228
+ referenceEvidenceVersion: z49.number().int().positive().optional(),
12229
+ expectedEvidenceHash: z49.string().optional(),
12230
+ question: z49.object({
12231
+ prompt: z49.string().min(1).max(240),
12232
+ helpText: z49.string().min(1).max(300).optional(),
12233
+ options: z49.array(z49.object({
12160
12234
  value: ProductReferenceUserChoiceEnum,
12161
- label: z48.string().min(1).max(120),
12162
- description: z48.string().min(1).max(240).optional()
12235
+ label: z49.string().min(1).max(120),
12236
+ description: z49.string().min(1).max(240).optional()
12163
12237
  })).min(2).max(4)
12164
12238
  }).optional(),
12165
12239
  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([
12240
+ scopeKey: z49.string().optional(),
12241
+ scopeSnapshotId: z49.string().uuid().optional(),
12242
+ scopeHash: z49.string().optional(),
12243
+ baseReferenceSetHash: z49.string().optional(),
12244
+ phase: z49.enum([
12171
12245
  "preparation",
12172
12246
  "final"
12173
12247
  ]).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(),
12248
+ selectedRefKeys: z49.array(z49.string().min(1).max(200)).optional(),
12249
+ allowedDecisions: z49.array(ProductReferenceResolutionDecisionEnum).optional(),
12250
+ customAngleDraft: z49.string().optional(),
12251
+ painPointsDraft: z49.string().optional(),
12252
+ benefitsDraft: z49.string().optional(),
12253
+ featuresDraft: z49.array(z49.string()).optional(),
12180
12254
  // Recommendation consumed only when the caller explicitly sends
12181
12255
  // gapDurationSeconds: 30 in the angle approval action.
12182
12256
  gapDurationChoice: GapDurationChoiceMirror.optional(),
@@ -12185,17 +12259,17 @@ var StatusForResolveSchema = z48.object({
12185
12259
  // keys. `actorId` (the saved custom actor the picker stored) was silently
12186
12260
  // dropped here, so the approval handler below could not echo it back on the
12187
12261
  // 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()
12262
+ angles: z49.array(z49.object({
12263
+ id: z49.string().uuid(),
12264
+ content: z49.string(),
12265
+ creativeDirection: z49.string(),
12266
+ actor: z49.string(),
12267
+ actorId: z49.string().nullable().optional()
12194
12268
  }).passthrough()).optional(),
12195
- panels: z48.array(z48.object({
12196
- beatId: z48.string(),
12197
- voiceover: z48.string(),
12198
- visualDirection: z48.string()
12269
+ panels: z49.array(z49.object({
12270
+ beatId: z49.string(),
12271
+ voiceover: z49.string(),
12272
+ visualDirection: z49.string()
12199
12273
  }).passthrough()).optional()
12200
12274
  }).optional()
12201
12275
  }).passthrough();
@@ -12708,59 +12782,59 @@ __name(registerTaskTools, "registerTaskTools");
12708
12782
 
12709
12783
  // src/tools/creatives.ts
12710
12784
  import { randomUUID } from "crypto";
12711
- import { z as z49 } from "zod";
12785
+ import { z as z50 } from "zod";
12712
12786
  var CreativeRefs = {
12713
12787
  images: ImagesInput,
12714
12788
  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
12789
  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.")
12790
+ 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.'),
12791
+ 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.'),
12792
+ 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".'),
12793
+ 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.'),
12794
+ 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."),
12795
+ 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.'),
12796
+ 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.'),
12797
+ isCombo: z50.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
12798
+ 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."),
12799
+ 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."),
12800
+ 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."),
12801
+ 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.'),
12802
+ 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."),
12803
+ 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
12804
  };
12731
- var VideoInput = z49.object({
12805
+ var VideoInput = z50.object({
12732
12806
  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".'),
12807
+ title: z50.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
12808
+ 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
12809
  language: CreativeRefs.language,
12736
12810
  country: CreativeRefs.country,
12737
- aspectRatio: z49.enum([
12811
+ aspectRatio: z50.enum([
12738
12812
  "9:16",
12739
12813
  "16:9",
12740
12814
  "Auto"
12741
12815
  ]).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)
12816
+ durationSeconds: z50.union([
12817
+ z50.literal(15),
12818
+ z50.literal(30)
12745
12819
  ]).default(15).describe("Opcional. Duraci\xF3n objetivo: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
12746
12820
  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
12821
  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
12822
  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"].'),
12823
+ 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
12824
  price: CreativeRefs.price,
12751
12825
  offer: CreativeRefs.offer,
12752
12826
  productContext: CreativeRefs.productContext,
12753
12827
  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."),
12828
+ 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.'),
12829
+ 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.'),
12830
+ 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."),
12831
+ 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."),
12832
+ 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
12833
  competitorScanEnabled: CreativeRefs.competitorScanEnabled,
12760
12834
  brandId: CreativeRefs.brandId,
12761
12835
  projectId: CreativeRefs.projectId
12762
12836
  }).strict();
12763
- var FreeVideoQualityEnum = z49.enum([
12837
+ var FreeVideoQualityEnum = z50.enum([
12764
12838
  "economical",
12765
12839
  "high_detail"
12766
12840
  ]);
@@ -12782,38 +12856,38 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
12782
12856
  15
12783
12857
  ]
12784
12858
  };
12785
- var FreeVideoInput = z49.object({
12859
+ var FreeVideoInput = z50.object({
12786
12860
  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."),
12861
+ 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
12862
  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."),
12863
+ 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
12864
  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.")
12865
+ generateAiMusic: z50.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
12866
+ addSubtitles: z50.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
12867
+ 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
12868
  }).strict();
12795
12869
  var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
12796
12870
  var archetypeList = ImageCreativeArchetypeEnum.options.join(" | ");
12797
12871
  var visualTreatmentList = ImageCreativeVisualTreatmentEnum.options.join(" | ");
12798
12872
  var aspectRatioList = ImageCreativeAspectRatioEnum.options.join(" | ");
12799
- var ImageInput = z49.object({
12873
+ var ImageInput = z50.object({
12800
12874
  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".'),
12875
+ productTitle: z50.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
12876
+ primaryAngle: z50.string().min(1).describe('\xC1ngulo de venta principal. Ej. "Reduce arrugas en 14 d\xEDas".'),
12803
12877
  buyerPersona: CreativeRefs.buyerPersona,
12804
12878
  language: CreativeRefs.language,
12805
12879
  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.'),
12880
+ nVariants: z50.number().int().min(1).max(6).optional().describe("Opcional. N\xFAmero de variantes a generar (1-6). Default 3."),
12881
+ 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
12882
  imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
12809
12883
  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
12884
  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."),
12885
+ 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
12886
  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.'),
12887
+ generateAdCopy: z50.boolean().optional().describe("Opcional. Si true, tambi\xE9n genera headline/body/CTA para el ad. Default false."),
12888
+ 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."),
12889
+ features: z50.array(z50.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
12890
+ 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
12891
  price: CreativeRefs.price,
12818
12892
  compareAtPrice: CreativeRefs.compareAtPrice,
12819
12893
  offer: CreativeRefs.offer,
@@ -12827,17 +12901,17 @@ var ImageInput = z49.object({
12827
12901
  headline: CreativeRefs.headline,
12828
12902
  subheadline: CreativeRefs.subheadline
12829
12903
  });
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".')
12904
+ var EditImageCreativeInput = z50.object({
12905
+ taskId: z50.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
12906
+ variantIndex: z50.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
12907
+ 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
12908
  });
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."),
12909
+ var LandingInput = z50.object({
12910
+ 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
12911
  images: CreativeRefs.images,
12838
12912
  language: CreativeRefs.language,
12839
12913
  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.'),
12914
+ 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
12915
  buyerPersona: CreativeRefs.buyerPersona,
12842
12916
  price: CreativeRefs.price,
12843
12917
  compareAtPrice: CreativeRefs.compareAtPrice,
@@ -12852,6 +12926,7 @@ var LandingInput = z49.object({
12852
12926
  creativeDirection: CreativeRefs.creativeDirection,
12853
12927
  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
12928
  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".'),
12929
+ 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
12930
  headline: CreativeRefs.headline,
12856
12931
  subheadline: CreativeRefs.subheadline
12857
12932
  });
@@ -12962,8 +13037,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
12962
13037
  __name(registerCreativeTools, "registerCreativeTools");
12963
13038
 
12964
13039
  // src/tools/creative-variants.ts
12965
- import { z as z50 } from "zod";
12966
- var LandingSectionKeyEnum = z50.enum([
13040
+ import { z as z51 } from "zod";
13041
+ var LandingSectionKeyEnum = z51.enum([
12967
13042
  "problem_hook",
12968
13043
  "problem_cost",
12969
13044
  "solution_mechanism",
@@ -13003,24 +13078,24 @@ var LandingSectionKeyEnum = z50.enum([
13003
13078
  "lifestyle_fit",
13004
13079
  "join_lifestyle"
13005
13080
  ]);
13006
- var CreativeVariantKindEnum = z50.enum([
13081
+ var CreativeVariantKindEnum = z51.enum([
13007
13082
  "video",
13008
13083
  "image",
13009
13084
  "landing"
13010
13085
  ]);
13011
- var EstimateCreativeVariantInputBase = z50.object({
13012
- sourceTaskId: z50.string().uuid().describe("ID de la tarea original completada."),
13086
+ var EstimateCreativeVariantInputBase = z51.object({
13087
+ sourceTaskId: z51.string().uuid().describe("ID de la tarea original completada."),
13013
13088
  kind: CreativeVariantKindEnum,
13014
13089
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
13015
13090
  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)."),
13091
+ nVariants: z51.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
13017
13092
  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.")
13093
+ 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
13094
  }).strict();
13020
13095
  var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
13021
13096
  if (input.kind === "video" && input.nVariants !== void 0) {
13022
13097
  ctx.addIssue({
13023
- code: z50.ZodIssueCode.custom,
13098
+ code: z51.ZodIssueCode.custom,
13024
13099
  path: [
13025
13100
  "nVariants"
13026
13101
  ],
@@ -13030,7 +13105,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
13030
13105
  if (input.kind !== "video") {
13031
13106
  if (input.videoPreset !== void 0) {
13032
13107
  ctx.addIssue({
13033
- code: z50.ZodIssueCode.custom,
13108
+ code: z51.ZodIssueCode.custom,
13034
13109
  path: [
13035
13110
  "videoPreset"
13036
13111
  ],
@@ -13039,7 +13114,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
13039
13114
  }
13040
13115
  if (input.videoResolution !== void 0) {
13041
13116
  ctx.addIssue({
13042
- code: z50.ZodIssueCode.custom,
13117
+ code: z51.ZodIssueCode.custom,
13043
13118
  path: [
13044
13119
  "videoResolution"
13045
13120
  ],
@@ -13049,7 +13124,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
13049
13124
  }
13050
13125
  if (input.kind !== "image" && input.nVariants !== void 0) {
13051
13126
  ctx.addIssue({
13052
- code: z50.ZodIssueCode.custom,
13127
+ code: z51.ZodIssueCode.custom,
13053
13128
  path: [
13054
13129
  "nVariants"
13055
13130
  ],
@@ -13059,7 +13134,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
13059
13134
  if (input.kind !== "landing") {
13060
13135
  if (input.sectionKey !== void 0) {
13061
13136
  ctx.addIssue({
13062
- code: z50.ZodIssueCode.custom,
13137
+ code: z51.ZodIssueCode.custom,
13063
13138
  path: [
13064
13139
  "sectionKey"
13065
13140
  ],
@@ -13068,7 +13143,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
13068
13143
  }
13069
13144
  if (input.instructions !== void 0) {
13070
13145
  ctx.addIssue({
13071
- code: z50.ZodIssueCode.custom,
13146
+ code: z51.ZodIssueCode.custom,
13072
13147
  path: [
13073
13148
  "instructions"
13074
13149
  ],
@@ -13077,31 +13152,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
13077
13152
  }
13078
13153
  }
13079
13154
  });
13080
- var CreateCreativeVariantInputBase = z50.object({
13081
- sourceTaskId: z50.string().uuid().describe("ID de la tarea original completada."),
13155
+ var CreateCreativeVariantInputBase = z51.object({
13156
+ sourceTaskId: z51.string().uuid().describe("ID de la tarea original completada."),
13082
13157
  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."),
13158
+ confirm: z51.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
13159
+ 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."),
13160
+ angle: z51.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
13161
+ buyerPersona: z51.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
13162
+ scriptNotes: z51.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
13163
+ creativeDirection: z51.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
13089
13164
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
13090
13165
  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)."),
13166
+ generateAiMusic: z51.boolean().optional().describe("Opcional para video."),
13167
+ nVariants: z51.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
13093
13168
  imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
13094
13169
  creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
13095
13170
  visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
13096
13171
  aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
13097
- styleMix: z50.boolean().optional().describe("Opcional para imagen."),
13172
+ styleMix: z51.boolean().optional().describe("Opcional para imagen."),
13098
13173
  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.")
13174
+ 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
13175
  }).strict();
13101
13176
  var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
13102
13177
  if ((input.kind === "video" || input.kind === "image") && !input.angle) {
13103
13178
  ctx.addIssue({
13104
- code: z50.ZodIssueCode.custom,
13179
+ code: z51.ZodIssueCode.custom,
13105
13180
  path: [
13106
13181
  "angle"
13107
13182
  ],
@@ -13110,7 +13185,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
13110
13185
  }
13111
13186
  if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
13112
13187
  ctx.addIssue({
13113
- code: z50.ZodIssueCode.custom,
13188
+ code: z51.ZodIssueCode.custom,
13114
13189
  path: [
13115
13190
  "instructions"
13116
13191
  ],
@@ -13156,7 +13231,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
13156
13231
  for (const field of fieldsByKind[input.kind]) {
13157
13232
  if (input[field] !== void 0) {
13158
13233
  ctx.addIssue({
13159
- code: z50.ZodIssueCode.custom,
13234
+ code: z51.ZodIssueCode.custom,
13160
13235
  path: [
13161
13236
  field
13162
13237
  ],
@@ -13273,27 +13348,27 @@ function registerCreativeVariantTools(server, api) {
13273
13348
  __name(registerCreativeVariantTools, "registerCreativeVariantTools");
13274
13349
 
13275
13350
  // 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.')
13351
+ import { z as z52 } from "zod";
13352
+ var GetVideoScriptInput = z52.object({
13353
+ taskId: z52.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
13354
+ 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
13355
  }).strict();
13281
13356
  var VIDEO_SCRIPT_APPROVAL_MAX_SCENES2 = 50;
13282
13357
  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, {
13358
+ var ApproveSceneEdit = z52.object({
13359
+ index: z52.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
13360
+ dialogue: z52.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
13286
13361
  message: "dialogue no puede ser s\xF3lo espacios"
13287
13362
  }).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
13363
  }).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.")
13364
+ var ApproveVideoScriptInput = z52.object({
13365
+ taskId: z52.string().min(1).describe("ID de la tarea."),
13366
+ 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.'),
13367
+ 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
13368
  }).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.'),
13369
+ var RegenerateVideoScriptInput = z52.object({
13370
+ taskId: z52.string().min(1).describe("ID de la tarea."),
13371
+ 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
13372
  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
13373
  }).strict();
13299
13374
  function registerScriptReviewTools(server, api) {
@@ -13344,9 +13419,9 @@ function registerScriptReviewTools(server, api) {
13344
13419
  __name(registerScriptReviewTools, "registerScriptReviewTools");
13345
13420
 
13346
13421
  // src/tools/connections.ts
13347
- import { z as z52 } from "zod";
13422
+ import { z as z53 } from "zod";
13348
13423
  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 () => {
13424
+ 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
13425
  try {
13351
13426
  const r = await api.getJson("/v1/shopify/shops");
13352
13427
  return asText(r);
@@ -13354,10 +13429,10 @@ function registerConnectionTools(server, api) {
13354
13429
  throw translateError(e);
13355
13430
  }
13356
13431
  });
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()
13432
+ 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({
13433
+ shopDomain: z53.string().min(3).max(120),
13434
+ query: z53.string().trim().max(120).optional(),
13435
+ taskId: z53.string().uuid().optional()
13361
13436
  }).shape, READS_EXTERNAL, async ({ shopDomain, query, taskId }) => {
13362
13437
  try {
13363
13438
  const params = new URLSearchParams({
@@ -13371,7 +13446,7 @@ function registerConnectionTools(server, api) {
13371
13446
  throw translateError(e);
13372
13447
  }
13373
13448
  });
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 () => {
13449
+ 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
13450
  try {
13376
13451
  const r = await api.getJson("/v1/facebook/ad-accounts");
13377
13452
  return asText(r);
@@ -13381,7 +13456,7 @@ function registerConnectionTools(server, api) {
13381
13456
  });
13382
13457
  server.registerTool("list_meta_destinations", {
13383
13458
  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,
13459
+ inputSchema: z53.object({}).shape,
13385
13460
  annotations: READS_EXTERNAL,
13386
13461
  _meta: {
13387
13462
  "openai/widgetAccessible": true
@@ -13394,7 +13469,7 @@ function registerConnectionTools(server, api) {
13394
13469
  throw translateError(e);
13395
13470
  }
13396
13471
  });
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 () => {
13472
+ 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
13473
  try {
13399
13474
  const r = await api.getJson("/v1/tiktok/advertisers");
13400
13475
  return asText(r);
@@ -13406,9 +13481,9 @@ function registerConnectionTools(server, api) {
13406
13481
  __name(registerConnectionTools, "registerConnectionTools");
13407
13482
 
13408
13483
  // src/tools/actors.ts
13409
- import { z as z53 } from "zod";
13484
+ import { z as z54 } from "zod";
13410
13485
  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 () => {
13486
+ 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
13487
  try {
13413
13488
  const rows = await api.getJson("/v1/actors");
13414
13489
  const actors = (Array.isArray(rows) ? rows : []).filter((actor) => actor.status === "ready").map(({ id, name, description, gender, voiceId }) => ({
@@ -13429,39 +13504,39 @@ function registerActorTools(server, api) {
13429
13504
  __name(registerActorTools, "registerActorTools");
13430
13505
 
13431
13506
  // 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),
13507
+ import { z as z55 } from "zod";
13508
+ var ShopifyInput = z55.object({
13509
+ taskId: z55.string().min(1),
13510
+ shopDomain: z55.string().min(1),
13436
13511
  /** Override: number of landing images to include. Default = ALL images the
13437
13512
  * task generated (the MCP fetches /v1/results first to count). Bounded
13438
13513
  * generously here; the backend validates each index against
13439
13514
  * 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(),
13515
+ numLandingImages: z55.number().int().min(1).max(20).optional(),
13516
+ variantIndex: z55.number().int().min(0).optional(),
13442
13517
  /** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
13443
13518
  * When true, the landing renders variant-picker pills; when false, it ships
13444
13519
  * a single-option product page. Defaults to false. */
13445
- showVariantPicker: z54.boolean().optional(),
13520
+ showVariantPicker: z55.boolean().optional(),
13446
13521
  /** Default `auto` updates the product previously published for this task and
13447
13522
  * shop. Use `existing` with targetProductId to choose another product, or
13448
13523
  * `new` only when the user explicitly wants a duplicate/new listing. */
13449
- publicationMode: z54.enum([
13524
+ publicationMode: z55.enum([
13450
13525
  "auto",
13451
13526
  "existing",
13452
13527
  "new"
13453
13528
  ]).optional(),
13454
13529
  /** Shopify product GID, numeric id, or admin product URL. Required when
13455
13530
  * publicationMode is `existing`. */
13456
- targetProductId: z54.string().trim().min(1).max(300).optional(),
13531
+ targetProductId: z55.string().trim().min(1).max(300).optional(),
13457
13532
  /** 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()
13533
+ announcementBarEnabled: z55.boolean().optional(),
13534
+ announcementBarText: z55.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional()
13460
13535
  });
13461
13536
  var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
13462
13537
  if (value.announcementBarEnabled && !value.announcementBarText) {
13463
13538
  ctx.addIssue({
13464
- code: z54.ZodIssueCode.custom,
13539
+ code: z55.ZodIssueCode.custom,
13465
13540
  path: [
13466
13541
  "announcementBarText"
13467
13542
  ],
@@ -13470,7 +13545,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
13470
13545
  }
13471
13546
  if (!value.announcementBarEnabled && value.announcementBarText) {
13472
13547
  ctx.addIssue({
13473
- code: z54.ZodIssueCode.custom,
13548
+ code: z55.ZodIssueCode.custom,
13474
13549
  path: [
13475
13550
  "announcementBarText"
13476
13551
  ],
@@ -13484,90 +13559,90 @@ function parseShopifyInput(rawInput) {
13484
13559
  return parsed.data;
13485
13560
  }
13486
13561
  __name(parseShopifyInput, "parseShopifyInput");
13487
- var McpCampaignConfig = z54.object({
13562
+ var McpCampaignConfig = z55.object({
13488
13563
  /** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
13489
13564
  * converts to the account currency server-side. Do NOT pre-convert: on a COP
13490
13565
  * account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
13491
- dailyBudgetUsd: z54.number().positive().optional(),
13566
+ dailyBudgetUsd: z55.number().positive().optional(),
13492
13567
  /** ISO-3166-1 alpha-2 country codes. Meta accepts max 1 (single-country
13493
13568
  * 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()
13569
+ targetCountries: z55.array(z55.string().length(2)).max(1).optional(),
13570
+ campaignName: z55.string().trim().min(1).max(100).optional()
13496
13571
  });
13497
13572
  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),
13573
+ var MetaInput = z55.object({
13574
+ taskId: z55.string().min(1),
13500
13575
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
13501
- portfolioId: z54.string().trim().min(1),
13576
+ portfolioId: z55.string().trim().min(1),
13502
13577
  /** Exact Facebook Page selected from `list_meta_destinations`. */
13503
- pageId: z54.string().trim().min(1),
13578
+ pageId: z55.string().trim().min(1),
13504
13579
  adAccountId: McpAdAccountId,
13505
- pixelId: z54.string().min(1).optional(),
13506
- landingUrl: z54.string().url().optional(),
13580
+ pixelId: z55.string().min(1).optional(),
13581
+ landingUrl: z55.string().url().optional(),
13507
13582
  /** Select which angles to publish by 0-based index. Omit to publish all
13508
13583
  * successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
13509
- angleIndexes: z54.array(z54.number().int().nonnegative()).optional(),
13584
+ angleIndexes: z55.array(z55.number().int().nonnegative()).optional(),
13510
13585
  campaignConfig: McpCampaignConfig.optional(),
13511
13586
  /** Override the ad's primary text (body copy). If omitted, ProductMaker
13512
13587
  * uses the auto-generated copy attached to the task. Capped at 500 chars
13513
13588
  * (Meta's primary-text limit). */
13514
- primaryText: z54.string().trim().min(1).max(500).optional(),
13589
+ primaryText: z55.string().trim().min(1).max(500).optional(),
13515
13590
  /** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
13516
13591
  * (wa.me) instead of a landing page. */
13517
- phoneNumber: z54.string().min(8).max(32).optional()
13592
+ phoneNumber: z55.string().min(8).max(32).optional()
13518
13593
  });
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([
13594
+ var GroupedTaskSource = z55.object({
13595
+ type: z55.literal("task"),
13596
+ taskId: z55.string().min(1),
13597
+ angleIndex: z55.number().int().min(0).optional(),
13598
+ videoVariant: z55.enum([
13524
13599
  "with_subtitles",
13525
13600
  "without_subtitles"
13526
13601
  ]).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()
13602
+ imageVariantIndex: z55.number().int().min(0).optional()
13603
+ });
13604
+ var GroupedMediaSource = z55.object({
13605
+ type: z55.literal("media"),
13606
+ 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."),
13607
+ 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".'),
13608
+ thumbnailUrl: z55.string().url().optional(),
13609
+ thumbnailPath: z55.string().min(1).optional()
13535
13610
  }).refine((value) => Boolean(value.url) !== Boolean(value.path), {
13536
13611
  message: "media source needs exactly one of `url` or `path`"
13537
13612
  }).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
13538
13613
  message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
13539
13614
  });
13540
- var GroupedUploadedAssetSource = z54.object({
13541
- type: z54.literal("asset"),
13615
+ var GroupedUploadedAssetSource = z55.object({
13616
+ type: z55.literal("asset"),
13542
13617
  /** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
13543
- assetId: z54.string().uuid(),
13544
- thumbnailAssetId: z54.string().uuid().optional()
13618
+ assetId: z55.string().uuid(),
13619
+ thumbnailAssetId: z55.string().uuid().optional()
13545
13620
  });
13546
- var GroupedCreative = z54.object({
13547
- type: z54.enum([
13621
+ var GroupedCreative = z55.object({
13622
+ type: z55.enum([
13548
13623
  "image",
13549
13624
  "video"
13550
13625
  ]),
13551
- source: z54.union([
13626
+ source: z55.union([
13552
13627
  GroupedTaskSource,
13553
13628
  GroupedMediaSource,
13554
13629
  GroupedUploadedAssetSource
13555
13630
  ]),
13556
- title: z54.string().max(120).optional(),
13557
- description: z54.string().max(500).optional(),
13631
+ title: z55.string().max(120).optional(),
13632
+ description: z55.string().max(500).optional(),
13558
13633
  cta: MetaCtaType.optional(),
13559
- creativeId: z54.string().min(1).optional()
13634
+ creativeId: z55.string().min(1).optional()
13560
13635
  });
13561
- var GroupedCampaignConfigBase = z54.object({
13636
+ var GroupedCampaignConfigBase = z55.object({
13562
13637
  campaignType: MetaCampaignType.default("sales"),
13563
13638
  optimizationMode: MetaOptimizationMode.default("advantage_plus"),
13564
13639
  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)
13640
+ campaignDailyBudget: z55.number().int().positive().optional(),
13641
+ adSets: z55.array(z55.object({
13642
+ tempId: z55.string().min(1).max(80),
13643
+ name: z55.string().min(1).max(100),
13644
+ dailyBudget: z55.number().int().positive().optional(),
13645
+ creativeIds: z55.array(z55.string().min(1)).min(1)
13571
13646
  })).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
13572
13647
  /**
13573
13648
  * Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
@@ -13575,17 +13650,17 @@ var GroupedCampaignConfigBase = z54.object({
13575
13650
  * opaque `invalid_literal` and made the WhatsApp destination — supported by
13576
13651
  * the API since #849 — unreachable from this tool.
13577
13652
  */
13578
- destination: z54.discriminatedUnion("type", [
13579
- z54.object({
13580
- type: z54.literal("landing"),
13581
- landingUrl: z54.string().url()
13653
+ destination: z55.discriminatedUnion("type", [
13654
+ z55.object({
13655
+ type: z55.literal("landing"),
13656
+ landingUrl: z55.string().url()
13582
13657
  }),
13583
- z54.object({
13584
- type: z54.literal("whatsapp"),
13585
- phoneNumber: z54.string().min(8).max(32)
13658
+ z55.object({
13659
+ type: z55.literal("whatsapp"),
13660
+ phoneNumber: z55.string().min(8).max(32)
13586
13661
  })
13587
13662
  ]),
13588
- saveAsDefault: z54.boolean().default(false),
13663
+ saveAsDefault: z55.boolean().default(false),
13589
13664
  budgetPolicy: MetaBudgetPolicy.optional()
13590
13665
  });
13591
13666
  function resolveBudgetMode(value) {
@@ -13599,7 +13674,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
13599
13674
  const budgetMode = resolveBudgetMode(value);
13600
13675
  if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
13601
13676
  ctx.addIssue({
13602
- code: z54.ZodIssueCode.custom,
13677
+ code: z55.ZodIssueCode.custom,
13603
13678
  path: [
13604
13679
  "campaignDailyBudget"
13605
13680
  ],
@@ -13610,7 +13685,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
13610
13685
  value.adSets.forEach((adSet, index) => {
13611
13686
  if (adSet.dailyBudget === void 0) {
13612
13687
  ctx.addIssue({
13613
- code: z54.ZodIssueCode.custom,
13688
+ code: z55.ZodIssueCode.custom,
13614
13689
  path: [
13615
13690
  "adSets",
13616
13691
  index,
@@ -13625,26 +13700,26 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
13625
13700
  ...value,
13626
13701
  budgetMode: resolveBudgetMode(value)
13627
13702
  }));
13628
- var PublishCreativesToMetaInputBase = z54.object({
13629
- creatives: z54.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
13703
+ var PublishCreativesToMetaInputBase = z55.object({
13704
+ creatives: z55.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
13630
13705
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
13631
- portfolioId: z54.string().trim().min(1),
13706
+ portfolioId: z55.string().trim().min(1),
13632
13707
  /** Exact Facebook Page selected from `list_meta_destinations`. */
13633
- pageId: z54.string().trim().min(1),
13708
+ pageId: z55.string().trim().min(1),
13634
13709
  adAccountId: McpAdAccountId,
13635
- pixelId: z54.string().min(1).optional(),
13710
+ pixelId: z55.string().min(1).optional(),
13636
13711
  /** Required unless `campaignConfig.destination` is whatsapp — see the
13637
13712
  * 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),
13713
+ landingUrl: z55.string().url().optional(),
13714
+ targetCountry: z55.string().length(2),
13715
+ campaignName: z55.string().trim().min(1).max(100),
13641
13716
  campaignConfig: GroupedCampaignConfig.optional()
13642
13717
  });
13643
13718
  var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
13644
13719
  const destination = value.campaignConfig?.destination;
13645
13720
  if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
13646
13721
  ctx.addIssue({
13647
- code: z54.ZodIssueCode.custom,
13722
+ code: z55.ZodIssueCode.custom,
13648
13723
  path: [
13649
13724
  "landingUrl"
13650
13725
  ],
@@ -13653,7 +13728,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
13653
13728
  }
13654
13729
  if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
13655
13730
  ctx.addIssue({
13656
- code: z54.ZodIssueCode.custom,
13731
+ code: z55.ZodIssueCode.custom,
13657
13732
  path: [
13658
13733
  "campaignConfig",
13659
13734
  "destination",
@@ -13672,16 +13747,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
13672
13747
  }
13673
13748
  return value;
13674
13749
  });
13675
- var PresignUploadResponseSchema = z54.object({
13676
- uploadUrl: z54.string().url().refine((value) => {
13750
+ var PresignUploadResponseSchema = z55.object({
13751
+ uploadUrl: z55.string().url().refine((value) => {
13677
13752
  const url = new URL(value);
13678
13753
  return !url.username && !url.password && url.protocol === "https:";
13679
13754
  }, "presigned upload URL must be HTTPS without embedded credentials"),
13680
- publicUrl: z54.string().url().refine((value) => {
13755
+ publicUrl: z55.string().url().refine((value) => {
13681
13756
  const url = new URL(value);
13682
13757
  return !url.username && !url.password;
13683
13758
  }, "public media URL must not contain embedded credentials"),
13684
- stagingAssetId: z54.string().uuid()
13759
+ stagingAssetId: z55.string().uuid()
13685
13760
  });
13686
13761
  async function uploadResolvedMedia(api, media, assetRole) {
13687
13762
  if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
@@ -13706,16 +13781,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
13706
13781
  return uploadResolvedMedia(api, media, assetRole);
13707
13782
  }
13708
13783
  __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(),
13784
+ var TikTokInput = z55.object({
13785
+ taskId: z55.string().min(1),
13786
+ advertiserId: z55.string().min(1),
13787
+ pixelId: z55.string().min(1).optional(),
13788
+ landingUrl: z55.string().url().optional(),
13789
+ angleIndexes: z55.array(z55.number().int().nonnegative()).optional(),
13715
13790
  campaignConfig: McpCampaignConfig.optional(),
13716
13791
  /** Override the ad's description (TikTok's body copy). If omitted,
13717
13792
  * ProductMaker uses the auto-generated copy attached to the task. */
13718
- primaryText: z54.string().trim().min(1).max(500).optional()
13793
+ primaryText: z55.string().trim().min(1).max(500).optional()
13719
13794
  });
13720
13795
  function registerPublishTools(server, api, opts = {}) {
13721
13796
  const transport = opts.transport ?? "http";
@@ -13965,38 +14040,38 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
13965
14040
 
13966
14041
  // src/tools/meta-upload.ts
13967
14042
  import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
13968
- import { z as z55 } from "zod";
13969
- var UploadSessionInputBase = z55.object({
13970
- mediaKind: z55.enum([
14043
+ import { z as z56 } from "zod";
14044
+ var UploadSessionInputBase = z56.object({
14045
+ mediaKind: z56.enum([
13971
14046
  "image",
13972
14047
  "video",
13973
14048
  "mixed"
13974
14049
  ]).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([
14050
+ assetRole: z56.enum([
13976
14051
  "media",
13977
14052
  "thumbnail"
13978
14053
  ]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
13979
- uploadPurpose: z55.enum([
14054
+ uploadPurpose: z56.enum([
13980
14055
  "product_reference",
13981
14056
  "creative",
13982
14057
  "generic"
13983
14058
  ]).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.")
14059
+ 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
14060
  });
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()
14061
+ var OpenAiFileReference = z56.object({
14062
+ 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."),
14063
+ file_id: z56.string().min(1),
14064
+ mime_type: z56.string().min(1).optional(),
14065
+ file_name: z56.string().min(1).optional()
13991
14066
  });
13992
14067
  var UploadSessionToolInputShape = {
13993
14068
  ...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.")
14069
+ 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
14070
  };
13996
- var UploadSessionToolInput = z55.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
14071
+ var UploadSessionToolInput = z56.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
13997
14072
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
13998
14073
  ctx.addIssue({
13999
- code: z55.ZodIssueCode.custom,
14074
+ code: z56.ZodIssueCode.custom,
14000
14075
  path: [
14001
14076
  "mediaKind"
14002
14077
  ],
@@ -14005,7 +14080,7 @@ var UploadSessionToolInput = z55.object(UploadSessionToolInputShape).superRefine
14005
14080
  }
14006
14081
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
14007
14082
  ctx.addIssue({
14008
- code: z55.ZodIssueCode.custom,
14083
+ code: z56.ZodIssueCode.custom,
14009
14084
  path: [
14010
14085
  "maxFiles"
14011
14086
  ],
@@ -14014,7 +14089,7 @@ var UploadSessionToolInput = z55.object(UploadSessionToolInputShape).superRefine
14014
14089
  }
14015
14090
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
14016
14091
  ctx.addIssue({
14017
- code: z55.ZodIssueCode.custom,
14092
+ code: z56.ZodIssueCode.custom,
14018
14093
  path: [
14019
14094
  "maxFiles"
14020
14095
  ],
@@ -14022,38 +14097,38 @@ var UploadSessionToolInput = z55.object(UploadSessionToolInputShape).superRefine
14022
14097
  });
14023
14098
  }
14024
14099
  });
14025
- var UploadSessionResponse = z55.object({
14026
- sessionId: z55.string().uuid(),
14027
- uploadPageUrl: z55.string().url(),
14028
- mediaKind: z55.enum([
14100
+ var UploadSessionResponse = z56.object({
14101
+ sessionId: z56.string().uuid(),
14102
+ uploadPageUrl: z56.string().url(),
14103
+ mediaKind: z56.enum([
14029
14104
  "image",
14030
14105
  "video",
14031
14106
  "mixed"
14032
14107
  ]),
14033
- assetRole: z55.enum([
14108
+ assetRole: z56.enum([
14034
14109
  "media",
14035
14110
  "thumbnail"
14036
14111
  ]),
14037
- maxFiles: z55.number().int().positive(),
14038
- expiresAt: z55.string().datetime()
14112
+ maxFiles: z56.number().int().positive(),
14113
+ expiresAt: z56.string().datetime()
14039
14114
  });
14040
- var UploadStatusInput = z55.object({
14041
- sessionId: z55.string().uuid().describe("The sessionId returned by request_media_upload.")
14115
+ var UploadStatusInput = z56.object({
14116
+ sessionId: z56.string().uuid().describe("The sessionId returned by request_media_upload.")
14042
14117
  });
14043
- var UniversalUploadStatusResponse = z55.discriminatedUnion("status", [
14044
- z55.object({
14045
- status: z55.literal("pending"),
14046
- assets: z55.array(z55.never()).length(0)
14118
+ var UniversalUploadStatusResponse = z56.discriminatedUnion("status", [
14119
+ z56.object({
14120
+ status: z56.literal("pending"),
14121
+ assets: z56.array(z56.never()).length(0)
14047
14122
  }),
14048
- z55.object({
14049
- status: z55.literal("uploaded"),
14050
- assets: z55.array(z55.object({
14051
- assetId: z55.string().uuid(),
14052
- mediaKind: z55.enum([
14123
+ z56.object({
14124
+ status: z56.literal("uploaded"),
14125
+ assets: z56.array(z56.object({
14126
+ assetId: z56.string().uuid(),
14127
+ mediaKind: z56.enum([
14053
14128
  "image",
14054
14129
  "video"
14055
14130
  ]),
14056
- assetRole: z55.enum([
14131
+ assetRole: z56.enum([
14057
14132
  "media",
14058
14133
  "thumbnail"
14059
14134
  ])
@@ -14061,13 +14136,13 @@ var UniversalUploadStatusResponse = z55.discriminatedUnion("status", [
14061
14136
  })
14062
14137
  ]);
14063
14138
  var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
14064
- uploadPurpose: z55.enum([
14139
+ uploadPurpose: z56.enum([
14065
14140
  "product_reference",
14066
14141
  "creative",
14067
14142
  "generic"
14068
14143
  ]),
14069
- checkToolName: z55.literal("check_media_upload"),
14070
- resolveEndpoint: z55.string().url()
14144
+ checkToolName: z56.literal("check_media_upload"),
14145
+ resolveEndpoint: z56.string().url()
14071
14146
  });
14072
14147
  function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
14073
14148
  const url = new URL(uploadPageUrl);
@@ -14158,13 +14233,13 @@ function registerMediaUploadTools(server, api) {
14158
14233
  __name(registerMediaUploadTools, "registerMediaUploadTools");
14159
14234
 
14160
14235
  // 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.")
14236
+ import { z as z57 } from "zod";
14237
+ var MetaStatusInput = z57.object({
14238
+ campaignId: z57.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
14164
14239
  });
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.")
14240
+ var TikTokStatusInput = z57.object({
14241
+ campaignId: z57.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
14242
+ advertiserId: z57.string().min(1).describe("The same advertiserId used to publish the campaign.")
14168
14243
  });
14169
14244
  function registerCampaignTools(server, api) {
14170
14245
  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 +14336,10 @@ function renderTikTokStatusMarkdown(r) {
14261
14336
  __name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
14262
14337
 
14263
14338
  // ../../packages/product-economics/src/product-costing.ts
14264
- import { z as z58 } from "zod";
14339
+ import { z as z59 } from "zod";
14265
14340
 
14266
14341
  // ../../packages/product-economics/src/product-costing-countries.ts
14267
- import { z as z57 } from "zod";
14342
+ import { z as z58 } from "zod";
14268
14343
 
14269
14344
  // ../../packages/product-economics/src/product-costing-shipping-references.json
14270
14345
  var product_costing_shipping_references_default = {
@@ -14328,21 +14403,21 @@ var product_costing_shipping_references_default = {
14328
14403
  };
14329
14404
 
14330
14405
  // ../../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([
14406
+ var ShippingReferenceSchema = z58.object({
14407
+ reference: z58.number().positive(),
14408
+ min: z58.number().nonnegative(),
14409
+ max: z58.number().positive(),
14410
+ updatedAt: z58.string().date(),
14411
+ confidence: z58.enum([
14337
14412
  "high",
14338
14413
  "medium",
14339
14414
  "medium-low"
14340
14415
  ]),
14341
- sources: z57.array(z57.string().url().startsWith("https://")).min(1).max(3)
14416
+ sources: z58.array(z58.string().url().startsWith("https://")).min(1).max(3)
14342
14417
  }).superRefine(({ reference, min, max }, context) => {
14343
14418
  if (min > reference || reference > max) {
14344
14419
  context.addIssue({
14345
- code: z57.ZodIssueCode.custom,
14420
+ code: z58.ZodIssueCode.custom,
14346
14421
  message: "shipping_reference_outside_range",
14347
14422
  path: [
14348
14423
  "reference"
@@ -14350,7 +14425,7 @@ var ShippingReferenceSchema = z57.object({
14350
14425
  });
14351
14426
  }
14352
14427
  });
14353
- var SHIPPING_REFERENCES = z57.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
14428
+ var SHIPPING_REFERENCES = z58.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
14354
14429
  var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
14355
14430
  var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
14356
14431
  "MX",
@@ -14532,18 +14607,18 @@ function getProductCostingCountryName(country) {
14532
14607
  __name(getProductCostingCountryName, "getProductCostingCountryName");
14533
14608
 
14534
14609
  // ../../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")
14610
+ var ProductCostingInputSchema = z59.object({
14611
+ country: z59.string().refine(isProductCostingCountryCode, "unsupported_country"),
14612
+ supplierCost: z59.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
14613
+ shippingCost: z59.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
14614
+ returnRate: z59.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
14615
+ cancellationRate: z59.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
14616
+ adsManagerCpa: z59.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
14617
+ desiredMargin: z59.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
14543
14618
  }).superRefine(({ returnRate, cancellationRate }, context) => {
14544
14619
  if (returnRate + cancellationRate >= 1) {
14545
14620
  context.addIssue({
14546
- code: z58.ZodIssueCode.custom,
14621
+ code: z59.ZodIssueCode.custom,
14547
14622
  message: "delivery_rate_positive",
14548
14623
  path: [
14549
14624
  "cancellationRate"
@@ -14610,14 +14685,14 @@ function calculateProductCosting(rawInput) {
14610
14685
  __name(calculateProductCosting, "calculateProductCosting");
14611
14686
 
14612
14687
  // 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, {
14688
+ import { z as z60 } from "zod";
14689
+ var optionalAmount = /* @__PURE__ */ __name((description) => z60.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
14690
+ var optionalPercent = /* @__PURE__ */ __name((description) => z60.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
14691
+ var ProductCostingToolInput = z60.object({
14692
+ country: z60.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
14618
14693
  message: "Pa\xEDs no soportado por ProductMaker."
14619
14694
  }).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."),
14695
+ 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
14696
  supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
14622
14697
  shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
14623
14698
  shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
@@ -14749,7 +14824,7 @@ function formatPercent(value) {
14749
14824
  __name(formatPercent, "formatPercent");
14750
14825
 
14751
14826
  // src/tools/product-research.ts
14752
- import { z as z60 } from "zod";
14827
+ import { z as z61 } from "zod";
14753
14828
 
14754
14829
  // src/tools/product-research-idempotency.ts
14755
14830
  import { createHash as createHash2 } from "crypto";
@@ -14865,17 +14940,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
14865
14940
  ]);
14866
14941
  var POLL_INTERVAL_MS = 5e3;
14867
14942
  var MAX_WAIT_SECONDS = 120;
14868
- var FindInput = z60.object({
14943
+ var FindInput = z61.object({
14869
14944
  targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
14870
14945
  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.")
14946
+ 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.`),
14947
+ 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
14948
  });
14874
- var GetInput = z60.object({
14875
- runId: z60.string().uuid().describe("ID del run devuelto por find_winning_products.")
14949
+ var GetInput = z61.object({
14950
+ runId: z61.string().uuid().describe("ID del run devuelto por find_winning_products.")
14876
14951
  });
14877
- var ListInput = z60.object({
14878
- limit: z60.number().int().min(1).max(20).default(10)
14952
+ var ListInput = z61.object({
14953
+ limit: z61.number().int().min(1).max(20).default(10)
14879
14954
  });
14880
14955
  function textResult(text) {
14881
14956
  return {
@@ -14967,14 +15042,14 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
14967
15042
  __name(registerProductResearchTools, "registerProductResearchTools");
14968
15043
 
14969
15044
  // src/tools/dropshipping-projects.ts
14970
- import { z as z61 } from "zod";
14971
- var ProjectId = z61.string().uuid();
14972
- var DropshippingProjectStatus = z61.enum([
15045
+ import { z as z62 } from "zod";
15046
+ var ProjectId = z62.string().uuid();
15047
+ var DropshippingProjectStatus = z62.enum([
14973
15048
  "active",
14974
15049
  "completed",
14975
15050
  "archived"
14976
15051
  ]);
14977
- var DropshippingProjectPhase = z61.enum([
15052
+ var DropshippingProjectPhase = z62.enum([
14978
15053
  "research",
14979
15054
  "costing",
14980
15055
  "media",
@@ -14983,21 +15058,21 @@ var DropshippingProjectPhase = z61.enum([
14983
15058
  "advertising",
14984
15059
  "complete"
14985
15060
  ]);
14986
- var DropshippingRewardMilestone = z61.enum([
15061
+ var DropshippingRewardMilestone = z62.enum([
14987
15062
  "product_selected",
14988
15063
  "costing_saved",
14989
15064
  "product_media_ready",
14990
15065
  "creatives_completed",
14991
15066
  "campaign_created"
14992
15067
  ]);
14993
- var TargetCountry = z61.enum([
15068
+ var TargetCountry = z62.enum([
14994
15069
  "CO",
14995
15070
  "MX",
14996
15071
  "PE",
14997
15072
  "EC",
14998
15073
  "CL"
14999
15074
  ]);
15000
- var ResearchCategory = z61.enum([
15075
+ var ResearchCategory = z62.enum([
15001
15076
  "auto",
15002
15077
  "automotive",
15003
15078
  "kitchen",
@@ -15012,7 +15087,7 @@ var ResearchCategory = z61.enum([
15012
15087
  "garden",
15013
15088
  "cleaning"
15014
15089
  ]);
15015
- var HttpUrl3 = z61.string().url().max(2e3).refine((value) => {
15090
+ var HttpUrl3 = z62.string().url().max(2e3).refine((value) => {
15016
15091
  try {
15017
15092
  return [
15018
15093
  "http:",
@@ -15022,43 +15097,43 @@ var HttpUrl3 = z61.string().url().max(2e3).refine((value) => {
15022
15097
  return false;
15023
15098
  }
15024
15099
  }, "URL must use HTTP(S)");
15025
- var ResearchCandidateOrigin = z61.object({
15026
- type: z61.literal("research_candidate"),
15100
+ var ResearchCandidateOrigin = z62.object({
15101
+ type: z62.literal("research_candidate"),
15027
15102
  runId: ProjectId,
15028
- candidateSourceId: z61.string().min(1).max(160)
15103
+ candidateSourceId: z62.string().min(1).max(160)
15029
15104
  });
15030
- var TaskOrigin = z61.object({
15031
- type: z61.literal("task"),
15105
+ var TaskOrigin = z62.object({
15106
+ type: z62.literal("task"),
15032
15107
  taskId: ProjectId
15033
15108
  });
15034
- var ManualOrigin = z61.object({
15035
- type: z61.literal("manual"),
15109
+ var ManualOrigin = z62.object({
15110
+ type: z62.literal("manual"),
15036
15111
  clientRequestId: ProjectId,
15037
- country: z61.string().min(2).max(3).optional()
15112
+ country: z62.string().min(2).max(3).optional()
15038
15113
  });
15039
- var StartProjectInput = z61.object({
15040
- origin: z61.discriminatedUnion("type", [
15114
+ var StartProjectInput = z62.object({
15115
+ origin: z62.discriminatedUnion("type", [
15041
15116
  ResearchCandidateOrigin,
15042
15117
  TaskOrigin,
15043
15118
  ManualOrigin
15044
15119
  ]),
15045
- productName: z61.string().trim().min(1).max(240).optional(),
15120
+ productName: z62.string().trim().min(1).max(240).optional(),
15046
15121
  productUrl: HttpUrl3.optional(),
15047
- country: z61.string().min(2).max(3).optional(),
15048
- languageCode: z61.string().min(2).max(16).optional()
15122
+ country: z62.string().min(2).max(3).optional(),
15123
+ languageCode: z62.string().min(2).max(16).optional()
15049
15124
  }).strict();
15050
- var CostProjectInput = z61.object({
15125
+ var CostProjectInput = z62.object({
15051
15126
  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({
15127
+ version: z62.number().int().positive(),
15128
+ country: z62.string().trim().min(2).max(3),
15129
+ supplierCost: z62.number().finite().positive(),
15130
+ shippingCost: z62.number().finite().nonnegative(),
15131
+ returnRate: z62.number().finite().min(0).lt(1),
15132
+ cancellationRate: z62.number().finite().min(0).lt(1),
15133
+ adsManagerCpa: z62.number().finite().nonnegative(),
15134
+ desiredMargin: z62.number().finite().min(0).lt(1)
15135
+ });
15136
+ var GuideInput = z62.object({
15062
15137
  projectId: ProjectId.optional()
15063
15138
  }).strict();
15064
15139
  var NEXT_ACTION_KINDS = [
@@ -15076,29 +15151,29 @@ var NEXT_ACTION_KINDS = [
15076
15151
  "repair_meta_campaign",
15077
15152
  "review_paused_campaign"
15078
15153
  ];
15079
- var DropshippingProjectNextAction = z61.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z61.object({
15080
- kind: z61.literal(kind),
15081
- href: z61.string().min(1)
15154
+ var DropshippingProjectNextAction = z62.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z62.object({
15155
+ kind: z62.literal(kind),
15156
+ href: z62.string().min(1)
15082
15157
  })));
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)
15158
+ var CostingInputSchema = z62.object({
15159
+ country: z62.string().min(2).max(3),
15160
+ supplierCost: z62.number().finite().positive(),
15161
+ shippingCost: z62.number().finite().nonnegative(),
15162
+ returnRate: z62.number().finite().min(0).lt(1),
15163
+ cancellationRate: z62.number().finite().min(0).lt(1),
15164
+ adsManagerCpa: z62.number().finite().nonnegative(),
15165
+ desiredMargin: z62.number().finite().min(0).lt(1)
15091
15166
  }).superRefine(({ returnRate, cancellationRate }, context) => {
15092
15167
  if (returnRate + cancellationRate >= 1) context.addIssue({
15093
- code: z61.ZodIssueCode.custom,
15168
+ code: z62.ZodIssueCode.custom,
15094
15169
  path: [
15095
15170
  "cancellationRate"
15096
15171
  ]
15097
15172
  });
15098
15173
  });
15099
- var FiniteCostingNumber = z61.number().finite();
15100
- var CostingResultSchema = z61.object({
15101
- country: z61.string().min(2).max(3),
15174
+ var FiniteCostingNumber = z62.number().finite();
15175
+ var CostingResultSchema = z62.object({
15176
+ country: z62.string().min(2).max(3),
15102
15177
  deliveryRate: FiniteCostingNumber,
15103
15178
  adjustedShippingCost: FiniteCostingNumber,
15104
15179
  adjustedCpa: FiniteCostingNumber,
@@ -15111,44 +15186,44 @@ var CostingResultSchema = z61.object({
15111
15186
  estimatedProfit: FiniteCostingNumber,
15112
15187
  actualMargin: FiniteCostingNumber,
15113
15188
  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({
15189
+ wasPriceAutoAdjusted: z62.boolean(),
15190
+ profitabilityStatus: z62.literal("healthy")
15191
+ });
15192
+ var RewardProgressSchema = z62.object({
15193
+ campaignKey: z62.literal("dropshipping-launch-v1"),
15194
+ totalCredits: z62.number().int().positive(),
15195
+ earnedCredits: z62.number().int().nonnegative(),
15196
+ milestones: z62.array(z62.object({
15122
15197
  milestone: DropshippingRewardMilestone,
15123
- credits: z61.number().int().positive(),
15124
- available: z61.boolean().optional(),
15125
- earned: z61.boolean(),
15198
+ credits: z62.number().int().positive(),
15199
+ available: z62.boolean().optional(),
15200
+ earned: z62.boolean(),
15126
15201
  grantId: ProjectId.nullable(),
15127
- grantedAt: z61.string().datetime().nullable()
15202
+ grantedAt: z62.string().datetime().nullable()
15128
15203
  })).length(DropshippingRewardMilestone.options.length)
15129
15204
  });
15130
- var ProjectResponseSchema = z61.object({
15205
+ var ProjectResponseSchema = z62.object({
15131
15206
  id: ProjectId,
15132
15207
  taskId: ProjectId.nullable(),
15133
15208
  status: DropshippingProjectStatus,
15134
- originKey: z61.string().min(1),
15209
+ originKey: z62.string().min(1),
15135
15210
  researchRunId: ProjectId.nullable(),
15136
- candidateSourceId: z61.string().nullable(),
15137
- productName: z61.string().nullable(),
15211
+ candidateSourceId: z62.string().nullable(),
15212
+ productName: z62.string().nullable(),
15138
15213
  productUrl: HttpUrl3.nullable(),
15139
15214
  referenceImageUrl: HttpUrl3.nullable(),
15140
- targetCountry: z61.string().nullable(),
15141
- languageCode: z61.string().nullable(),
15142
- hasReferenceImage: z61.boolean(),
15215
+ targetCountry: z62.string().nullable(),
15216
+ languageCode: z62.string().nullable(),
15217
+ hasReferenceImage: z62.boolean(),
15143
15218
  costingInput: CostingInputSchema.nullable(),
15144
15219
  costingResult: CostingResultSchema.nullable(),
15145
- costingVersion: z61.number().int().positive().nullable(),
15146
- version: z61.number().int().positive(),
15220
+ costingVersion: z62.number().int().positive().nullable(),
15221
+ version: z62.number().int().positive(),
15147
15222
  phase: DropshippingProjectPhase,
15148
15223
  nextAction: DropshippingProjectNextAction.nullable(),
15149
15224
  rewards: RewardProgressSchema,
15150
- createdAt: z61.string().datetime(),
15151
- updatedAt: z61.string().datetime()
15225
+ createdAt: z62.string().datetime(),
15226
+ updatedAt: z62.string().datetime()
15152
15227
  }).passthrough();
15153
15228
  var NEXT_ACTION_GUIDANCE = {
15154
15229
  cost_product: "Llama `cost_dropshipping_project` con el costo real del proveedor. Nunca lo inventes: p\xEDdeselo al usuario.",