@productmaker/mcp 3.4.0 → 3.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/http.js +1012 -885
  2. package/dist/stdio.js +1000 -873
  3. package/package.json +1 -1
package/dist/http.js CHANGED
@@ -3692,6 +3692,32 @@ var StatusResponse = z24.object({
3692
3692
  requiresAction: z24.boolean().optional(),
3693
3693
  /** True when the task needs the user's attention rather than passive progress. */
3694
3694
  needsReview: z24.boolean().optional(),
3695
+ /**
3696
+ * THE answer to "does this task still owe the seller a question — now OR later
3697
+ * in this run?". The chat leaves for /tasks/:id only on an explicit `false`,
3698
+ * and /tasks/:id bounces her back on `true`. ONE field drives BOTH directions
3699
+ * on purpose: deciding them on two different facts is what looped
3700
+ * /tasks/:id ↔ wizard before (see apps/web/lib/task-routing.ts).
3701
+ *
3702
+ * STRICTLY WIDER THAN `needsReview`, and the difference is the whole point:
3703
+ * · `needsReview` answers "is a gate open RIGHT NOW", and it under-reports —
3704
+ * `buildPendingUserAction` only serves the reference-grouping question when
3705
+ * it is RENDERABLE, so an unconfirmed target reports `false` while
3706
+ * `angles.worker` will still pause at the END of the angles stage.
3707
+ * · this field adds the gates that are GUARANTEED to open: both pause flags,
3708
+ * plus that same worker prediction, through the one shared helper.
3709
+ *
3710
+ * Absent (undefined) means "an older API that cannot answer" — the client must
3711
+ * treat that as `true` and stay put. Uncertainty resolves to staying: a false
3712
+ * positive costs her a wait, a false negative strands her on a screen that
3713
+ * cannot render the gate (prod bd4d0bb1 / 52dc15a7, both refunded and
3714
+ * undelivered).
3715
+ *
3716
+ * ALWAYS false on a terminal task. `pauseForAngleReview` SURVIVES on completed
3717
+ * tasks, so without that guard a finished landing would report `true` forever
3718
+ * and get bounced into a chat with nothing left to ask.
3719
+ */
3720
+ willAskAgain: z24.boolean().optional(),
3695
3721
  /** True when an open gate exists that somebody can actually ANSWER. A strictly
3696
3722
  * narrower fact than `needsReview` — see the identical field on `TaskSummary`
3697
3723
  * below for why conflating the two produced a call to action that led nowhere. */
@@ -3826,6 +3852,9 @@ var CostEstimationType = z25.enum([
3826
3852
  "landing-regenerate",
3827
3853
  "landing-creative",
3828
3854
  "campaign-copy",
3855
+ "brand-extract",
3856
+ "persona-suggest",
3857
+ "chat-parse",
3829
3858
  "service-creative",
3830
3859
  "actor-grid"
3831
3860
  ]);
@@ -3991,11 +4020,14 @@ var LandingCreativeEstimationOptions = z25.object({
3991
4020
  landingStrategy: LandingStrategySchema.optional()
3992
4021
  });
3993
4022
  var CampaignCopyEstimationOptions = z25.object({
3994
- /** Number of creatives to generate copy for (1-4) */
3995
- nCreatives: z25.number().int().min(1).max(4),
3996
- /** Number of image creatives that will use vision analysis (0-4) */
3997
- nImages: z25.number().int().min(0).max(4).default(0)
3998
- });
4023
+ /** Number of creatives in the one copy-completion request (1-10). */
4024
+ nCreatives: z25.number().int().min(1).max(10),
4025
+ /** Number of image creatives that can each use one vision analysis (0-10). */
4026
+ nImages: z25.number().int().min(0).max(10).default(0)
4027
+ });
4028
+ var BrandExtractEstimationOptions = z25.object({}).strict();
4029
+ var PersonaSuggestEstimationOptions = z25.object({}).strict();
4030
+ var ChatParseEstimationOptions = z25.object({}).strict();
3999
4031
  var ServiceCreativeEstimationOptions = z25.object({
4000
4032
  mediaAssetCount: z25.number().int().min(0).max(8).optional(),
4001
4033
  uploadedVideoDurationSeconds: z25.number().min(0).max(240).optional()
@@ -4034,6 +4066,18 @@ var CostEstimationRequest = z25.discriminatedUnion("type", [
4034
4066
  type: z25.literal("campaign-copy"),
4035
4067
  options: CampaignCopyEstimationOptions
4036
4068
  }),
4069
+ z25.object({
4070
+ type: z25.literal("brand-extract"),
4071
+ options: BrandExtractEstimationOptions
4072
+ }),
4073
+ z25.object({
4074
+ type: z25.literal("persona-suggest"),
4075
+ options: PersonaSuggestEstimationOptions
4076
+ }),
4077
+ z25.object({
4078
+ type: z25.literal("chat-parse"),
4079
+ options: ChatParseEstimationOptions
4080
+ }),
4037
4081
  z25.object({
4038
4082
  type: z25.literal("service-creative"),
4039
4083
  options: ServiceCreativeEstimationOptions
@@ -4533,6 +4577,9 @@ var VideoMixQaJobSchema = z30.object({
4533
4577
  });
4534
4578
  var BrandExtractJobSchema = z30.object({
4535
4579
  brandId: z30.string().uuid(),
4580
+ // Generation is part of the durable paid-spend identity. Default 1 keeps
4581
+ // pre-migration BullMQ payloads parseable; their DB state fails safe.
4582
+ generation: z30.number().int().positive().default(1),
4536
4583
  url: z30.string().url().refine((value) => {
4537
4584
  const protocol = new URL(value).protocol;
4538
4585
  return protocol === "http:" || protocol === "https:";
@@ -5578,6 +5625,10 @@ var TikTokCreateCampaignResponseSchema = z35.object({
5578
5625
  adsManagerUrl: z35.string().optional()
5579
5626
  });
5580
5627
 
5628
+ // ../../packages/types/src/pricing-gemini-omni.ts
5629
+ var GEMINI_OMNI_FLAT_OUR_COST_CENTS = 84;
5630
+ var GEMINI_OMNI_FLAT_USER_PRICE_CENTS = 168;
5631
+
5581
5632
  // ../../packages/types/src/pricing.ts
5582
5633
  var CREDITS_PER_USD_CENT = 10;
5583
5634
  var CREDITS_PER_DOLLAR = 100 * CREDITS_PER_USD_CENT;
@@ -5986,6 +6037,18 @@ var DEFAULT_PRICING = {
5986
6037
  ourCostCents: 120,
5987
6038
  userPriceCents: 240
5988
6039
  },
6040
+ // Gemini Omni Video (gemini-omni-video) — Mix primary generator since
6041
+ // 2026-08-18. FLAT per generation: 168 KIE credits = $0.84, identical at
6042
+ // 720p and 1080p and independent of the 3.5-10s trim window. Do NOT add
6043
+ // per-second overrides for this key — resolveSuccessBilling bills it flat.
6044
+ //
6045
+ // Shares the constants with the pre-submit ESTIMATOR (mix-cost.ts) rather
6046
+ // than repeating the numbers: a literal here that drifted from the estimator
6047
+ // would quote one price and charge another on every mix.
6048
+ "kie:gemini-omni-video": {
6049
+ ourCostCents: GEMINI_OMNI_FLAT_OUR_COST_CENTS,
6050
+ userPriceCents: GEMINI_OMNI_FLAT_USER_PRICE_CENTS
6051
+ },
5989
6052
  "kie:video-lipsync-generation": {
5990
6053
  ourCostCents: 45,
5991
6054
  userPriceCents: 90
@@ -7949,7 +8012,57 @@ var FeatureSpec = z36.object({
7949
8012
  });
7950
8013
 
7951
8014
  // ../../packages/types/src/mix.ts
8015
+ import { z as z38 } from "zod";
8016
+
8017
+ // ../../packages/types/src/mix-degradation.ts
7952
8018
  import { z as z37 } from "zod";
8019
+ var MIX_DEGRADATION_REASONS = [
8020
+ /**
8021
+ * At least one scene the mix PLANNED is missing from the delivered video, so
8022
+ * the result is shorter than the source. Set at assemble time by comparing
8023
+ * the concat set against the planned scene set — the scene's own code (if it
8024
+ * had one) never reaches the mix-level rollup, which only sees scenes that
8025
+ * SUCCEEDED, and that is exactly how a live 17.00s-of-20.00s delivery
8026
+ * shipped with degradedReason NULL and no banner at all.
8027
+ *
8028
+ * ORDERING: FIRST, above every refusal code. A short delivery must never be
8029
+ * MASKED. It used to sit below the three content refusals on the theory that
8030
+ * a refusal names something the user can change AND explains the missing
8031
+ * scene — but it does neither reliably: in a 3-scene mix where scene 1 fails
8032
+ * outright and scene 2 ships through Wan after a reference refusal, the
8033
+ * refusal copy reads "we used a lower-quality alternative", a claim about
8034
+ * QUALITY that says nothing about the video being shorter than what was paid
8035
+ * for, and that is actively wrong about the dropped scene (for which we used
8036
+ * nothing). Every other code in this list describes a scene that DID ship.
8037
+ */
8038
+ "scenes_dropped",
8039
+ /** Google's safety filter rejected the user's reference photo. Deterministic. */
8040
+ "reference_rejected",
8041
+ /** Google refused the wording of the change description. */
8042
+ "prompt_rejected",
8043
+ /**
8044
+ * The provider refused the content but its message names neither the
8045
+ * reference nor the wording, so we cannot say which. Distinct from
8046
+ * 'provider_unavailable' on purpose: "unavailable" invites the user to retry
8047
+ * unchanged, which can never succeed against a content refusal and only
8048
+ * burns their credits. This code tells them something must change.
8049
+ */
8050
+ "content_rejected",
8051
+ /**
8052
+ * The scene's length fell outside Gemini's usable 3.5s-10s trim window —
8053
+ * EITHER bound. Deliberately ONE code for both: the user controls neither
8054
+ * (scene segmentation is entirely ours), so "too short" and "too long" are
8055
+ * not differently actionable, and one honest explanation beats two that
8056
+ * both amount to "our segmentation produced a length the primary generator
8057
+ * cannot take".
8058
+ */
8059
+ "scene_length_unsupported",
8060
+ /** Transient provider failures exhausted the budget. */
8061
+ "provider_unavailable"
8062
+ ];
8063
+ var MixDegradationReasonSchema = z37.enum(MIX_DEGRADATION_REASONS);
8064
+
8065
+ // ../../packages/types/src/mix.ts
7953
8066
  var MEDIA_TYPES = [
7954
8067
  "video",
7955
8068
  "image"
@@ -7987,38 +8100,38 @@ function isPublicHttpsUrl(raw) {
7987
8100
  return true;
7988
8101
  }
7989
8102
  __name(isPublicHttpsUrl, "isPublicHttpsUrl");
7990
- var PublicHttpsUrl = z37.string().url().refine(isPublicHttpsUrl, {
8103
+ var PublicHttpsUrl = z38.string().url().refine(isPublicHttpsUrl, {
7991
8104
  message: "must be a public HTTPS URL"
7992
8105
  });
7993
- var InternalAssetPath = z37.string().regex(/^\/(?:api|v1)\/assets\/[A-Za-z0-9._~%/-]+$/, "must be a public HTTPS URL or an internal asset path");
7994
- var MixImageUrl = z37.union([
8106
+ var InternalAssetPath = z38.string().regex(/^\/(?:api|v1)\/assets\/[A-Za-z0-9._~%/-]+$/, "must be a public HTTPS URL or an internal asset path");
8107
+ var MixImageUrl = z38.union([
7995
8108
  PublicHttpsUrl,
7996
8109
  InternalAssetPath
7997
8110
  ]);
7998
- var MixAxes = z37.object({
7999
- product: z37.boolean(),
8000
- person: z37.boolean(),
8001
- setting: z37.boolean()
8002
- });
8003
- var MixReferences = z37.object({
8004
- product: z37.array(PublicHttpsUrl).max(3, "at most 3 product references"),
8005
- person: z37.array(PublicHttpsUrl).max(3, "at most 3 person references"),
8006
- setting: z37.array(PublicHttpsUrl).max(3, "at most 3 setting references")
8007
- });
8008
- var MixImageEdit = z37.object({
8009
- instruction: z37.string().min(1).max(600),
8010
- imageUrls: z37.array(MixImageUrl).min(1).max(3)
8011
- });
8012
- var MixRequest = z37.object({
8013
- mediaType: z37.enum(MEDIA_TYPES),
8014
- originalUrl: z37.union([
8111
+ var MixAxes = z38.object({
8112
+ product: z38.boolean(),
8113
+ person: z38.boolean(),
8114
+ setting: z38.boolean()
8115
+ });
8116
+ var MixReferences = z38.object({
8117
+ product: z38.array(PublicHttpsUrl).max(3, "at most 3 product references"),
8118
+ person: z38.array(PublicHttpsUrl).max(3, "at most 3 person references"),
8119
+ setting: z38.array(PublicHttpsUrl).max(3, "at most 3 setting references")
8120
+ });
8121
+ var MixImageEdit = z38.object({
8122
+ instruction: z38.string().min(1).max(600),
8123
+ imageUrls: z38.array(MixImageUrl).min(1).max(3)
8124
+ });
8125
+ var MixRequest = z38.object({
8126
+ mediaType: z38.enum(MEDIA_TYPES),
8127
+ originalUrl: z38.union([
8015
8128
  PublicHttpsUrl,
8016
8129
  InternalAssetPath
8017
8130
  ]),
8018
8131
  axes: MixAxes,
8019
8132
  references: MixReferences,
8020
- personText: z37.string().max(500).optional(),
8021
- settingText: z37.string().max(500).optional(),
8133
+ personText: z38.string().max(500).optional(),
8134
+ settingText: z38.string().max(500).optional(),
8022
8135
  /**
8023
8136
  * Optional public URL of a user-uploaded audio file (mp3/wav). Wan Video
8024
8137
  * Edit has no audio input and the mix never lipsyncs: the Wan output is
@@ -8027,11 +8140,11 @@ var MixRequest = z37.object({
8027
8140
  * (mute + overlay). No per-scene slicing, no `reference_audio_urls`.
8028
8141
  */
8029
8142
  audioUrl: PublicHttpsUrl.optional(),
8030
- resolution: z37.enum(RESOLUTIONS).default("720p"),
8031
- originalDurationSec: z37.number().positive().max(600).optional(),
8143
+ resolution: z38.enum(RESOLUTIONS).default("720p"),
8144
+ originalDurationSec: z38.number().positive().max(600).optional(),
8032
8145
  image: MixImageEdit.optional(),
8033
- sourceTaskId: z37.string().max(64).optional(),
8034
- sourceCreativeId: z37.string().max(64).optional()
8146
+ sourceTaskId: z38.string().max(64).optional(),
8147
+ sourceCreativeId: z38.string().max(64).optional()
8035
8148
  }).superRefine((req, ctx) => {
8036
8149
  if (req.mediaType === "image") {
8037
8150
  if (!req.image) {
@@ -8065,18 +8178,18 @@ var MixRequest = z37.object({
8065
8178
  });
8066
8179
  }
8067
8180
  });
8068
- var ReferenceMap = z37.object({
8069
- product: z37.object({
8070
- start: z37.number().int(),
8071
- end: z37.number().int()
8181
+ var ReferenceMap = z38.object({
8182
+ product: z38.object({
8183
+ start: z38.number().int(),
8184
+ end: z38.number().int()
8072
8185
  }).optional(),
8073
- person: z37.object({
8074
- start: z37.number().int(),
8075
- end: z37.number().int()
8186
+ person: z38.object({
8187
+ start: z38.number().int(),
8188
+ end: z38.number().int()
8076
8189
  }).optional(),
8077
- setting: z37.object({
8078
- start: z37.number().int(),
8079
- end: z37.number().int()
8190
+ setting: z38.object({
8191
+ start: z38.number().int(),
8192
+ end: z38.number().int()
8080
8193
  }).optional()
8081
8194
  });
8082
8195
  var SCENE_CLIP_TYPES = [
@@ -8092,39 +8205,39 @@ var INSTANCE_CARDINALITIES = [
8092
8205
  "multiple_same",
8093
8206
  "multiple_distinct"
8094
8207
  ];
8095
- var SceneSegment = z37.object({
8096
- index: z37.number().int().positive(),
8097
- startTs: z37.number().nonnegative(),
8098
- endTs: z37.number().positive(),
8099
- seedanceDuration: z37.number().int().min(4).max(15),
8208
+ var SceneSegment = z38.object({
8209
+ index: z38.number().int().positive(),
8210
+ startTs: z38.number().nonnegative(),
8211
+ endTs: z38.number().positive(),
8212
+ seedanceDuration: z38.number().int().min(4).max(15),
8100
8213
  // Pass 1 / Pass 2 outputs (all optional — populated when the rich analyzer
8101
8214
  // runs and empty on fallback).
8102
- action: z37.string().optional(),
8103
- motion: z37.string().optional(),
8104
- clipType: z37.enum(SCENE_CLIP_TYPES).optional(),
8105
- hasCharacter: z37.boolean().optional(),
8106
- faceVisible: z37.boolean().optional(),
8215
+ action: z38.string().optional(),
8216
+ motion: z38.string().optional(),
8217
+ clipType: z38.enum(SCENE_CLIP_TYPES).optional(),
8218
+ hasCharacter: z38.boolean().optional(),
8219
+ faceVisible: z38.boolean().optional(),
8107
8220
  // Pass 2 refinement — rich per-scene metadata used by buildMixPrompt.
8108
- startState: z37.string().optional(),
8109
- endState: z37.string().optional(),
8110
- cameraMovement: z37.string().optional(),
8111
- emotion: z37.string().optional(),
8112
- productPlacement: z37.string().optional(),
8113
- productInteraction: z37.string().optional(),
8114
- settingDescription: z37.string().optional(),
8115
- dialogue: z37.string().optional(),
8221
+ startState: z38.string().optional(),
8222
+ endState: z38.string().optional(),
8223
+ cameraMovement: z38.string().optional(),
8224
+ emotion: z38.string().optional(),
8225
+ productPlacement: z38.string().optional(),
8226
+ productInteraction: z38.string().optional(),
8227
+ settingDescription: z38.string().optional(),
8228
+ dialogue: z38.string().optional(),
8116
8229
  // Main vs extras / noise (our addition on top of the script's schema).
8117
- mainPersonDescription: z37.string().optional(),
8118
- mainProductDescription: z37.string().optional(),
8119
- personInstances: z37.enum(INSTANCE_CARDINALITIES).optional(),
8120
- productInstances: z37.enum(INSTANCE_CARDINALITIES).optional(),
8230
+ mainPersonDescription: z38.string().optional(),
8231
+ mainProductDescription: z38.string().optional(),
8232
+ personInstances: z38.enum(INSTANCE_CARDINALITIES).optional(),
8233
+ productInstances: z38.enum(INSTANCE_CARDINALITIES).optional(),
8121
8234
  /**
8122
8235
  * Seconds of prev-clipType content absorbed at the start of this scene by
8123
8236
  * Pass 2.7's clipType boundary margin. When > 0 and the scene is a
8124
8237
  * pass-through (no Seedance), the concatenator prepends a held-still
8125
8238
  * preamble (nano-banana-swapped first frame) to hide the leak.
8126
8239
  */
8127
- absorbedMarginSec: z37.number().nonnegative().optional(),
8240
+ absorbedMarginSec: z38.number().nonnegative().optional(),
8128
8241
  /**
8129
8242
  * True when the scene shows post-production graphics baked into the frame:
8130
8243
  * caption/subtitle text, infographic overlay cards, or inset
@@ -8133,33 +8246,39 @@ var SceneSegment = z37.object({
8133
8246
  * (mentioning nonexistent overlays gives the generator license to
8134
8247
  * fabricate them).
8135
8248
  */
8136
- hasOverlayGraphics: z37.boolean().optional()
8249
+ hasOverlayGraphics: z38.boolean().optional()
8137
8250
  });
8138
- var MixSceneResult = z37.object({
8139
- index: z37.number().int().positive(),
8140
- status: z37.enum([
8251
+ var MixSceneResult = z38.object({
8252
+ index: z38.number().int().positive(),
8253
+ status: z38.enum([
8141
8254
  "queued",
8142
8255
  "submitted",
8143
8256
  "done",
8144
8257
  "failed"
8145
8258
  ]),
8146
- seedanceTaskId: z37.string().optional(),
8147
- videoUrl: z37.string().url().optional(),
8148
- error: z37.string().optional()
8149
- });
8150
- var MixResult = z37.object({
8151
- mixTaskId: z37.string().uuid(),
8152
- status: z37.enum([
8259
+ seedanceTaskId: z38.string().optional(),
8260
+ videoUrl: z38.string().url().optional(),
8261
+ error: z38.string().optional(),
8262
+ degradedReason: MixDegradationReasonSchema.optional()
8263
+ });
8264
+ var MixResult = z38.object({
8265
+ mixTaskId: z38.string().uuid(),
8266
+ status: z38.enum([
8153
8267
  "queued",
8154
8268
  "processing",
8155
8269
  "done",
8156
8270
  "error"
8157
8271
  ]),
8158
- resultUrl: z37.string().url().optional(),
8159
- scenes: z37.array(MixSceneResult).default([]),
8160
- failReason: z37.string().optional()
8272
+ resultUrl: z38.string().url().optional(),
8273
+ scenes: z38.array(MixSceneResult).default([]),
8274
+ failReason: z38.string().optional(),
8275
+ degradedReason: MixDegradationReasonSchema.optional()
8161
8276
  });
8162
8277
 
8278
+ // ../../packages/types/src/mix-cost.ts
8279
+ var MAX_QA_RETRIES_PER_SCENE_UPPER_BOUND = 1;
8280
+ var MAX_BILLABLE_GENERATIONS_PER_BLOCK = 1 + MAX_QA_RETRIES_PER_SCENE_UPPER_BOUND;
8281
+
8163
8282
  // ../../packages/types/src/product-delivery-format.ts
8164
8283
  var DELIVERY_FAMILIES = [
8165
8284
  "solid_dose",
@@ -8248,41 +8367,41 @@ var DECLARATION = DELIVERY_FAMILIES.map((family) => [
8248
8367
  ]);
8249
8368
 
8250
8369
  // ../../packages/types/src/task-type.ts
8251
- import { z as z38 } from "zod";
8252
- var TaskTypeSchema = z38.enum([
8370
+ import { z as z39 } from "zod";
8371
+ var TaskTypeSchema = z39.enum([
8253
8372
  "product",
8254
8373
  "service"
8255
8374
  ]);
8256
8375
 
8257
8376
  // ../../packages/types/src/landing-regeneration.ts
8258
- import { z as z39 } from "zod";
8259
- var LandingRegenerationStatus = z39.enum([
8377
+ import { z as z40 } from "zod";
8378
+ var LandingRegenerationStatus = z40.enum([
8260
8379
  "queued",
8261
8380
  "processing",
8262
8381
  "published",
8263
8382
  "failed"
8264
8383
  ]);
8265
- var RegenerateLandingRoleResponse = z39.object({
8266
- ok: z39.literal(true),
8384
+ var RegenerateLandingRoleResponse = z40.object({
8385
+ ok: z40.literal(true),
8267
8386
  role: LandingRole,
8268
- promptIndex: z39.number().int().nonnegative(),
8269
- operationId: z39.string().min(1)
8387
+ promptIndex: z40.number().int().nonnegative(),
8388
+ operationId: z40.string().min(1)
8270
8389
  });
8271
- var LandingRegenerationStatusResponse = z39.object({
8272
- ok: z39.literal(true),
8273
- operationId: z39.string().min(1),
8390
+ var LandingRegenerationStatusResponse = z40.object({
8391
+ ok: z40.literal(true),
8392
+ operationId: z40.string().min(1),
8274
8393
  role: LandingRole,
8275
8394
  status: LandingRegenerationStatus,
8276
- refunded: z39.boolean(),
8277
- failureReason: z39.string().nullable(),
8278
- publishedAssetKey: z39.string().nullable(),
8279
- updatedAt: z39.string().datetime()
8395
+ refunded: z40.boolean(),
8396
+ failureReason: z40.string().nullable(),
8397
+ publishedAssetKey: z40.string().nullable(),
8398
+ updatedAt: z40.string().datetime()
8280
8399
  });
8281
8400
 
8282
8401
  // ../../packages/types/src/video-edit.ts
8283
- import { z as z40 } from "zod";
8402
+ import { z as z41 } from "zod";
8284
8403
  var MAX_SEGMENT_SECONDS = 3;
8285
- var VideoEditStatusSchema = z40.enum([
8404
+ var VideoEditStatusSchema = z41.enum([
8286
8405
  "pending",
8287
8406
  "processing",
8288
8407
  "assembling",
@@ -8291,9 +8410,9 @@ var VideoEditStatusSchema = z40.enum([
8291
8410
  "discarded",
8292
8411
  "failed"
8293
8412
  ]);
8294
- var VideoEditTimeSectionSchema = z40.object({
8295
- startSec: z40.number().min(0),
8296
- endSec: z40.number().positive()
8413
+ var VideoEditTimeSectionSchema = z41.object({
8414
+ startSec: z41.number().min(0),
8415
+ endSec: z41.number().positive()
8297
8416
  }).refine((v) => v.endSec > v.startSec, {
8298
8417
  message: "endSec must be after startSec",
8299
8418
  path: [
@@ -8305,45 +8424,45 @@ var VideoEditTimeSectionSchema = z40.object({
8305
8424
  "endSec"
8306
8425
  ]
8307
8426
  });
8308
- var VideoEditRequestSchema = z40.object({
8309
- comment: z40.string().trim().min(1).max(2e3),
8310
- sections: z40.array(VideoEditTimeSectionSchema).min(1).optional()
8427
+ var VideoEditRequestSchema = z41.object({
8428
+ comment: z41.string().trim().min(1).max(2e3),
8429
+ sections: z41.array(VideoEditTimeSectionSchema).min(1).optional()
8311
8430
  });
8312
- var VideoEditModeSchema = z40.enum([
8431
+ var VideoEditModeSchema = z41.enum([
8313
8432
  "wan_edit",
8314
8433
  "regenerate"
8315
8434
  ]);
8316
- var VideoRegenerationEngineSchema = z40.enum([
8435
+ var VideoRegenerationEngineSchema = z41.enum([
8317
8436
  "free_text",
8318
8437
  "free_image",
8319
8438
  "single_call",
8320
8439
  "multi_shot"
8321
8440
  ]);
8322
- var VideoRegenerationRouteFingerprintSchema = z40.string().trim().min(1).max(128);
8323
- var RegenerateEditRequestSchema = z40.object({
8324
- angleKey: z40.string().min(1),
8325
- comment: z40.string().min(1).max(2e3)
8441
+ var VideoRegenerationRouteFingerprintSchema = z41.string().trim().min(1).max(128);
8442
+ var RegenerateEditRequestSchema = z41.object({
8443
+ angleKey: z41.string().min(1),
8444
+ comment: z41.string().min(1).max(2e3)
8326
8445
  });
8327
8446
 
8328
8447
  // ../../packages/types/src/uploaded-asset.ts
8329
- import { z as z41 } from "zod";
8330
- var UploadedAssetMediaKind = z41.enum([
8448
+ import { z as z42 } from "zod";
8449
+ var UploadedAssetMediaKind = z42.enum([
8331
8450
  "image",
8332
8451
  "video"
8333
8452
  ]);
8334
- var UploadedAssetSessionMediaKind = z41.enum([
8453
+ var UploadedAssetSessionMediaKind = z42.enum([
8335
8454
  "image",
8336
8455
  "video",
8337
8456
  "mixed"
8338
8457
  ]);
8339
- var UploadedAssetRole = z41.enum([
8458
+ var UploadedAssetRole = z42.enum([
8340
8459
  "media",
8341
8460
  "thumbnail"
8342
8461
  ]);
8343
8462
  var UPLOADED_ASSET_MAX_FILES = 10;
8344
8463
  var UPLOADED_ASSET_IMAGE_MAX_FILES = 5;
8345
- var UploadedAssetId = z41.string().uuid();
8346
- var HttpsUrl = z41.string().url().refine((value) => {
8464
+ var UploadedAssetId = z42.string().uuid();
8465
+ var HttpsUrl = z42.string().url().refine((value) => {
8347
8466
  try {
8348
8467
  const url = new URL(value);
8349
8468
  return url.protocol === "https:" && !url.username && !url.password;
@@ -8351,23 +8470,23 @@ var HttpsUrl = z41.string().url().refine((value) => {
8351
8470
  return false;
8352
8471
  }
8353
8472
  }, "URL must use https");
8354
- var UtcDateTime = z41.string().datetime().refine((value) => {
8473
+ var UtcDateTime = z42.string().datetime().refine((value) => {
8355
8474
  const parts = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?Z$/.exec(value);
8356
8475
  const timestamp = Date.parse(value);
8357
8476
  if (!parts || Number.isNaN(timestamp)) return false;
8358
8477
  const date = new Date(timestamp);
8359
8478
  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]);
8360
8479
  }, "datetime must be a valid UTC calendar instant");
8361
- var UploadedAssetRef = z41.object({
8480
+ var UploadedAssetRef = z42.object({
8362
8481
  assetId: UploadedAssetId
8363
8482
  }).strict();
8364
8483
  var UploadedAssetCompletion = UploadedAssetRef.extend({
8365
8484
  mediaKind: UploadedAssetMediaKind,
8366
8485
  assetRole: UploadedAssetRole
8367
8486
  }).strict();
8368
- var UploadedAssetMetadata = z41.object({
8487
+ var UploadedAssetMetadata = z42.object({
8369
8488
  assetId: UploadedAssetId,
8370
- ownerId: z41.string().min(1),
8489
+ ownerId: z42.string().min(1),
8371
8490
  mediaKind: UploadedAssetMediaKind,
8372
8491
  assetRole: UploadedAssetRole,
8373
8492
  createdAt: UtcDateTime,
@@ -8375,7 +8494,7 @@ var UploadedAssetMetadata = z41.object({
8375
8494
  }).strict().superRefine((value, ctx) => {
8376
8495
  if (Date.parse(value.expiresAt) <= Date.parse(value.createdAt)) {
8377
8496
  ctx.addIssue({
8378
- code: z41.ZodIssueCode.custom,
8497
+ code: z42.ZodIssueCode.custom,
8379
8498
  path: [
8380
8499
  "expiresAt"
8381
8500
  ],
@@ -8383,27 +8502,27 @@ var UploadedAssetMetadata = z41.object({
8383
8502
  });
8384
8503
  }
8385
8504
  });
8386
- var MediaSourceRef = z41.object({
8505
+ var MediaSourceRef = z42.object({
8387
8506
  url: HttpsUrl.optional(),
8388
- path: z41.string().min(1).optional(),
8507
+ path: z42.string().min(1).optional(),
8389
8508
  assetId: UploadedAssetId.optional()
8390
8509
  }).strict().superRefine((value, ctx) => {
8391
8510
  const sourceCount = Number(value.url !== void 0) + Number(value.path !== void 0) + Number(value.assetId !== void 0);
8392
8511
  if (sourceCount !== 1) {
8393
8512
  ctx.addIssue({
8394
- code: z41.ZodIssueCode.custom,
8513
+ code: z42.ZodIssueCode.custom,
8395
8514
  message: "media source needs exactly one of url, path, or assetId"
8396
8515
  });
8397
8516
  }
8398
8517
  });
8399
- var UploadedAssetSessionRequest = z41.object({
8518
+ var UploadedAssetSessionRequest = z42.object({
8400
8519
  mediaKind: UploadedAssetSessionMediaKind,
8401
8520
  assetRole: UploadedAssetRole.default("media"),
8402
- maxFiles: z41.number().int().min(1).max(UPLOADED_ASSET_MAX_FILES).optional()
8521
+ maxFiles: z42.number().int().min(1).max(UPLOADED_ASSET_MAX_FILES).optional()
8403
8522
  }).strict().superRefine((value, ctx) => {
8404
8523
  if (value.mediaKind === "mixed" && value.assetRole === "thumbnail") {
8405
8524
  ctx.addIssue({
8406
- code: z41.ZodIssueCode.custom,
8525
+ code: z42.ZodIssueCode.custom,
8407
8526
  path: [
8408
8527
  "mediaKind"
8409
8528
  ],
@@ -8412,7 +8531,7 @@ var UploadedAssetSessionRequest = z41.object({
8412
8531
  }
8413
8532
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
8414
8533
  ctx.addIssue({
8415
- code: z41.ZodIssueCode.custom,
8534
+ code: z42.ZodIssueCode.custom,
8416
8535
  path: [
8417
8536
  "maxFiles"
8418
8537
  ],
@@ -8421,7 +8540,7 @@ var UploadedAssetSessionRequest = z41.object({
8421
8540
  }
8422
8541
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > UPLOADED_ASSET_IMAGE_MAX_FILES) {
8423
8542
  ctx.addIssue({
8424
- code: z41.ZodIssueCode.custom,
8543
+ code: z42.ZodIssueCode.custom,
8425
8544
  path: [
8426
8545
  "maxFiles"
8427
8546
  ],
@@ -8430,7 +8549,7 @@ var UploadedAssetSessionRequest = z41.object({
8430
8549
  }
8431
8550
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
8432
8551
  ctx.addIssue({
8433
- code: z41.ZodIssueCode.custom,
8552
+ code: z42.ZodIssueCode.custom,
8434
8553
  path: [
8435
8554
  "mediaKind"
8436
8555
  ],
@@ -8438,32 +8557,32 @@ var UploadedAssetSessionRequest = z41.object({
8438
8557
  });
8439
8558
  }
8440
8559
  });
8441
- var UploadedAssetSessionStatus = z41.discriminatedUnion("status", [
8442
- z41.object({
8443
- status: z41.literal("pending"),
8444
- assets: z41.array(UploadedAssetCompletion).length(0)
8560
+ var UploadedAssetSessionStatus = z42.discriminatedUnion("status", [
8561
+ z42.object({
8562
+ status: z42.literal("pending"),
8563
+ assets: z42.array(UploadedAssetCompletion).length(0)
8445
8564
  }).strict(),
8446
- z41.object({
8447
- status: z41.literal("uploaded"),
8448
- assets: z41.array(UploadedAssetCompletion).min(1).max(UPLOADED_ASSET_MAX_FILES)
8565
+ z42.object({
8566
+ status: z42.literal("uploaded"),
8567
+ assets: z42.array(UploadedAssetCompletion).min(1).max(UPLOADED_ASSET_MAX_FILES)
8449
8568
  }).strict()
8450
8569
  ]);
8451
- var UploadedAssetAdoptionRequest = z41.object({
8570
+ var UploadedAssetAdoptionRequest = z42.object({
8452
8571
  assetId: UploadedAssetId,
8453
- ownerId: z41.string().min(1),
8454
- consumer: z41.string().min(1).max(100),
8455
- idempotencyKey: z41.string().min(1).max(255)
8572
+ ownerId: z42.string().min(1),
8573
+ consumer: z42.string().min(1).max(100),
8574
+ idempotencyKey: z42.string().min(1).max(255)
8456
8575
  }).strict();
8457
8576
 
8458
8577
  // ../../packages/types/src/dropshipping-project.ts
8459
- import { z as z42 } from "zod";
8460
- var DropshippingProjectStatusSchema = z42.enum([
8578
+ import { z as z43 } from "zod";
8579
+ var DropshippingProjectStatusSchema = z43.enum([
8461
8580
  "active",
8462
8581
  "completed",
8463
8582
  "archived"
8464
8583
  ]);
8465
8584
  var DROPSHIPPING_LAUNCH_REWARD_CAMPAIGN = "dropshipping-launch-v1";
8466
- var DropshippingRewardMilestoneSchema = z42.enum([
8585
+ var DropshippingRewardMilestoneSchema = z43.enum([
8467
8586
  "product_selected",
8468
8587
  "costing_saved",
8469
8588
  "product_media_ready",
@@ -8478,21 +8597,21 @@ var DROPSHIPPING_LAUNCH_REWARD_CREDITS = {
8478
8597
  campaign_created: 200
8479
8598
  };
8480
8599
  var DROPSHIPPING_LAUNCH_REWARD_TOTAL_CREDITS = Object.values(DROPSHIPPING_LAUNCH_REWARD_CREDITS).reduce((sum, credits) => sum + credits, 0);
8481
- var DropshippingProjectRewardMilestoneStateSchema = z42.object({
8600
+ var DropshippingProjectRewardMilestoneStateSchema = z43.object({
8482
8601
  milestone: DropshippingRewardMilestoneSchema,
8483
- credits: z42.number().int().positive(),
8484
- available: z42.boolean().optional(),
8485
- earned: z42.boolean(),
8486
- grantId: z42.string().uuid().nullable(),
8487
- grantedAt: z42.string().datetime().nullable()
8488
- });
8489
- var DropshippingProjectRewardProgressSchema = z42.object({
8490
- campaignKey: z42.literal(DROPSHIPPING_LAUNCH_REWARD_CAMPAIGN),
8491
- totalCredits: z42.number().int().positive(),
8492
- earnedCredits: z42.number().int().nonnegative(),
8493
- milestones: z42.array(DropshippingProjectRewardMilestoneStateSchema).length(DropshippingRewardMilestoneSchema.options.length)
8494
- });
8495
- var DropshippingProjectPhaseSchema = z42.enum([
8602
+ credits: z43.number().int().positive(),
8603
+ available: z43.boolean().optional(),
8604
+ earned: z43.boolean(),
8605
+ grantId: z43.string().uuid().nullable(),
8606
+ grantedAt: z43.string().datetime().nullable()
8607
+ });
8608
+ var DropshippingProjectRewardProgressSchema = z43.object({
8609
+ campaignKey: z43.literal(DROPSHIPPING_LAUNCH_REWARD_CAMPAIGN),
8610
+ totalCredits: z43.number().int().positive(),
8611
+ earnedCredits: z43.number().int().nonnegative(),
8612
+ milestones: z43.array(DropshippingProjectRewardMilestoneStateSchema).length(DropshippingRewardMilestoneSchema.options.length)
8613
+ });
8614
+ var DropshippingProjectPhaseSchema = z43.enum([
8496
8615
  "research",
8497
8616
  "costing",
8498
8617
  "media",
@@ -8501,18 +8620,18 @@ var DropshippingProjectPhaseSchema = z42.enum([
8501
8620
  "advertising",
8502
8621
  "complete"
8503
8622
  ]);
8504
- var DropshippingProjectCostingInputSchema = z42.object({
8505
- country: z42.string().min(2).max(3),
8506
- supplierCost: z42.number().finite().positive(),
8507
- shippingCost: z42.number().finite().nonnegative(),
8508
- returnRate: z42.number().finite().min(0).lt(1),
8509
- cancellationRate: z42.number().finite().min(0).lt(1),
8510
- adsManagerCpa: z42.number().finite().nonnegative(),
8511
- desiredMargin: z42.number().finite().min(0).lt(1)
8623
+ var DropshippingProjectCostingInputSchema = z43.object({
8624
+ country: z43.string().min(2).max(3),
8625
+ supplierCost: z43.number().finite().positive(),
8626
+ shippingCost: z43.number().finite().nonnegative(),
8627
+ returnRate: z43.number().finite().min(0).lt(1),
8628
+ cancellationRate: z43.number().finite().min(0).lt(1),
8629
+ adsManagerCpa: z43.number().finite().nonnegative(),
8630
+ desiredMargin: z43.number().finite().min(0).lt(1)
8512
8631
  }).superRefine(({ returnRate, cancellationRate }, context) => {
8513
8632
  if (returnRate + cancellationRate >= 1) {
8514
8633
  context.addIssue({
8515
- code: z42.ZodIssueCode.custom,
8634
+ code: z43.ZodIssueCode.custom,
8516
8635
  path: [
8517
8636
  "cancellationRate"
8518
8637
  ],
@@ -8520,24 +8639,24 @@ var DropshippingProjectCostingInputSchema = z42.object({
8520
8639
  });
8521
8640
  }
8522
8641
  });
8523
- var DropshippingProjectCostingResultSchema = z42.object({
8524
- country: z42.string().min(2).max(3),
8525
- deliveryRate: z42.number().finite(),
8526
- adjustedShippingCost: z42.number().finite(),
8527
- adjustedCpa: z42.number().finite(),
8528
- totalCost: z42.number().finite(),
8529
- suggestedPrice: z42.number().finite(),
8530
- baseCommercialPrice: z42.number().finite(),
8531
- minimumSafePrice: z42.number().finite(),
8532
- commercialPrice: z42.number().finite(),
8533
- comparisonPrice: z42.number().finite(),
8534
- estimatedProfit: z42.number().finite(),
8535
- actualMargin: z42.number().finite(),
8536
- breakEvenAdsManagerCpa: z42.number().finite(),
8537
- wasPriceAutoAdjusted: z42.boolean(),
8538
- profitabilityStatus: z42.literal("healthy")
8539
- });
8540
- var HttpUrlSchema = z42.string().url().max(2e3).refine((value) => {
8642
+ var DropshippingProjectCostingResultSchema = z43.object({
8643
+ country: z43.string().min(2).max(3),
8644
+ deliveryRate: z43.number().finite(),
8645
+ adjustedShippingCost: z43.number().finite(),
8646
+ adjustedCpa: z43.number().finite(),
8647
+ totalCost: z43.number().finite(),
8648
+ suggestedPrice: z43.number().finite(),
8649
+ baseCommercialPrice: z43.number().finite(),
8650
+ minimumSafePrice: z43.number().finite(),
8651
+ commercialPrice: z43.number().finite(),
8652
+ comparisonPrice: z43.number().finite(),
8653
+ estimatedProfit: z43.number().finite(),
8654
+ actualMargin: z43.number().finite(),
8655
+ breakEvenAdsManagerCpa: z43.number().finite(),
8656
+ wasPriceAutoAdjusted: z43.boolean(),
8657
+ profitabilityStatus: z43.literal("healthy")
8658
+ });
8659
+ var HttpUrlSchema = z43.string().url().max(2e3).refine((value) => {
8541
8660
  try {
8542
8661
  return [
8543
8662
  "http:",
@@ -8547,124 +8666,124 @@ var HttpUrlSchema = z42.string().url().max(2e3).refine((value) => {
8547
8666
  return false;
8548
8667
  }
8549
8668
  }, "Product URL must use HTTP(S)");
8550
- var ResearchCandidateOriginSchema = z42.object({
8551
- type: z42.literal("research_candidate"),
8552
- runId: z42.string().uuid(),
8553
- candidateSourceId: z42.string().min(1).max(160)
8554
- });
8555
- var TaskOriginSchema = z42.object({
8556
- type: z42.literal("task"),
8557
- taskId: z42.string().uuid()
8558
- });
8559
- var ManualOriginSchema = z42.object({
8560
- type: z42.literal("manual"),
8561
- clientRequestId: z42.string().uuid(),
8562
- country: z42.string().min(2).max(3).optional()
8563
- });
8564
- var CreateDropshippingProjectRequestSchema = z42.object({
8565
- origin: z42.discriminatedUnion("type", [
8669
+ var ResearchCandidateOriginSchema = z43.object({
8670
+ type: z43.literal("research_candidate"),
8671
+ runId: z43.string().uuid(),
8672
+ candidateSourceId: z43.string().min(1).max(160)
8673
+ });
8674
+ var TaskOriginSchema = z43.object({
8675
+ type: z43.literal("task"),
8676
+ taskId: z43.string().uuid()
8677
+ });
8678
+ var ManualOriginSchema = z43.object({
8679
+ type: z43.literal("manual"),
8680
+ clientRequestId: z43.string().uuid(),
8681
+ country: z43.string().min(2).max(3).optional()
8682
+ });
8683
+ var CreateDropshippingProjectRequestSchema = z43.object({
8684
+ origin: z43.discriminatedUnion("type", [
8566
8685
  ResearchCandidateOriginSchema,
8567
8686
  TaskOriginSchema,
8568
8687
  ManualOriginSchema
8569
8688
  ]),
8570
- productName: z42.string().trim().min(1).max(240).optional(),
8689
+ productName: z43.string().trim().min(1).max(240).optional(),
8571
8690
  productUrl: HttpUrlSchema.optional(),
8572
- country: z42.string().min(2).max(3).optional(),
8573
- languageCode: z42.string().min(2).max(16).optional()
8691
+ country: z43.string().min(2).max(3).optional(),
8692
+ languageCode: z43.string().min(2).max(16).optional()
8574
8693
  }).strict();
8575
- var SaveDropshippingProjectCostingRequestSchema = z42.object({
8694
+ var SaveDropshippingProjectCostingRequestSchema = z43.object({
8576
8695
  input: DropshippingProjectCostingInputSchema,
8577
- version: z42.number().int().positive()
8696
+ version: z43.number().int().positive()
8578
8697
  }).strict();
8579
- var DropshippingProjectNextActionSchema = z42.discriminatedUnion("kind", [
8580
- z42.object({
8581
- kind: z42.literal("cost_product"),
8582
- href: z42.string().min(1)
8698
+ var DropshippingProjectNextActionSchema = z43.discriminatedUnion("kind", [
8699
+ z43.object({
8700
+ kind: z43.literal("cost_product"),
8701
+ href: z43.string().min(1)
8583
8702
  }),
8584
- z42.object({
8585
- kind: z42.literal("provide_product_media"),
8586
- href: z42.string().min(1)
8703
+ z43.object({
8704
+ kind: z43.literal("provide_product_media"),
8705
+ href: z43.string().min(1)
8587
8706
  }),
8588
- z42.object({
8589
- kind: z42.literal("generate_creatives"),
8590
- href: z42.string().min(1)
8707
+ z43.object({
8708
+ kind: z43.literal("generate_creatives"),
8709
+ href: z43.string().min(1)
8591
8710
  }),
8592
- z42.object({
8593
- kind: z42.literal("wait_for_creatives"),
8594
- href: z42.string().min(1)
8711
+ z43.object({
8712
+ kind: z43.literal("wait_for_creatives"),
8713
+ href: z43.string().min(1)
8595
8714
  }),
8596
- z42.object({
8597
- kind: z42.literal("repair_creatives"),
8598
- href: z42.string().min(1)
8715
+ z43.object({
8716
+ kind: z43.literal("repair_creatives"),
8717
+ href: z43.string().min(1)
8599
8718
  }),
8600
- z42.object({
8601
- kind: z42.literal("complete_creative_set"),
8602
- href: z42.string().min(1)
8719
+ z43.object({
8720
+ kind: z43.literal("complete_creative_set"),
8721
+ href: z43.string().min(1)
8603
8722
  }),
8604
- z42.object({
8605
- kind: z42.literal("connect_shopify"),
8606
- href: z42.string().min(1)
8723
+ z43.object({
8724
+ kind: z43.literal("connect_shopify"),
8725
+ href: z43.string().min(1)
8607
8726
  }),
8608
- z42.object({
8609
- kind: z42.literal("publish_storefront"),
8610
- href: z42.string().min(1)
8727
+ z43.object({
8728
+ kind: z43.literal("publish_storefront"),
8729
+ href: z43.string().min(1)
8611
8730
  }),
8612
- z42.object({
8613
- kind: z42.literal("wait_for_storefront"),
8614
- href: z42.string().min(1)
8731
+ z43.object({
8732
+ kind: z43.literal("wait_for_storefront"),
8733
+ href: z43.string().min(1)
8615
8734
  }),
8616
- z42.object({
8617
- kind: z42.literal("connect_meta"),
8618
- href: z42.string().min(1)
8735
+ z43.object({
8736
+ kind: z43.literal("connect_meta"),
8737
+ href: z43.string().min(1)
8619
8738
  }),
8620
- z42.object({
8621
- kind: z42.literal("create_meta_campaign"),
8622
- href: z42.string().min(1)
8739
+ z43.object({
8740
+ kind: z43.literal("create_meta_campaign"),
8741
+ href: z43.string().min(1)
8623
8742
  }),
8624
- z42.object({
8625
- kind: z42.literal("repair_meta_campaign"),
8626
- href: z42.string().min(1)
8743
+ z43.object({
8744
+ kind: z43.literal("repair_meta_campaign"),
8745
+ href: z43.string().min(1)
8627
8746
  }),
8628
- z42.object({
8629
- kind: z42.literal("review_paused_campaign"),
8630
- href: z42.string().min(1)
8747
+ z43.object({
8748
+ kind: z43.literal("review_paused_campaign"),
8749
+ href: z43.string().min(1)
8631
8750
  })
8632
8751
  ]);
8633
- var DropshippingProjectResponseSchema = z42.object({
8634
- id: z42.string().uuid(),
8635
- taskId: z42.string().uuid().nullable(),
8752
+ var DropshippingProjectResponseSchema = z43.object({
8753
+ id: z43.string().uuid(),
8754
+ taskId: z43.string().uuid().nullable(),
8636
8755
  status: DropshippingProjectStatusSchema,
8637
- originKey: z42.string().min(1),
8638
- researchRunId: z42.string().uuid().nullable(),
8639
- candidateSourceId: z42.string().nullable(),
8640
- productName: z42.string().nullable(),
8756
+ originKey: z43.string().min(1),
8757
+ researchRunId: z43.string().uuid().nullable(),
8758
+ candidateSourceId: z43.string().nullable(),
8759
+ productName: z43.string().nullable(),
8641
8760
  productUrl: HttpUrlSchema.nullable(),
8642
- referenceImageUrl: z42.string().url().nullable(),
8643
- hasReferenceImage: z42.boolean(),
8644
- targetCountry: z42.string().nullable(),
8645
- languageCode: z42.string().nullable(),
8761
+ referenceImageUrl: z43.string().url().nullable(),
8762
+ hasReferenceImage: z43.boolean(),
8763
+ targetCountry: z43.string().nullable(),
8764
+ languageCode: z43.string().nullable(),
8646
8765
  costingInput: DropshippingProjectCostingInputSchema.nullable(),
8647
8766
  costingResult: DropshippingProjectCostingResultSchema.nullable(),
8648
- costingVersion: z42.number().int().positive().nullable(),
8649
- version: z42.number().int().positive(),
8767
+ costingVersion: z43.number().int().positive().nullable(),
8768
+ version: z43.number().int().positive(),
8650
8769
  phase: DropshippingProjectPhaseSchema,
8651
8770
  nextAction: DropshippingProjectNextActionSchema.nullable(),
8652
8771
  rewards: DropshippingProjectRewardProgressSchema,
8653
- createdAt: z42.string().datetime(),
8654
- updatedAt: z42.string().datetime()
8772
+ createdAt: z43.string().datetime(),
8773
+ updatedAt: z43.string().datetime()
8655
8774
  });
8656
8775
 
8657
8776
  // ../../packages/types/src/scene-subject-contract.ts
8658
- import { z as z43 } from "zod";
8659
- var SceneSubjectContractSchema = z43.object({
8660
- maxPeople: z43.number().int().min(1).max(10),
8661
- minPeople: z43.number().int().min(0).max(10),
8662
- minDistinctPeople: z43.number().int().min(0).max(10),
8663
- maxHands: z43.number().int().min(0).max(20)
8777
+ import { z as z44 } from "zod";
8778
+ var SceneSubjectContractSchema = z44.object({
8779
+ maxPeople: z44.number().int().min(1).max(10),
8780
+ minPeople: z44.number().int().min(0).max(10),
8781
+ minDistinctPeople: z44.number().int().min(0).max(10),
8782
+ maxHands: z44.number().int().min(0).max(20)
8664
8783
  }).superRefine((value, ctx) => {
8665
8784
  if (value.minPeople > value.maxPeople) {
8666
8785
  ctx.addIssue({
8667
- code: z43.ZodIssueCode.custom,
8786
+ code: z44.ZodIssueCode.custom,
8668
8787
  path: [
8669
8788
  "minPeople"
8670
8789
  ],
@@ -8673,7 +8792,7 @@ var SceneSubjectContractSchema = z43.object({
8673
8792
  }
8674
8793
  if (value.minDistinctPeople > value.maxPeople) {
8675
8794
  ctx.addIssue({
8676
- code: z43.ZodIssueCode.custom,
8795
+ code: z44.ZodIssueCode.custom,
8677
8796
  path: [
8678
8797
  "minDistinctPeople"
8679
8798
  ],
@@ -8682,7 +8801,7 @@ var SceneSubjectContractSchema = z43.object({
8682
8801
  }
8683
8802
  if (value.minDistinctPeople > value.minPeople) {
8684
8803
  ctx.addIssue({
8685
- code: z43.ZodIssueCode.custom,
8804
+ code: z44.ZodIssueCode.custom,
8686
8805
  path: [
8687
8806
  "minDistinctPeople"
8688
8807
  ],
@@ -8692,7 +8811,7 @@ var SceneSubjectContractSchema = z43.object({
8692
8811
  });
8693
8812
 
8694
8813
  // ../../packages/types/src/service-creative.ts
8695
- import { z as z44 } from "zod";
8814
+ import { z as z45 } from "zod";
8696
8815
  var SERVICE_CREATIVE_PUBLIC_PRESETS = [
8697
8816
  "auto",
8698
8817
  "ugc_dynamic",
@@ -8700,19 +8819,19 @@ var SERVICE_CREATIVE_PUBLIC_PRESETS = [
8700
8819
  "cinematic",
8701
8820
  "wild_card"
8702
8821
  ];
8703
- var ServiceCreativePresetSchema = z44.enum(SERVICE_CREATIVE_PUBLIC_PRESETS);
8822
+ var ServiceCreativePresetSchema = z45.enum(SERVICE_CREATIVE_PUBLIC_PRESETS);
8704
8823
  var SERVICE_REVIEW_MODES = [
8705
8824
  "automatic",
8706
8825
  "guided"
8707
8826
  ];
8708
- var ServiceReviewModeSchema = z44.enum(SERVICE_REVIEW_MODES);
8827
+ var ServiceReviewModeSchema = z45.enum(SERVICE_REVIEW_MODES);
8709
8828
  var SERVICE_HIGGSFIELD_MODES = [
8710
8829
  "product_review",
8711
8830
  "ugc_how_to",
8712
8831
  "tv_spot",
8713
8832
  "wild_card"
8714
8833
  ];
8715
- var ServiceHiggsfieldModeSchema = z44.enum(SERVICE_HIGGSFIELD_MODES);
8834
+ var ServiceHiggsfieldModeSchema = z45.enum(SERVICE_HIGGSFIELD_MODES);
8716
8835
  var SERVICE_MEDIA_ROLES = [
8717
8836
  "screen_demo",
8718
8837
  "ad_reference",
@@ -8720,20 +8839,20 @@ var SERVICE_MEDIA_ROLES = [
8720
8839
  "presenter_reference",
8721
8840
  "brand_asset"
8722
8841
  ];
8723
- var ServiceMediaRoleSchema = z44.enum(SERVICE_MEDIA_ROLES);
8724
- var ServiceMediaAssetSchema = z44.object({
8842
+ var ServiceMediaRoleSchema = z45.enum(SERVICE_MEDIA_ROLES);
8843
+ var ServiceMediaAssetSchema = z45.object({
8725
8844
  role: ServiceMediaRoleSchema,
8726
- s3Key: z44.string().min(1),
8845
+ s3Key: z45.string().min(1),
8727
8846
  /** HMAC ticket returned by the authenticated service-media presign route. */
8728
- uploadToken: z44.string().min(1).optional(),
8729
- mimeType: z44.string().min(1),
8730
- durationSec: z44.number().positive().max(30).optional(),
8731
- sourceName: z44.string().max(255).optional()
8847
+ uploadToken: z45.string().min(1).optional(),
8848
+ mimeType: z45.string().min(1),
8849
+ durationSec: z45.number().positive().max(30).optional(),
8850
+ sourceName: z45.string().max(255).optional()
8732
8851
  }).superRefine((asset, ctx) => {
8733
8852
  const isVideoRole = asset.role === "screen_demo" || asset.role === "ad_reference";
8734
8853
  if (isVideoRole && !asset.mimeType.startsWith("video/")) {
8735
8854
  ctx.addIssue({
8736
- code: z44.ZodIssueCode.custom,
8855
+ code: z45.ZodIssueCode.custom,
8737
8856
  message: `${asset.role} requires video media`,
8738
8857
  path: [
8739
8858
  "mimeType"
@@ -8742,7 +8861,7 @@ var ServiceMediaAssetSchema = z44.object({
8742
8861
  }
8743
8862
  if (isVideoRole && asset.durationSec === void 0) {
8744
8863
  ctx.addIssue({
8745
- code: z44.ZodIssueCode.custom,
8864
+ code: z45.ZodIssueCode.custom,
8746
8865
  message: `${asset.role} requires durationSec`,
8747
8866
  path: [
8748
8867
  "durationSec"
@@ -8751,7 +8870,7 @@ var ServiceMediaAssetSchema = z44.object({
8751
8870
  }
8752
8871
  if (!isVideoRole && !asset.mimeType.startsWith("image/")) {
8753
8872
  ctx.addIssue({
8754
- code: z44.ZodIssueCode.custom,
8873
+ code: z45.ZodIssueCode.custom,
8755
8874
  message: `${asset.role} requires image media`,
8756
8875
  path: [
8757
8876
  "mimeType"
@@ -8759,13 +8878,13 @@ var ServiceMediaAssetSchema = z44.object({
8759
8878
  });
8760
8879
  }
8761
8880
  });
8762
- var ServiceMediaBundleSchema = z44.object({
8763
- assets: z44.array(ServiceMediaAssetSchema).max(15).default([])
8881
+ var ServiceMediaBundleSchema = z45.object({
8882
+ assets: z45.array(ServiceMediaAssetSchema).max(15).default([])
8764
8883
  }).superRefine((bundle, ctx) => {
8765
8884
  const adReferences = bundle.assets.filter((asset) => asset.role === "ad_reference");
8766
8885
  if (adReferences.length > 5) {
8767
8886
  ctx.addIssue({
8768
- code: z44.ZodIssueCode.custom,
8887
+ code: z45.ZodIssueCode.custom,
8769
8888
  message: "A maximum of five ad_reference videos is allowed",
8770
8889
  path: [
8771
8890
  "assets"
@@ -8775,7 +8894,7 @@ var ServiceMediaBundleSchema = z44.object({
8775
8894
  const screenDemos = bundle.assets.filter((asset) => asset.role === "screen_demo");
8776
8895
  if (screenDemos.length > 3) {
8777
8896
  ctx.addIssue({
8778
- code: z44.ZodIssueCode.custom,
8897
+ code: z45.ZodIssueCode.custom,
8779
8898
  message: "A maximum of three screen_demo videos is allowed",
8780
8899
  path: [
8781
8900
  "assets"
@@ -8792,33 +8911,33 @@ var SERVICE_MEDIA_ANALYSIS_KINDS = [
8792
8911
  "product",
8793
8912
  "other"
8794
8913
  ];
8795
- var ServiceMediaAnalysisKindSchema = z44.enum(SERVICE_MEDIA_ANALYSIS_KINDS);
8796
- var ServiceMediaAnalysisItemSchema = z44.object({
8797
- assetIndex: z44.number().int().nonnegative(),
8798
- mediaType: z44.enum([
8914
+ var ServiceMediaAnalysisKindSchema = z45.enum(SERVICE_MEDIA_ANALYSIS_KINDS);
8915
+ var ServiceMediaAnalysisItemSchema = z45.object({
8916
+ assetIndex: z45.number().int().nonnegative(),
8917
+ mediaType: z45.enum([
8799
8918
  "image",
8800
8919
  "video"
8801
8920
  ]),
8802
8921
  kind: ServiceMediaAnalysisKindSchema,
8803
- description: z44.string().min(1).max(1200),
8804
- tags: z44.array(z44.string().min(1).max(80)).max(12),
8805
- suggestedRoles: z44.array(ServiceMediaRoleSchema).max(4),
8806
- visiblePeople: z44.number().int().nonnegative().max(20).optional(),
8807
- ocrText: z44.string().max(2e3).optional(),
8808
- speechSummary: z44.string().max(2e3).optional()
8809
- });
8810
- var ServiceMediaAnalysisSchema = z44.object({
8811
- version: z44.literal(1),
8812
- analyzedAt: z44.string().datetime(),
8813
- pricingAction: z44.literal("service-media-analysis"),
8814
- assetFingerprint: z44.string().regex(/^[a-f0-9]{64}$/),
8922
+ description: z45.string().min(1).max(1200),
8923
+ tags: z45.array(z45.string().min(1).max(80)).max(12),
8924
+ suggestedRoles: z45.array(ServiceMediaRoleSchema).max(4),
8925
+ visiblePeople: z45.number().int().nonnegative().max(20).optional(),
8926
+ ocrText: z45.string().max(2e3).optional(),
8927
+ speechSummary: z45.string().max(2e3).optional()
8928
+ });
8929
+ var ServiceMediaAnalysisSchema = z45.object({
8930
+ version: z45.literal(1),
8931
+ analyzedAt: z45.string().datetime(),
8932
+ pricingAction: z45.literal("service-media-analysis"),
8933
+ assetFingerprint: z45.string().regex(/^[a-f0-9]{64}$/),
8815
8934
  /** Language used for human-readable descriptions and tags. Optional for old checkpoints. */
8816
- language: z44.enum([
8935
+ language: z45.enum([
8817
8936
  "es",
8818
8937
  "en",
8819
8938
  "pt"
8820
8939
  ]).optional(),
8821
- items: z44.array(ServiceMediaAnalysisItemSchema).max(15)
8940
+ items: z45.array(ServiceMediaAnalysisItemSchema).max(15)
8822
8941
  });
8823
8942
 
8824
8943
  // ../../packages/types/src/productmaker-capability-registry.ts
@@ -9335,7 +9454,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
9335
9454
  ], [
9336
9455
  "creative"
9337
9456
  ]),
9338
- defineCapability("generate_landing", "75947c5a70d26305ca07ab8d7bc0be710e862eb9319010ee66dd43e64fab2050", "credit_consuming", "creative", [
9457
+ defineCapability("generate_landing", "67520417176396516cd5ad358dca39f70a5c4a74169eecd85987217226c12251", "credit_consuming", "creative", [
9339
9458
  "credit_consuming",
9340
9459
  "state_change"
9341
9460
  ], [
@@ -9380,12 +9499,14 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
9380
9499
  "competitorScanEnabled",
9381
9500
  "landingStrategy",
9382
9501
  "landingImageFormat",
9502
+ "pauseForAngleReview",
9383
9503
  // MCP-only, like create_product_task's aiDecidesAll.
9384
9504
  "aiDecidesAll"
9385
9505
  ], [
9386
9506
  "competitorScanEnabled",
9387
9507
  "landingStrategy",
9388
- "landingImageFormat"
9508
+ "landingImageFormat",
9509
+ "pauseForAngleReview"
9389
9510
  ])
9390
9511
  ], [
9391
9512
  "product_reference"
@@ -9901,8 +10022,8 @@ var PRODUCTMAKER_MCP_CAPABILITIES = toLegacyCapabilityCatalog(PRODUCTMAKER_MCP_C
9901
10022
  var PRODUCTMAKER_MCP_CAPABILITY_NAMES = PRODUCTMAKER_MCP_CAPABILITY_REGISTRY.map((capability) => capability.name);
9902
10023
 
9903
10024
  // ../../packages/types/src/actor.ts
9904
- import { z as z45 } from "zod";
9905
- var ActorStatusSchema = z45.enum([
10025
+ import { z as z46 } from "zod";
10026
+ var ActorStatusSchema = z46.enum([
9906
10027
  "draft",
9907
10028
  "generating",
9908
10029
  "ready",
@@ -9911,18 +10032,18 @@ var ActorStatusSchema = z45.enum([
9911
10032
  var ACTOR_NAME_MAX_CHARS = 60;
9912
10033
  var ACTOR_DESCRIPTION_MAX_CHARS = 600;
9913
10034
  var ACTOR_CANDIDATE_COUNT = 4;
9914
- var ActorGenderSchema = z45.enum([
10035
+ var ActorGenderSchema = z46.enum([
9915
10036
  "female",
9916
10037
  "male",
9917
10038
  "non_binary"
9918
10039
  ]);
9919
- var ActorSchema = z45.object({
9920
- id: z45.string(),
9921
- name: z45.string().min(1).max(ACTOR_NAME_MAX_CHARS),
9922
- description: z45.string().max(ACTOR_DESCRIPTION_MAX_CHARS),
10040
+ var ActorSchema = z46.object({
10041
+ id: z46.string(),
10042
+ name: z46.string().min(1).max(ACTOR_NAME_MAX_CHARS),
10043
+ description: z46.string().max(ACTOR_DESCRIPTION_MAX_CHARS),
9923
10044
  gender: ActorGenderSchema,
9924
- voiceId: z45.string().nullable().optional(),
9925
- brandId: z45.string().nullable().optional(),
10045
+ voiceId: z46.string().nullable().optional(),
10046
+ brandId: z46.string().nullable().optional(),
9926
10047
  status: ActorStatusSchema,
9927
10048
  /**
9928
10049
  * A candidate-grid run is in flight RIGHT NOW.
@@ -9934,36 +10055,36 @@ var ActorSchema = z45.object({
9934
10055
  * timestamp with a TTL, so an orphaned run reads as `false` instead of
9935
10056
  * pinning the personaje forever.
9936
10057
  */
9937
- generating: z45.boolean().optional(),
9938
- photoUrl: z45.string().url().nullable().optional(),
9939
- avatarUrl: z45.string().url().nullable().optional(),
9940
- candidateUrls: z45.array(z45.string().url()).optional(),
10058
+ generating: z46.boolean().optional(),
10059
+ photoUrl: z46.string().url().nullable().optional(),
10060
+ avatarUrl: z46.string().url().nullable().optional(),
10061
+ candidateUrls: z46.array(z46.string().url()).optional(),
9941
10062
  /** Indices of candidateUrls that failed the anatomy check (Task 6). */
9942
- flaggedCandidateIndices: z45.array(z45.number().int()).optional()
10063
+ flaggedCandidateIndices: z46.array(z46.number().int()).optional()
9943
10064
  });
9944
- var CreateActorRequest = z45.object({
9945
- name: z45.string().min(1).max(ACTOR_NAME_MAX_CHARS),
9946
- description: z45.string().max(ACTOR_DESCRIPTION_MAX_CHARS).default(""),
10065
+ var CreateActorRequest = z46.object({
10066
+ name: z46.string().min(1).max(ACTOR_NAME_MAX_CHARS),
10067
+ description: z46.string().max(ACTOR_DESCRIPTION_MAX_CHARS).default(""),
9947
10068
  gender: ActorGenderSchema,
9948
- voiceId: z45.string().optional(),
9949
- brandId: z45.string().optional(),
9950
- sourcePhotoKey: z45.string().optional()
10069
+ voiceId: z46.string().optional(),
10070
+ brandId: z46.string().optional(),
10071
+ sourcePhotoKey: z46.string().optional()
9951
10072
  }).refine((v) => v.description.trim().length > 0 || !!v.sourcePhotoKey, {
9952
10073
  message: "Se necesita una descripci\xF3n o una foto"
9953
10074
  });
9954
- var UpdateActorRequest = z45.object({
9955
- name: z45.string().min(1).max(ACTOR_NAME_MAX_CHARS).optional(),
9956
- description: z45.string().max(ACTOR_DESCRIPTION_MAX_CHARS).optional(),
10075
+ var UpdateActorRequest = z46.object({
10076
+ name: z46.string().min(1).max(ACTOR_NAME_MAX_CHARS).optional(),
10077
+ description: z46.string().max(ACTOR_DESCRIPTION_MAX_CHARS).optional(),
9957
10078
  gender: ActorGenderSchema.optional(),
9958
- voiceId: z45.string().nullable().optional(),
9959
- brandId: z45.string().nullable().optional()
10079
+ voiceId: z46.string().nullable().optional(),
10080
+ brandId: z46.string().nullable().optional()
9960
10081
  });
9961
- var ApproveActorRequest = z45.object({
9962
- candidateIndex: z45.number().int().min(0).max(ACTOR_CANDIDATE_COUNT - 1)
10082
+ var ApproveActorRequest = z46.object({
10083
+ candidateIndex: z46.number().int().min(0).max(ACTOR_CANDIDATE_COUNT - 1)
9963
10084
  });
9964
10085
 
9965
10086
  // ../../packages/types/src/referral-dashboard.ts
9966
- import { z as z46 } from "zod";
10087
+ import { z as z47 } from "zod";
9967
10088
  var REFERRAL_DASHBOARD_RAW_STATUSES = [
9968
10089
  "ACTIVE",
9969
10090
  "PENDING",
@@ -9982,66 +10103,66 @@ var REFERRAL_DASHBOARD_PLAN_KINDS = [
9982
10103
  "last",
9983
10104
  "none"
9984
10105
  ];
9985
- var ReferralDashboardRawStatusSchema = z46.enum(REFERRAL_DASHBOARD_RAW_STATUSES);
9986
- var ReferralDashboardStateSchema = z46.enum(REFERRAL_DASHBOARD_STATES);
9987
- var ReferralDashboardPlanKindSchema = z46.enum(REFERRAL_DASHBOARD_PLAN_KINDS);
9988
- var ReferralDashboardStatusSchema = z46.enum([
10106
+ var ReferralDashboardRawStatusSchema = z47.enum(REFERRAL_DASHBOARD_RAW_STATUSES);
10107
+ var ReferralDashboardStateSchema = z47.enum(REFERRAL_DASHBOARD_STATES);
10108
+ var ReferralDashboardPlanKindSchema = z47.enum(REFERRAL_DASHBOARD_PLAN_KINDS);
10109
+ var ReferralDashboardStatusSchema = z47.enum([
9989
10110
  "all",
9990
10111
  "active",
9991
10112
  "pending",
9992
10113
  "inactive"
9993
10114
  ]).default("all");
9994
- var ReferralDashboardPlanSchema = z46.string().trim().min(1).max(100).optional();
9995
- var ReferralDashboardFiltersSchema = z46.object({
10115
+ var ReferralDashboardPlanSchema = z47.string().trim().min(1).max(100).optional();
10116
+ var ReferralDashboardFiltersSchema = z47.object({
9996
10117
  status: ReferralDashboardStatusSchema,
9997
10118
  plan: ReferralDashboardPlanSchema
9998
10119
  });
9999
- var ReferralDashboardSubscriptionSchema = z46.object({
10000
- planName: z46.string().nullable(),
10120
+ var ReferralDashboardSubscriptionSchema = z47.object({
10121
+ planName: z47.string().nullable(),
10001
10122
  planKind: ReferralDashboardPlanKindSchema,
10002
10123
  rawStatus: ReferralDashboardRawStatusSchema.nullable(),
10003
10124
  state: ReferralDashboardStateSchema,
10004
- currentPeriodEnd: z46.string().datetime({
10125
+ currentPeriodEnd: z47.string().datetime({
10005
10126
  offset: true
10006
10127
  }).nullable(),
10007
- cancelAtPeriodEnd: z46.boolean()
10128
+ cancelAtPeriodEnd: z47.boolean()
10008
10129
  });
10009
- var ReferralDashboardReferralSchema = z46.object({
10010
- id: z46.string().min(1),
10011
- registeredAt: z46.string().datetime({
10130
+ var ReferralDashboardReferralSchema = z47.object({
10131
+ id: z47.string().min(1),
10132
+ registeredAt: z47.string().datetime({
10012
10133
  offset: true
10013
10134
  }),
10014
10135
  // Kept in the response for compatibility with existing referral API clients.
10015
10136
  // The referrer dashboard intentionally does not render these legacy fields.
10016
- expiresAt: z46.string().datetime({
10137
+ expiresAt: z47.string().datetime({
10017
10138
  offset: true
10018
10139
  }).nullable().optional(),
10019
- status: z46.string().min(1).optional(),
10020
- referredUser: z46.object({
10021
- email: z46.string().nullable()
10140
+ status: z47.string().min(1).optional(),
10141
+ referredUser: z47.object({
10142
+ email: z47.string().nullable()
10022
10143
  }),
10023
10144
  subscription: ReferralDashboardSubscriptionSchema
10024
10145
  });
10025
- var ReferralDashboardReferralsPageSchema = z46.object({
10026
- referrals: z46.array(ReferralDashboardReferralSchema),
10027
- total: z46.number().int().nonnegative()
10146
+ var ReferralDashboardReferralsPageSchema = z47.object({
10147
+ referrals: z47.array(ReferralDashboardReferralSchema),
10148
+ total: z47.number().int().nonnegative()
10028
10149
  });
10029
- var ReferralDashboardPlanBreakdownSchema = z46.object({
10030
- planName: z46.string().nullable(),
10031
- count: z46.number().int().nonnegative()
10150
+ var ReferralDashboardPlanBreakdownSchema = z47.object({
10151
+ planName: z47.string().nullable(),
10152
+ count: z47.number().int().nonnegative()
10032
10153
  });
10033
- var ReferralDashboardMonthlyRegistrationSchema = z46.object({
10034
- month: z46.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/),
10035
- count: z46.number().int().nonnegative()
10154
+ var ReferralDashboardMonthlyRegistrationSchema = z47.object({
10155
+ month: z47.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/),
10156
+ count: z47.number().int().nonnegative()
10036
10157
  });
10037
- var ReferralDashboardOverviewSchema = z46.object({
10038
- totalReferredUsers: z46.number().int().nonnegative(),
10039
- activeUsers: z46.number().int().nonnegative(),
10040
- pendingUsers: z46.number().int().nonnegative(),
10041
- inactiveUsers: z46.number().int().nonnegative(),
10042
- noPlanUsers: z46.number().int().nonnegative(),
10043
- planBreakdown: z46.array(ReferralDashboardPlanBreakdownSchema),
10044
- monthlyRegistrations: z46.array(ReferralDashboardMonthlyRegistrationSchema).refine((months) => months.length === 6, "Expected six monthly registration buckets")
10158
+ var ReferralDashboardOverviewSchema = z47.object({
10159
+ totalReferredUsers: z47.number().int().nonnegative(),
10160
+ activeUsers: z47.number().int().nonnegative(),
10161
+ pendingUsers: z47.number().int().nonnegative(),
10162
+ inactiveUsers: z47.number().int().nonnegative(),
10163
+ noPlanUsers: z47.number().int().nonnegative(),
10164
+ planBreakdown: z47.array(ReferralDashboardPlanBreakdownSchema),
10165
+ monthlyRegistrations: z47.array(ReferralDashboardMonthlyRegistrationSchema).refine((months) => months.length === 6, "Expected six monthly registration buckets")
10045
10166
  });
10046
10167
 
10047
10168
  // ../../packages/types/src/mcp-oauth.ts
@@ -10803,19 +10924,19 @@ import { InsufficientScopeError, InvalidTokenError } from "@modelcontextprotocol
10803
10924
  import { createRemoteJWKSet as createRemoteJWKSet2, jwtVerify as jwtVerify2 } from "jose";
10804
10925
 
10805
10926
  // src/auth/oauth-config.ts
10806
- import { z as z47 } from "zod";
10927
+ import { z as z48 } from "zod";
10807
10928
  var MCP_RESOURCE = new URL("https://mcp.productmaker.app/mcp");
10808
10929
  var MCP_SCOPE = "mcp:access";
10809
- var oauthEnvSchema = z47.object({
10810
- MCP_REMOTE_AUTH_MODE: z47.literal("oauth"),
10811
- MCP_AUTH0_ISSUER: z47.string().trim().min(1),
10812
- MCP_AUTH0_AUDIENCE: z47.string().trim().refine((value) => value === MCP_RESOURCE.href, {
10930
+ var oauthEnvSchema = z48.object({
10931
+ MCP_REMOTE_AUTH_MODE: z48.literal("oauth"),
10932
+ MCP_AUTH0_ISSUER: z48.string().trim().min(1),
10933
+ MCP_AUTH0_AUDIENCE: z48.string().trim().refine((value) => value === MCP_RESOURCE.href, {
10813
10934
  message: `must equal ${MCP_RESOURCE.href}`
10814
10935
  }),
10815
- MCP_AUTH0_CLIENT_ID: z47.string().trim().min(1),
10816
- MCP_AUTH0_CLIENT_SECRET: z47.string().trim().min(1),
10817
- PM_API_AUDIENCE: z47.string().trim().min(1),
10818
- AUTH0_AUDIENCE: z47.string().trim().min(1)
10936
+ MCP_AUTH0_CLIENT_ID: z48.string().trim().min(1),
10937
+ MCP_AUTH0_CLIENT_SECRET: z48.string().trim().min(1),
10938
+ PM_API_AUDIENCE: z48.string().trim().min(1),
10939
+ AUTH0_AUDIENCE: z48.string().trim().min(1)
10819
10940
  });
10820
10941
  function formatZodIssues(error) {
10821
10942
  return error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
@@ -11557,7 +11678,7 @@ var ApiClient = class {
11557
11678
  };
11558
11679
 
11559
11680
  // src/index.ts
11560
- var MCP_VERSION = "3.4.0";
11681
+ var MCP_VERSION = "3.4.2";
11561
11682
 
11562
11683
  // src/meta-upload-app.ts
11563
11684
  import { readFileSync } from "fs";
@@ -11629,7 +11750,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
11629
11750
  __name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
11630
11751
 
11631
11752
  // src/tools/tasks.ts
11632
- import { z as z49 } from "zod";
11753
+ import { z as z50 } from "zod";
11633
11754
 
11634
11755
  // src/resolve-image.ts
11635
11756
  import { lookup as dnsLookup } from "dns/promises";
@@ -11869,6 +11990,7 @@ __name(resolveOne, "resolveOne");
11869
11990
 
11870
11991
  // src/status-poller.ts
11871
11992
  var TERMINAL = /* @__PURE__ */ new Set([
11993
+ "done",
11872
11994
  "complete",
11873
11995
  "error"
11874
11996
  ]);
@@ -12156,10 +12278,10 @@ async function resolveMediaRef(ref, opts) {
12156
12278
  __name(resolveMediaRef, "resolveMediaRef");
12157
12279
 
12158
12280
  // src/tools/shared.ts
12159
- import { z as z48 } from "zod";
12160
- var Lang = z48.string().min(2).max(10);
12161
- var Country = z48.string().min(2).max(3);
12162
- var LandingStrategyEnum = z48.enum([
12281
+ import { z as z49 } from "zod";
12282
+ var Lang = z49.string().min(2).max(10);
12283
+ var Country = z49.string().min(2).max(3);
12284
+ var LandingStrategyEnum = z49.enum([
12163
12285
  "auto",
12164
12286
  "classic",
12165
12287
  "pain_solution",
@@ -12168,12 +12290,12 @@ var LandingStrategyEnum = z48.enum([
12168
12290
  "offer_value",
12169
12291
  "lifestyle_identity"
12170
12292
  ]);
12171
- var LandingImageFormatEnum = z48.enum([
12293
+ var LandingImageFormatEnum = z49.enum([
12172
12294
  "9:16",
12173
12295
  "4:5",
12174
12296
  "1:1"
12175
12297
  ]);
12176
- var VideoPresetEnum = z48.enum([
12298
+ var VideoPresetEnum = z49.enum([
12177
12299
  "auto",
12178
12300
  "ugc_dynamic",
12179
12301
  "ugc_how_to",
@@ -12186,7 +12308,7 @@ var VideoPresetEnum = z48.enum([
12186
12308
  "pixar_problem",
12187
12309
  "pixar_sassy"
12188
12310
  ]);
12189
- var TaskCreativeVariantVideoPresetEnum = z48.enum([
12311
+ var TaskCreativeVariantVideoPresetEnum = z49.enum([
12190
12312
  "auto",
12191
12313
  "ugc_dynamic",
12192
12314
  "ugc_how_to",
@@ -12257,7 +12379,7 @@ function resolveVideoPreset(preset) {
12257
12379
  return VIDEO_PRESET_RESOLUTION[preset] ?? null;
12258
12380
  }
12259
12381
  __name(resolveVideoPreset, "resolveVideoPreset");
12260
- var VideoTierEnum = z48.enum([
12382
+ var VideoTierEnum = z49.enum([
12261
12383
  "basic"
12262
12384
  ]);
12263
12385
  function resolveVideoTier(_tier) {
@@ -12272,17 +12394,17 @@ function resolveVideoFormatForDuration(durationSeconds) {
12272
12394
  return durationSeconds === 30 ? "double_30s" : "single_15s";
12273
12395
  }
12274
12396
  __name(resolveVideoFormatForDuration, "resolveVideoFormatForDuration");
12275
- var VideoResolutionEnum = z48.enum([
12397
+ var VideoResolutionEnum = z49.enum([
12276
12398
  "480p",
12277
12399
  "720p"
12278
12400
  ]);
12279
- var VideoStyleEnum = z48.enum([
12401
+ var VideoStyleEnum = z49.enum([
12280
12402
  "ugc",
12281
12403
  "cartoon_3d",
12282
12404
  "product_only",
12283
12405
  "ai_dynamic"
12284
12406
  ]);
12285
- var NarrativeStyleEnum = z48.enum([
12407
+ var NarrativeStyleEnum = z49.enum([
12286
12408
  "review",
12287
12409
  "ugc_how_to",
12288
12410
  "problem_product_cta",
@@ -12299,7 +12421,7 @@ var NarrativeStyleEnum = z48.enum([
12299
12421
  "ugc_skeptic_confession",
12300
12422
  "ugc_demo_review"
12301
12423
  ]);
12302
- var PublicNarrativeStyleEnum = z48.enum([
12424
+ var PublicNarrativeStyleEnum = z49.enum([
12303
12425
  "review",
12304
12426
  "ugc_how_to",
12305
12427
  "ugc_unboxing_chaos",
@@ -12311,7 +12433,7 @@ var PublicNarrativeStyleEnum = z48.enum([
12311
12433
  "animated_problem_pixar",
12312
12434
  "sassy_product_pixar"
12313
12435
  ]);
12314
- var VideoModelEnum = z48.enum([
12436
+ var VideoModelEnum = z49.enum([
12315
12437
  "veo",
12316
12438
  "wan",
12317
12439
  "bytedance",
@@ -12319,29 +12441,29 @@ var VideoModelEnum = z48.enum([
12319
12441
  "grok",
12320
12442
  "kling"
12321
12443
  ]);
12322
- var ProductReferenceUserChoiceEnum = z48.enum([
12444
+ var ProductReferenceUserChoiceEnum = z49.enum([
12323
12445
  "same_product",
12324
12446
  "variants",
12325
12447
  "different_products",
12326
12448
  "combo_distinct"
12327
12449
  ]);
12328
- var ProductReferenceCandidateGroupingEnum = z48.enum([
12450
+ var ProductReferenceCandidateGroupingEnum = z49.enum([
12329
12451
  "same_product_same_variant",
12330
12452
  "same_product_different_variants",
12331
12453
  "different_products",
12332
12454
  "unclear"
12333
12455
  ]);
12334
- var ProductReferenceScopeEnum = z48.enum([
12456
+ var ProductReferenceScopeEnum = z49.enum([
12335
12457
  "base",
12336
12458
  "video_view_pack"
12337
12459
  ]);
12338
- var ProductReferenceResolutionDecisionEnum = z48.enum([
12460
+ var ProductReferenceResolutionDecisionEnum = z49.enum([
12339
12461
  "approve",
12340
12462
  "reject",
12341
12463
  "observed_only",
12342
12464
  "correct_view"
12343
12465
  ]);
12344
- var ProductReferenceRejectionReasonEnum = z48.enum([
12466
+ var ProductReferenceRejectionReasonEnum = z49.enum([
12345
12467
  "replacement_requested",
12346
12468
  "wrong_product_identity",
12347
12469
  "wrong_variant",
@@ -12352,13 +12474,13 @@ var ProductReferenceRejectionReasonEnum = z48.enum([
12352
12474
  "not_a_product_photo",
12353
12475
  "other"
12354
12476
  ]);
12355
- var GapDurationChoiceMirror = z48.object({
12356
- angleIndex: z48.number().int().nonnegative(),
12357
- recommendedSec: z48.union([
12358
- z48.literal(15),
12359
- z48.literal(30)
12477
+ var GapDurationChoiceMirror = z49.object({
12478
+ angleIndex: z49.number().int().nonnegative(),
12479
+ recommendedSec: z49.union([
12480
+ z49.literal(15),
12481
+ z49.literal(30)
12360
12482
  ]),
12361
- estimatedDeltaCredits: z48.number().int().nonnegative().optional()
12483
+ estimatedDeltaCredits: z49.number().int().nonnegative().optional()
12362
12484
  });
12363
12485
  function buildSelectedImageUrlsHash(urls) {
12364
12486
  const input = [
@@ -12368,13 +12490,13 @@ function buildSelectedImageUrlsHash(urls) {
12368
12490
  return `fnv1a:${hash.toString(16).padStart(8, "0")}:${urls.length}`;
12369
12491
  }
12370
12492
  __name(buildSelectedImageUrlsHash, "buildSelectedImageUrlsHash");
12371
- var ImageCreativeStyleEnum = z48.enum([
12493
+ var ImageCreativeStyleEnum = z49.enum([
12372
12494
  "studio",
12373
12495
  "floating",
12374
12496
  "ingredients",
12375
12497
  "in_use"
12376
12498
  ]);
12377
- var ImageCreativeArchetypeEnum = z48.enum([
12499
+ var ImageCreativeArchetypeEnum = z49.enum([
12378
12500
  "direct_response_product_ad",
12379
12501
  "hero_outcome",
12380
12502
  "offer_value_prop",
@@ -12383,20 +12505,20 @@ var ImageCreativeArchetypeEnum = z48.enum([
12383
12505
  "problem_solution",
12384
12506
  "lifestyle_identity"
12385
12507
  ]);
12386
- var ImageCreativeVisualTreatmentEnum = z48.enum([
12508
+ var ImageCreativeVisualTreatmentEnum = z49.enum([
12387
12509
  "performance_product_ad",
12388
12510
  "premium_dtc_carousel"
12389
12511
  ]);
12390
- var ImageCreativeAspectRatioEnum = z48.enum([
12512
+ var ImageCreativeAspectRatioEnum = z49.enum([
12391
12513
  "1:1",
12392
12514
  "4:5",
12393
12515
  "9:16",
12394
12516
  "16:9"
12395
12517
  ]);
12396
- var ImageRefSchema = z48.object({
12397
- 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.'),
12398
- 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`.'),
12399
- 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.")
12518
+ var ImageRefSchema = z49.object({
12519
+ url: z49.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.'),
12520
+ path: z49.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`.'),
12521
+ assetId: z49.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.")
12400
12522
  }).refine((v) => [
12401
12523
  v.url,
12402
12524
  v.path,
@@ -12404,11 +12526,11 @@ var ImageRefSchema = z48.object({
12404
12526
  ].filter(Boolean).length === 1, {
12405
12527
  message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
12406
12528
  });
12407
- var ImagesInput = z48.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
12529
+ var ImagesInput = z49.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
12408
12530
  const assetCount = images.filter((image) => Boolean(image.assetId)).length;
12409
12531
  if (assetCount > 0 && assetCount !== images.length) {
12410
12532
  ctx.addIssue({
12411
- code: z48.ZodIssueCode.custom,
12533
+ code: z49.ZodIssueCode.custom,
12412
12534
  message: "all image entries must use assetId, or all must use URL/path sources"
12413
12535
  });
12414
12536
  }
@@ -12478,14 +12600,14 @@ async function submitCreative(api, opts) {
12478
12600
  });
12479
12601
  }
12480
12602
  __name(submitCreative, "submitCreative");
12481
- var ResearchTargetCountryEnum = z48.enum([
12603
+ var ResearchTargetCountryEnum = z49.enum([
12482
12604
  "CO",
12483
12605
  "MX",
12484
12606
  "PE",
12485
12607
  "EC",
12486
12608
  "CL"
12487
12609
  ]);
12488
- var ResearchCategoryEnum = z48.enum([
12610
+ var ResearchCategoryEnum = z49.enum([
12489
12611
  "auto",
12490
12612
  "automotive",
12491
12613
  "kitchen",
@@ -12544,6 +12666,7 @@ var McpErrorCode = {
12544
12666
  REVOKED_API_KEY: "REVOKED_API_KEY",
12545
12667
  // Rate limit / quota
12546
12668
  RATE_LIMITED: "RATE_LIMITED",
12669
+ CREDIT_ADMISSION_UNAVAILABLE: "CREDIT_ADMISSION_UNAVAILABLE",
12547
12670
  // Input
12548
12671
  INVALID_INPUT: "INVALID_INPUT",
12549
12672
  INSUFFICIENT_CREDITS: "INSUFFICIENT_CREDITS",
@@ -12732,6 +12855,7 @@ var CODE_MESSAGES = {
12732
12855
  REVOKED_API_KEY: "API key revoked. Generate a new one at https://productmaker.app/account/api-keys.",
12733
12856
  // Rate
12734
12857
  RATE_LIMITED: "Too many requests. Wait a few seconds.",
12858
+ CREDIT_ADMISSION_UNAVAILABLE: "Credit admission is temporarily unavailable. Do not retry a paid action until ProductMaker can verify the balance.",
12735
12859
  INSUFFICIENT_CREDITS: "Insufficient credits for this action. Check your balance and add credits at https://productmaker.app before retrying.",
12736
12860
  TASK_QUOTA_EXCEEDED: "You reached the active-task limit. Wait for a task to finish before creating another variant.",
12737
12861
  // Generic
@@ -12826,6 +12950,7 @@ var INVALID_PARAM_CODES = /* @__PURE__ */ new Set([
12826
12950
  McpErrorCode.NO_META_AD_ACCOUNTS
12827
12951
  ]);
12828
12952
  var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
12953
+ McpErrorCode.CREDIT_ADMISSION_UNAVAILABLE,
12829
12954
  McpErrorCode.INSUFFICIENT_CREDITS,
12830
12955
  McpErrorCode.TASK_QUOTA_EXCEEDED,
12831
12956
  McpErrorCode.DROPSHIPPING_PROJECT_NOT_FOUND,
@@ -12924,6 +13049,7 @@ __name(looksLikeMeaningfulBackendMessage, "looksLikeMeaningfulBackendMessage");
12924
13049
  function resolveMessage(code, backendMessage) {
12925
13050
  const mapped = CODE_MESSAGES[code];
12926
13051
  const backend = typeof backendMessage === "string" ? backendMessage.trim() : "";
13052
+ if (code === McpErrorCode.CREDIT_ADMISSION_UNAVAILABLE && mapped) return mapped;
12927
13053
  if (mapped && backend && looksLikeMeaningfulBackendMessage(backend, mapped)) {
12928
13054
  return `${mapped} (Detail: ${backend})`;
12929
13055
  }
@@ -13133,54 +13259,54 @@ function renderOutputsMarkdown(outputs) {
13133
13259
  __name(renderOutputsMarkdown, "renderOutputsMarkdown");
13134
13260
 
13135
13261
  // src/tools/tasks.ts
13136
- var CreateProductTaskInput = z49.object({
13262
+ var CreateProductTaskInput = z50.object({
13137
13263
  images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
13138
- 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."),
13139
- 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."),
13264
+ projectId: z50.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
13265
+ productUrl: z50.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."),
13140
13266
  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.'),
13141
13267
  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.'),
13142
- 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.'),
13143
- 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".'),
13144
- 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.'),
13145
- 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.'),
13146
- 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."),
13147
- 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.'),
13268
+ price: z50.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.'),
13269
+ compareAtPrice: z50.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".'),
13270
+ offer: z50.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.'),
13271
+ paymentMethods: z50.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.'),
13272
+ 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."),
13273
+ productLabel: z50.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.'),
13148
13274
  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.'),
13149
- durationSeconds: z49.union([
13150
- z49.literal(15),
13151
- z49.literal(30)
13275
+ durationSeconds: z50.union([
13276
+ z50.literal(15),
13277
+ z50.literal(30)
13152
13278
  ]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
13153
- 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."),
13154
- 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."),
13279
+ 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. \xDAsalo si quiere decidir 15/30s cuando aparezca un winner. Default false."),
13280
+ 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, 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."),
13155
13281
  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.'),
13156
13282
  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).'),
13157
- 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."),
13283
+ multiAngleVideos: z50.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."),
13158
13284
  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.'),
13159
- outputs: z49.array(z49.enum([
13285
+ outputs: z50.array(z50.enum([
13160
13286
  "landing",
13161
13287
  "video",
13162
13288
  "image"
13163
13289
  ])).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.'),
13164
- 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."),
13165
- 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."),
13166
- 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."),
13167
- 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.'),
13168
- 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."),
13169
- 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."),
13290
+ 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."),
13291
+ 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 los outputs generados."),
13292
+ actorId: z50.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."),
13293
+ creativeDirection: z50.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.'),
13294
+ headline: z50.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."),
13295
+ 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."),
13170
13296
  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".'),
13171
13297
  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".')
13172
13298
  }).strict();
13173
- var CreateServiceVideoInput = z49.object({
13174
- 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."),
13175
- 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.'),
13299
+ var CreateServiceVideoInput = z50.object({
13300
+ landingUrl: z50.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
13301
+ additionalContext: z50.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
13176
13302
  language: Lang.describe("Idioma del video: es, en o pt."),
13177
- 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.'),
13178
- brandId: z49.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
13179
- reviewMode: z49.enum([
13303
+ voiceId: z50.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.'),
13304
+ brandId: z50.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
13305
+ reviewMode: z50.enum([
13180
13306
  "automatic",
13181
13307
  "guided"
13182
13308
  ]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
13183
- videoPreset: z49.enum([
13309
+ videoPreset: z50.enum([
13184
13310
  "auto",
13185
13311
  "ugc_dynamic",
13186
13312
  "ugc_how_to",
@@ -13188,51 +13314,51 @@ var CreateServiceVideoInput = z49.object({
13188
13314
  "wild_card"
13189
13315
  ]).default("auto")
13190
13316
  }).strict();
13191
- var GetTaskStatusInput = z49.object({
13192
- taskId: z49.string().min(1),
13193
- waitSeconds: z49.number().int().min(0).max(120).optional()
13194
- });
13195
- var ListTasksInput = z49.object({
13196
- limit: z49.number().int().min(1).max(50).optional(),
13197
- offset: z49.number().int().min(0).optional(),
13198
- search: z49.string().optional()
13199
- });
13200
- var EditTaskDraftInput = z49.object({
13201
- taskId: z49.string().min(1),
13202
- angleIndex: z49.number().int().min(0),
13203
- angle: z49.object({
13204
- angle: z49.string().min(1).max(480),
13205
- buyerPersona: z49.string().min(1).max(360),
13206
- actor: z49.string().min(1).max(360).optional(),
13207
- 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."),
13208
- gender: z49.enum([
13317
+ var GetTaskStatusInput = z50.object({
13318
+ taskId: z50.string().min(1),
13319
+ waitSeconds: z50.number().int().min(0).max(120).optional()
13320
+ });
13321
+ var ListTasksInput = z50.object({
13322
+ limit: z50.number().int().min(1).max(50).optional(),
13323
+ offset: z50.number().int().min(0).optional(),
13324
+ search: z50.string().optional()
13325
+ });
13326
+ var EditTaskDraftInput = z50.object({
13327
+ taskId: z50.string().min(1),
13328
+ angleIndex: z50.number().int().min(0),
13329
+ angle: z50.object({
13330
+ angle: z50.string().min(1).max(480),
13331
+ buyerPersona: z50.string().min(1).max(360),
13332
+ actor: z50.string().min(1).max(360).optional(),
13333
+ actorId: z50.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."),
13334
+ gender: z50.enum([
13209
13335
  "female",
13210
13336
  "male"
13211
13337
  ]).optional(),
13212
- scriptNotes: z49.string().max(2e3).optional()
13338
+ scriptNotes: z50.string().max(2e3).optional()
13213
13339
  })
13214
13340
  });
13215
- var PendingActionPayload = z49.discriminatedUnion("kind", [
13216
- z49.object({
13217
- kind: z49.literal("product_reference_set_approval"),
13341
+ var PendingActionPayload = z50.discriminatedUnion("kind", [
13342
+ z50.object({
13343
+ kind: z50.literal("product_reference_set_approval"),
13218
13344
  scope: ProductReferenceScopeEnum,
13219
- scopeKey: z49.string().min(1).max(120),
13220
- scopeSnapshotId: z49.string().uuid(),
13221
- expectedScopeHash: z49.string().min(1).max(128),
13345
+ scopeKey: z50.string().min(1).max(120),
13346
+ scopeSnapshotId: z50.string().uuid(),
13347
+ expectedScopeHash: z50.string().min(1).max(128),
13222
13348
  decision: ProductReferenceResolutionDecisionEnum,
13223
13349
  reason: ProductReferenceRejectionReasonEnum.optional(),
13224
- affectedRefKeys: z49.array(z49.string().min(1).max(200)).min(1).optional(),
13225
- recoveryAction: z49.enum([
13350
+ affectedRefKeys: z50.array(z50.string().min(1).max(200)).min(1).optional(),
13351
+ recoveryAction: z50.enum([
13226
13352
  "remove",
13227
13353
  "replace",
13228
13354
  "upload",
13229
13355
  "return_to_selection"
13230
13356
  ]).optional()
13231
13357
  }),
13232
- z49.object({
13233
- kind: z49.literal("product_reference_confirmation"),
13358
+ z50.object({
13359
+ kind: z50.literal("product_reference_confirmation"),
13234
13360
  userChoice: ProductReferenceUserChoiceEnum.optional(),
13235
- confirmedProductNames: z49.array(z49.string().min(1).max(120)).min(2).max(8).optional(),
13361
+ confirmedProductNames: z50.array(z50.string().min(1).max(120)).min(2).max(8).optional(),
13236
13362
  // SCOPED multi-scene opt-in — the ONLY way STANDARD ("Multiescena") is
13237
13363
  // reachable via MCP. Valid ONLY together with userChoice='variants' (same
13238
13364
  // product in several colors): renders one shot per color and stitches them,
@@ -13243,50 +13369,50 @@ var PendingActionPayload = z49.discriminatedUnion("kind", [
13243
13369
  // safe because multi-scene IS the intended render for a color variant set,
13244
13370
  // not a blind quality upsell. Maps to `videoTier: 'standard'` on the
13245
13371
  // confirm call; the backend re-gates it (variants + variant_set only).
13246
- 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".')
13372
+ useMultiSceneShowcase: z50.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".')
13247
13373
  }),
13248
- z49.object({
13249
- kind: z49.literal("angle_review_approval"),
13374
+ z50.object({
13375
+ kind: z50.literal("angle_review_approval"),
13250
13376
  // All edits are optional — empty action body just approves the
13251
13377
  // backend-generated draft as-is. Field shapes mirror the angle-review
13252
13378
  // request contracts in @packages/types/wizard.ts; the handler routes to
13253
13379
  // the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
13254
- customAngle: z49.string().min(1).max(480).optional(),
13380
+ customAngle: z50.string().min(1).max(480).optional(),
13255
13381
  // Keep the shared MCP action within the strictest downstream contract:
13256
13382
  // autopilot/image resume endpoints cap these fields at 1500 characters.
13257
- painPoints: z49.string().max(1500).optional(),
13258
- benefits: z49.string().max(1500).optional(),
13259
- features: z49.array(z49.string().min(1).max(300)).max(10).optional(),
13260
- gapDurationSeconds: z49.union([
13261
- z49.literal(15),
13262
- z49.literal(30)
13383
+ painPoints: z50.string().max(1500).optional(),
13384
+ benefits: z50.string().max(1500).optional(),
13385
+ features: z50.array(z50.string().min(1).max(300)).max(10).optional(),
13386
+ gapDurationSeconds: z50.union([
13387
+ z50.literal(15),
13388
+ z50.literal(30)
13263
13389
  ]).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.")
13264
13390
  }),
13265
- z49.object({
13266
- kind: z49.literal("service_angle_approval"),
13267
- angleId: z49.string().uuid(),
13268
- content: z49.string().min(1).max(480).optional(),
13269
- creativeDirection: z49.string().min(1).max(1500).optional(),
13270
- actor: z49.string().min(1).max(360).optional()
13391
+ z50.object({
13392
+ kind: z50.literal("service_angle_approval"),
13393
+ angleId: z50.string().uuid(),
13394
+ content: z50.string().min(1).max(480).optional(),
13395
+ creativeDirection: z50.string().min(1).max(1500).optional(),
13396
+ actor: z50.string().min(1).max(360).optional()
13271
13397
  }),
13272
- z49.object({
13273
- kind: z49.literal("service_script_approval"),
13274
- voiceovers: z49.record(z49.string(), z49.string().min(1).max(600)).optional(),
13275
- visualDirections: z49.record(z49.string(), z49.string().min(1).max(1200)).optional()
13398
+ z50.object({
13399
+ kind: z50.literal("service_script_approval"),
13400
+ voiceovers: z50.record(z50.string(), z50.string().min(1).max(600)).optional(),
13401
+ visualDirections: z50.record(z50.string(), z50.string().min(1).max(1200)).optional()
13276
13402
  })
13277
13403
  ]);
13278
- var ResolvePendingActionInput = z49.object({
13279
- taskId: z49.string().min(1),
13404
+ var ResolvePendingActionInput = z50.object({
13405
+ taskId: z50.string().min(1),
13280
13406
  action: PendingActionPayload
13281
13407
  }).strict();
13282
13408
  function resolveVariantConfirmVideoTier(action) {
13283
13409
  return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
13284
13410
  }
13285
13411
  __name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
13286
- var StatusForResolveSchema = z49.object({
13412
+ var StatusForResolveSchema = z50.object({
13287
13413
  // Metadata used to select the backend resume contract. Older API responses
13288
13414
  // may omit these fields, so the resolver keeps the generic fallback.
13289
- kind: z49.enum([
13415
+ kind: z50.enum([
13290
13416
  "autopilot",
13291
13417
  "video",
13292
13418
  "image",
@@ -13294,24 +13420,24 @@ var StatusForResolveSchema = z49.object({
13294
13420
  "mix",
13295
13421
  "service"
13296
13422
  ]).optional(),
13297
- selectedOutputs: z49.array(z49.enum([
13423
+ selectedOutputs: z50.array(z50.enum([
13298
13424
  "landing",
13299
13425
  "video",
13300
13426
  "image"
13301
13427
  ])).optional(),
13302
- videoAngleCount: z49.number().int().min(1).max(3).optional(),
13303
- ugcFormat: z49.enum([
13428
+ videoAngleCount: z50.number().int().min(1).max(3).optional(),
13429
+ ugcFormat: z50.enum([
13304
13430
  "single_8s",
13305
13431
  "single_15s",
13306
13432
  "double_30s"
13307
13433
  ]).optional(),
13308
- videoStyle: z49.enum([
13434
+ videoStyle: z50.enum([
13309
13435
  "ugc",
13310
13436
  "cartoon_3d",
13311
13437
  "product_only",
13312
13438
  "ai_dynamic"
13313
13439
  ]).optional(),
13314
- videoModel: z49.enum([
13440
+ videoModel: z50.enum([
13315
13441
  "veo",
13316
13442
  "wan",
13317
13443
  "bytedance",
@@ -13319,62 +13445,62 @@ var StatusForResolveSchema = z49.object({
13319
13445
  "grok",
13320
13446
  "kling"
13321
13447
  ]).optional(),
13322
- videoTier: z49.enum([
13448
+ videoTier: z50.enum([
13323
13449
  "legacy",
13324
13450
  "standard",
13325
13451
  "pro",
13326
13452
  "single_call"
13327
13453
  ]).optional(),
13328
- videoResolution: z49.enum([
13454
+ videoResolution: z50.enum([
13329
13455
  "480p",
13330
13456
  "720p"
13331
13457
  ]).optional(),
13332
13458
  narrativeStyle: NarrativeStyleEnum.optional(),
13333
- pendingUserAction: z49.object({
13334
- kind: z49.string(),
13335
- candidateGrouping: z49.string().optional(),
13336
- selectedImageUrls: z49.array(z49.string()).optional(),
13337
- proposedProductNames: z49.array(z49.string()).optional(),
13459
+ pendingUserAction: z50.object({
13460
+ kind: z50.string(),
13461
+ candidateGrouping: z50.string().optional(),
13462
+ selectedImageUrls: z50.array(z50.string()).optional(),
13463
+ proposedProductNames: z50.array(z50.string()).optional(),
13338
13464
  // Adaptive reference questions are server-owned. Echo only the evidence
13339
13465
  // identity and the choices shown by the current snapshot; never accept a
13340
13466
  // client-supplied reference set as authorization.
13341
- options: z49.array(ProductReferenceUserChoiceEnum).max(4).optional(),
13342
- mode: z49.enum([
13467
+ options: z50.array(ProductReferenceUserChoiceEnum).max(4).optional(),
13468
+ mode: z50.enum([
13343
13469
  "question",
13344
13470
  "visual_recovery"
13345
13471
  ]).optional(),
13346
- decisionKey: z49.string().optional(),
13347
- questionOrdinal: z49.number().int().min(1).max(5).optional(),
13348
- questionCeiling: z49.union([
13349
- z49.literal(3),
13350
- z49.literal(5)
13472
+ decisionKey: z50.string().optional(),
13473
+ questionOrdinal: z50.number().int().min(1).max(5).optional(),
13474
+ questionCeiling: z50.union([
13475
+ z50.literal(3),
13476
+ z50.literal(5)
13351
13477
  ]).optional(),
13352
- referenceEvidenceVersion: z49.number().int().positive().optional(),
13353
- expectedEvidenceHash: z49.string().optional(),
13354
- question: z49.object({
13355
- prompt: z49.string().min(1).max(240),
13356
- helpText: z49.string().min(1).max(300).optional(),
13357
- options: z49.array(z49.object({
13478
+ referenceEvidenceVersion: z50.number().int().positive().optional(),
13479
+ expectedEvidenceHash: z50.string().optional(),
13480
+ question: z50.object({
13481
+ prompt: z50.string().min(1).max(240),
13482
+ helpText: z50.string().min(1).max(300).optional(),
13483
+ options: z50.array(z50.object({
13358
13484
  value: ProductReferenceUserChoiceEnum,
13359
- label: z49.string().min(1).max(120),
13360
- description: z49.string().min(1).max(240).optional()
13485
+ label: z50.string().min(1).max(120),
13486
+ description: z50.string().min(1).max(240).optional()
13361
13487
  })).min(2).max(4)
13362
13488
  }).optional(),
13363
13489
  scope: ProductReferenceScopeEnum.optional(),
13364
- scopeKey: z49.string().optional(),
13365
- scopeSnapshotId: z49.string().uuid().optional(),
13366
- scopeHash: z49.string().optional(),
13367
- baseReferenceSetHash: z49.string().optional(),
13368
- phase: z49.enum([
13490
+ scopeKey: z50.string().optional(),
13491
+ scopeSnapshotId: z50.string().uuid().optional(),
13492
+ scopeHash: z50.string().optional(),
13493
+ baseReferenceSetHash: z50.string().optional(),
13494
+ phase: z50.enum([
13369
13495
  "preparation",
13370
13496
  "final"
13371
13497
  ]).optional(),
13372
- selectedRefKeys: z49.array(z49.string().min(1).max(200)).optional(),
13373
- allowedDecisions: z49.array(ProductReferenceResolutionDecisionEnum).optional(),
13374
- customAngleDraft: z49.string().optional(),
13375
- painPointsDraft: z49.string().optional(),
13376
- benefitsDraft: z49.string().optional(),
13377
- featuresDraft: z49.array(z49.string()).optional(),
13498
+ selectedRefKeys: z50.array(z50.string().min(1).max(200)).optional(),
13499
+ allowedDecisions: z50.array(ProductReferenceResolutionDecisionEnum).optional(),
13500
+ customAngleDraft: z50.string().optional(),
13501
+ painPointsDraft: z50.string().optional(),
13502
+ benefitsDraft: z50.string().optional(),
13503
+ featuresDraft: z50.array(z50.string()).optional(),
13378
13504
  // Recommendation consumed only when the caller explicitly sends
13379
13505
  // gapDurationSeconds: 30 in the angle approval action.
13380
13506
  gapDurationChoice: GapDurationChoiceMirror.optional(),
@@ -13383,17 +13509,17 @@ var StatusForResolveSchema = z49.object({
13383
13509
  // keys. `actorId` (the saved custom actor the picker stored) was silently
13384
13510
  // dropped here, so the approval handler below could not echo it back on the
13385
13511
  // PATCH — the selection looked accepted and reached no render.
13386
- angles: z49.array(z49.object({
13387
- id: z49.string().uuid(),
13388
- content: z49.string(),
13389
- creativeDirection: z49.string(),
13390
- actor: z49.string(),
13391
- actorId: z49.string().nullable().optional()
13512
+ angles: z50.array(z50.object({
13513
+ id: z50.string().uuid(),
13514
+ content: z50.string(),
13515
+ creativeDirection: z50.string(),
13516
+ actor: z50.string(),
13517
+ actorId: z50.string().nullable().optional()
13392
13518
  }).passthrough()).optional(),
13393
- panels: z49.array(z49.object({
13394
- beatId: z49.string(),
13395
- voiceover: z49.string(),
13396
- visualDirection: z49.string()
13519
+ panels: z50.array(z50.object({
13520
+ beatId: z50.string(),
13521
+ voiceover: z50.string(),
13522
+ visualDirection: z50.string()
13397
13523
  }).passthrough()).optional()
13398
13524
  }).optional()
13399
13525
  }).passthrough();
@@ -13906,59 +14032,59 @@ __name(registerTaskTools, "registerTaskTools");
13906
14032
 
13907
14033
  // src/tools/creatives.ts
13908
14034
  import { randomUUID } from "crypto";
13909
- import { z as z50 } from "zod";
14035
+ import { z as z51 } from "zod";
13910
14036
  var CreativeRefs = {
13911
14037
  images: ImagesInput,
13912
14038
  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.'),
13913
14039
  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.'),
13914
- 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.'),
13915
- 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.'),
13916
- 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".'),
13917
- 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.'),
13918
- 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."),
13919
- 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.'),
13920
- 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.'),
13921
- isCombo: z50.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
13922
- 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."),
13923
- 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."),
13924
- 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."),
13925
- 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.'),
13926
- 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."),
13927
- 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.")
14040
+ price: z51.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.'),
14041
+ offer: z51.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.'),
14042
+ compareAtPrice: z51.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
14043
+ paymentMethods: z51.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.'),
14044
+ productContext: z51.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."),
14045
+ productLabel: z51.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.'),
14046
+ buyerPersona: z51.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.'),
14047
+ isCombo: z51.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
14048
+ competitorScanEnabled: z51.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."),
14049
+ brandId: z51.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."),
14050
+ projectId: z51.string().uuid().optional().describe("Opcional. ID de un proyecto guiado de dropshipping activo del usuario. Enlaza esta generaci\xF3n con su progreso y recompensas."),
14051
+ creativeDirection: z51.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.'),
14052
+ headline: z51.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."),
14053
+ subheadline: z51.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.")
13928
14054
  };
13929
- var VideoInput = z50.object({
14055
+ var VideoInput = z51.object({
13930
14056
  images: CreativeRefs.images,
13931
- title: z50.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
13932
- 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".'),
14057
+ title: z51.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
14058
+ primaryAngle: z51.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".'),
13933
14059
  language: CreativeRefs.language,
13934
14060
  country: CreativeRefs.country,
13935
- aspectRatio: z50.enum([
14061
+ aspectRatio: z51.enum([
13936
14062
  "9:16",
13937
14063
  "16:9",
13938
14064
  "Auto"
13939
14065
  ]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
13940
- durationSeconds: z50.union([
13941
- z50.literal(15),
13942
- z50.literal(30)
14066
+ durationSeconds: z51.union([
14067
+ z51.literal(15),
14068
+ z51.literal(30)
13943
14069
  ]).default(15).describe("Opcional. Duraci\xF3n objetivo: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
13944
14070
  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).'),
13945
14071
  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.'),
13946
14072
  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).'),
13947
- 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"].'),
14073
+ features: z51.array(z51.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
13948
14074
  price: CreativeRefs.price,
13949
14075
  offer: CreativeRefs.offer,
13950
14076
  productContext: CreativeRefs.productContext,
13951
14077
  productLabel: CreativeRefs.productLabel,
13952
- 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.'),
13953
- 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.'),
13954
- 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."),
13955
- 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."),
13956
- 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."),
14078
+ cta: z51.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.'),
14079
+ scriptNotes: z51.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.'),
14080
+ pauseForVideoScriptReview: z51.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."),
14081
+ pauseForAngleReview: z51.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."),
14082
+ aiDecidesAll: z51.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."),
13957
14083
  competitorScanEnabled: CreativeRefs.competitorScanEnabled,
13958
14084
  brandId: CreativeRefs.brandId,
13959
14085
  projectId: CreativeRefs.projectId
13960
14086
  }).strict();
13961
- var FreeVideoQualityEnum = z50.enum([
14087
+ var FreeVideoQualityEnum = z51.enum([
13962
14088
  "economical",
13963
14089
  "high_detail"
13964
14090
  ]);
@@ -13980,38 +14106,38 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
13980
14106
  15
13981
14107
  ]
13982
14108
  };
13983
- var FreeVideoInput = z50.object({
14109
+ var FreeVideoInput = z51.object({
13984
14110
  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."),
13985
- 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."),
14111
+ rawPrompt: z51.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."),
13986
14112
  quality: FreeVideoQualityEnum.describe('Calidad del video: "economical" = Econ\xF3mico o "high_detail" = Alto detalle.'),
13987
- 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."),
14113
+ durationSeconds: z51.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."),
13988
14114
  videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
13989
- generateAiMusic: z50.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
13990
- addSubtitles: z50.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
13991
- 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.")
14115
+ generateAiMusic: z51.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
14116
+ addSubtitles: z51.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
14117
+ idempotencyKey: z51.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.")
13992
14118
  }).strict();
13993
14119
  var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
13994
14120
  var archetypeList = ImageCreativeArchetypeEnum.options.join(" | ");
13995
14121
  var visualTreatmentList = ImageCreativeVisualTreatmentEnum.options.join(" | ");
13996
14122
  var aspectRatioList = ImageCreativeAspectRatioEnum.options.join(" | ");
13997
- var ImageInput = z50.object({
14123
+ var ImageInput = z51.object({
13998
14124
  images: CreativeRefs.images,
13999
- productTitle: z50.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
14000
- primaryAngle: z50.string().min(1).describe('\xC1ngulo de venta principal. Ej. "Reduce arrugas en 14 d\xEDas".'),
14125
+ productTitle: z51.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
14126
+ primaryAngle: z51.string().min(1).describe('\xC1ngulo de venta principal. Ej. "Reduce arrugas en 14 d\xEDas".'),
14001
14127
  buyerPersona: CreativeRefs.buyerPersona,
14002
14128
  language: CreativeRefs.language,
14003
14129
  country: CreativeRefs.country,
14004
- nVariants: z50.number().int().min(1).max(6).optional().describe("Opcional. N\xFAmero de variantes a generar (1-6). Default 3."),
14005
- 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.'),
14130
+ nVariants: z51.number().int().min(1).max(6).optional().describe("Opcional. N\xFAmero de variantes a generar (1-6). Default 3."),
14131
+ imageModel: z51.string().optional().describe('Opcional. Modelo de imagen. Ej. "gpt-image-2", "nano-banana-2". Om\xEDtelo para usar el default optimizado por costo/calidad.'),
14006
14132
  imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
14007
14133
  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).`),
14008
14134
  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.`),
14009
- 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."),
14135
+ styleMix: z51.boolean().optional().describe("Opcional. Si true, las N variantes mezclan distintos imageStyle para A/B test. Si false/omitido, todas comparten estilo. Default false."),
14010
14136
  aspectRatio: ImageCreativeAspectRatioEnum.optional().describe(`Opcional. Relaci\xF3n de aspecto. Valores: ${aspectRatioList}. Default "4:5" (vertical Instagram feed).`),
14011
- generateAdCopy: z50.boolean().optional().describe("Opcional. Si true, tambi\xE9n genera headline/body/CTA para el ad. Default false."),
14012
- 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."),
14013
- features: z50.array(z50.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
14014
- 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.'),
14137
+ generateAdCopy: z51.boolean().optional().describe("Opcional. Si true, tambi\xE9n genera headline/body/CTA para el ad. Default false."),
14138
+ pauseForAngleReview: z51.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."),
14139
+ features: z51.array(z51.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
14140
+ brandColors: z51.array(z51.string()).optional().describe('Opcional. Paleta de marca en hex. Ej. ["#FF6B35", "#004E89"]. Si se omite, la IA elige seg\xFAn el producto.'),
14015
14141
  price: CreativeRefs.price,
14016
14142
  compareAtPrice: CreativeRefs.compareAtPrice,
14017
14143
  offer: CreativeRefs.offer,
@@ -14025,17 +14151,17 @@ var ImageInput = z50.object({
14025
14151
  headline: CreativeRefs.headline,
14026
14152
  subheadline: CreativeRefs.subheadline
14027
14153
  });
14028
- var EditImageCreativeInput = z50.object({
14029
- taskId: z50.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
14030
- variantIndex: z50.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
14031
- 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".')
14154
+ var EditImageCreativeInput = z51.object({
14155
+ taskId: z51.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
14156
+ variantIndex: z51.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
14157
+ instruction: z51.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".')
14032
14158
  });
14033
- var LandingInput = z50.object({
14034
- 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."),
14159
+ var LandingInput = z51.object({
14160
+ aiDecidesAll: z51.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."),
14035
14161
  images: CreativeRefs.images,
14036
14162
  language: CreativeRefs.language,
14037
14163
  country: CreativeRefs.country,
14038
- 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.'),
14164
+ salesAngle: z51.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.'),
14039
14165
  buyerPersona: CreativeRefs.buyerPersona,
14040
14166
  price: CreativeRefs.price,
14041
14167
  compareAtPrice: CreativeRefs.compareAtPrice,
@@ -14050,6 +14176,7 @@ var LandingInput = z50.object({
14050
14176
  creativeDirection: CreativeRefs.creativeDirection,
14051
14177
  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".'),
14052
14178
  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".'),
14179
+ pauseForAngleReview: z51.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."),
14053
14180
  headline: CreativeRefs.headline,
14054
14181
  subheadline: CreativeRefs.subheadline
14055
14182
  });
@@ -14160,8 +14287,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
14160
14287
  __name(registerCreativeTools, "registerCreativeTools");
14161
14288
 
14162
14289
  // src/tools/creative-variants.ts
14163
- import { z as z51 } from "zod";
14164
- var LandingSectionKeyEnum = z51.enum([
14290
+ import { z as z52 } from "zod";
14291
+ var LandingSectionKeyEnum = z52.enum([
14165
14292
  "problem_hook",
14166
14293
  "problem_cost",
14167
14294
  "solution_mechanism",
@@ -14201,24 +14328,24 @@ var LandingSectionKeyEnum = z51.enum([
14201
14328
  "lifestyle_fit",
14202
14329
  "join_lifestyle"
14203
14330
  ]);
14204
- var CreativeVariantKindEnum = z51.enum([
14331
+ var CreativeVariantKindEnum = z52.enum([
14205
14332
  "video",
14206
14333
  "image",
14207
14334
  "landing"
14208
14335
  ]);
14209
- var EstimateCreativeVariantInputBase = z51.object({
14210
- sourceTaskId: z51.string().uuid().describe("ID de la tarea original completada."),
14336
+ var EstimateCreativeVariantInputBase = z52.object({
14337
+ sourceTaskId: z52.string().uuid().describe("ID de la tarea original completada."),
14211
14338
  kind: CreativeVariantKindEnum,
14212
14339
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
14213
14340
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
14214
- nVariants: z51.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
14341
+ nVariants: z52.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
14215
14342
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
14216
- 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.")
14343
+ instructions: z52.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.")
14217
14344
  }).strict();
14218
14345
  var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
14219
14346
  if (input.kind === "video" && input.nVariants !== void 0) {
14220
14347
  ctx.addIssue({
14221
- code: z51.ZodIssueCode.custom,
14348
+ code: z52.ZodIssueCode.custom,
14222
14349
  path: [
14223
14350
  "nVariants"
14224
14351
  ],
@@ -14228,7 +14355,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
14228
14355
  if (input.kind !== "video") {
14229
14356
  if (input.videoPreset !== void 0) {
14230
14357
  ctx.addIssue({
14231
- code: z51.ZodIssueCode.custom,
14358
+ code: z52.ZodIssueCode.custom,
14232
14359
  path: [
14233
14360
  "videoPreset"
14234
14361
  ],
@@ -14237,7 +14364,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
14237
14364
  }
14238
14365
  if (input.videoResolution !== void 0) {
14239
14366
  ctx.addIssue({
14240
- code: z51.ZodIssueCode.custom,
14367
+ code: z52.ZodIssueCode.custom,
14241
14368
  path: [
14242
14369
  "videoResolution"
14243
14370
  ],
@@ -14247,7 +14374,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
14247
14374
  }
14248
14375
  if (input.kind !== "image" && input.nVariants !== void 0) {
14249
14376
  ctx.addIssue({
14250
- code: z51.ZodIssueCode.custom,
14377
+ code: z52.ZodIssueCode.custom,
14251
14378
  path: [
14252
14379
  "nVariants"
14253
14380
  ],
@@ -14257,7 +14384,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
14257
14384
  if (input.kind !== "landing") {
14258
14385
  if (input.sectionKey !== void 0) {
14259
14386
  ctx.addIssue({
14260
- code: z51.ZodIssueCode.custom,
14387
+ code: z52.ZodIssueCode.custom,
14261
14388
  path: [
14262
14389
  "sectionKey"
14263
14390
  ],
@@ -14266,7 +14393,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
14266
14393
  }
14267
14394
  if (input.instructions !== void 0) {
14268
14395
  ctx.addIssue({
14269
- code: z51.ZodIssueCode.custom,
14396
+ code: z52.ZodIssueCode.custom,
14270
14397
  path: [
14271
14398
  "instructions"
14272
14399
  ],
@@ -14275,31 +14402,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
14275
14402
  }
14276
14403
  }
14277
14404
  });
14278
- var CreateCreativeVariantInputBase = z51.object({
14279
- sourceTaskId: z51.string().uuid().describe("ID de la tarea original completada."),
14405
+ var CreateCreativeVariantInputBase = z52.object({
14406
+ sourceTaskId: z52.string().uuid().describe("ID de la tarea original completada."),
14280
14407
  kind: CreativeVariantKindEnum,
14281
- confirm: z51.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
14282
- 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."),
14283
- angle: z51.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
14284
- buyerPersona: z51.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
14285
- scriptNotes: z51.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
14286
- creativeDirection: z51.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
14408
+ confirm: z52.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
14409
+ clientRequestId: z52.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."),
14410
+ angle: z52.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
14411
+ buyerPersona: z52.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
14412
+ scriptNotes: z52.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
14413
+ creativeDirection: z52.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
14287
14414
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
14288
14415
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
14289
- generateAiMusic: z51.boolean().optional().describe("Opcional para video."),
14290
- nVariants: z51.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
14416
+ generateAiMusic: z52.boolean().optional().describe("Opcional para video."),
14417
+ nVariants: z52.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
14291
14418
  imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
14292
14419
  creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
14293
14420
  visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
14294
14421
  aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
14295
- styleMix: z51.boolean().optional().describe("Opcional para imagen."),
14422
+ styleMix: z52.boolean().optional().describe("Opcional para imagen."),
14296
14423
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
14297
- 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.")
14424
+ instructions: z52.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.")
14298
14425
  }).strict();
14299
14426
  var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
14300
14427
  if ((input.kind === "video" || input.kind === "image") && !input.angle) {
14301
14428
  ctx.addIssue({
14302
- code: z51.ZodIssueCode.custom,
14429
+ code: z52.ZodIssueCode.custom,
14303
14430
  path: [
14304
14431
  "angle"
14305
14432
  ],
@@ -14308,7 +14435,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
14308
14435
  }
14309
14436
  if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
14310
14437
  ctx.addIssue({
14311
- code: z51.ZodIssueCode.custom,
14438
+ code: z52.ZodIssueCode.custom,
14312
14439
  path: [
14313
14440
  "instructions"
14314
14441
  ],
@@ -14354,7 +14481,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
14354
14481
  for (const field of fieldsByKind[input.kind]) {
14355
14482
  if (input[field] !== void 0) {
14356
14483
  ctx.addIssue({
14357
- code: z51.ZodIssueCode.custom,
14484
+ code: z52.ZodIssueCode.custom,
14358
14485
  path: [
14359
14486
  field
14360
14487
  ],
@@ -14471,27 +14598,27 @@ function registerCreativeVariantTools(server, api) {
14471
14598
  __name(registerCreativeVariantTools, "registerCreativeVariantTools");
14472
14599
 
14473
14600
  // src/tools/script-review.ts
14474
- import { z as z52 } from "zod";
14475
- var GetVideoScriptInput = z52.object({
14476
- taskId: z52.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
14477
- 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.')
14601
+ import { z as z53 } from "zod";
14602
+ var GetVideoScriptInput = z53.object({
14603
+ taskId: z53.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
14604
+ angleKey: z53.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.')
14478
14605
  }).strict();
14479
14606
  var VIDEO_SCRIPT_APPROVAL_MAX_SCENES2 = 50;
14480
14607
  var VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2 = 2e3;
14481
- var ApproveSceneEdit = z52.object({
14482
- index: z52.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
14483
- dialogue: z52.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
14608
+ var ApproveSceneEdit = z53.object({
14609
+ index: z53.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
14610
+ dialogue: z53.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
14484
14611
  message: "dialogue no puede ser s\xF3lo espacios"
14485
14612
  }).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.")
14486
14613
  }).strict();
14487
- var ApproveVideoScriptInput = z52.object({
14488
- taskId: z52.string().min(1).describe("ID de la tarea."),
14489
- 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.'),
14490
- 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.")
14614
+ var ApproveVideoScriptInput = z53.object({
14615
+ taskId: z53.string().min(1).describe("ID de la tarea."),
14616
+ angleKey: z53.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.'),
14617
+ scenes: z53.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.")
14491
14618
  }).strict();
14492
- var RegenerateVideoScriptInput = z52.object({
14493
- taskId: z52.string().min(1).describe("ID de la tarea."),
14494
- 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.'),
14619
+ var RegenerateVideoScriptInput = z53.object({
14620
+ taskId: z53.string().min(1).describe("ID de la tarea."),
14621
+ angleKey: z53.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.'),
14495
14622
  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).')
14496
14623
  }).strict();
14497
14624
  function registerScriptReviewTools(server, api) {
@@ -14542,9 +14669,9 @@ function registerScriptReviewTools(server, api) {
14542
14669
  __name(registerScriptReviewTools, "registerScriptReviewTools");
14543
14670
 
14544
14671
  // src/tools/connections.ts
14545
- import { z as z53 } from "zod";
14672
+ import { z as z54 } from "zod";
14546
14673
  function registerConnectionTools(server, api) {
14547
- 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 () => {
14674
+ 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.", z54.object({}).shape, READS_INTERNAL, async () => {
14548
14675
  try {
14549
14676
  const r = await api.getJson("/v1/shopify/shops");
14550
14677
  return asText(r);
@@ -14552,10 +14679,10 @@ function registerConnectionTools(server, api) {
14552
14679
  throw translateError(e);
14553
14680
  }
14554
14681
  });
14555
- 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({
14556
- shopDomain: z53.string().min(3).max(120),
14557
- query: z53.string().trim().max(120).optional(),
14558
- taskId: z53.string().uuid().optional()
14682
+ 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.', z54.object({
14683
+ shopDomain: z54.string().min(3).max(120),
14684
+ query: z54.string().trim().max(120).optional(),
14685
+ taskId: z54.string().uuid().optional()
14559
14686
  }).shape, READS_EXTERNAL, async ({ shopDomain, query, taskId }) => {
14560
14687
  try {
14561
14688
  const params = new URLSearchParams({
@@ -14569,7 +14696,7 @@ function registerConnectionTools(server, api) {
14569
14696
  throw translateError(e);
14570
14697
  }
14571
14698
  });
14572
- 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 () => {
14699
+ 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.", z54.object({}).shape, READS_EXTERNAL, async () => {
14573
14700
  try {
14574
14701
  const r = await api.getJson("/v1/facebook/ad-accounts");
14575
14702
  return asText(r);
@@ -14579,7 +14706,7 @@ function registerConnectionTools(server, api) {
14579
14706
  });
14580
14707
  server.registerTool("list_meta_destinations", {
14581
14708
  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.",
14582
- inputSchema: z53.object({}).shape,
14709
+ inputSchema: z54.object({}).shape,
14583
14710
  annotations: READS_EXTERNAL,
14584
14711
  _meta: {
14585
14712
  "openai/widgetAccessible": true
@@ -14592,7 +14719,7 @@ function registerConnectionTools(server, api) {
14592
14719
  throw translateError(e);
14593
14720
  }
14594
14721
  });
14595
- 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 () => {
14722
+ 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.", z54.object({}).shape, READS_EXTERNAL, async () => {
14596
14723
  try {
14597
14724
  const r = await api.getJson("/v1/tiktok/advertisers");
14598
14725
  return asText(r);
@@ -14604,9 +14731,9 @@ function registerConnectionTools(server, api) {
14604
14731
  __name(registerConnectionTools, "registerConnectionTools");
14605
14732
 
14606
14733
  // src/tools/actors.ts
14607
- import { z as z54 } from "zod";
14734
+ import { z as z55 } from "zod";
14608
14735
  function registerActorTools(server, api) {
14609
- 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 () => {
14736
+ 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.", z55.object({}).shape, READS_INTERNAL, async () => {
14610
14737
  try {
14611
14738
  const rows = await api.getJson("/v1/actors");
14612
14739
  const actors = (Array.isArray(rows) ? rows : []).filter((actor) => actor.status === "ready").map(({ id, name, description, gender, voiceId }) => ({
@@ -14627,39 +14754,39 @@ function registerActorTools(server, api) {
14627
14754
  __name(registerActorTools, "registerActorTools");
14628
14755
 
14629
14756
  // src/tools/publish.ts
14630
- import { z as z55 } from "zod";
14631
- var ShopifyInput = z55.object({
14632
- taskId: z55.string().min(1),
14633
- shopDomain: z55.string().min(1),
14757
+ import { z as z56 } from "zod";
14758
+ var ShopifyInput = z56.object({
14759
+ taskId: z56.string().min(1),
14760
+ shopDomain: z56.string().min(1),
14634
14761
  /** Override: number of landing images to include. Default = ALL images the
14635
14762
  * task generated (the MCP fetches /v1/results first to count). Bounded
14636
14763
  * generously here; the backend validates each index against
14637
14764
  * landing.images.length and rejects out-of-range. */
14638
- numLandingImages: z55.number().int().min(1).max(20).optional(),
14639
- variantIndex: z55.number().int().min(0).optional(),
14765
+ numLandingImages: z56.number().int().min(1).max(20).optional(),
14766
+ variantIndex: z56.number().int().min(0).optional(),
14640
14767
  /** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
14641
14768
  * When true, the landing renders variant-picker pills; when false, it ships
14642
14769
  * a single-option product page. Defaults to false. */
14643
- showVariantPicker: z55.boolean().optional(),
14770
+ showVariantPicker: z56.boolean().optional(),
14644
14771
  /** Default `auto` updates the product previously published for this task and
14645
14772
  * shop. Use `existing` with targetProductId to choose another product, or
14646
14773
  * `new` only when the user explicitly wants a duplicate/new listing. */
14647
- publicationMode: z55.enum([
14774
+ publicationMode: z56.enum([
14648
14775
  "auto",
14649
14776
  "existing",
14650
14777
  "new"
14651
14778
  ]).optional(),
14652
14779
  /** Shopify product GID, numeric id, or admin product URL. Required when
14653
14780
  * publicationMode is `existing`. */
14654
- targetProductId: z55.string().trim().min(1).max(300).optional(),
14781
+ targetProductId: z56.string().trim().min(1).max(300).optional(),
14655
14782
  /** Add an announcement bar text above add-to-cart (optional). */
14656
- announcementBarEnabled: z55.boolean().optional(),
14657
- announcementBarText: z55.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional()
14783
+ announcementBarEnabled: z56.boolean().optional(),
14784
+ announcementBarText: z56.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional()
14658
14785
  });
14659
14786
  var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
14660
14787
  if (value.announcementBarEnabled && !value.announcementBarText) {
14661
14788
  ctx.addIssue({
14662
- code: z55.ZodIssueCode.custom,
14789
+ code: z56.ZodIssueCode.custom,
14663
14790
  path: [
14664
14791
  "announcementBarText"
14665
14792
  ],
@@ -14668,7 +14795,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
14668
14795
  }
14669
14796
  if (!value.announcementBarEnabled && value.announcementBarText) {
14670
14797
  ctx.addIssue({
14671
- code: z55.ZodIssueCode.custom,
14798
+ code: z56.ZodIssueCode.custom,
14672
14799
  path: [
14673
14800
  "announcementBarText"
14674
14801
  ],
@@ -14682,90 +14809,90 @@ function parseShopifyInput(rawInput) {
14682
14809
  return parsed.data;
14683
14810
  }
14684
14811
  __name(parseShopifyInput, "parseShopifyInput");
14685
- var McpCampaignConfig = z55.object({
14812
+ var McpCampaignConfig = z56.object({
14686
14813
  /** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
14687
14814
  * converts to the account currency server-side. Do NOT pre-convert: on a COP
14688
14815
  * account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
14689
- dailyBudgetUsd: z55.number().positive().optional(),
14816
+ dailyBudgetUsd: z56.number().positive().optional(),
14690
14817
  /** ISO-3166-1 alpha-2 country codes. Meta accepts max 1 (single-country
14691
14818
  * ad set). TikTok takes only the first entry. */
14692
- targetCountries: z55.array(z55.string().length(2)).max(1).optional(),
14693
- campaignName: z55.string().trim().min(1).max(100).optional()
14819
+ targetCountries: z56.array(z56.string().length(2)).max(1).optional(),
14820
+ campaignName: z56.string().trim().min(1).max(100).optional()
14694
14821
  });
14695
14822
  var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
14696
- var MetaInput = z55.object({
14697
- taskId: z55.string().min(1),
14823
+ var MetaInput = z56.object({
14824
+ taskId: z56.string().min(1),
14698
14825
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
14699
- portfolioId: z55.string().trim().min(1),
14826
+ portfolioId: z56.string().trim().min(1),
14700
14827
  /** Exact Facebook Page selected from `list_meta_destinations`. */
14701
- pageId: z55.string().trim().min(1),
14828
+ pageId: z56.string().trim().min(1),
14702
14829
  adAccountId: McpAdAccountId,
14703
- pixelId: z55.string().min(1).optional(),
14704
- landingUrl: z55.string().url().optional(),
14830
+ pixelId: z56.string().min(1).optional(),
14831
+ landingUrl: z56.string().url().optional(),
14705
14832
  /** Select which angles to publish by 0-based index. Omit to publish all
14706
14833
  * successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
14707
- angleIndexes: z55.array(z55.number().int().nonnegative()).optional(),
14834
+ angleIndexes: z56.array(z56.number().int().nonnegative()).optional(),
14708
14835
  campaignConfig: McpCampaignConfig.optional(),
14709
14836
  /** Override the ad's primary text (body copy). If omitted, ProductMaker
14710
14837
  * uses the auto-generated copy attached to the task. Capped at 500 chars
14711
14838
  * (Meta's primary-text limit). */
14712
- primaryText: z55.string().trim().min(1).max(500).optional(),
14839
+ primaryText: z56.string().trim().min(1).max(500).optional(),
14713
14840
  /** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
14714
14841
  * (wa.me) instead of a landing page. */
14715
- phoneNumber: z55.string().min(8).max(32).optional()
14842
+ phoneNumber: z56.string().min(8).max(32).optional()
14716
14843
  });
14717
- var GroupedTaskSource = z55.object({
14718
- type: z55.literal("task"),
14719
- taskId: z55.string().min(1),
14720
- angleIndex: z55.number().int().min(0).optional(),
14721
- videoVariant: z55.enum([
14844
+ var GroupedTaskSource = z56.object({
14845
+ type: z56.literal("task"),
14846
+ taskId: z56.string().min(1),
14847
+ angleIndex: z56.number().int().min(0).optional(),
14848
+ videoVariant: z56.enum([
14722
14849
  "with_subtitles",
14723
14850
  "without_subtitles"
14724
14851
  ]).optional(),
14725
- imageVariantIndex: z55.number().int().min(0).optional()
14726
- });
14727
- var GroupedMediaSource = z55.object({
14728
- type: z55.literal("media"),
14729
- 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."),
14730
- 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".'),
14731
- thumbnailUrl: z55.string().url().optional(),
14732
- thumbnailPath: z55.string().min(1).optional()
14852
+ imageVariantIndex: z56.number().int().min(0).optional()
14853
+ });
14854
+ var GroupedMediaSource = z56.object({
14855
+ type: z56.literal("media"),
14856
+ url: z56.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
14857
+ path: z56.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".'),
14858
+ thumbnailUrl: z56.string().url().optional(),
14859
+ thumbnailPath: z56.string().min(1).optional()
14733
14860
  }).refine((value) => Boolean(value.url) !== Boolean(value.path), {
14734
14861
  message: "media source needs exactly one of `url` or `path`"
14735
14862
  }).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
14736
14863
  message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
14737
14864
  });
14738
- var GroupedUploadedAssetSource = z55.object({
14739
- type: z55.literal("asset"),
14865
+ var GroupedUploadedAssetSource = z56.object({
14866
+ type: z56.literal("asset"),
14740
14867
  /** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
14741
- assetId: z55.string().uuid(),
14742
- thumbnailAssetId: z55.string().uuid().optional()
14868
+ assetId: z56.string().uuid(),
14869
+ thumbnailAssetId: z56.string().uuid().optional()
14743
14870
  });
14744
- var GroupedCreative = z55.object({
14745
- type: z55.enum([
14871
+ var GroupedCreative = z56.object({
14872
+ type: z56.enum([
14746
14873
  "image",
14747
14874
  "video"
14748
14875
  ]),
14749
- source: z55.union([
14876
+ source: z56.union([
14750
14877
  GroupedTaskSource,
14751
14878
  GroupedMediaSource,
14752
14879
  GroupedUploadedAssetSource
14753
14880
  ]),
14754
- title: z55.string().max(120).optional(),
14755
- description: z55.string().max(500).optional(),
14881
+ title: z56.string().max(120).optional(),
14882
+ description: z56.string().max(500).optional(),
14756
14883
  cta: MetaCtaType.optional(),
14757
- creativeId: z55.string().min(1).optional()
14884
+ creativeId: z56.string().min(1).optional()
14758
14885
  });
14759
- var GroupedCampaignConfigBase = z55.object({
14886
+ var GroupedCampaignConfigBase = z56.object({
14760
14887
  campaignType: MetaCampaignType.default("sales"),
14761
14888
  optimizationMode: MetaOptimizationMode.default("advantage_plus"),
14762
14889
  budgetMode: MetaBudgetMode.optional(),
14763
- campaignDailyBudget: z55.number().int().positive().optional(),
14764
- adSets: z55.array(z55.object({
14765
- tempId: z55.string().min(1).max(80),
14766
- name: z55.string().min(1).max(100),
14767
- dailyBudget: z55.number().int().positive().optional(),
14768
- creativeIds: z55.array(z55.string().min(1)).min(1)
14890
+ campaignDailyBudget: z56.number().int().positive().optional(),
14891
+ adSets: z56.array(z56.object({
14892
+ tempId: z56.string().min(1).max(80),
14893
+ name: z56.string().min(1).max(100),
14894
+ dailyBudget: z56.number().int().positive().optional(),
14895
+ creativeIds: z56.array(z56.string().min(1)).min(1)
14769
14896
  })).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
14770
14897
  /**
14771
14898
  * Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
@@ -14773,17 +14900,17 @@ var GroupedCampaignConfigBase = z55.object({
14773
14900
  * opaque `invalid_literal` and made the WhatsApp destination — supported by
14774
14901
  * the API since #849 — unreachable from this tool.
14775
14902
  */
14776
- destination: z55.discriminatedUnion("type", [
14777
- z55.object({
14778
- type: z55.literal("landing"),
14779
- landingUrl: z55.string().url()
14903
+ destination: z56.discriminatedUnion("type", [
14904
+ z56.object({
14905
+ type: z56.literal("landing"),
14906
+ landingUrl: z56.string().url()
14780
14907
  }),
14781
- z55.object({
14782
- type: z55.literal("whatsapp"),
14783
- phoneNumber: z55.string().min(8).max(32)
14908
+ z56.object({
14909
+ type: z56.literal("whatsapp"),
14910
+ phoneNumber: z56.string().min(8).max(32)
14784
14911
  })
14785
14912
  ]),
14786
- saveAsDefault: z55.boolean().default(false),
14913
+ saveAsDefault: z56.boolean().default(false),
14787
14914
  budgetPolicy: MetaBudgetPolicy.optional()
14788
14915
  });
14789
14916
  function resolveBudgetMode(value) {
@@ -14797,7 +14924,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
14797
14924
  const budgetMode = resolveBudgetMode(value);
14798
14925
  if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
14799
14926
  ctx.addIssue({
14800
- code: z55.ZodIssueCode.custom,
14927
+ code: z56.ZodIssueCode.custom,
14801
14928
  path: [
14802
14929
  "campaignDailyBudget"
14803
14930
  ],
@@ -14808,7 +14935,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
14808
14935
  value.adSets.forEach((adSet, index) => {
14809
14936
  if (adSet.dailyBudget === void 0) {
14810
14937
  ctx.addIssue({
14811
- code: z55.ZodIssueCode.custom,
14938
+ code: z56.ZodIssueCode.custom,
14812
14939
  path: [
14813
14940
  "adSets",
14814
14941
  index,
@@ -14823,26 +14950,26 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
14823
14950
  ...value,
14824
14951
  budgetMode: resolveBudgetMode(value)
14825
14952
  }));
14826
- var PublishCreativesToMetaInputBase = z55.object({
14827
- creatives: z55.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
14953
+ var PublishCreativesToMetaInputBase = z56.object({
14954
+ creatives: z56.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
14828
14955
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
14829
- portfolioId: z55.string().trim().min(1),
14956
+ portfolioId: z56.string().trim().min(1),
14830
14957
  /** Exact Facebook Page selected from `list_meta_destinations`. */
14831
- pageId: z55.string().trim().min(1),
14958
+ pageId: z56.string().trim().min(1),
14832
14959
  adAccountId: McpAdAccountId,
14833
- pixelId: z55.string().min(1).optional(),
14960
+ pixelId: z56.string().min(1).optional(),
14834
14961
  /** Required unless `campaignConfig.destination` is whatsapp — see the
14835
14962
  * superRefine below. Mirrors the API's `UploadToMetaRequest`. */
14836
- landingUrl: z55.string().url().optional(),
14837
- targetCountry: z55.string().length(2),
14838
- campaignName: z55.string().trim().min(1).max(100),
14963
+ landingUrl: z56.string().url().optional(),
14964
+ targetCountry: z56.string().length(2),
14965
+ campaignName: z56.string().trim().min(1).max(100),
14839
14966
  campaignConfig: GroupedCampaignConfig.optional()
14840
14967
  });
14841
14968
  var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
14842
14969
  const destination = value.campaignConfig?.destination;
14843
14970
  if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
14844
14971
  ctx.addIssue({
14845
- code: z55.ZodIssueCode.custom,
14972
+ code: z56.ZodIssueCode.custom,
14846
14973
  path: [
14847
14974
  "landingUrl"
14848
14975
  ],
@@ -14851,7 +14978,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
14851
14978
  }
14852
14979
  if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
14853
14980
  ctx.addIssue({
14854
- code: z55.ZodIssueCode.custom,
14981
+ code: z56.ZodIssueCode.custom,
14855
14982
  path: [
14856
14983
  "campaignConfig",
14857
14984
  "destination",
@@ -14870,16 +14997,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
14870
14997
  }
14871
14998
  return value;
14872
14999
  });
14873
- var PresignUploadResponseSchema = z55.object({
14874
- uploadUrl: z55.string().url().refine((value) => {
15000
+ var PresignUploadResponseSchema = z56.object({
15001
+ uploadUrl: z56.string().url().refine((value) => {
14875
15002
  const url = new URL(value);
14876
15003
  return !url.username && !url.password && url.protocol === "https:";
14877
15004
  }, "presigned upload URL must be HTTPS without embedded credentials"),
14878
- publicUrl: z55.string().url().refine((value) => {
15005
+ publicUrl: z56.string().url().refine((value) => {
14879
15006
  const url = new URL(value);
14880
15007
  return !url.username && !url.password;
14881
15008
  }, "public media URL must not contain embedded credentials"),
14882
- stagingAssetId: z55.string().uuid()
15009
+ stagingAssetId: z56.string().uuid()
14883
15010
  });
14884
15011
  async function uploadResolvedMedia(api, media, assetRole) {
14885
15012
  if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
@@ -14904,16 +15031,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
14904
15031
  return uploadResolvedMedia(api, media, assetRole);
14905
15032
  }
14906
15033
  __name(resolveAndUploadMedia, "resolveAndUploadMedia");
14907
- var TikTokInput = z55.object({
14908
- taskId: z55.string().min(1),
14909
- advertiserId: z55.string().min(1),
14910
- pixelId: z55.string().min(1).optional(),
14911
- landingUrl: z55.string().url().optional(),
14912
- angleIndexes: z55.array(z55.number().int().nonnegative()).optional(),
15034
+ var TikTokInput = z56.object({
15035
+ taskId: z56.string().min(1),
15036
+ advertiserId: z56.string().min(1),
15037
+ pixelId: z56.string().min(1).optional(),
15038
+ landingUrl: z56.string().url().optional(),
15039
+ angleIndexes: z56.array(z56.number().int().nonnegative()).optional(),
14913
15040
  campaignConfig: McpCampaignConfig.optional(),
14914
15041
  /** Override the ad's description (TikTok's body copy). If omitted,
14915
15042
  * ProductMaker uses the auto-generated copy attached to the task. */
14916
- primaryText: z55.string().trim().min(1).max(500).optional()
15043
+ primaryText: z56.string().trim().min(1).max(500).optional()
14917
15044
  });
14918
15045
  function registerPublishTools(server, api, opts = {}) {
14919
15046
  const transport = opts.transport ?? "http";
@@ -15163,38 +15290,38 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
15163
15290
 
15164
15291
  // src/tools/meta-upload.ts
15165
15292
  import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
15166
- import { z as z56 } from "zod";
15167
- var UploadSessionInputBase = z56.object({
15168
- mediaKind: z56.enum([
15293
+ import { z as z57 } from "zod";
15294
+ var UploadSessionInputBase = z57.object({
15295
+ mediaKind: z57.enum([
15169
15296
  "image",
15170
15297
  "video",
15171
15298
  "mixed"
15172
15299
  ]).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."),
15173
- assetRole: z56.enum([
15300
+ assetRole: z57.enum([
15174
15301
  "media",
15175
15302
  "thumbnail"
15176
15303
  ]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
15177
- uploadPurpose: z56.enum([
15304
+ uploadPurpose: z57.enum([
15178
15305
  "product_reference",
15179
15306
  "creative",
15180
15307
  "generic"
15181
15308
  ]).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."),
15182
- maxFiles: z56.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
15309
+ maxFiles: z57.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
15183
15310
  });
15184
- var OpenAiFileReference = z56.object({
15185
- 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."),
15186
- file_id: z56.string().min(1),
15187
- mime_type: z56.string().min(1).optional(),
15188
- file_name: z56.string().min(1).optional()
15311
+ var OpenAiFileReference = z57.object({
15312
+ download_url: z57.string().url().optional().describe("Optional host-provided download URL. The App prefers getFileDownloadUrl(file_id) and the server never fetches this URL."),
15313
+ file_id: z57.string().min(1),
15314
+ mime_type: z57.string().min(1).optional(),
15315
+ file_name: z57.string().min(1).optional()
15189
15316
  });
15190
15317
  var UploadSessionToolInputShape = {
15191
15318
  ...UploadSessionInputBase.shape,
15192
- 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.")
15319
+ files: z57.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.")
15193
15320
  };
15194
- var UploadSessionToolInput = z56.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
15321
+ var UploadSessionToolInput = z57.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
15195
15322
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
15196
15323
  ctx.addIssue({
15197
- code: z56.ZodIssueCode.custom,
15324
+ code: z57.ZodIssueCode.custom,
15198
15325
  path: [
15199
15326
  "mediaKind"
15200
15327
  ],
@@ -15203,7 +15330,7 @@ var UploadSessionToolInput = z56.object(UploadSessionToolInputShape).superRefine
15203
15330
  }
15204
15331
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
15205
15332
  ctx.addIssue({
15206
- code: z56.ZodIssueCode.custom,
15333
+ code: z57.ZodIssueCode.custom,
15207
15334
  path: [
15208
15335
  "maxFiles"
15209
15336
  ],
@@ -15212,7 +15339,7 @@ var UploadSessionToolInput = z56.object(UploadSessionToolInputShape).superRefine
15212
15339
  }
15213
15340
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
15214
15341
  ctx.addIssue({
15215
- code: z56.ZodIssueCode.custom,
15342
+ code: z57.ZodIssueCode.custom,
15216
15343
  path: [
15217
15344
  "maxFiles"
15218
15345
  ],
@@ -15220,38 +15347,38 @@ var UploadSessionToolInput = z56.object(UploadSessionToolInputShape).superRefine
15220
15347
  });
15221
15348
  }
15222
15349
  });
15223
- var UploadSessionResponse = z56.object({
15224
- sessionId: z56.string().uuid(),
15225
- uploadPageUrl: z56.string().url(),
15226
- mediaKind: z56.enum([
15350
+ var UploadSessionResponse = z57.object({
15351
+ sessionId: z57.string().uuid(),
15352
+ uploadPageUrl: z57.string().url(),
15353
+ mediaKind: z57.enum([
15227
15354
  "image",
15228
15355
  "video",
15229
15356
  "mixed"
15230
15357
  ]),
15231
- assetRole: z56.enum([
15358
+ assetRole: z57.enum([
15232
15359
  "media",
15233
15360
  "thumbnail"
15234
15361
  ]),
15235
- maxFiles: z56.number().int().positive(),
15236
- expiresAt: z56.string().datetime()
15362
+ maxFiles: z57.number().int().positive(),
15363
+ expiresAt: z57.string().datetime()
15237
15364
  });
15238
- var UploadStatusInput = z56.object({
15239
- sessionId: z56.string().uuid().describe("The sessionId returned by request_media_upload.")
15365
+ var UploadStatusInput = z57.object({
15366
+ sessionId: z57.string().uuid().describe("The sessionId returned by request_media_upload.")
15240
15367
  });
15241
- var UniversalUploadStatusResponse = z56.discriminatedUnion("status", [
15242
- z56.object({
15243
- status: z56.literal("pending"),
15244
- assets: z56.array(z56.never()).length(0)
15368
+ var UniversalUploadStatusResponse = z57.discriminatedUnion("status", [
15369
+ z57.object({
15370
+ status: z57.literal("pending"),
15371
+ assets: z57.array(z57.never()).length(0)
15245
15372
  }),
15246
- z56.object({
15247
- status: z56.literal("uploaded"),
15248
- assets: z56.array(z56.object({
15249
- assetId: z56.string().uuid(),
15250
- mediaKind: z56.enum([
15373
+ z57.object({
15374
+ status: z57.literal("uploaded"),
15375
+ assets: z57.array(z57.object({
15376
+ assetId: z57.string().uuid(),
15377
+ mediaKind: z57.enum([
15251
15378
  "image",
15252
15379
  "video"
15253
15380
  ]),
15254
- assetRole: z56.enum([
15381
+ assetRole: z57.enum([
15255
15382
  "media",
15256
15383
  "thumbnail"
15257
15384
  ])
@@ -15259,13 +15386,13 @@ var UniversalUploadStatusResponse = z56.discriminatedUnion("status", [
15259
15386
  })
15260
15387
  ]);
15261
15388
  var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
15262
- uploadPurpose: z56.enum([
15389
+ uploadPurpose: z57.enum([
15263
15390
  "product_reference",
15264
15391
  "creative",
15265
15392
  "generic"
15266
15393
  ]),
15267
- checkToolName: z56.literal("check_media_upload"),
15268
- resolveEndpoint: z56.string().url()
15394
+ checkToolName: z57.literal("check_media_upload"),
15395
+ resolveEndpoint: z57.string().url()
15269
15396
  });
15270
15397
  function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
15271
15398
  const url = new URL(uploadPageUrl);
@@ -15356,13 +15483,13 @@ function registerMediaUploadTools(server, api) {
15356
15483
  __name(registerMediaUploadTools, "registerMediaUploadTools");
15357
15484
 
15358
15485
  // src/tools/campaigns.ts
15359
- import { z as z57 } from "zod";
15360
- var MetaStatusInput = z57.object({
15361
- campaignId: z57.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
15486
+ import { z as z58 } from "zod";
15487
+ var MetaStatusInput = z58.object({
15488
+ campaignId: z58.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
15362
15489
  });
15363
- var TikTokStatusInput = z57.object({
15364
- campaignId: z57.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
15365
- advertiserId: z57.string().min(1).describe("The same advertiserId used to publish the campaign.")
15490
+ var TikTokStatusInput = z58.object({
15491
+ campaignId: z58.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
15492
+ advertiserId: z58.string().min(1).describe("The same advertiserId used to publish the campaign.")
15366
15493
  });
15367
15494
  function registerCampaignTools(server, api) {
15368
15495
  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) => {
@@ -15459,10 +15586,10 @@ function renderTikTokStatusMarkdown(r) {
15459
15586
  __name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
15460
15587
 
15461
15588
  // ../../packages/product-economics/src/product-costing.ts
15462
- import { z as z59 } from "zod";
15589
+ import { z as z60 } from "zod";
15463
15590
 
15464
15591
  // ../../packages/product-economics/src/product-costing-countries.ts
15465
- import { z as z58 } from "zod";
15592
+ import { z as z59 } from "zod";
15466
15593
 
15467
15594
  // ../../packages/product-economics/src/product-costing-shipping-references.json
15468
15595
  var product_costing_shipping_references_default = {
@@ -15526,21 +15653,21 @@ var product_costing_shipping_references_default = {
15526
15653
  };
15527
15654
 
15528
15655
  // ../../packages/product-economics/src/product-costing-countries.ts
15529
- var ShippingReferenceSchema = z58.object({
15530
- reference: z58.number().positive(),
15531
- min: z58.number().nonnegative(),
15532
- max: z58.number().positive(),
15533
- updatedAt: z58.string().date(),
15534
- confidence: z58.enum([
15656
+ var ShippingReferenceSchema = z59.object({
15657
+ reference: z59.number().positive(),
15658
+ min: z59.number().nonnegative(),
15659
+ max: z59.number().positive(),
15660
+ updatedAt: z59.string().date(),
15661
+ confidence: z59.enum([
15535
15662
  "high",
15536
15663
  "medium",
15537
15664
  "medium-low"
15538
15665
  ]),
15539
- sources: z58.array(z58.string().url().startsWith("https://")).min(1).max(3)
15666
+ sources: z59.array(z59.string().url().startsWith("https://")).min(1).max(3)
15540
15667
  }).superRefine(({ reference, min, max }, context) => {
15541
15668
  if (min > reference || reference > max) {
15542
15669
  context.addIssue({
15543
- code: z58.ZodIssueCode.custom,
15670
+ code: z59.ZodIssueCode.custom,
15544
15671
  message: "shipping_reference_outside_range",
15545
15672
  path: [
15546
15673
  "reference"
@@ -15548,7 +15675,7 @@ var ShippingReferenceSchema = z58.object({
15548
15675
  });
15549
15676
  }
15550
15677
  });
15551
- var SHIPPING_REFERENCES = z58.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
15678
+ var SHIPPING_REFERENCES = z59.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
15552
15679
  var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
15553
15680
  var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
15554
15681
  "MX",
@@ -15730,18 +15857,18 @@ function getProductCostingCountryName(country) {
15730
15857
  __name(getProductCostingCountryName, "getProductCostingCountryName");
15731
15858
 
15732
15859
  // ../../packages/product-economics/src/product-costing.ts
15733
- var ProductCostingInputSchema = z59.object({
15734
- country: z59.string().refine(isProductCostingCountryCode, "unsupported_country"),
15735
- supplierCost: z59.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
15736
- shippingCost: z59.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
15737
- returnRate: z59.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
15738
- cancellationRate: z59.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
15739
- adsManagerCpa: z59.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
15740
- desiredMargin: z59.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
15860
+ var ProductCostingInputSchema = z60.object({
15861
+ country: z60.string().refine(isProductCostingCountryCode, "unsupported_country"),
15862
+ supplierCost: z60.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
15863
+ shippingCost: z60.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
15864
+ returnRate: z60.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
15865
+ cancellationRate: z60.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
15866
+ adsManagerCpa: z60.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
15867
+ desiredMargin: z60.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
15741
15868
  }).superRefine(({ returnRate, cancellationRate }, context) => {
15742
15869
  if (returnRate + cancellationRate >= 1) {
15743
15870
  context.addIssue({
15744
- code: z59.ZodIssueCode.custom,
15871
+ code: z60.ZodIssueCode.custom,
15745
15872
  message: "delivery_rate_positive",
15746
15873
  path: [
15747
15874
  "cancellationRate"
@@ -15808,14 +15935,14 @@ function calculateProductCosting(rawInput) {
15808
15935
  __name(calculateProductCosting, "calculateProductCosting");
15809
15936
 
15810
15937
  // src/tools/product-costing.ts
15811
- import { z as z60 } from "zod";
15812
- var optionalAmount = /* @__PURE__ */ __name((description) => z60.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
15813
- var optionalPercent = /* @__PURE__ */ __name((description) => z60.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
15814
- var ProductCostingToolInput = z60.object({
15815
- country: z60.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
15938
+ import { z as z61 } from "zod";
15939
+ var optionalAmount = /* @__PURE__ */ __name((description) => z61.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
15940
+ var optionalPercent = /* @__PURE__ */ __name((description) => z61.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
15941
+ var ProductCostingToolInput = z61.object({
15942
+ country: z61.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
15816
15943
  message: "Pa\xEDs no soportado por ProductMaker."
15817
15944
  }).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
15818
- 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."),
15945
+ supplierCost: z61.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."),
15819
15946
  supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
15820
15947
  shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
15821
15948
  shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
@@ -15947,7 +16074,7 @@ function formatPercent(value) {
15947
16074
  __name(formatPercent, "formatPercent");
15948
16075
 
15949
16076
  // src/tools/product-research.ts
15950
- import { z as z61 } from "zod";
16077
+ import { z as z62 } from "zod";
15951
16078
 
15952
16079
  // src/tools/product-research-idempotency.ts
15953
16080
  import { createHash as createHash3 } from "crypto";
@@ -16063,17 +16190,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
16063
16190
  ]);
16064
16191
  var POLL_INTERVAL_MS = 5e3;
16065
16192
  var MAX_WAIT_SECONDS = 120;
16066
- var FindInput = z61.object({
16193
+ var FindInput = z62.object({
16067
16194
  targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
16068
16195
  categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
16069
- 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.`),
16070
- 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.")
16196
+ confirmed: z62.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
16197
+ waitSeconds: z62.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
16071
16198
  });
16072
- var GetInput = z61.object({
16073
- runId: z61.string().uuid().describe("ID del run devuelto por find_winning_products.")
16199
+ var GetInput = z62.object({
16200
+ runId: z62.string().uuid().describe("ID del run devuelto por find_winning_products.")
16074
16201
  });
16075
- var ListInput = z61.object({
16076
- limit: z61.number().int().min(1).max(20).default(10)
16202
+ var ListInput = z62.object({
16203
+ limit: z62.number().int().min(1).max(20).default(10)
16077
16204
  });
16078
16205
  function textResult(text) {
16079
16206
  return {
@@ -16165,14 +16292,14 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
16165
16292
  __name(registerProductResearchTools, "registerProductResearchTools");
16166
16293
 
16167
16294
  // src/tools/dropshipping-projects.ts
16168
- import { z as z62 } from "zod";
16169
- var ProjectId = z62.string().uuid();
16170
- var DropshippingProjectStatus = z62.enum([
16295
+ import { z as z63 } from "zod";
16296
+ var ProjectId = z63.string().uuid();
16297
+ var DropshippingProjectStatus = z63.enum([
16171
16298
  "active",
16172
16299
  "completed",
16173
16300
  "archived"
16174
16301
  ]);
16175
- var DropshippingProjectPhase = z62.enum([
16302
+ var DropshippingProjectPhase = z63.enum([
16176
16303
  "research",
16177
16304
  "costing",
16178
16305
  "media",
@@ -16181,21 +16308,21 @@ var DropshippingProjectPhase = z62.enum([
16181
16308
  "advertising",
16182
16309
  "complete"
16183
16310
  ]);
16184
- var DropshippingRewardMilestone = z62.enum([
16311
+ var DropshippingRewardMilestone = z63.enum([
16185
16312
  "product_selected",
16186
16313
  "costing_saved",
16187
16314
  "product_media_ready",
16188
16315
  "creatives_completed",
16189
16316
  "campaign_created"
16190
16317
  ]);
16191
- var TargetCountry = z62.enum([
16318
+ var TargetCountry = z63.enum([
16192
16319
  "CO",
16193
16320
  "MX",
16194
16321
  "PE",
16195
16322
  "EC",
16196
16323
  "CL"
16197
16324
  ]);
16198
- var ResearchCategory = z62.enum([
16325
+ var ResearchCategory = z63.enum([
16199
16326
  "auto",
16200
16327
  "automotive",
16201
16328
  "kitchen",
@@ -16210,7 +16337,7 @@ var ResearchCategory = z62.enum([
16210
16337
  "garden",
16211
16338
  "cleaning"
16212
16339
  ]);
16213
- var HttpUrl3 = z62.string().url().max(2e3).refine((value) => {
16340
+ var HttpUrl3 = z63.string().url().max(2e3).refine((value) => {
16214
16341
  try {
16215
16342
  return [
16216
16343
  "http:",
@@ -16220,43 +16347,43 @@ var HttpUrl3 = z62.string().url().max(2e3).refine((value) => {
16220
16347
  return false;
16221
16348
  }
16222
16349
  }, "URL must use HTTP(S)");
16223
- var ResearchCandidateOrigin = z62.object({
16224
- type: z62.literal("research_candidate"),
16350
+ var ResearchCandidateOrigin = z63.object({
16351
+ type: z63.literal("research_candidate"),
16225
16352
  runId: ProjectId,
16226
- candidateSourceId: z62.string().min(1).max(160)
16353
+ candidateSourceId: z63.string().min(1).max(160)
16227
16354
  });
16228
- var TaskOrigin = z62.object({
16229
- type: z62.literal("task"),
16355
+ var TaskOrigin = z63.object({
16356
+ type: z63.literal("task"),
16230
16357
  taskId: ProjectId
16231
16358
  });
16232
- var ManualOrigin = z62.object({
16233
- type: z62.literal("manual"),
16359
+ var ManualOrigin = z63.object({
16360
+ type: z63.literal("manual"),
16234
16361
  clientRequestId: ProjectId,
16235
- country: z62.string().min(2).max(3).optional()
16362
+ country: z63.string().min(2).max(3).optional()
16236
16363
  });
16237
- var StartProjectInput = z62.object({
16238
- origin: z62.discriminatedUnion("type", [
16364
+ var StartProjectInput = z63.object({
16365
+ origin: z63.discriminatedUnion("type", [
16239
16366
  ResearchCandidateOrigin,
16240
16367
  TaskOrigin,
16241
16368
  ManualOrigin
16242
16369
  ]),
16243
- productName: z62.string().trim().min(1).max(240).optional(),
16370
+ productName: z63.string().trim().min(1).max(240).optional(),
16244
16371
  productUrl: HttpUrl3.optional(),
16245
- country: z62.string().min(2).max(3).optional(),
16246
- languageCode: z62.string().min(2).max(16).optional()
16372
+ country: z63.string().min(2).max(3).optional(),
16373
+ languageCode: z63.string().min(2).max(16).optional()
16247
16374
  }).strict();
16248
- var CostProjectInput = z62.object({
16375
+ var CostProjectInput = z63.object({
16249
16376
  projectId: ProjectId,
16250
- version: z62.number().int().positive(),
16251
- country: z62.string().trim().min(2).max(3),
16252
- supplierCost: z62.number().finite().positive(),
16253
- shippingCost: z62.number().finite().nonnegative(),
16254
- returnRate: z62.number().finite().min(0).lt(1),
16255
- cancellationRate: z62.number().finite().min(0).lt(1),
16256
- adsManagerCpa: z62.number().finite().nonnegative(),
16257
- desiredMargin: z62.number().finite().min(0).lt(1)
16258
- });
16259
- var GuideInput = z62.object({
16377
+ version: z63.number().int().positive(),
16378
+ country: z63.string().trim().min(2).max(3),
16379
+ supplierCost: z63.number().finite().positive(),
16380
+ shippingCost: z63.number().finite().nonnegative(),
16381
+ returnRate: z63.number().finite().min(0).lt(1),
16382
+ cancellationRate: z63.number().finite().min(0).lt(1),
16383
+ adsManagerCpa: z63.number().finite().nonnegative(),
16384
+ desiredMargin: z63.number().finite().min(0).lt(1)
16385
+ });
16386
+ var GuideInput = z63.object({
16260
16387
  projectId: ProjectId.optional()
16261
16388
  }).strict();
16262
16389
  var NEXT_ACTION_KINDS = [
@@ -16274,29 +16401,29 @@ var NEXT_ACTION_KINDS = [
16274
16401
  "repair_meta_campaign",
16275
16402
  "review_paused_campaign"
16276
16403
  ];
16277
- var DropshippingProjectNextAction = z62.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z62.object({
16278
- kind: z62.literal(kind),
16279
- href: z62.string().min(1)
16404
+ var DropshippingProjectNextAction = z63.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z63.object({
16405
+ kind: z63.literal(kind),
16406
+ href: z63.string().min(1)
16280
16407
  })));
16281
- var CostingInputSchema = z62.object({
16282
- country: z62.string().min(2).max(3),
16283
- supplierCost: z62.number().finite().positive(),
16284
- shippingCost: z62.number().finite().nonnegative(),
16285
- returnRate: z62.number().finite().min(0).lt(1),
16286
- cancellationRate: z62.number().finite().min(0).lt(1),
16287
- adsManagerCpa: z62.number().finite().nonnegative(),
16288
- desiredMargin: z62.number().finite().min(0).lt(1)
16408
+ var CostingInputSchema = z63.object({
16409
+ country: z63.string().min(2).max(3),
16410
+ supplierCost: z63.number().finite().positive(),
16411
+ shippingCost: z63.number().finite().nonnegative(),
16412
+ returnRate: z63.number().finite().min(0).lt(1),
16413
+ cancellationRate: z63.number().finite().min(0).lt(1),
16414
+ adsManagerCpa: z63.number().finite().nonnegative(),
16415
+ desiredMargin: z63.number().finite().min(0).lt(1)
16289
16416
  }).superRefine(({ returnRate, cancellationRate }, context) => {
16290
16417
  if (returnRate + cancellationRate >= 1) context.addIssue({
16291
- code: z62.ZodIssueCode.custom,
16418
+ code: z63.ZodIssueCode.custom,
16292
16419
  path: [
16293
16420
  "cancellationRate"
16294
16421
  ]
16295
16422
  });
16296
16423
  });
16297
- var FiniteCostingNumber = z62.number().finite();
16298
- var CostingResultSchema = z62.object({
16299
- country: z62.string().min(2).max(3),
16424
+ var FiniteCostingNumber = z63.number().finite();
16425
+ var CostingResultSchema = z63.object({
16426
+ country: z63.string().min(2).max(3),
16300
16427
  deliveryRate: FiniteCostingNumber,
16301
16428
  adjustedShippingCost: FiniteCostingNumber,
16302
16429
  adjustedCpa: FiniteCostingNumber,
@@ -16309,44 +16436,44 @@ var CostingResultSchema = z62.object({
16309
16436
  estimatedProfit: FiniteCostingNumber,
16310
16437
  actualMargin: FiniteCostingNumber,
16311
16438
  breakEvenAdsManagerCpa: FiniteCostingNumber,
16312
- wasPriceAutoAdjusted: z62.boolean(),
16313
- profitabilityStatus: z62.literal("healthy")
16314
- });
16315
- var RewardProgressSchema = z62.object({
16316
- campaignKey: z62.literal("dropshipping-launch-v1"),
16317
- totalCredits: z62.number().int().positive(),
16318
- earnedCredits: z62.number().int().nonnegative(),
16319
- milestones: z62.array(z62.object({
16439
+ wasPriceAutoAdjusted: z63.boolean(),
16440
+ profitabilityStatus: z63.literal("healthy")
16441
+ });
16442
+ var RewardProgressSchema = z63.object({
16443
+ campaignKey: z63.literal("dropshipping-launch-v1"),
16444
+ totalCredits: z63.number().int().positive(),
16445
+ earnedCredits: z63.number().int().nonnegative(),
16446
+ milestones: z63.array(z63.object({
16320
16447
  milestone: DropshippingRewardMilestone,
16321
- credits: z62.number().int().positive(),
16322
- available: z62.boolean().optional(),
16323
- earned: z62.boolean(),
16448
+ credits: z63.number().int().positive(),
16449
+ available: z63.boolean().optional(),
16450
+ earned: z63.boolean(),
16324
16451
  grantId: ProjectId.nullable(),
16325
- grantedAt: z62.string().datetime().nullable()
16452
+ grantedAt: z63.string().datetime().nullable()
16326
16453
  })).length(DropshippingRewardMilestone.options.length)
16327
16454
  });
16328
- var ProjectResponseSchema = z62.object({
16455
+ var ProjectResponseSchema = z63.object({
16329
16456
  id: ProjectId,
16330
16457
  taskId: ProjectId.nullable(),
16331
16458
  status: DropshippingProjectStatus,
16332
- originKey: z62.string().min(1),
16459
+ originKey: z63.string().min(1),
16333
16460
  researchRunId: ProjectId.nullable(),
16334
- candidateSourceId: z62.string().nullable(),
16335
- productName: z62.string().nullable(),
16461
+ candidateSourceId: z63.string().nullable(),
16462
+ productName: z63.string().nullable(),
16336
16463
  productUrl: HttpUrl3.nullable(),
16337
16464
  referenceImageUrl: HttpUrl3.nullable(),
16338
- targetCountry: z62.string().nullable(),
16339
- languageCode: z62.string().nullable(),
16340
- hasReferenceImage: z62.boolean(),
16465
+ targetCountry: z63.string().nullable(),
16466
+ languageCode: z63.string().nullable(),
16467
+ hasReferenceImage: z63.boolean(),
16341
16468
  costingInput: CostingInputSchema.nullable(),
16342
16469
  costingResult: CostingResultSchema.nullable(),
16343
- costingVersion: z62.number().int().positive().nullable(),
16344
- version: z62.number().int().positive(),
16470
+ costingVersion: z63.number().int().positive().nullable(),
16471
+ version: z63.number().int().positive(),
16345
16472
  phase: DropshippingProjectPhase,
16346
16473
  nextAction: DropshippingProjectNextAction.nullable(),
16347
16474
  rewards: RewardProgressSchema,
16348
- createdAt: z62.string().datetime(),
16349
- updatedAt: z62.string().datetime()
16475
+ createdAt: z63.string().datetime(),
16476
+ updatedAt: z63.string().datetime()
16350
16477
  }).passthrough();
16351
16478
  var NEXT_ACTION_GUIDANCE = {
16352
16479
  cost_product: "Llama `cost_dropshipping_project` con el costo real del proveedor. Nunca lo inventes: p\xEDdeselo al usuario.",