@productmaker/mcp 3.4.0 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/http.js +955 -880
  2. package/dist/stdio.js +943 -868
  3. package/package.json +1 -1
package/dist/http.js CHANGED
@@ -5578,6 +5578,10 @@ var TikTokCreateCampaignResponseSchema = z35.object({
5578
5578
  adsManagerUrl: z35.string().optional()
5579
5579
  });
5580
5580
 
5581
+ // ../../packages/types/src/pricing-gemini-omni.ts
5582
+ var GEMINI_OMNI_FLAT_OUR_COST_CENTS = 84;
5583
+ var GEMINI_OMNI_FLAT_USER_PRICE_CENTS = 168;
5584
+
5581
5585
  // ../../packages/types/src/pricing.ts
5582
5586
  var CREDITS_PER_USD_CENT = 10;
5583
5587
  var CREDITS_PER_DOLLAR = 100 * CREDITS_PER_USD_CENT;
@@ -5986,6 +5990,18 @@ var DEFAULT_PRICING = {
5986
5990
  ourCostCents: 120,
5987
5991
  userPriceCents: 240
5988
5992
  },
5993
+ // Gemini Omni Video (gemini-omni-video) — Mix primary generator since
5994
+ // 2026-08-18. FLAT per generation: 168 KIE credits = $0.84, identical at
5995
+ // 720p and 1080p and independent of the 3.5-10s trim window. Do NOT add
5996
+ // per-second overrides for this key — resolveSuccessBilling bills it flat.
5997
+ //
5998
+ // Shares the constants with the pre-submit ESTIMATOR (mix-cost.ts) rather
5999
+ // than repeating the numbers: a literal here that drifted from the estimator
6000
+ // would quote one price and charge another on every mix.
6001
+ "kie:gemini-omni-video": {
6002
+ ourCostCents: GEMINI_OMNI_FLAT_OUR_COST_CENTS,
6003
+ userPriceCents: GEMINI_OMNI_FLAT_USER_PRICE_CENTS
6004
+ },
5989
6005
  "kie:video-lipsync-generation": {
5990
6006
  ourCostCents: 45,
5991
6007
  userPriceCents: 90
@@ -7949,7 +7965,57 @@ var FeatureSpec = z36.object({
7949
7965
  });
7950
7966
 
7951
7967
  // ../../packages/types/src/mix.ts
7968
+ import { z as z38 } from "zod";
7969
+
7970
+ // ../../packages/types/src/mix-degradation.ts
7952
7971
  import { z as z37 } from "zod";
7972
+ var MIX_DEGRADATION_REASONS = [
7973
+ /**
7974
+ * At least one scene the mix PLANNED is missing from the delivered video, so
7975
+ * the result is shorter than the source. Set at assemble time by comparing
7976
+ * the concat set against the planned scene set — the scene's own code (if it
7977
+ * had one) never reaches the mix-level rollup, which only sees scenes that
7978
+ * SUCCEEDED, and that is exactly how a live 17.00s-of-20.00s delivery
7979
+ * shipped with degradedReason NULL and no banner at all.
7980
+ *
7981
+ * ORDERING: FIRST, above every refusal code. A short delivery must never be
7982
+ * MASKED. It used to sit below the three content refusals on the theory that
7983
+ * a refusal names something the user can change AND explains the missing
7984
+ * scene — but it does neither reliably: in a 3-scene mix where scene 1 fails
7985
+ * outright and scene 2 ships through Wan after a reference refusal, the
7986
+ * refusal copy reads "we used a lower-quality alternative", a claim about
7987
+ * QUALITY that says nothing about the video being shorter than what was paid
7988
+ * for, and that is actively wrong about the dropped scene (for which we used
7989
+ * nothing). Every other code in this list describes a scene that DID ship.
7990
+ */
7991
+ "scenes_dropped",
7992
+ /** Google's safety filter rejected the user's reference photo. Deterministic. */
7993
+ "reference_rejected",
7994
+ /** Google refused the wording of the change description. */
7995
+ "prompt_rejected",
7996
+ /**
7997
+ * The provider refused the content but its message names neither the
7998
+ * reference nor the wording, so we cannot say which. Distinct from
7999
+ * 'provider_unavailable' on purpose: "unavailable" invites the user to retry
8000
+ * unchanged, which can never succeed against a content refusal and only
8001
+ * burns their credits. This code tells them something must change.
8002
+ */
8003
+ "content_rejected",
8004
+ /**
8005
+ * The scene's length fell outside Gemini's usable 3.5s-10s trim window —
8006
+ * EITHER bound. Deliberately ONE code for both: the user controls neither
8007
+ * (scene segmentation is entirely ours), so "too short" and "too long" are
8008
+ * not differently actionable, and one honest explanation beats two that
8009
+ * both amount to "our segmentation produced a length the primary generator
8010
+ * cannot take".
8011
+ */
8012
+ "scene_length_unsupported",
8013
+ /** Transient provider failures exhausted the budget. */
8014
+ "provider_unavailable"
8015
+ ];
8016
+ var MixDegradationReasonSchema = z37.enum(MIX_DEGRADATION_REASONS);
8017
+
8018
+ // ../../packages/types/src/mix.ts
7953
8019
  var MEDIA_TYPES = [
7954
8020
  "video",
7955
8021
  "image"
@@ -7987,38 +8053,38 @@ function isPublicHttpsUrl(raw) {
7987
8053
  return true;
7988
8054
  }
7989
8055
  __name(isPublicHttpsUrl, "isPublicHttpsUrl");
7990
- var PublicHttpsUrl = z37.string().url().refine(isPublicHttpsUrl, {
8056
+ var PublicHttpsUrl = z38.string().url().refine(isPublicHttpsUrl, {
7991
8057
  message: "must be a public HTTPS URL"
7992
8058
  });
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([
8059
+ var InternalAssetPath = z38.string().regex(/^\/(?:api|v1)\/assets\/[A-Za-z0-9._~%/-]+$/, "must be a public HTTPS URL or an internal asset path");
8060
+ var MixImageUrl = z38.union([
7995
8061
  PublicHttpsUrl,
7996
8062
  InternalAssetPath
7997
8063
  ]);
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([
8064
+ var MixAxes = z38.object({
8065
+ product: z38.boolean(),
8066
+ person: z38.boolean(),
8067
+ setting: z38.boolean()
8068
+ });
8069
+ var MixReferences = z38.object({
8070
+ product: z38.array(PublicHttpsUrl).max(3, "at most 3 product references"),
8071
+ person: z38.array(PublicHttpsUrl).max(3, "at most 3 person references"),
8072
+ setting: z38.array(PublicHttpsUrl).max(3, "at most 3 setting references")
8073
+ });
8074
+ var MixImageEdit = z38.object({
8075
+ instruction: z38.string().min(1).max(600),
8076
+ imageUrls: z38.array(MixImageUrl).min(1).max(3)
8077
+ });
8078
+ var MixRequest = z38.object({
8079
+ mediaType: z38.enum(MEDIA_TYPES),
8080
+ originalUrl: z38.union([
8015
8081
  PublicHttpsUrl,
8016
8082
  InternalAssetPath
8017
8083
  ]),
8018
8084
  axes: MixAxes,
8019
8085
  references: MixReferences,
8020
- personText: z37.string().max(500).optional(),
8021
- settingText: z37.string().max(500).optional(),
8086
+ personText: z38.string().max(500).optional(),
8087
+ settingText: z38.string().max(500).optional(),
8022
8088
  /**
8023
8089
  * Optional public URL of a user-uploaded audio file (mp3/wav). Wan Video
8024
8090
  * Edit has no audio input and the mix never lipsyncs: the Wan output is
@@ -8027,11 +8093,11 @@ var MixRequest = z37.object({
8027
8093
  * (mute + overlay). No per-scene slicing, no `reference_audio_urls`.
8028
8094
  */
8029
8095
  audioUrl: PublicHttpsUrl.optional(),
8030
- resolution: z37.enum(RESOLUTIONS).default("720p"),
8031
- originalDurationSec: z37.number().positive().max(600).optional(),
8096
+ resolution: z38.enum(RESOLUTIONS).default("720p"),
8097
+ originalDurationSec: z38.number().positive().max(600).optional(),
8032
8098
  image: MixImageEdit.optional(),
8033
- sourceTaskId: z37.string().max(64).optional(),
8034
- sourceCreativeId: z37.string().max(64).optional()
8099
+ sourceTaskId: z38.string().max(64).optional(),
8100
+ sourceCreativeId: z38.string().max(64).optional()
8035
8101
  }).superRefine((req, ctx) => {
8036
8102
  if (req.mediaType === "image") {
8037
8103
  if (!req.image) {
@@ -8065,18 +8131,18 @@ var MixRequest = z37.object({
8065
8131
  });
8066
8132
  }
8067
8133
  });
8068
- var ReferenceMap = z37.object({
8069
- product: z37.object({
8070
- start: z37.number().int(),
8071
- end: z37.number().int()
8134
+ var ReferenceMap = z38.object({
8135
+ product: z38.object({
8136
+ start: z38.number().int(),
8137
+ end: z38.number().int()
8072
8138
  }).optional(),
8073
- person: z37.object({
8074
- start: z37.number().int(),
8075
- end: z37.number().int()
8139
+ person: z38.object({
8140
+ start: z38.number().int(),
8141
+ end: z38.number().int()
8076
8142
  }).optional(),
8077
- setting: z37.object({
8078
- start: z37.number().int(),
8079
- end: z37.number().int()
8143
+ setting: z38.object({
8144
+ start: z38.number().int(),
8145
+ end: z38.number().int()
8080
8146
  }).optional()
8081
8147
  });
8082
8148
  var SCENE_CLIP_TYPES = [
@@ -8092,39 +8158,39 @@ var INSTANCE_CARDINALITIES = [
8092
8158
  "multiple_same",
8093
8159
  "multiple_distinct"
8094
8160
  ];
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),
8161
+ var SceneSegment = z38.object({
8162
+ index: z38.number().int().positive(),
8163
+ startTs: z38.number().nonnegative(),
8164
+ endTs: z38.number().positive(),
8165
+ seedanceDuration: z38.number().int().min(4).max(15),
8100
8166
  // Pass 1 / Pass 2 outputs (all optional — populated when the rich analyzer
8101
8167
  // 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(),
8168
+ action: z38.string().optional(),
8169
+ motion: z38.string().optional(),
8170
+ clipType: z38.enum(SCENE_CLIP_TYPES).optional(),
8171
+ hasCharacter: z38.boolean().optional(),
8172
+ faceVisible: z38.boolean().optional(),
8107
8173
  // 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(),
8174
+ startState: z38.string().optional(),
8175
+ endState: z38.string().optional(),
8176
+ cameraMovement: z38.string().optional(),
8177
+ emotion: z38.string().optional(),
8178
+ productPlacement: z38.string().optional(),
8179
+ productInteraction: z38.string().optional(),
8180
+ settingDescription: z38.string().optional(),
8181
+ dialogue: z38.string().optional(),
8116
8182
  // 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(),
8183
+ mainPersonDescription: z38.string().optional(),
8184
+ mainProductDescription: z38.string().optional(),
8185
+ personInstances: z38.enum(INSTANCE_CARDINALITIES).optional(),
8186
+ productInstances: z38.enum(INSTANCE_CARDINALITIES).optional(),
8121
8187
  /**
8122
8188
  * Seconds of prev-clipType content absorbed at the start of this scene by
8123
8189
  * Pass 2.7's clipType boundary margin. When > 0 and the scene is a
8124
8190
  * pass-through (no Seedance), the concatenator prepends a held-still
8125
8191
  * preamble (nano-banana-swapped first frame) to hide the leak.
8126
8192
  */
8127
- absorbedMarginSec: z37.number().nonnegative().optional(),
8193
+ absorbedMarginSec: z38.number().nonnegative().optional(),
8128
8194
  /**
8129
8195
  * True when the scene shows post-production graphics baked into the frame:
8130
8196
  * caption/subtitle text, infographic overlay cards, or inset
@@ -8133,33 +8199,39 @@ var SceneSegment = z37.object({
8133
8199
  * (mentioning nonexistent overlays gives the generator license to
8134
8200
  * fabricate them).
8135
8201
  */
8136
- hasOverlayGraphics: z37.boolean().optional()
8202
+ hasOverlayGraphics: z38.boolean().optional()
8137
8203
  });
8138
- var MixSceneResult = z37.object({
8139
- index: z37.number().int().positive(),
8140
- status: z37.enum([
8204
+ var MixSceneResult = z38.object({
8205
+ index: z38.number().int().positive(),
8206
+ status: z38.enum([
8141
8207
  "queued",
8142
8208
  "submitted",
8143
8209
  "done",
8144
8210
  "failed"
8145
8211
  ]),
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([
8212
+ seedanceTaskId: z38.string().optional(),
8213
+ videoUrl: z38.string().url().optional(),
8214
+ error: z38.string().optional(),
8215
+ degradedReason: MixDegradationReasonSchema.optional()
8216
+ });
8217
+ var MixResult = z38.object({
8218
+ mixTaskId: z38.string().uuid(),
8219
+ status: z38.enum([
8153
8220
  "queued",
8154
8221
  "processing",
8155
8222
  "done",
8156
8223
  "error"
8157
8224
  ]),
8158
- resultUrl: z37.string().url().optional(),
8159
- scenes: z37.array(MixSceneResult).default([]),
8160
- failReason: z37.string().optional()
8225
+ resultUrl: z38.string().url().optional(),
8226
+ scenes: z38.array(MixSceneResult).default([]),
8227
+ failReason: z38.string().optional(),
8228
+ degradedReason: MixDegradationReasonSchema.optional()
8161
8229
  });
8162
8230
 
8231
+ // ../../packages/types/src/mix-cost.ts
8232
+ var MAX_QA_RETRIES_PER_SCENE_UPPER_BOUND = 1;
8233
+ var MAX_BILLABLE_GENERATIONS_PER_BLOCK = 1 + MAX_QA_RETRIES_PER_SCENE_UPPER_BOUND;
8234
+
8163
8235
  // ../../packages/types/src/product-delivery-format.ts
8164
8236
  var DELIVERY_FAMILIES = [
8165
8237
  "solid_dose",
@@ -8248,41 +8320,41 @@ var DECLARATION = DELIVERY_FAMILIES.map((family) => [
8248
8320
  ]);
8249
8321
 
8250
8322
  // ../../packages/types/src/task-type.ts
8251
- import { z as z38 } from "zod";
8252
- var TaskTypeSchema = z38.enum([
8323
+ import { z as z39 } from "zod";
8324
+ var TaskTypeSchema = z39.enum([
8253
8325
  "product",
8254
8326
  "service"
8255
8327
  ]);
8256
8328
 
8257
8329
  // ../../packages/types/src/landing-regeneration.ts
8258
- import { z as z39 } from "zod";
8259
- var LandingRegenerationStatus = z39.enum([
8330
+ import { z as z40 } from "zod";
8331
+ var LandingRegenerationStatus = z40.enum([
8260
8332
  "queued",
8261
8333
  "processing",
8262
8334
  "published",
8263
8335
  "failed"
8264
8336
  ]);
8265
- var RegenerateLandingRoleResponse = z39.object({
8266
- ok: z39.literal(true),
8337
+ var RegenerateLandingRoleResponse = z40.object({
8338
+ ok: z40.literal(true),
8267
8339
  role: LandingRole,
8268
- promptIndex: z39.number().int().nonnegative(),
8269
- operationId: z39.string().min(1)
8340
+ promptIndex: z40.number().int().nonnegative(),
8341
+ operationId: z40.string().min(1)
8270
8342
  });
8271
- var LandingRegenerationStatusResponse = z39.object({
8272
- ok: z39.literal(true),
8273
- operationId: z39.string().min(1),
8343
+ var LandingRegenerationStatusResponse = z40.object({
8344
+ ok: z40.literal(true),
8345
+ operationId: z40.string().min(1),
8274
8346
  role: LandingRole,
8275
8347
  status: LandingRegenerationStatus,
8276
- refunded: z39.boolean(),
8277
- failureReason: z39.string().nullable(),
8278
- publishedAssetKey: z39.string().nullable(),
8279
- updatedAt: z39.string().datetime()
8348
+ refunded: z40.boolean(),
8349
+ failureReason: z40.string().nullable(),
8350
+ publishedAssetKey: z40.string().nullable(),
8351
+ updatedAt: z40.string().datetime()
8280
8352
  });
8281
8353
 
8282
8354
  // ../../packages/types/src/video-edit.ts
8283
- import { z as z40 } from "zod";
8355
+ import { z as z41 } from "zod";
8284
8356
  var MAX_SEGMENT_SECONDS = 3;
8285
- var VideoEditStatusSchema = z40.enum([
8357
+ var VideoEditStatusSchema = z41.enum([
8286
8358
  "pending",
8287
8359
  "processing",
8288
8360
  "assembling",
@@ -8291,9 +8363,9 @@ var VideoEditStatusSchema = z40.enum([
8291
8363
  "discarded",
8292
8364
  "failed"
8293
8365
  ]);
8294
- var VideoEditTimeSectionSchema = z40.object({
8295
- startSec: z40.number().min(0),
8296
- endSec: z40.number().positive()
8366
+ var VideoEditTimeSectionSchema = z41.object({
8367
+ startSec: z41.number().min(0),
8368
+ endSec: z41.number().positive()
8297
8369
  }).refine((v) => v.endSec > v.startSec, {
8298
8370
  message: "endSec must be after startSec",
8299
8371
  path: [
@@ -8305,45 +8377,45 @@ var VideoEditTimeSectionSchema = z40.object({
8305
8377
  "endSec"
8306
8378
  ]
8307
8379
  });
8308
- var VideoEditRequestSchema = z40.object({
8309
- comment: z40.string().trim().min(1).max(2e3),
8310
- sections: z40.array(VideoEditTimeSectionSchema).min(1).optional()
8380
+ var VideoEditRequestSchema = z41.object({
8381
+ comment: z41.string().trim().min(1).max(2e3),
8382
+ sections: z41.array(VideoEditTimeSectionSchema).min(1).optional()
8311
8383
  });
8312
- var VideoEditModeSchema = z40.enum([
8384
+ var VideoEditModeSchema = z41.enum([
8313
8385
  "wan_edit",
8314
8386
  "regenerate"
8315
8387
  ]);
8316
- var VideoRegenerationEngineSchema = z40.enum([
8388
+ var VideoRegenerationEngineSchema = z41.enum([
8317
8389
  "free_text",
8318
8390
  "free_image",
8319
8391
  "single_call",
8320
8392
  "multi_shot"
8321
8393
  ]);
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)
8394
+ var VideoRegenerationRouteFingerprintSchema = z41.string().trim().min(1).max(128);
8395
+ var RegenerateEditRequestSchema = z41.object({
8396
+ angleKey: z41.string().min(1),
8397
+ comment: z41.string().min(1).max(2e3)
8326
8398
  });
8327
8399
 
8328
8400
  // ../../packages/types/src/uploaded-asset.ts
8329
- import { z as z41 } from "zod";
8330
- var UploadedAssetMediaKind = z41.enum([
8401
+ import { z as z42 } from "zod";
8402
+ var UploadedAssetMediaKind = z42.enum([
8331
8403
  "image",
8332
8404
  "video"
8333
8405
  ]);
8334
- var UploadedAssetSessionMediaKind = z41.enum([
8406
+ var UploadedAssetSessionMediaKind = z42.enum([
8335
8407
  "image",
8336
8408
  "video",
8337
8409
  "mixed"
8338
8410
  ]);
8339
- var UploadedAssetRole = z41.enum([
8411
+ var UploadedAssetRole = z42.enum([
8340
8412
  "media",
8341
8413
  "thumbnail"
8342
8414
  ]);
8343
8415
  var UPLOADED_ASSET_MAX_FILES = 10;
8344
8416
  var UPLOADED_ASSET_IMAGE_MAX_FILES = 5;
8345
- var UploadedAssetId = z41.string().uuid();
8346
- var HttpsUrl = z41.string().url().refine((value) => {
8417
+ var UploadedAssetId = z42.string().uuid();
8418
+ var HttpsUrl = z42.string().url().refine((value) => {
8347
8419
  try {
8348
8420
  const url = new URL(value);
8349
8421
  return url.protocol === "https:" && !url.username && !url.password;
@@ -8351,23 +8423,23 @@ var HttpsUrl = z41.string().url().refine((value) => {
8351
8423
  return false;
8352
8424
  }
8353
8425
  }, "URL must use https");
8354
- var UtcDateTime = z41.string().datetime().refine((value) => {
8426
+ var UtcDateTime = z42.string().datetime().refine((value) => {
8355
8427
  const parts = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?Z$/.exec(value);
8356
8428
  const timestamp = Date.parse(value);
8357
8429
  if (!parts || Number.isNaN(timestamp)) return false;
8358
8430
  const date = new Date(timestamp);
8359
8431
  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
8432
  }, "datetime must be a valid UTC calendar instant");
8361
- var UploadedAssetRef = z41.object({
8433
+ var UploadedAssetRef = z42.object({
8362
8434
  assetId: UploadedAssetId
8363
8435
  }).strict();
8364
8436
  var UploadedAssetCompletion = UploadedAssetRef.extend({
8365
8437
  mediaKind: UploadedAssetMediaKind,
8366
8438
  assetRole: UploadedAssetRole
8367
8439
  }).strict();
8368
- var UploadedAssetMetadata = z41.object({
8440
+ var UploadedAssetMetadata = z42.object({
8369
8441
  assetId: UploadedAssetId,
8370
- ownerId: z41.string().min(1),
8442
+ ownerId: z42.string().min(1),
8371
8443
  mediaKind: UploadedAssetMediaKind,
8372
8444
  assetRole: UploadedAssetRole,
8373
8445
  createdAt: UtcDateTime,
@@ -8375,7 +8447,7 @@ var UploadedAssetMetadata = z41.object({
8375
8447
  }).strict().superRefine((value, ctx) => {
8376
8448
  if (Date.parse(value.expiresAt) <= Date.parse(value.createdAt)) {
8377
8449
  ctx.addIssue({
8378
- code: z41.ZodIssueCode.custom,
8450
+ code: z42.ZodIssueCode.custom,
8379
8451
  path: [
8380
8452
  "expiresAt"
8381
8453
  ],
@@ -8383,27 +8455,27 @@ var UploadedAssetMetadata = z41.object({
8383
8455
  });
8384
8456
  }
8385
8457
  });
8386
- var MediaSourceRef = z41.object({
8458
+ var MediaSourceRef = z42.object({
8387
8459
  url: HttpsUrl.optional(),
8388
- path: z41.string().min(1).optional(),
8460
+ path: z42.string().min(1).optional(),
8389
8461
  assetId: UploadedAssetId.optional()
8390
8462
  }).strict().superRefine((value, ctx) => {
8391
8463
  const sourceCount = Number(value.url !== void 0) + Number(value.path !== void 0) + Number(value.assetId !== void 0);
8392
8464
  if (sourceCount !== 1) {
8393
8465
  ctx.addIssue({
8394
- code: z41.ZodIssueCode.custom,
8466
+ code: z42.ZodIssueCode.custom,
8395
8467
  message: "media source needs exactly one of url, path, or assetId"
8396
8468
  });
8397
8469
  }
8398
8470
  });
8399
- var UploadedAssetSessionRequest = z41.object({
8471
+ var UploadedAssetSessionRequest = z42.object({
8400
8472
  mediaKind: UploadedAssetSessionMediaKind,
8401
8473
  assetRole: UploadedAssetRole.default("media"),
8402
- maxFiles: z41.number().int().min(1).max(UPLOADED_ASSET_MAX_FILES).optional()
8474
+ maxFiles: z42.number().int().min(1).max(UPLOADED_ASSET_MAX_FILES).optional()
8403
8475
  }).strict().superRefine((value, ctx) => {
8404
8476
  if (value.mediaKind === "mixed" && value.assetRole === "thumbnail") {
8405
8477
  ctx.addIssue({
8406
- code: z41.ZodIssueCode.custom,
8478
+ code: z42.ZodIssueCode.custom,
8407
8479
  path: [
8408
8480
  "mediaKind"
8409
8481
  ],
@@ -8412,7 +8484,7 @@ var UploadedAssetSessionRequest = z41.object({
8412
8484
  }
8413
8485
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
8414
8486
  ctx.addIssue({
8415
- code: z41.ZodIssueCode.custom,
8487
+ code: z42.ZodIssueCode.custom,
8416
8488
  path: [
8417
8489
  "maxFiles"
8418
8490
  ],
@@ -8421,7 +8493,7 @@ var UploadedAssetSessionRequest = z41.object({
8421
8493
  }
8422
8494
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > UPLOADED_ASSET_IMAGE_MAX_FILES) {
8423
8495
  ctx.addIssue({
8424
- code: z41.ZodIssueCode.custom,
8496
+ code: z42.ZodIssueCode.custom,
8425
8497
  path: [
8426
8498
  "maxFiles"
8427
8499
  ],
@@ -8430,7 +8502,7 @@ var UploadedAssetSessionRequest = z41.object({
8430
8502
  }
8431
8503
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
8432
8504
  ctx.addIssue({
8433
- code: z41.ZodIssueCode.custom,
8505
+ code: z42.ZodIssueCode.custom,
8434
8506
  path: [
8435
8507
  "mediaKind"
8436
8508
  ],
@@ -8438,32 +8510,32 @@ var UploadedAssetSessionRequest = z41.object({
8438
8510
  });
8439
8511
  }
8440
8512
  });
8441
- var UploadedAssetSessionStatus = z41.discriminatedUnion("status", [
8442
- z41.object({
8443
- status: z41.literal("pending"),
8444
- assets: z41.array(UploadedAssetCompletion).length(0)
8513
+ var UploadedAssetSessionStatus = z42.discriminatedUnion("status", [
8514
+ z42.object({
8515
+ status: z42.literal("pending"),
8516
+ assets: z42.array(UploadedAssetCompletion).length(0)
8445
8517
  }).strict(),
8446
- z41.object({
8447
- status: z41.literal("uploaded"),
8448
- assets: z41.array(UploadedAssetCompletion).min(1).max(UPLOADED_ASSET_MAX_FILES)
8518
+ z42.object({
8519
+ status: z42.literal("uploaded"),
8520
+ assets: z42.array(UploadedAssetCompletion).min(1).max(UPLOADED_ASSET_MAX_FILES)
8449
8521
  }).strict()
8450
8522
  ]);
8451
- var UploadedAssetAdoptionRequest = z41.object({
8523
+ var UploadedAssetAdoptionRequest = z42.object({
8452
8524
  assetId: UploadedAssetId,
8453
- ownerId: z41.string().min(1),
8454
- consumer: z41.string().min(1).max(100),
8455
- idempotencyKey: z41.string().min(1).max(255)
8525
+ ownerId: z42.string().min(1),
8526
+ consumer: z42.string().min(1).max(100),
8527
+ idempotencyKey: z42.string().min(1).max(255)
8456
8528
  }).strict();
8457
8529
 
8458
8530
  // ../../packages/types/src/dropshipping-project.ts
8459
- import { z as z42 } from "zod";
8460
- var DropshippingProjectStatusSchema = z42.enum([
8531
+ import { z as z43 } from "zod";
8532
+ var DropshippingProjectStatusSchema = z43.enum([
8461
8533
  "active",
8462
8534
  "completed",
8463
8535
  "archived"
8464
8536
  ]);
8465
8537
  var DROPSHIPPING_LAUNCH_REWARD_CAMPAIGN = "dropshipping-launch-v1";
8466
- var DropshippingRewardMilestoneSchema = z42.enum([
8538
+ var DropshippingRewardMilestoneSchema = z43.enum([
8467
8539
  "product_selected",
8468
8540
  "costing_saved",
8469
8541
  "product_media_ready",
@@ -8478,21 +8550,21 @@ var DROPSHIPPING_LAUNCH_REWARD_CREDITS = {
8478
8550
  campaign_created: 200
8479
8551
  };
8480
8552
  var DROPSHIPPING_LAUNCH_REWARD_TOTAL_CREDITS = Object.values(DROPSHIPPING_LAUNCH_REWARD_CREDITS).reduce((sum, credits) => sum + credits, 0);
8481
- var DropshippingProjectRewardMilestoneStateSchema = z42.object({
8553
+ var DropshippingProjectRewardMilestoneStateSchema = z43.object({
8482
8554
  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([
8555
+ credits: z43.number().int().positive(),
8556
+ available: z43.boolean().optional(),
8557
+ earned: z43.boolean(),
8558
+ grantId: z43.string().uuid().nullable(),
8559
+ grantedAt: z43.string().datetime().nullable()
8560
+ });
8561
+ var DropshippingProjectRewardProgressSchema = z43.object({
8562
+ campaignKey: z43.literal(DROPSHIPPING_LAUNCH_REWARD_CAMPAIGN),
8563
+ totalCredits: z43.number().int().positive(),
8564
+ earnedCredits: z43.number().int().nonnegative(),
8565
+ milestones: z43.array(DropshippingProjectRewardMilestoneStateSchema).length(DropshippingRewardMilestoneSchema.options.length)
8566
+ });
8567
+ var DropshippingProjectPhaseSchema = z43.enum([
8496
8568
  "research",
8497
8569
  "costing",
8498
8570
  "media",
@@ -8501,18 +8573,18 @@ var DropshippingProjectPhaseSchema = z42.enum([
8501
8573
  "advertising",
8502
8574
  "complete"
8503
8575
  ]);
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)
8576
+ var DropshippingProjectCostingInputSchema = z43.object({
8577
+ country: z43.string().min(2).max(3),
8578
+ supplierCost: z43.number().finite().positive(),
8579
+ shippingCost: z43.number().finite().nonnegative(),
8580
+ returnRate: z43.number().finite().min(0).lt(1),
8581
+ cancellationRate: z43.number().finite().min(0).lt(1),
8582
+ adsManagerCpa: z43.number().finite().nonnegative(),
8583
+ desiredMargin: z43.number().finite().min(0).lt(1)
8512
8584
  }).superRefine(({ returnRate, cancellationRate }, context) => {
8513
8585
  if (returnRate + cancellationRate >= 1) {
8514
8586
  context.addIssue({
8515
- code: z42.ZodIssueCode.custom,
8587
+ code: z43.ZodIssueCode.custom,
8516
8588
  path: [
8517
8589
  "cancellationRate"
8518
8590
  ],
@@ -8520,24 +8592,24 @@ var DropshippingProjectCostingInputSchema = z42.object({
8520
8592
  });
8521
8593
  }
8522
8594
  });
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) => {
8595
+ var DropshippingProjectCostingResultSchema = z43.object({
8596
+ country: z43.string().min(2).max(3),
8597
+ deliveryRate: z43.number().finite(),
8598
+ adjustedShippingCost: z43.number().finite(),
8599
+ adjustedCpa: z43.number().finite(),
8600
+ totalCost: z43.number().finite(),
8601
+ suggestedPrice: z43.number().finite(),
8602
+ baseCommercialPrice: z43.number().finite(),
8603
+ minimumSafePrice: z43.number().finite(),
8604
+ commercialPrice: z43.number().finite(),
8605
+ comparisonPrice: z43.number().finite(),
8606
+ estimatedProfit: z43.number().finite(),
8607
+ actualMargin: z43.number().finite(),
8608
+ breakEvenAdsManagerCpa: z43.number().finite(),
8609
+ wasPriceAutoAdjusted: z43.boolean(),
8610
+ profitabilityStatus: z43.literal("healthy")
8611
+ });
8612
+ var HttpUrlSchema = z43.string().url().max(2e3).refine((value) => {
8541
8613
  try {
8542
8614
  return [
8543
8615
  "http:",
@@ -8547,124 +8619,124 @@ var HttpUrlSchema = z42.string().url().max(2e3).refine((value) => {
8547
8619
  return false;
8548
8620
  }
8549
8621
  }, "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", [
8622
+ var ResearchCandidateOriginSchema = z43.object({
8623
+ type: z43.literal("research_candidate"),
8624
+ runId: z43.string().uuid(),
8625
+ candidateSourceId: z43.string().min(1).max(160)
8626
+ });
8627
+ var TaskOriginSchema = z43.object({
8628
+ type: z43.literal("task"),
8629
+ taskId: z43.string().uuid()
8630
+ });
8631
+ var ManualOriginSchema = z43.object({
8632
+ type: z43.literal("manual"),
8633
+ clientRequestId: z43.string().uuid(),
8634
+ country: z43.string().min(2).max(3).optional()
8635
+ });
8636
+ var CreateDropshippingProjectRequestSchema = z43.object({
8637
+ origin: z43.discriminatedUnion("type", [
8566
8638
  ResearchCandidateOriginSchema,
8567
8639
  TaskOriginSchema,
8568
8640
  ManualOriginSchema
8569
8641
  ]),
8570
- productName: z42.string().trim().min(1).max(240).optional(),
8642
+ productName: z43.string().trim().min(1).max(240).optional(),
8571
8643
  productUrl: HttpUrlSchema.optional(),
8572
- country: z42.string().min(2).max(3).optional(),
8573
- languageCode: z42.string().min(2).max(16).optional()
8644
+ country: z43.string().min(2).max(3).optional(),
8645
+ languageCode: z43.string().min(2).max(16).optional()
8574
8646
  }).strict();
8575
- var SaveDropshippingProjectCostingRequestSchema = z42.object({
8647
+ var SaveDropshippingProjectCostingRequestSchema = z43.object({
8576
8648
  input: DropshippingProjectCostingInputSchema,
8577
- version: z42.number().int().positive()
8649
+ version: z43.number().int().positive()
8578
8650
  }).strict();
8579
- var DropshippingProjectNextActionSchema = z42.discriminatedUnion("kind", [
8580
- z42.object({
8581
- kind: z42.literal("cost_product"),
8582
- href: z42.string().min(1)
8651
+ var DropshippingProjectNextActionSchema = z43.discriminatedUnion("kind", [
8652
+ z43.object({
8653
+ kind: z43.literal("cost_product"),
8654
+ href: z43.string().min(1)
8583
8655
  }),
8584
- z42.object({
8585
- kind: z42.literal("provide_product_media"),
8586
- href: z42.string().min(1)
8656
+ z43.object({
8657
+ kind: z43.literal("provide_product_media"),
8658
+ href: z43.string().min(1)
8587
8659
  }),
8588
- z42.object({
8589
- kind: z42.literal("generate_creatives"),
8590
- href: z42.string().min(1)
8660
+ z43.object({
8661
+ kind: z43.literal("generate_creatives"),
8662
+ href: z43.string().min(1)
8591
8663
  }),
8592
- z42.object({
8593
- kind: z42.literal("wait_for_creatives"),
8594
- href: z42.string().min(1)
8664
+ z43.object({
8665
+ kind: z43.literal("wait_for_creatives"),
8666
+ href: z43.string().min(1)
8595
8667
  }),
8596
- z42.object({
8597
- kind: z42.literal("repair_creatives"),
8598
- href: z42.string().min(1)
8668
+ z43.object({
8669
+ kind: z43.literal("repair_creatives"),
8670
+ href: z43.string().min(1)
8599
8671
  }),
8600
- z42.object({
8601
- kind: z42.literal("complete_creative_set"),
8602
- href: z42.string().min(1)
8672
+ z43.object({
8673
+ kind: z43.literal("complete_creative_set"),
8674
+ href: z43.string().min(1)
8603
8675
  }),
8604
- z42.object({
8605
- kind: z42.literal("connect_shopify"),
8606
- href: z42.string().min(1)
8676
+ z43.object({
8677
+ kind: z43.literal("connect_shopify"),
8678
+ href: z43.string().min(1)
8607
8679
  }),
8608
- z42.object({
8609
- kind: z42.literal("publish_storefront"),
8610
- href: z42.string().min(1)
8680
+ z43.object({
8681
+ kind: z43.literal("publish_storefront"),
8682
+ href: z43.string().min(1)
8611
8683
  }),
8612
- z42.object({
8613
- kind: z42.literal("wait_for_storefront"),
8614
- href: z42.string().min(1)
8684
+ z43.object({
8685
+ kind: z43.literal("wait_for_storefront"),
8686
+ href: z43.string().min(1)
8615
8687
  }),
8616
- z42.object({
8617
- kind: z42.literal("connect_meta"),
8618
- href: z42.string().min(1)
8688
+ z43.object({
8689
+ kind: z43.literal("connect_meta"),
8690
+ href: z43.string().min(1)
8619
8691
  }),
8620
- z42.object({
8621
- kind: z42.literal("create_meta_campaign"),
8622
- href: z42.string().min(1)
8692
+ z43.object({
8693
+ kind: z43.literal("create_meta_campaign"),
8694
+ href: z43.string().min(1)
8623
8695
  }),
8624
- z42.object({
8625
- kind: z42.literal("repair_meta_campaign"),
8626
- href: z42.string().min(1)
8696
+ z43.object({
8697
+ kind: z43.literal("repair_meta_campaign"),
8698
+ href: z43.string().min(1)
8627
8699
  }),
8628
- z42.object({
8629
- kind: z42.literal("review_paused_campaign"),
8630
- href: z42.string().min(1)
8700
+ z43.object({
8701
+ kind: z43.literal("review_paused_campaign"),
8702
+ href: z43.string().min(1)
8631
8703
  })
8632
8704
  ]);
8633
- var DropshippingProjectResponseSchema = z42.object({
8634
- id: z42.string().uuid(),
8635
- taskId: z42.string().uuid().nullable(),
8705
+ var DropshippingProjectResponseSchema = z43.object({
8706
+ id: z43.string().uuid(),
8707
+ taskId: z43.string().uuid().nullable(),
8636
8708
  status: DropshippingProjectStatusSchema,
8637
- originKey: z42.string().min(1),
8638
- researchRunId: z42.string().uuid().nullable(),
8639
- candidateSourceId: z42.string().nullable(),
8640
- productName: z42.string().nullable(),
8709
+ originKey: z43.string().min(1),
8710
+ researchRunId: z43.string().uuid().nullable(),
8711
+ candidateSourceId: z43.string().nullable(),
8712
+ productName: z43.string().nullable(),
8641
8713
  productUrl: HttpUrlSchema.nullable(),
8642
- referenceImageUrl: z42.string().url().nullable(),
8643
- hasReferenceImage: z42.boolean(),
8644
- targetCountry: z42.string().nullable(),
8645
- languageCode: z42.string().nullable(),
8714
+ referenceImageUrl: z43.string().url().nullable(),
8715
+ hasReferenceImage: z43.boolean(),
8716
+ targetCountry: z43.string().nullable(),
8717
+ languageCode: z43.string().nullable(),
8646
8718
  costingInput: DropshippingProjectCostingInputSchema.nullable(),
8647
8719
  costingResult: DropshippingProjectCostingResultSchema.nullable(),
8648
- costingVersion: z42.number().int().positive().nullable(),
8649
- version: z42.number().int().positive(),
8720
+ costingVersion: z43.number().int().positive().nullable(),
8721
+ version: z43.number().int().positive(),
8650
8722
  phase: DropshippingProjectPhaseSchema,
8651
8723
  nextAction: DropshippingProjectNextActionSchema.nullable(),
8652
8724
  rewards: DropshippingProjectRewardProgressSchema,
8653
- createdAt: z42.string().datetime(),
8654
- updatedAt: z42.string().datetime()
8725
+ createdAt: z43.string().datetime(),
8726
+ updatedAt: z43.string().datetime()
8655
8727
  });
8656
8728
 
8657
8729
  // ../../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)
8730
+ import { z as z44 } from "zod";
8731
+ var SceneSubjectContractSchema = z44.object({
8732
+ maxPeople: z44.number().int().min(1).max(10),
8733
+ minPeople: z44.number().int().min(0).max(10),
8734
+ minDistinctPeople: z44.number().int().min(0).max(10),
8735
+ maxHands: z44.number().int().min(0).max(20)
8664
8736
  }).superRefine((value, ctx) => {
8665
8737
  if (value.minPeople > value.maxPeople) {
8666
8738
  ctx.addIssue({
8667
- code: z43.ZodIssueCode.custom,
8739
+ code: z44.ZodIssueCode.custom,
8668
8740
  path: [
8669
8741
  "minPeople"
8670
8742
  ],
@@ -8673,7 +8745,7 @@ var SceneSubjectContractSchema = z43.object({
8673
8745
  }
8674
8746
  if (value.minDistinctPeople > value.maxPeople) {
8675
8747
  ctx.addIssue({
8676
- code: z43.ZodIssueCode.custom,
8748
+ code: z44.ZodIssueCode.custom,
8677
8749
  path: [
8678
8750
  "minDistinctPeople"
8679
8751
  ],
@@ -8682,7 +8754,7 @@ var SceneSubjectContractSchema = z43.object({
8682
8754
  }
8683
8755
  if (value.minDistinctPeople > value.minPeople) {
8684
8756
  ctx.addIssue({
8685
- code: z43.ZodIssueCode.custom,
8757
+ code: z44.ZodIssueCode.custom,
8686
8758
  path: [
8687
8759
  "minDistinctPeople"
8688
8760
  ],
@@ -8692,7 +8764,7 @@ var SceneSubjectContractSchema = z43.object({
8692
8764
  });
8693
8765
 
8694
8766
  // ../../packages/types/src/service-creative.ts
8695
- import { z as z44 } from "zod";
8767
+ import { z as z45 } from "zod";
8696
8768
  var SERVICE_CREATIVE_PUBLIC_PRESETS = [
8697
8769
  "auto",
8698
8770
  "ugc_dynamic",
@@ -8700,19 +8772,19 @@ var SERVICE_CREATIVE_PUBLIC_PRESETS = [
8700
8772
  "cinematic",
8701
8773
  "wild_card"
8702
8774
  ];
8703
- var ServiceCreativePresetSchema = z44.enum(SERVICE_CREATIVE_PUBLIC_PRESETS);
8775
+ var ServiceCreativePresetSchema = z45.enum(SERVICE_CREATIVE_PUBLIC_PRESETS);
8704
8776
  var SERVICE_REVIEW_MODES = [
8705
8777
  "automatic",
8706
8778
  "guided"
8707
8779
  ];
8708
- var ServiceReviewModeSchema = z44.enum(SERVICE_REVIEW_MODES);
8780
+ var ServiceReviewModeSchema = z45.enum(SERVICE_REVIEW_MODES);
8709
8781
  var SERVICE_HIGGSFIELD_MODES = [
8710
8782
  "product_review",
8711
8783
  "ugc_how_to",
8712
8784
  "tv_spot",
8713
8785
  "wild_card"
8714
8786
  ];
8715
- var ServiceHiggsfieldModeSchema = z44.enum(SERVICE_HIGGSFIELD_MODES);
8787
+ var ServiceHiggsfieldModeSchema = z45.enum(SERVICE_HIGGSFIELD_MODES);
8716
8788
  var SERVICE_MEDIA_ROLES = [
8717
8789
  "screen_demo",
8718
8790
  "ad_reference",
@@ -8720,20 +8792,20 @@ var SERVICE_MEDIA_ROLES = [
8720
8792
  "presenter_reference",
8721
8793
  "brand_asset"
8722
8794
  ];
8723
- var ServiceMediaRoleSchema = z44.enum(SERVICE_MEDIA_ROLES);
8724
- var ServiceMediaAssetSchema = z44.object({
8795
+ var ServiceMediaRoleSchema = z45.enum(SERVICE_MEDIA_ROLES);
8796
+ var ServiceMediaAssetSchema = z45.object({
8725
8797
  role: ServiceMediaRoleSchema,
8726
- s3Key: z44.string().min(1),
8798
+ s3Key: z45.string().min(1),
8727
8799
  /** 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()
8800
+ uploadToken: z45.string().min(1).optional(),
8801
+ mimeType: z45.string().min(1),
8802
+ durationSec: z45.number().positive().max(30).optional(),
8803
+ sourceName: z45.string().max(255).optional()
8732
8804
  }).superRefine((asset, ctx) => {
8733
8805
  const isVideoRole = asset.role === "screen_demo" || asset.role === "ad_reference";
8734
8806
  if (isVideoRole && !asset.mimeType.startsWith("video/")) {
8735
8807
  ctx.addIssue({
8736
- code: z44.ZodIssueCode.custom,
8808
+ code: z45.ZodIssueCode.custom,
8737
8809
  message: `${asset.role} requires video media`,
8738
8810
  path: [
8739
8811
  "mimeType"
@@ -8742,7 +8814,7 @@ var ServiceMediaAssetSchema = z44.object({
8742
8814
  }
8743
8815
  if (isVideoRole && asset.durationSec === void 0) {
8744
8816
  ctx.addIssue({
8745
- code: z44.ZodIssueCode.custom,
8817
+ code: z45.ZodIssueCode.custom,
8746
8818
  message: `${asset.role} requires durationSec`,
8747
8819
  path: [
8748
8820
  "durationSec"
@@ -8751,7 +8823,7 @@ var ServiceMediaAssetSchema = z44.object({
8751
8823
  }
8752
8824
  if (!isVideoRole && !asset.mimeType.startsWith("image/")) {
8753
8825
  ctx.addIssue({
8754
- code: z44.ZodIssueCode.custom,
8826
+ code: z45.ZodIssueCode.custom,
8755
8827
  message: `${asset.role} requires image media`,
8756
8828
  path: [
8757
8829
  "mimeType"
@@ -8759,13 +8831,13 @@ var ServiceMediaAssetSchema = z44.object({
8759
8831
  });
8760
8832
  }
8761
8833
  });
8762
- var ServiceMediaBundleSchema = z44.object({
8763
- assets: z44.array(ServiceMediaAssetSchema).max(15).default([])
8834
+ var ServiceMediaBundleSchema = z45.object({
8835
+ assets: z45.array(ServiceMediaAssetSchema).max(15).default([])
8764
8836
  }).superRefine((bundle, ctx) => {
8765
8837
  const adReferences = bundle.assets.filter((asset) => asset.role === "ad_reference");
8766
8838
  if (adReferences.length > 5) {
8767
8839
  ctx.addIssue({
8768
- code: z44.ZodIssueCode.custom,
8840
+ code: z45.ZodIssueCode.custom,
8769
8841
  message: "A maximum of five ad_reference videos is allowed",
8770
8842
  path: [
8771
8843
  "assets"
@@ -8775,7 +8847,7 @@ var ServiceMediaBundleSchema = z44.object({
8775
8847
  const screenDemos = bundle.assets.filter((asset) => asset.role === "screen_demo");
8776
8848
  if (screenDemos.length > 3) {
8777
8849
  ctx.addIssue({
8778
- code: z44.ZodIssueCode.custom,
8850
+ code: z45.ZodIssueCode.custom,
8779
8851
  message: "A maximum of three screen_demo videos is allowed",
8780
8852
  path: [
8781
8853
  "assets"
@@ -8792,33 +8864,33 @@ var SERVICE_MEDIA_ANALYSIS_KINDS = [
8792
8864
  "product",
8793
8865
  "other"
8794
8866
  ];
8795
- var ServiceMediaAnalysisKindSchema = z44.enum(SERVICE_MEDIA_ANALYSIS_KINDS);
8796
- var ServiceMediaAnalysisItemSchema = z44.object({
8797
- assetIndex: z44.number().int().nonnegative(),
8798
- mediaType: z44.enum([
8867
+ var ServiceMediaAnalysisKindSchema = z45.enum(SERVICE_MEDIA_ANALYSIS_KINDS);
8868
+ var ServiceMediaAnalysisItemSchema = z45.object({
8869
+ assetIndex: z45.number().int().nonnegative(),
8870
+ mediaType: z45.enum([
8799
8871
  "image",
8800
8872
  "video"
8801
8873
  ]),
8802
8874
  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}$/),
8875
+ description: z45.string().min(1).max(1200),
8876
+ tags: z45.array(z45.string().min(1).max(80)).max(12),
8877
+ suggestedRoles: z45.array(ServiceMediaRoleSchema).max(4),
8878
+ visiblePeople: z45.number().int().nonnegative().max(20).optional(),
8879
+ ocrText: z45.string().max(2e3).optional(),
8880
+ speechSummary: z45.string().max(2e3).optional()
8881
+ });
8882
+ var ServiceMediaAnalysisSchema = z45.object({
8883
+ version: z45.literal(1),
8884
+ analyzedAt: z45.string().datetime(),
8885
+ pricingAction: z45.literal("service-media-analysis"),
8886
+ assetFingerprint: z45.string().regex(/^[a-f0-9]{64}$/),
8815
8887
  /** Language used for human-readable descriptions and tags. Optional for old checkpoints. */
8816
- language: z44.enum([
8888
+ language: z45.enum([
8817
8889
  "es",
8818
8890
  "en",
8819
8891
  "pt"
8820
8892
  ]).optional(),
8821
- items: z44.array(ServiceMediaAnalysisItemSchema).max(15)
8893
+ items: z45.array(ServiceMediaAnalysisItemSchema).max(15)
8822
8894
  });
8823
8895
 
8824
8896
  // ../../packages/types/src/productmaker-capability-registry.ts
@@ -9335,7 +9407,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
9335
9407
  ], [
9336
9408
  "creative"
9337
9409
  ]),
9338
- defineCapability("generate_landing", "75947c5a70d26305ca07ab8d7bc0be710e862eb9319010ee66dd43e64fab2050", "credit_consuming", "creative", [
9410
+ defineCapability("generate_landing", "67520417176396516cd5ad358dca39f70a5c4a74169eecd85987217226c12251", "credit_consuming", "creative", [
9339
9411
  "credit_consuming",
9340
9412
  "state_change"
9341
9413
  ], [
@@ -9380,12 +9452,14 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
9380
9452
  "competitorScanEnabled",
9381
9453
  "landingStrategy",
9382
9454
  "landingImageFormat",
9455
+ "pauseForAngleReview",
9383
9456
  // MCP-only, like create_product_task's aiDecidesAll.
9384
9457
  "aiDecidesAll"
9385
9458
  ], [
9386
9459
  "competitorScanEnabled",
9387
9460
  "landingStrategy",
9388
- "landingImageFormat"
9461
+ "landingImageFormat",
9462
+ "pauseForAngleReview"
9389
9463
  ])
9390
9464
  ], [
9391
9465
  "product_reference"
@@ -9901,8 +9975,8 @@ var PRODUCTMAKER_MCP_CAPABILITIES = toLegacyCapabilityCatalog(PRODUCTMAKER_MCP_C
9901
9975
  var PRODUCTMAKER_MCP_CAPABILITY_NAMES = PRODUCTMAKER_MCP_CAPABILITY_REGISTRY.map((capability) => capability.name);
9902
9976
 
9903
9977
  // ../../packages/types/src/actor.ts
9904
- import { z as z45 } from "zod";
9905
- var ActorStatusSchema = z45.enum([
9978
+ import { z as z46 } from "zod";
9979
+ var ActorStatusSchema = z46.enum([
9906
9980
  "draft",
9907
9981
  "generating",
9908
9982
  "ready",
@@ -9911,18 +9985,18 @@ var ActorStatusSchema = z45.enum([
9911
9985
  var ACTOR_NAME_MAX_CHARS = 60;
9912
9986
  var ACTOR_DESCRIPTION_MAX_CHARS = 600;
9913
9987
  var ACTOR_CANDIDATE_COUNT = 4;
9914
- var ActorGenderSchema = z45.enum([
9988
+ var ActorGenderSchema = z46.enum([
9915
9989
  "female",
9916
9990
  "male",
9917
9991
  "non_binary"
9918
9992
  ]);
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),
9993
+ var ActorSchema = z46.object({
9994
+ id: z46.string(),
9995
+ name: z46.string().min(1).max(ACTOR_NAME_MAX_CHARS),
9996
+ description: z46.string().max(ACTOR_DESCRIPTION_MAX_CHARS),
9923
9997
  gender: ActorGenderSchema,
9924
- voiceId: z45.string().nullable().optional(),
9925
- brandId: z45.string().nullable().optional(),
9998
+ voiceId: z46.string().nullable().optional(),
9999
+ brandId: z46.string().nullable().optional(),
9926
10000
  status: ActorStatusSchema,
9927
10001
  /**
9928
10002
  * A candidate-grid run is in flight RIGHT NOW.
@@ -9934,36 +10008,36 @@ var ActorSchema = z45.object({
9934
10008
  * timestamp with a TTL, so an orphaned run reads as `false` instead of
9935
10009
  * pinning the personaje forever.
9936
10010
  */
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(),
10011
+ generating: z46.boolean().optional(),
10012
+ photoUrl: z46.string().url().nullable().optional(),
10013
+ avatarUrl: z46.string().url().nullable().optional(),
10014
+ candidateUrls: z46.array(z46.string().url()).optional(),
9941
10015
  /** Indices of candidateUrls that failed the anatomy check (Task 6). */
9942
- flaggedCandidateIndices: z45.array(z45.number().int()).optional()
10016
+ flaggedCandidateIndices: z46.array(z46.number().int()).optional()
9943
10017
  });
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(""),
10018
+ var CreateActorRequest = z46.object({
10019
+ name: z46.string().min(1).max(ACTOR_NAME_MAX_CHARS),
10020
+ description: z46.string().max(ACTOR_DESCRIPTION_MAX_CHARS).default(""),
9947
10021
  gender: ActorGenderSchema,
9948
- voiceId: z45.string().optional(),
9949
- brandId: z45.string().optional(),
9950
- sourcePhotoKey: z45.string().optional()
10022
+ voiceId: z46.string().optional(),
10023
+ brandId: z46.string().optional(),
10024
+ sourcePhotoKey: z46.string().optional()
9951
10025
  }).refine((v) => v.description.trim().length > 0 || !!v.sourcePhotoKey, {
9952
10026
  message: "Se necesita una descripci\xF3n o una foto"
9953
10027
  });
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(),
10028
+ var UpdateActorRequest = z46.object({
10029
+ name: z46.string().min(1).max(ACTOR_NAME_MAX_CHARS).optional(),
10030
+ description: z46.string().max(ACTOR_DESCRIPTION_MAX_CHARS).optional(),
9957
10031
  gender: ActorGenderSchema.optional(),
9958
- voiceId: z45.string().nullable().optional(),
9959
- brandId: z45.string().nullable().optional()
10032
+ voiceId: z46.string().nullable().optional(),
10033
+ brandId: z46.string().nullable().optional()
9960
10034
  });
9961
- var ApproveActorRequest = z45.object({
9962
- candidateIndex: z45.number().int().min(0).max(ACTOR_CANDIDATE_COUNT - 1)
10035
+ var ApproveActorRequest = z46.object({
10036
+ candidateIndex: z46.number().int().min(0).max(ACTOR_CANDIDATE_COUNT - 1)
9963
10037
  });
9964
10038
 
9965
10039
  // ../../packages/types/src/referral-dashboard.ts
9966
- import { z as z46 } from "zod";
10040
+ import { z as z47 } from "zod";
9967
10041
  var REFERRAL_DASHBOARD_RAW_STATUSES = [
9968
10042
  "ACTIVE",
9969
10043
  "PENDING",
@@ -9982,66 +10056,66 @@ var REFERRAL_DASHBOARD_PLAN_KINDS = [
9982
10056
  "last",
9983
10057
  "none"
9984
10058
  ];
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([
10059
+ var ReferralDashboardRawStatusSchema = z47.enum(REFERRAL_DASHBOARD_RAW_STATUSES);
10060
+ var ReferralDashboardStateSchema = z47.enum(REFERRAL_DASHBOARD_STATES);
10061
+ var ReferralDashboardPlanKindSchema = z47.enum(REFERRAL_DASHBOARD_PLAN_KINDS);
10062
+ var ReferralDashboardStatusSchema = z47.enum([
9989
10063
  "all",
9990
10064
  "active",
9991
10065
  "pending",
9992
10066
  "inactive"
9993
10067
  ]).default("all");
9994
- var ReferralDashboardPlanSchema = z46.string().trim().min(1).max(100).optional();
9995
- var ReferralDashboardFiltersSchema = z46.object({
10068
+ var ReferralDashboardPlanSchema = z47.string().trim().min(1).max(100).optional();
10069
+ var ReferralDashboardFiltersSchema = z47.object({
9996
10070
  status: ReferralDashboardStatusSchema,
9997
10071
  plan: ReferralDashboardPlanSchema
9998
10072
  });
9999
- var ReferralDashboardSubscriptionSchema = z46.object({
10000
- planName: z46.string().nullable(),
10073
+ var ReferralDashboardSubscriptionSchema = z47.object({
10074
+ planName: z47.string().nullable(),
10001
10075
  planKind: ReferralDashboardPlanKindSchema,
10002
10076
  rawStatus: ReferralDashboardRawStatusSchema.nullable(),
10003
10077
  state: ReferralDashboardStateSchema,
10004
- currentPeriodEnd: z46.string().datetime({
10078
+ currentPeriodEnd: z47.string().datetime({
10005
10079
  offset: true
10006
10080
  }).nullable(),
10007
- cancelAtPeriodEnd: z46.boolean()
10081
+ cancelAtPeriodEnd: z47.boolean()
10008
10082
  });
10009
- var ReferralDashboardReferralSchema = z46.object({
10010
- id: z46.string().min(1),
10011
- registeredAt: z46.string().datetime({
10083
+ var ReferralDashboardReferralSchema = z47.object({
10084
+ id: z47.string().min(1),
10085
+ registeredAt: z47.string().datetime({
10012
10086
  offset: true
10013
10087
  }),
10014
10088
  // Kept in the response for compatibility with existing referral API clients.
10015
10089
  // The referrer dashboard intentionally does not render these legacy fields.
10016
- expiresAt: z46.string().datetime({
10090
+ expiresAt: z47.string().datetime({
10017
10091
  offset: true
10018
10092
  }).nullable().optional(),
10019
- status: z46.string().min(1).optional(),
10020
- referredUser: z46.object({
10021
- email: z46.string().nullable()
10093
+ status: z47.string().min(1).optional(),
10094
+ referredUser: z47.object({
10095
+ email: z47.string().nullable()
10022
10096
  }),
10023
10097
  subscription: ReferralDashboardSubscriptionSchema
10024
10098
  });
10025
- var ReferralDashboardReferralsPageSchema = z46.object({
10026
- referrals: z46.array(ReferralDashboardReferralSchema),
10027
- total: z46.number().int().nonnegative()
10099
+ var ReferralDashboardReferralsPageSchema = z47.object({
10100
+ referrals: z47.array(ReferralDashboardReferralSchema),
10101
+ total: z47.number().int().nonnegative()
10028
10102
  });
10029
- var ReferralDashboardPlanBreakdownSchema = z46.object({
10030
- planName: z46.string().nullable(),
10031
- count: z46.number().int().nonnegative()
10103
+ var ReferralDashboardPlanBreakdownSchema = z47.object({
10104
+ planName: z47.string().nullable(),
10105
+ count: z47.number().int().nonnegative()
10032
10106
  });
10033
- var ReferralDashboardMonthlyRegistrationSchema = z46.object({
10034
- month: z46.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/),
10035
- count: z46.number().int().nonnegative()
10107
+ var ReferralDashboardMonthlyRegistrationSchema = z47.object({
10108
+ month: z47.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/),
10109
+ count: z47.number().int().nonnegative()
10036
10110
  });
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")
10111
+ var ReferralDashboardOverviewSchema = z47.object({
10112
+ totalReferredUsers: z47.number().int().nonnegative(),
10113
+ activeUsers: z47.number().int().nonnegative(),
10114
+ pendingUsers: z47.number().int().nonnegative(),
10115
+ inactiveUsers: z47.number().int().nonnegative(),
10116
+ noPlanUsers: z47.number().int().nonnegative(),
10117
+ planBreakdown: z47.array(ReferralDashboardPlanBreakdownSchema),
10118
+ monthlyRegistrations: z47.array(ReferralDashboardMonthlyRegistrationSchema).refine((months) => months.length === 6, "Expected six monthly registration buckets")
10045
10119
  });
10046
10120
 
10047
10121
  // ../../packages/types/src/mcp-oauth.ts
@@ -10803,19 +10877,19 @@ import { InsufficientScopeError, InvalidTokenError } from "@modelcontextprotocol
10803
10877
  import { createRemoteJWKSet as createRemoteJWKSet2, jwtVerify as jwtVerify2 } from "jose";
10804
10878
 
10805
10879
  // src/auth/oauth-config.ts
10806
- import { z as z47 } from "zod";
10880
+ import { z as z48 } from "zod";
10807
10881
  var MCP_RESOURCE = new URL("https://mcp.productmaker.app/mcp");
10808
10882
  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, {
10883
+ var oauthEnvSchema = z48.object({
10884
+ MCP_REMOTE_AUTH_MODE: z48.literal("oauth"),
10885
+ MCP_AUTH0_ISSUER: z48.string().trim().min(1),
10886
+ MCP_AUTH0_AUDIENCE: z48.string().trim().refine((value) => value === MCP_RESOURCE.href, {
10813
10887
  message: `must equal ${MCP_RESOURCE.href}`
10814
10888
  }),
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)
10889
+ MCP_AUTH0_CLIENT_ID: z48.string().trim().min(1),
10890
+ MCP_AUTH0_CLIENT_SECRET: z48.string().trim().min(1),
10891
+ PM_API_AUDIENCE: z48.string().trim().min(1),
10892
+ AUTH0_AUDIENCE: z48.string().trim().min(1)
10819
10893
  });
10820
10894
  function formatZodIssues(error) {
10821
10895
  return error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
@@ -11557,7 +11631,7 @@ var ApiClient = class {
11557
11631
  };
11558
11632
 
11559
11633
  // src/index.ts
11560
- var MCP_VERSION = "3.4.0";
11634
+ var MCP_VERSION = "3.4.1";
11561
11635
 
11562
11636
  // src/meta-upload-app.ts
11563
11637
  import { readFileSync } from "fs";
@@ -11629,7 +11703,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
11629
11703
  __name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
11630
11704
 
11631
11705
  // src/tools/tasks.ts
11632
- import { z as z49 } from "zod";
11706
+ import { z as z50 } from "zod";
11633
11707
 
11634
11708
  // src/resolve-image.ts
11635
11709
  import { lookup as dnsLookup } from "dns/promises";
@@ -12156,10 +12230,10 @@ async function resolveMediaRef(ref, opts) {
12156
12230
  __name(resolveMediaRef, "resolveMediaRef");
12157
12231
 
12158
12232
  // 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([
12233
+ import { z as z49 } from "zod";
12234
+ var Lang = z49.string().min(2).max(10);
12235
+ var Country = z49.string().min(2).max(3);
12236
+ var LandingStrategyEnum = z49.enum([
12163
12237
  "auto",
12164
12238
  "classic",
12165
12239
  "pain_solution",
@@ -12168,12 +12242,12 @@ var LandingStrategyEnum = z48.enum([
12168
12242
  "offer_value",
12169
12243
  "lifestyle_identity"
12170
12244
  ]);
12171
- var LandingImageFormatEnum = z48.enum([
12245
+ var LandingImageFormatEnum = z49.enum([
12172
12246
  "9:16",
12173
12247
  "4:5",
12174
12248
  "1:1"
12175
12249
  ]);
12176
- var VideoPresetEnum = z48.enum([
12250
+ var VideoPresetEnum = z49.enum([
12177
12251
  "auto",
12178
12252
  "ugc_dynamic",
12179
12253
  "ugc_how_to",
@@ -12186,7 +12260,7 @@ var VideoPresetEnum = z48.enum([
12186
12260
  "pixar_problem",
12187
12261
  "pixar_sassy"
12188
12262
  ]);
12189
- var TaskCreativeVariantVideoPresetEnum = z48.enum([
12263
+ var TaskCreativeVariantVideoPresetEnum = z49.enum([
12190
12264
  "auto",
12191
12265
  "ugc_dynamic",
12192
12266
  "ugc_how_to",
@@ -12257,7 +12331,7 @@ function resolveVideoPreset(preset) {
12257
12331
  return VIDEO_PRESET_RESOLUTION[preset] ?? null;
12258
12332
  }
12259
12333
  __name(resolveVideoPreset, "resolveVideoPreset");
12260
- var VideoTierEnum = z48.enum([
12334
+ var VideoTierEnum = z49.enum([
12261
12335
  "basic"
12262
12336
  ]);
12263
12337
  function resolveVideoTier(_tier) {
@@ -12272,17 +12346,17 @@ function resolveVideoFormatForDuration(durationSeconds) {
12272
12346
  return durationSeconds === 30 ? "double_30s" : "single_15s";
12273
12347
  }
12274
12348
  __name(resolveVideoFormatForDuration, "resolveVideoFormatForDuration");
12275
- var VideoResolutionEnum = z48.enum([
12349
+ var VideoResolutionEnum = z49.enum([
12276
12350
  "480p",
12277
12351
  "720p"
12278
12352
  ]);
12279
- var VideoStyleEnum = z48.enum([
12353
+ var VideoStyleEnum = z49.enum([
12280
12354
  "ugc",
12281
12355
  "cartoon_3d",
12282
12356
  "product_only",
12283
12357
  "ai_dynamic"
12284
12358
  ]);
12285
- var NarrativeStyleEnum = z48.enum([
12359
+ var NarrativeStyleEnum = z49.enum([
12286
12360
  "review",
12287
12361
  "ugc_how_to",
12288
12362
  "problem_product_cta",
@@ -12299,7 +12373,7 @@ var NarrativeStyleEnum = z48.enum([
12299
12373
  "ugc_skeptic_confession",
12300
12374
  "ugc_demo_review"
12301
12375
  ]);
12302
- var PublicNarrativeStyleEnum = z48.enum([
12376
+ var PublicNarrativeStyleEnum = z49.enum([
12303
12377
  "review",
12304
12378
  "ugc_how_to",
12305
12379
  "ugc_unboxing_chaos",
@@ -12311,7 +12385,7 @@ var PublicNarrativeStyleEnum = z48.enum([
12311
12385
  "animated_problem_pixar",
12312
12386
  "sassy_product_pixar"
12313
12387
  ]);
12314
- var VideoModelEnum = z48.enum([
12388
+ var VideoModelEnum = z49.enum([
12315
12389
  "veo",
12316
12390
  "wan",
12317
12391
  "bytedance",
@@ -12319,29 +12393,29 @@ var VideoModelEnum = z48.enum([
12319
12393
  "grok",
12320
12394
  "kling"
12321
12395
  ]);
12322
- var ProductReferenceUserChoiceEnum = z48.enum([
12396
+ var ProductReferenceUserChoiceEnum = z49.enum([
12323
12397
  "same_product",
12324
12398
  "variants",
12325
12399
  "different_products",
12326
12400
  "combo_distinct"
12327
12401
  ]);
12328
- var ProductReferenceCandidateGroupingEnum = z48.enum([
12402
+ var ProductReferenceCandidateGroupingEnum = z49.enum([
12329
12403
  "same_product_same_variant",
12330
12404
  "same_product_different_variants",
12331
12405
  "different_products",
12332
12406
  "unclear"
12333
12407
  ]);
12334
- var ProductReferenceScopeEnum = z48.enum([
12408
+ var ProductReferenceScopeEnum = z49.enum([
12335
12409
  "base",
12336
12410
  "video_view_pack"
12337
12411
  ]);
12338
- var ProductReferenceResolutionDecisionEnum = z48.enum([
12412
+ var ProductReferenceResolutionDecisionEnum = z49.enum([
12339
12413
  "approve",
12340
12414
  "reject",
12341
12415
  "observed_only",
12342
12416
  "correct_view"
12343
12417
  ]);
12344
- var ProductReferenceRejectionReasonEnum = z48.enum([
12418
+ var ProductReferenceRejectionReasonEnum = z49.enum([
12345
12419
  "replacement_requested",
12346
12420
  "wrong_product_identity",
12347
12421
  "wrong_variant",
@@ -12352,13 +12426,13 @@ var ProductReferenceRejectionReasonEnum = z48.enum([
12352
12426
  "not_a_product_photo",
12353
12427
  "other"
12354
12428
  ]);
12355
- var GapDurationChoiceMirror = z48.object({
12356
- angleIndex: z48.number().int().nonnegative(),
12357
- recommendedSec: z48.union([
12358
- z48.literal(15),
12359
- z48.literal(30)
12429
+ var GapDurationChoiceMirror = z49.object({
12430
+ angleIndex: z49.number().int().nonnegative(),
12431
+ recommendedSec: z49.union([
12432
+ z49.literal(15),
12433
+ z49.literal(30)
12360
12434
  ]),
12361
- estimatedDeltaCredits: z48.number().int().nonnegative().optional()
12435
+ estimatedDeltaCredits: z49.number().int().nonnegative().optional()
12362
12436
  });
12363
12437
  function buildSelectedImageUrlsHash(urls) {
12364
12438
  const input = [
@@ -12368,13 +12442,13 @@ function buildSelectedImageUrlsHash(urls) {
12368
12442
  return `fnv1a:${hash.toString(16).padStart(8, "0")}:${urls.length}`;
12369
12443
  }
12370
12444
  __name(buildSelectedImageUrlsHash, "buildSelectedImageUrlsHash");
12371
- var ImageCreativeStyleEnum = z48.enum([
12445
+ var ImageCreativeStyleEnum = z49.enum([
12372
12446
  "studio",
12373
12447
  "floating",
12374
12448
  "ingredients",
12375
12449
  "in_use"
12376
12450
  ]);
12377
- var ImageCreativeArchetypeEnum = z48.enum([
12451
+ var ImageCreativeArchetypeEnum = z49.enum([
12378
12452
  "direct_response_product_ad",
12379
12453
  "hero_outcome",
12380
12454
  "offer_value_prop",
@@ -12383,20 +12457,20 @@ var ImageCreativeArchetypeEnum = z48.enum([
12383
12457
  "problem_solution",
12384
12458
  "lifestyle_identity"
12385
12459
  ]);
12386
- var ImageCreativeVisualTreatmentEnum = z48.enum([
12460
+ var ImageCreativeVisualTreatmentEnum = z49.enum([
12387
12461
  "performance_product_ad",
12388
12462
  "premium_dtc_carousel"
12389
12463
  ]);
12390
- var ImageCreativeAspectRatioEnum = z48.enum([
12464
+ var ImageCreativeAspectRatioEnum = z49.enum([
12391
12465
  "1:1",
12392
12466
  "4:5",
12393
12467
  "9:16",
12394
12468
  "16:9"
12395
12469
  ]);
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.")
12470
+ var ImageRefSchema = z49.object({
12471
+ 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.'),
12472
+ 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`.'),
12473
+ 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
12474
  }).refine((v) => [
12401
12475
  v.url,
12402
12476
  v.path,
@@ -12404,11 +12478,11 @@ var ImageRefSchema = z48.object({
12404
12478
  ].filter(Boolean).length === 1, {
12405
12479
  message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
12406
12480
  });
12407
- var ImagesInput = z48.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
12481
+ var ImagesInput = z49.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
12408
12482
  const assetCount = images.filter((image) => Boolean(image.assetId)).length;
12409
12483
  if (assetCount > 0 && assetCount !== images.length) {
12410
12484
  ctx.addIssue({
12411
- code: z48.ZodIssueCode.custom,
12485
+ code: z49.ZodIssueCode.custom,
12412
12486
  message: "all image entries must use assetId, or all must use URL/path sources"
12413
12487
  });
12414
12488
  }
@@ -12478,14 +12552,14 @@ async function submitCreative(api, opts) {
12478
12552
  });
12479
12553
  }
12480
12554
  __name(submitCreative, "submitCreative");
12481
- var ResearchTargetCountryEnum = z48.enum([
12555
+ var ResearchTargetCountryEnum = z49.enum([
12482
12556
  "CO",
12483
12557
  "MX",
12484
12558
  "PE",
12485
12559
  "EC",
12486
12560
  "CL"
12487
12561
  ]);
12488
- var ResearchCategoryEnum = z48.enum([
12562
+ var ResearchCategoryEnum = z49.enum([
12489
12563
  "auto",
12490
12564
  "automotive",
12491
12565
  "kitchen",
@@ -13133,54 +13207,54 @@ function renderOutputsMarkdown(outputs) {
13133
13207
  __name(renderOutputsMarkdown, "renderOutputsMarkdown");
13134
13208
 
13135
13209
  // src/tools/tasks.ts
13136
- var CreateProductTaskInput = z49.object({
13210
+ var CreateProductTaskInput = z50.object({
13137
13211
  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."),
13212
+ 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."),
13213
+ 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
13214
  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
13215
  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.'),
13216
+ 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.'),
13217
+ 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".'),
13218
+ 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.'),
13219
+ 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.'),
13220
+ 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."),
13221
+ 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
13222
  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)
13223
+ durationSeconds: z50.union([
13224
+ z50.literal(15),
13225
+ z50.literal(30)
13152
13226
  ]).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."),
13227
+ 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."),
13228
+ 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
13229
  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
13230
  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."),
13231
+ 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
13232
  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([
13233
+ outputs: z50.array(z50.enum([
13160
13234
  "landing",
13161
13235
  "video",
13162
13236
  "image"
13163
13237
  ])).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."),
13238
+ 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."),
13239
+ 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."),
13240
+ 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."),
13241
+ 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.'),
13242
+ 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."),
13243
+ 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
13244
  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
13245
  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
13246
  }).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.'),
13247
+ var CreateServiceVideoInput = z50.object({
13248
+ 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."),
13249
+ 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
13250
  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([
13251
+ 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.'),
13252
+ brandId: z50.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
13253
+ reviewMode: z50.enum([
13180
13254
  "automatic",
13181
13255
  "guided"
13182
13256
  ]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
13183
- videoPreset: z49.enum([
13257
+ videoPreset: z50.enum([
13184
13258
  "auto",
13185
13259
  "ugc_dynamic",
13186
13260
  "ugc_how_to",
@@ -13188,51 +13262,51 @@ var CreateServiceVideoInput = z49.object({
13188
13262
  "wild_card"
13189
13263
  ]).default("auto")
13190
13264
  }).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([
13265
+ var GetTaskStatusInput = z50.object({
13266
+ taskId: z50.string().min(1),
13267
+ waitSeconds: z50.number().int().min(0).max(120).optional()
13268
+ });
13269
+ var ListTasksInput = z50.object({
13270
+ limit: z50.number().int().min(1).max(50).optional(),
13271
+ offset: z50.number().int().min(0).optional(),
13272
+ search: z50.string().optional()
13273
+ });
13274
+ var EditTaskDraftInput = z50.object({
13275
+ taskId: z50.string().min(1),
13276
+ angleIndex: z50.number().int().min(0),
13277
+ angle: z50.object({
13278
+ angle: z50.string().min(1).max(480),
13279
+ buyerPersona: z50.string().min(1).max(360),
13280
+ actor: z50.string().min(1).max(360).optional(),
13281
+ 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."),
13282
+ gender: z50.enum([
13209
13283
  "female",
13210
13284
  "male"
13211
13285
  ]).optional(),
13212
- scriptNotes: z49.string().max(2e3).optional()
13286
+ scriptNotes: z50.string().max(2e3).optional()
13213
13287
  })
13214
13288
  });
13215
- var PendingActionPayload = z49.discriminatedUnion("kind", [
13216
- z49.object({
13217
- kind: z49.literal("product_reference_set_approval"),
13289
+ var PendingActionPayload = z50.discriminatedUnion("kind", [
13290
+ z50.object({
13291
+ kind: z50.literal("product_reference_set_approval"),
13218
13292
  scope: ProductReferenceScopeEnum,
13219
- scopeKey: z49.string().min(1).max(120),
13220
- scopeSnapshotId: z49.string().uuid(),
13221
- expectedScopeHash: z49.string().min(1).max(128),
13293
+ scopeKey: z50.string().min(1).max(120),
13294
+ scopeSnapshotId: z50.string().uuid(),
13295
+ expectedScopeHash: z50.string().min(1).max(128),
13222
13296
  decision: ProductReferenceResolutionDecisionEnum,
13223
13297
  reason: ProductReferenceRejectionReasonEnum.optional(),
13224
- affectedRefKeys: z49.array(z49.string().min(1).max(200)).min(1).optional(),
13225
- recoveryAction: z49.enum([
13298
+ affectedRefKeys: z50.array(z50.string().min(1).max(200)).min(1).optional(),
13299
+ recoveryAction: z50.enum([
13226
13300
  "remove",
13227
13301
  "replace",
13228
13302
  "upload",
13229
13303
  "return_to_selection"
13230
13304
  ]).optional()
13231
13305
  }),
13232
- z49.object({
13233
- kind: z49.literal("product_reference_confirmation"),
13306
+ z50.object({
13307
+ kind: z50.literal("product_reference_confirmation"),
13234
13308
  userChoice: ProductReferenceUserChoiceEnum.optional(),
13235
- confirmedProductNames: z49.array(z49.string().min(1).max(120)).min(2).max(8).optional(),
13309
+ confirmedProductNames: z50.array(z50.string().min(1).max(120)).min(2).max(8).optional(),
13236
13310
  // SCOPED multi-scene opt-in — the ONLY way STANDARD ("Multiescena") is
13237
13311
  // reachable via MCP. Valid ONLY together with userChoice='variants' (same
13238
13312
  // product in several colors): renders one shot per color and stitches them,
@@ -13243,50 +13317,50 @@ var PendingActionPayload = z49.discriminatedUnion("kind", [
13243
13317
  // safe because multi-scene IS the intended render for a color variant set,
13244
13318
  // not a blind quality upsell. Maps to `videoTier: 'standard'` on the
13245
13319
  // 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".')
13320
+ 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
13321
  }),
13248
- z49.object({
13249
- kind: z49.literal("angle_review_approval"),
13322
+ z50.object({
13323
+ kind: z50.literal("angle_review_approval"),
13250
13324
  // All edits are optional — empty action body just approves the
13251
13325
  // backend-generated draft as-is. Field shapes mirror the angle-review
13252
13326
  // request contracts in @packages/types/wizard.ts; the handler routes to
13253
13327
  // the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
13254
- customAngle: z49.string().min(1).max(480).optional(),
13328
+ customAngle: z50.string().min(1).max(480).optional(),
13255
13329
  // Keep the shared MCP action within the strictest downstream contract:
13256
13330
  // 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)
13331
+ painPoints: z50.string().max(1500).optional(),
13332
+ benefits: z50.string().max(1500).optional(),
13333
+ features: z50.array(z50.string().min(1).max(300)).max(10).optional(),
13334
+ gapDurationSeconds: z50.union([
13335
+ z50.literal(15),
13336
+ z50.literal(30)
13263
13337
  ]).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
13338
  }),
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()
13339
+ z50.object({
13340
+ kind: z50.literal("service_angle_approval"),
13341
+ angleId: z50.string().uuid(),
13342
+ content: z50.string().min(1).max(480).optional(),
13343
+ creativeDirection: z50.string().min(1).max(1500).optional(),
13344
+ actor: z50.string().min(1).max(360).optional()
13271
13345
  }),
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()
13346
+ z50.object({
13347
+ kind: z50.literal("service_script_approval"),
13348
+ voiceovers: z50.record(z50.string(), z50.string().min(1).max(600)).optional(),
13349
+ visualDirections: z50.record(z50.string(), z50.string().min(1).max(1200)).optional()
13276
13350
  })
13277
13351
  ]);
13278
- var ResolvePendingActionInput = z49.object({
13279
- taskId: z49.string().min(1),
13352
+ var ResolvePendingActionInput = z50.object({
13353
+ taskId: z50.string().min(1),
13280
13354
  action: PendingActionPayload
13281
13355
  }).strict();
13282
13356
  function resolveVariantConfirmVideoTier(action) {
13283
13357
  return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
13284
13358
  }
13285
13359
  __name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
13286
- var StatusForResolveSchema = z49.object({
13360
+ var StatusForResolveSchema = z50.object({
13287
13361
  // Metadata used to select the backend resume contract. Older API responses
13288
13362
  // may omit these fields, so the resolver keeps the generic fallback.
13289
- kind: z49.enum([
13363
+ kind: z50.enum([
13290
13364
  "autopilot",
13291
13365
  "video",
13292
13366
  "image",
@@ -13294,24 +13368,24 @@ var StatusForResolveSchema = z49.object({
13294
13368
  "mix",
13295
13369
  "service"
13296
13370
  ]).optional(),
13297
- selectedOutputs: z49.array(z49.enum([
13371
+ selectedOutputs: z50.array(z50.enum([
13298
13372
  "landing",
13299
13373
  "video",
13300
13374
  "image"
13301
13375
  ])).optional(),
13302
- videoAngleCount: z49.number().int().min(1).max(3).optional(),
13303
- ugcFormat: z49.enum([
13376
+ videoAngleCount: z50.number().int().min(1).max(3).optional(),
13377
+ ugcFormat: z50.enum([
13304
13378
  "single_8s",
13305
13379
  "single_15s",
13306
13380
  "double_30s"
13307
13381
  ]).optional(),
13308
- videoStyle: z49.enum([
13382
+ videoStyle: z50.enum([
13309
13383
  "ugc",
13310
13384
  "cartoon_3d",
13311
13385
  "product_only",
13312
13386
  "ai_dynamic"
13313
13387
  ]).optional(),
13314
- videoModel: z49.enum([
13388
+ videoModel: z50.enum([
13315
13389
  "veo",
13316
13390
  "wan",
13317
13391
  "bytedance",
@@ -13319,62 +13393,62 @@ var StatusForResolveSchema = z49.object({
13319
13393
  "grok",
13320
13394
  "kling"
13321
13395
  ]).optional(),
13322
- videoTier: z49.enum([
13396
+ videoTier: z50.enum([
13323
13397
  "legacy",
13324
13398
  "standard",
13325
13399
  "pro",
13326
13400
  "single_call"
13327
13401
  ]).optional(),
13328
- videoResolution: z49.enum([
13402
+ videoResolution: z50.enum([
13329
13403
  "480p",
13330
13404
  "720p"
13331
13405
  ]).optional(),
13332
13406
  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(),
13407
+ pendingUserAction: z50.object({
13408
+ kind: z50.string(),
13409
+ candidateGrouping: z50.string().optional(),
13410
+ selectedImageUrls: z50.array(z50.string()).optional(),
13411
+ proposedProductNames: z50.array(z50.string()).optional(),
13338
13412
  // Adaptive reference questions are server-owned. Echo only the evidence
13339
13413
  // identity and the choices shown by the current snapshot; never accept a
13340
13414
  // client-supplied reference set as authorization.
13341
- options: z49.array(ProductReferenceUserChoiceEnum).max(4).optional(),
13342
- mode: z49.enum([
13415
+ options: z50.array(ProductReferenceUserChoiceEnum).max(4).optional(),
13416
+ mode: z50.enum([
13343
13417
  "question",
13344
13418
  "visual_recovery"
13345
13419
  ]).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)
13420
+ decisionKey: z50.string().optional(),
13421
+ questionOrdinal: z50.number().int().min(1).max(5).optional(),
13422
+ questionCeiling: z50.union([
13423
+ z50.literal(3),
13424
+ z50.literal(5)
13351
13425
  ]).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({
13426
+ referenceEvidenceVersion: z50.number().int().positive().optional(),
13427
+ expectedEvidenceHash: z50.string().optional(),
13428
+ question: z50.object({
13429
+ prompt: z50.string().min(1).max(240),
13430
+ helpText: z50.string().min(1).max(300).optional(),
13431
+ options: z50.array(z50.object({
13358
13432
  value: ProductReferenceUserChoiceEnum,
13359
- label: z49.string().min(1).max(120),
13360
- description: z49.string().min(1).max(240).optional()
13433
+ label: z50.string().min(1).max(120),
13434
+ description: z50.string().min(1).max(240).optional()
13361
13435
  })).min(2).max(4)
13362
13436
  }).optional(),
13363
13437
  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([
13438
+ scopeKey: z50.string().optional(),
13439
+ scopeSnapshotId: z50.string().uuid().optional(),
13440
+ scopeHash: z50.string().optional(),
13441
+ baseReferenceSetHash: z50.string().optional(),
13442
+ phase: z50.enum([
13369
13443
  "preparation",
13370
13444
  "final"
13371
13445
  ]).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(),
13446
+ selectedRefKeys: z50.array(z50.string().min(1).max(200)).optional(),
13447
+ allowedDecisions: z50.array(ProductReferenceResolutionDecisionEnum).optional(),
13448
+ customAngleDraft: z50.string().optional(),
13449
+ painPointsDraft: z50.string().optional(),
13450
+ benefitsDraft: z50.string().optional(),
13451
+ featuresDraft: z50.array(z50.string()).optional(),
13378
13452
  // Recommendation consumed only when the caller explicitly sends
13379
13453
  // gapDurationSeconds: 30 in the angle approval action.
13380
13454
  gapDurationChoice: GapDurationChoiceMirror.optional(),
@@ -13383,17 +13457,17 @@ var StatusForResolveSchema = z49.object({
13383
13457
  // keys. `actorId` (the saved custom actor the picker stored) was silently
13384
13458
  // dropped here, so the approval handler below could not echo it back on the
13385
13459
  // 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()
13460
+ angles: z50.array(z50.object({
13461
+ id: z50.string().uuid(),
13462
+ content: z50.string(),
13463
+ creativeDirection: z50.string(),
13464
+ actor: z50.string(),
13465
+ actorId: z50.string().nullable().optional()
13392
13466
  }).passthrough()).optional(),
13393
- panels: z49.array(z49.object({
13394
- beatId: z49.string(),
13395
- voiceover: z49.string(),
13396
- visualDirection: z49.string()
13467
+ panels: z50.array(z50.object({
13468
+ beatId: z50.string(),
13469
+ voiceover: z50.string(),
13470
+ visualDirection: z50.string()
13397
13471
  }).passthrough()).optional()
13398
13472
  }).optional()
13399
13473
  }).passthrough();
@@ -13906,59 +13980,59 @@ __name(registerTaskTools, "registerTaskTools");
13906
13980
 
13907
13981
  // src/tools/creatives.ts
13908
13982
  import { randomUUID } from "crypto";
13909
- import { z as z50 } from "zod";
13983
+ import { z as z51 } from "zod";
13910
13984
  var CreativeRefs = {
13911
13985
  images: ImagesInput,
13912
13986
  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
13987
  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.")
13988
+ 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.'),
13989
+ 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.'),
13990
+ 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".'),
13991
+ 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.'),
13992
+ 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."),
13993
+ 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.'),
13994
+ 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.'),
13995
+ isCombo: z51.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
13996
+ 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."),
13997
+ 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."),
13998
+ 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."),
13999
+ 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.'),
14000
+ 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."),
14001
+ 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
14002
  };
13929
- var VideoInput = z50.object({
14003
+ var VideoInput = z51.object({
13930
14004
  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".'),
14005
+ title: z51.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
14006
+ 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
14007
  language: CreativeRefs.language,
13934
14008
  country: CreativeRefs.country,
13935
- aspectRatio: z50.enum([
14009
+ aspectRatio: z51.enum([
13936
14010
  "9:16",
13937
14011
  "16:9",
13938
14012
  "Auto"
13939
14013
  ]).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)
14014
+ durationSeconds: z51.union([
14015
+ z51.literal(15),
14016
+ z51.literal(30)
13943
14017
  ]).default(15).describe("Opcional. Duraci\xF3n objetivo: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
13944
14018
  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
14019
  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
14020
  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"].'),
14021
+ 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
14022
  price: CreativeRefs.price,
13949
14023
  offer: CreativeRefs.offer,
13950
14024
  productContext: CreativeRefs.productContext,
13951
14025
  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."),
14026
+ 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.'),
14027
+ 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.'),
14028
+ 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."),
14029
+ 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."),
14030
+ 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
14031
  competitorScanEnabled: CreativeRefs.competitorScanEnabled,
13958
14032
  brandId: CreativeRefs.brandId,
13959
14033
  projectId: CreativeRefs.projectId
13960
14034
  }).strict();
13961
- var FreeVideoQualityEnum = z50.enum([
14035
+ var FreeVideoQualityEnum = z51.enum([
13962
14036
  "economical",
13963
14037
  "high_detail"
13964
14038
  ]);
@@ -13980,38 +14054,38 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
13980
14054
  15
13981
14055
  ]
13982
14056
  };
13983
- var FreeVideoInput = z50.object({
14057
+ var FreeVideoInput = z51.object({
13984
14058
  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."),
14059
+ 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
14060
  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."),
14061
+ 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
14062
  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.")
14063
+ generateAiMusic: z51.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
14064
+ addSubtitles: z51.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
14065
+ 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
14066
  }).strict();
13993
14067
  var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
13994
14068
  var archetypeList = ImageCreativeArchetypeEnum.options.join(" | ");
13995
14069
  var visualTreatmentList = ImageCreativeVisualTreatmentEnum.options.join(" | ");
13996
14070
  var aspectRatioList = ImageCreativeAspectRatioEnum.options.join(" | ");
13997
- var ImageInput = z50.object({
14071
+ var ImageInput = z51.object({
13998
14072
  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".'),
14073
+ productTitle: z51.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
14074
+ primaryAngle: z51.string().min(1).describe('\xC1ngulo de venta principal. Ej. "Reduce arrugas en 14 d\xEDas".'),
14001
14075
  buyerPersona: CreativeRefs.buyerPersona,
14002
14076
  language: CreativeRefs.language,
14003
14077
  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.'),
14078
+ nVariants: z51.number().int().min(1).max(6).optional().describe("Opcional. N\xFAmero de variantes a generar (1-6). Default 3."),
14079
+ 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
14080
  imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
14007
14081
  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
14082
  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."),
14083
+ 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
14084
  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.'),
14085
+ generateAdCopy: z51.boolean().optional().describe("Opcional. Si true, tambi\xE9n genera headline/body/CTA para el ad. Default false."),
14086
+ 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."),
14087
+ features: z51.array(z51.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
14088
+ 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
14089
  price: CreativeRefs.price,
14016
14090
  compareAtPrice: CreativeRefs.compareAtPrice,
14017
14091
  offer: CreativeRefs.offer,
@@ -14025,17 +14099,17 @@ var ImageInput = z50.object({
14025
14099
  headline: CreativeRefs.headline,
14026
14100
  subheadline: CreativeRefs.subheadline
14027
14101
  });
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".')
14102
+ var EditImageCreativeInput = z51.object({
14103
+ taskId: z51.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
14104
+ variantIndex: z51.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
14105
+ 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
14106
  });
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."),
14107
+ var LandingInput = z51.object({
14108
+ 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
14109
  images: CreativeRefs.images,
14036
14110
  language: CreativeRefs.language,
14037
14111
  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.'),
14112
+ 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
14113
  buyerPersona: CreativeRefs.buyerPersona,
14040
14114
  price: CreativeRefs.price,
14041
14115
  compareAtPrice: CreativeRefs.compareAtPrice,
@@ -14050,6 +14124,7 @@ var LandingInput = z50.object({
14050
14124
  creativeDirection: CreativeRefs.creativeDirection,
14051
14125
  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
14126
  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".'),
14127
+ 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
14128
  headline: CreativeRefs.headline,
14054
14129
  subheadline: CreativeRefs.subheadline
14055
14130
  });
@@ -14160,8 +14235,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
14160
14235
  __name(registerCreativeTools, "registerCreativeTools");
14161
14236
 
14162
14237
  // src/tools/creative-variants.ts
14163
- import { z as z51 } from "zod";
14164
- var LandingSectionKeyEnum = z51.enum([
14238
+ import { z as z52 } from "zod";
14239
+ var LandingSectionKeyEnum = z52.enum([
14165
14240
  "problem_hook",
14166
14241
  "problem_cost",
14167
14242
  "solution_mechanism",
@@ -14201,24 +14276,24 @@ var LandingSectionKeyEnum = z51.enum([
14201
14276
  "lifestyle_fit",
14202
14277
  "join_lifestyle"
14203
14278
  ]);
14204
- var CreativeVariantKindEnum = z51.enum([
14279
+ var CreativeVariantKindEnum = z52.enum([
14205
14280
  "video",
14206
14281
  "image",
14207
14282
  "landing"
14208
14283
  ]);
14209
- var EstimateCreativeVariantInputBase = z51.object({
14210
- sourceTaskId: z51.string().uuid().describe("ID de la tarea original completada."),
14284
+ var EstimateCreativeVariantInputBase = z52.object({
14285
+ sourceTaskId: z52.string().uuid().describe("ID de la tarea original completada."),
14211
14286
  kind: CreativeVariantKindEnum,
14212
14287
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
14213
14288
  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)."),
14289
+ nVariants: z52.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
14215
14290
  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.")
14291
+ 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
14292
  }).strict();
14218
14293
  var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
14219
14294
  if (input.kind === "video" && input.nVariants !== void 0) {
14220
14295
  ctx.addIssue({
14221
- code: z51.ZodIssueCode.custom,
14296
+ code: z52.ZodIssueCode.custom,
14222
14297
  path: [
14223
14298
  "nVariants"
14224
14299
  ],
@@ -14228,7 +14303,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
14228
14303
  if (input.kind !== "video") {
14229
14304
  if (input.videoPreset !== void 0) {
14230
14305
  ctx.addIssue({
14231
- code: z51.ZodIssueCode.custom,
14306
+ code: z52.ZodIssueCode.custom,
14232
14307
  path: [
14233
14308
  "videoPreset"
14234
14309
  ],
@@ -14237,7 +14312,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
14237
14312
  }
14238
14313
  if (input.videoResolution !== void 0) {
14239
14314
  ctx.addIssue({
14240
- code: z51.ZodIssueCode.custom,
14315
+ code: z52.ZodIssueCode.custom,
14241
14316
  path: [
14242
14317
  "videoResolution"
14243
14318
  ],
@@ -14247,7 +14322,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
14247
14322
  }
14248
14323
  if (input.kind !== "image" && input.nVariants !== void 0) {
14249
14324
  ctx.addIssue({
14250
- code: z51.ZodIssueCode.custom,
14325
+ code: z52.ZodIssueCode.custom,
14251
14326
  path: [
14252
14327
  "nVariants"
14253
14328
  ],
@@ -14257,7 +14332,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
14257
14332
  if (input.kind !== "landing") {
14258
14333
  if (input.sectionKey !== void 0) {
14259
14334
  ctx.addIssue({
14260
- code: z51.ZodIssueCode.custom,
14335
+ code: z52.ZodIssueCode.custom,
14261
14336
  path: [
14262
14337
  "sectionKey"
14263
14338
  ],
@@ -14266,7 +14341,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
14266
14341
  }
14267
14342
  if (input.instructions !== void 0) {
14268
14343
  ctx.addIssue({
14269
- code: z51.ZodIssueCode.custom,
14344
+ code: z52.ZodIssueCode.custom,
14270
14345
  path: [
14271
14346
  "instructions"
14272
14347
  ],
@@ -14275,31 +14350,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
14275
14350
  }
14276
14351
  }
14277
14352
  });
14278
- var CreateCreativeVariantInputBase = z51.object({
14279
- sourceTaskId: z51.string().uuid().describe("ID de la tarea original completada."),
14353
+ var CreateCreativeVariantInputBase = z52.object({
14354
+ sourceTaskId: z52.string().uuid().describe("ID de la tarea original completada."),
14280
14355
  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."),
14356
+ confirm: z52.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
14357
+ 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."),
14358
+ angle: z52.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
14359
+ buyerPersona: z52.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
14360
+ scriptNotes: z52.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
14361
+ creativeDirection: z52.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
14287
14362
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
14288
14363
  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)."),
14364
+ generateAiMusic: z52.boolean().optional().describe("Opcional para video."),
14365
+ nVariants: z52.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
14291
14366
  imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
14292
14367
  creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
14293
14368
  visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
14294
14369
  aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
14295
- styleMix: z51.boolean().optional().describe("Opcional para imagen."),
14370
+ styleMix: z52.boolean().optional().describe("Opcional para imagen."),
14296
14371
  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.")
14372
+ 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
14373
  }).strict();
14299
14374
  var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
14300
14375
  if ((input.kind === "video" || input.kind === "image") && !input.angle) {
14301
14376
  ctx.addIssue({
14302
- code: z51.ZodIssueCode.custom,
14377
+ code: z52.ZodIssueCode.custom,
14303
14378
  path: [
14304
14379
  "angle"
14305
14380
  ],
@@ -14308,7 +14383,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
14308
14383
  }
14309
14384
  if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
14310
14385
  ctx.addIssue({
14311
- code: z51.ZodIssueCode.custom,
14386
+ code: z52.ZodIssueCode.custom,
14312
14387
  path: [
14313
14388
  "instructions"
14314
14389
  ],
@@ -14354,7 +14429,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
14354
14429
  for (const field of fieldsByKind[input.kind]) {
14355
14430
  if (input[field] !== void 0) {
14356
14431
  ctx.addIssue({
14357
- code: z51.ZodIssueCode.custom,
14432
+ code: z52.ZodIssueCode.custom,
14358
14433
  path: [
14359
14434
  field
14360
14435
  ],
@@ -14471,27 +14546,27 @@ function registerCreativeVariantTools(server, api) {
14471
14546
  __name(registerCreativeVariantTools, "registerCreativeVariantTools");
14472
14547
 
14473
14548
  // 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.')
14549
+ import { z as z53 } from "zod";
14550
+ var GetVideoScriptInput = z53.object({
14551
+ taskId: z53.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
14552
+ 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
14553
  }).strict();
14479
14554
  var VIDEO_SCRIPT_APPROVAL_MAX_SCENES2 = 50;
14480
14555
  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, {
14556
+ var ApproveSceneEdit = z53.object({
14557
+ index: z53.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
14558
+ dialogue: z53.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
14484
14559
  message: "dialogue no puede ser s\xF3lo espacios"
14485
14560
  }).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
14561
  }).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.")
14562
+ var ApproveVideoScriptInput = z53.object({
14563
+ taskId: z53.string().min(1).describe("ID de la tarea."),
14564
+ 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.'),
14565
+ 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
14566
  }).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.'),
14567
+ var RegenerateVideoScriptInput = z53.object({
14568
+ taskId: z53.string().min(1).describe("ID de la tarea."),
14569
+ 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
14570
  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
14571
  }).strict();
14497
14572
  function registerScriptReviewTools(server, api) {
@@ -14542,9 +14617,9 @@ function registerScriptReviewTools(server, api) {
14542
14617
  __name(registerScriptReviewTools, "registerScriptReviewTools");
14543
14618
 
14544
14619
  // src/tools/connections.ts
14545
- import { z as z53 } from "zod";
14620
+ import { z as z54 } from "zod";
14546
14621
  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 () => {
14622
+ 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
14623
  try {
14549
14624
  const r = await api.getJson("/v1/shopify/shops");
14550
14625
  return asText(r);
@@ -14552,10 +14627,10 @@ function registerConnectionTools(server, api) {
14552
14627
  throw translateError(e);
14553
14628
  }
14554
14629
  });
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()
14630
+ 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({
14631
+ shopDomain: z54.string().min(3).max(120),
14632
+ query: z54.string().trim().max(120).optional(),
14633
+ taskId: z54.string().uuid().optional()
14559
14634
  }).shape, READS_EXTERNAL, async ({ shopDomain, query, taskId }) => {
14560
14635
  try {
14561
14636
  const params = new URLSearchParams({
@@ -14569,7 +14644,7 @@ function registerConnectionTools(server, api) {
14569
14644
  throw translateError(e);
14570
14645
  }
14571
14646
  });
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 () => {
14647
+ 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
14648
  try {
14574
14649
  const r = await api.getJson("/v1/facebook/ad-accounts");
14575
14650
  return asText(r);
@@ -14579,7 +14654,7 @@ function registerConnectionTools(server, api) {
14579
14654
  });
14580
14655
  server.registerTool("list_meta_destinations", {
14581
14656
  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,
14657
+ inputSchema: z54.object({}).shape,
14583
14658
  annotations: READS_EXTERNAL,
14584
14659
  _meta: {
14585
14660
  "openai/widgetAccessible": true
@@ -14592,7 +14667,7 @@ function registerConnectionTools(server, api) {
14592
14667
  throw translateError(e);
14593
14668
  }
14594
14669
  });
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 () => {
14670
+ 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
14671
  try {
14597
14672
  const r = await api.getJson("/v1/tiktok/advertisers");
14598
14673
  return asText(r);
@@ -14604,9 +14679,9 @@ function registerConnectionTools(server, api) {
14604
14679
  __name(registerConnectionTools, "registerConnectionTools");
14605
14680
 
14606
14681
  // src/tools/actors.ts
14607
- import { z as z54 } from "zod";
14682
+ import { z as z55 } from "zod";
14608
14683
  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 () => {
14684
+ 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
14685
  try {
14611
14686
  const rows = await api.getJson("/v1/actors");
14612
14687
  const actors = (Array.isArray(rows) ? rows : []).filter((actor) => actor.status === "ready").map(({ id, name, description, gender, voiceId }) => ({
@@ -14627,39 +14702,39 @@ function registerActorTools(server, api) {
14627
14702
  __name(registerActorTools, "registerActorTools");
14628
14703
 
14629
14704
  // 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),
14705
+ import { z as z56 } from "zod";
14706
+ var ShopifyInput = z56.object({
14707
+ taskId: z56.string().min(1),
14708
+ shopDomain: z56.string().min(1),
14634
14709
  /** Override: number of landing images to include. Default = ALL images the
14635
14710
  * task generated (the MCP fetches /v1/results first to count). Bounded
14636
14711
  * generously here; the backend validates each index against
14637
14712
  * 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(),
14713
+ numLandingImages: z56.number().int().min(1).max(20).optional(),
14714
+ variantIndex: z56.number().int().min(0).optional(),
14640
14715
  /** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
14641
14716
  * When true, the landing renders variant-picker pills; when false, it ships
14642
14717
  * a single-option product page. Defaults to false. */
14643
- showVariantPicker: z55.boolean().optional(),
14718
+ showVariantPicker: z56.boolean().optional(),
14644
14719
  /** Default `auto` updates the product previously published for this task and
14645
14720
  * shop. Use `existing` with targetProductId to choose another product, or
14646
14721
  * `new` only when the user explicitly wants a duplicate/new listing. */
14647
- publicationMode: z55.enum([
14722
+ publicationMode: z56.enum([
14648
14723
  "auto",
14649
14724
  "existing",
14650
14725
  "new"
14651
14726
  ]).optional(),
14652
14727
  /** Shopify product GID, numeric id, or admin product URL. Required when
14653
14728
  * publicationMode is `existing`. */
14654
- targetProductId: z55.string().trim().min(1).max(300).optional(),
14729
+ targetProductId: z56.string().trim().min(1).max(300).optional(),
14655
14730
  /** 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()
14731
+ announcementBarEnabled: z56.boolean().optional(),
14732
+ announcementBarText: z56.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional()
14658
14733
  });
14659
14734
  var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
14660
14735
  if (value.announcementBarEnabled && !value.announcementBarText) {
14661
14736
  ctx.addIssue({
14662
- code: z55.ZodIssueCode.custom,
14737
+ code: z56.ZodIssueCode.custom,
14663
14738
  path: [
14664
14739
  "announcementBarText"
14665
14740
  ],
@@ -14668,7 +14743,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
14668
14743
  }
14669
14744
  if (!value.announcementBarEnabled && value.announcementBarText) {
14670
14745
  ctx.addIssue({
14671
- code: z55.ZodIssueCode.custom,
14746
+ code: z56.ZodIssueCode.custom,
14672
14747
  path: [
14673
14748
  "announcementBarText"
14674
14749
  ],
@@ -14682,90 +14757,90 @@ function parseShopifyInput(rawInput) {
14682
14757
  return parsed.data;
14683
14758
  }
14684
14759
  __name(parseShopifyInput, "parseShopifyInput");
14685
- var McpCampaignConfig = z55.object({
14760
+ var McpCampaignConfig = z56.object({
14686
14761
  /** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
14687
14762
  * converts to the account currency server-side. Do NOT pre-convert: on a COP
14688
14763
  * account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
14689
- dailyBudgetUsd: z55.number().positive().optional(),
14764
+ dailyBudgetUsd: z56.number().positive().optional(),
14690
14765
  /** ISO-3166-1 alpha-2 country codes. Meta accepts max 1 (single-country
14691
14766
  * 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()
14767
+ targetCountries: z56.array(z56.string().length(2)).max(1).optional(),
14768
+ campaignName: z56.string().trim().min(1).max(100).optional()
14694
14769
  });
14695
14770
  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),
14771
+ var MetaInput = z56.object({
14772
+ taskId: z56.string().min(1),
14698
14773
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
14699
- portfolioId: z55.string().trim().min(1),
14774
+ portfolioId: z56.string().trim().min(1),
14700
14775
  /** Exact Facebook Page selected from `list_meta_destinations`. */
14701
- pageId: z55.string().trim().min(1),
14776
+ pageId: z56.string().trim().min(1),
14702
14777
  adAccountId: McpAdAccountId,
14703
- pixelId: z55.string().min(1).optional(),
14704
- landingUrl: z55.string().url().optional(),
14778
+ pixelId: z56.string().min(1).optional(),
14779
+ landingUrl: z56.string().url().optional(),
14705
14780
  /** Select which angles to publish by 0-based index. Omit to publish all
14706
14781
  * successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
14707
- angleIndexes: z55.array(z55.number().int().nonnegative()).optional(),
14782
+ angleIndexes: z56.array(z56.number().int().nonnegative()).optional(),
14708
14783
  campaignConfig: McpCampaignConfig.optional(),
14709
14784
  /** Override the ad's primary text (body copy). If omitted, ProductMaker
14710
14785
  * uses the auto-generated copy attached to the task. Capped at 500 chars
14711
14786
  * (Meta's primary-text limit). */
14712
- primaryText: z55.string().trim().min(1).max(500).optional(),
14787
+ primaryText: z56.string().trim().min(1).max(500).optional(),
14713
14788
  /** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
14714
14789
  * (wa.me) instead of a landing page. */
14715
- phoneNumber: z55.string().min(8).max(32).optional()
14790
+ phoneNumber: z56.string().min(8).max(32).optional()
14716
14791
  });
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([
14792
+ var GroupedTaskSource = z56.object({
14793
+ type: z56.literal("task"),
14794
+ taskId: z56.string().min(1),
14795
+ angleIndex: z56.number().int().min(0).optional(),
14796
+ videoVariant: z56.enum([
14722
14797
  "with_subtitles",
14723
14798
  "without_subtitles"
14724
14799
  ]).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()
14800
+ imageVariantIndex: z56.number().int().min(0).optional()
14801
+ });
14802
+ var GroupedMediaSource = z56.object({
14803
+ type: z56.literal("media"),
14804
+ 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."),
14805
+ 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".'),
14806
+ thumbnailUrl: z56.string().url().optional(),
14807
+ thumbnailPath: z56.string().min(1).optional()
14733
14808
  }).refine((value) => Boolean(value.url) !== Boolean(value.path), {
14734
14809
  message: "media source needs exactly one of `url` or `path`"
14735
14810
  }).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
14736
14811
  message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
14737
14812
  });
14738
- var GroupedUploadedAssetSource = z55.object({
14739
- type: z55.literal("asset"),
14813
+ var GroupedUploadedAssetSource = z56.object({
14814
+ type: z56.literal("asset"),
14740
14815
  /** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
14741
- assetId: z55.string().uuid(),
14742
- thumbnailAssetId: z55.string().uuid().optional()
14816
+ assetId: z56.string().uuid(),
14817
+ thumbnailAssetId: z56.string().uuid().optional()
14743
14818
  });
14744
- var GroupedCreative = z55.object({
14745
- type: z55.enum([
14819
+ var GroupedCreative = z56.object({
14820
+ type: z56.enum([
14746
14821
  "image",
14747
14822
  "video"
14748
14823
  ]),
14749
- source: z55.union([
14824
+ source: z56.union([
14750
14825
  GroupedTaskSource,
14751
14826
  GroupedMediaSource,
14752
14827
  GroupedUploadedAssetSource
14753
14828
  ]),
14754
- title: z55.string().max(120).optional(),
14755
- description: z55.string().max(500).optional(),
14829
+ title: z56.string().max(120).optional(),
14830
+ description: z56.string().max(500).optional(),
14756
14831
  cta: MetaCtaType.optional(),
14757
- creativeId: z55.string().min(1).optional()
14832
+ creativeId: z56.string().min(1).optional()
14758
14833
  });
14759
- var GroupedCampaignConfigBase = z55.object({
14834
+ var GroupedCampaignConfigBase = z56.object({
14760
14835
  campaignType: MetaCampaignType.default("sales"),
14761
14836
  optimizationMode: MetaOptimizationMode.default("advantage_plus"),
14762
14837
  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)
14838
+ campaignDailyBudget: z56.number().int().positive().optional(),
14839
+ adSets: z56.array(z56.object({
14840
+ tempId: z56.string().min(1).max(80),
14841
+ name: z56.string().min(1).max(100),
14842
+ dailyBudget: z56.number().int().positive().optional(),
14843
+ creativeIds: z56.array(z56.string().min(1)).min(1)
14769
14844
  })).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
14770
14845
  /**
14771
14846
  * Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
@@ -14773,17 +14848,17 @@ var GroupedCampaignConfigBase = z55.object({
14773
14848
  * opaque `invalid_literal` and made the WhatsApp destination — supported by
14774
14849
  * the API since #849 — unreachable from this tool.
14775
14850
  */
14776
- destination: z55.discriminatedUnion("type", [
14777
- z55.object({
14778
- type: z55.literal("landing"),
14779
- landingUrl: z55.string().url()
14851
+ destination: z56.discriminatedUnion("type", [
14852
+ z56.object({
14853
+ type: z56.literal("landing"),
14854
+ landingUrl: z56.string().url()
14780
14855
  }),
14781
- z55.object({
14782
- type: z55.literal("whatsapp"),
14783
- phoneNumber: z55.string().min(8).max(32)
14856
+ z56.object({
14857
+ type: z56.literal("whatsapp"),
14858
+ phoneNumber: z56.string().min(8).max(32)
14784
14859
  })
14785
14860
  ]),
14786
- saveAsDefault: z55.boolean().default(false),
14861
+ saveAsDefault: z56.boolean().default(false),
14787
14862
  budgetPolicy: MetaBudgetPolicy.optional()
14788
14863
  });
14789
14864
  function resolveBudgetMode(value) {
@@ -14797,7 +14872,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
14797
14872
  const budgetMode = resolveBudgetMode(value);
14798
14873
  if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
14799
14874
  ctx.addIssue({
14800
- code: z55.ZodIssueCode.custom,
14875
+ code: z56.ZodIssueCode.custom,
14801
14876
  path: [
14802
14877
  "campaignDailyBudget"
14803
14878
  ],
@@ -14808,7 +14883,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
14808
14883
  value.adSets.forEach((adSet, index) => {
14809
14884
  if (adSet.dailyBudget === void 0) {
14810
14885
  ctx.addIssue({
14811
- code: z55.ZodIssueCode.custom,
14886
+ code: z56.ZodIssueCode.custom,
14812
14887
  path: [
14813
14888
  "adSets",
14814
14889
  index,
@@ -14823,26 +14898,26 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
14823
14898
  ...value,
14824
14899
  budgetMode: resolveBudgetMode(value)
14825
14900
  }));
14826
- var PublishCreativesToMetaInputBase = z55.object({
14827
- creatives: z55.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
14901
+ var PublishCreativesToMetaInputBase = z56.object({
14902
+ creatives: z56.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
14828
14903
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
14829
- portfolioId: z55.string().trim().min(1),
14904
+ portfolioId: z56.string().trim().min(1),
14830
14905
  /** Exact Facebook Page selected from `list_meta_destinations`. */
14831
- pageId: z55.string().trim().min(1),
14906
+ pageId: z56.string().trim().min(1),
14832
14907
  adAccountId: McpAdAccountId,
14833
- pixelId: z55.string().min(1).optional(),
14908
+ pixelId: z56.string().min(1).optional(),
14834
14909
  /** Required unless `campaignConfig.destination` is whatsapp — see the
14835
14910
  * 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),
14911
+ landingUrl: z56.string().url().optional(),
14912
+ targetCountry: z56.string().length(2),
14913
+ campaignName: z56.string().trim().min(1).max(100),
14839
14914
  campaignConfig: GroupedCampaignConfig.optional()
14840
14915
  });
14841
14916
  var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
14842
14917
  const destination = value.campaignConfig?.destination;
14843
14918
  if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
14844
14919
  ctx.addIssue({
14845
- code: z55.ZodIssueCode.custom,
14920
+ code: z56.ZodIssueCode.custom,
14846
14921
  path: [
14847
14922
  "landingUrl"
14848
14923
  ],
@@ -14851,7 +14926,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
14851
14926
  }
14852
14927
  if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
14853
14928
  ctx.addIssue({
14854
- code: z55.ZodIssueCode.custom,
14929
+ code: z56.ZodIssueCode.custom,
14855
14930
  path: [
14856
14931
  "campaignConfig",
14857
14932
  "destination",
@@ -14870,16 +14945,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
14870
14945
  }
14871
14946
  return value;
14872
14947
  });
14873
- var PresignUploadResponseSchema = z55.object({
14874
- uploadUrl: z55.string().url().refine((value) => {
14948
+ var PresignUploadResponseSchema = z56.object({
14949
+ uploadUrl: z56.string().url().refine((value) => {
14875
14950
  const url = new URL(value);
14876
14951
  return !url.username && !url.password && url.protocol === "https:";
14877
14952
  }, "presigned upload URL must be HTTPS without embedded credentials"),
14878
- publicUrl: z55.string().url().refine((value) => {
14953
+ publicUrl: z56.string().url().refine((value) => {
14879
14954
  const url = new URL(value);
14880
14955
  return !url.username && !url.password;
14881
14956
  }, "public media URL must not contain embedded credentials"),
14882
- stagingAssetId: z55.string().uuid()
14957
+ stagingAssetId: z56.string().uuid()
14883
14958
  });
14884
14959
  async function uploadResolvedMedia(api, media, assetRole) {
14885
14960
  if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
@@ -14904,16 +14979,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
14904
14979
  return uploadResolvedMedia(api, media, assetRole);
14905
14980
  }
14906
14981
  __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(),
14982
+ var TikTokInput = z56.object({
14983
+ taskId: z56.string().min(1),
14984
+ advertiserId: z56.string().min(1),
14985
+ pixelId: z56.string().min(1).optional(),
14986
+ landingUrl: z56.string().url().optional(),
14987
+ angleIndexes: z56.array(z56.number().int().nonnegative()).optional(),
14913
14988
  campaignConfig: McpCampaignConfig.optional(),
14914
14989
  /** Override the ad's description (TikTok's body copy). If omitted,
14915
14990
  * ProductMaker uses the auto-generated copy attached to the task. */
14916
- primaryText: z55.string().trim().min(1).max(500).optional()
14991
+ primaryText: z56.string().trim().min(1).max(500).optional()
14917
14992
  });
14918
14993
  function registerPublishTools(server, api, opts = {}) {
14919
14994
  const transport = opts.transport ?? "http";
@@ -15163,38 +15238,38 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
15163
15238
 
15164
15239
  // src/tools/meta-upload.ts
15165
15240
  import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
15166
- import { z as z56 } from "zod";
15167
- var UploadSessionInputBase = z56.object({
15168
- mediaKind: z56.enum([
15241
+ import { z as z57 } from "zod";
15242
+ var UploadSessionInputBase = z57.object({
15243
+ mediaKind: z57.enum([
15169
15244
  "image",
15170
15245
  "video",
15171
15246
  "mixed"
15172
15247
  ]).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([
15248
+ assetRole: z57.enum([
15174
15249
  "media",
15175
15250
  "thumbnail"
15176
15251
  ]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
15177
- uploadPurpose: z56.enum([
15252
+ uploadPurpose: z57.enum([
15178
15253
  "product_reference",
15179
15254
  "creative",
15180
15255
  "generic"
15181
15256
  ]).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.")
15257
+ 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
15258
  });
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()
15259
+ var OpenAiFileReference = z57.object({
15260
+ 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."),
15261
+ file_id: z57.string().min(1),
15262
+ mime_type: z57.string().min(1).optional(),
15263
+ file_name: z57.string().min(1).optional()
15189
15264
  });
15190
15265
  var UploadSessionToolInputShape = {
15191
15266
  ...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.")
15267
+ 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
15268
  };
15194
- var UploadSessionToolInput = z56.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
15269
+ var UploadSessionToolInput = z57.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
15195
15270
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
15196
15271
  ctx.addIssue({
15197
- code: z56.ZodIssueCode.custom,
15272
+ code: z57.ZodIssueCode.custom,
15198
15273
  path: [
15199
15274
  "mediaKind"
15200
15275
  ],
@@ -15203,7 +15278,7 @@ var UploadSessionToolInput = z56.object(UploadSessionToolInputShape).superRefine
15203
15278
  }
15204
15279
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
15205
15280
  ctx.addIssue({
15206
- code: z56.ZodIssueCode.custom,
15281
+ code: z57.ZodIssueCode.custom,
15207
15282
  path: [
15208
15283
  "maxFiles"
15209
15284
  ],
@@ -15212,7 +15287,7 @@ var UploadSessionToolInput = z56.object(UploadSessionToolInputShape).superRefine
15212
15287
  }
15213
15288
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
15214
15289
  ctx.addIssue({
15215
- code: z56.ZodIssueCode.custom,
15290
+ code: z57.ZodIssueCode.custom,
15216
15291
  path: [
15217
15292
  "maxFiles"
15218
15293
  ],
@@ -15220,38 +15295,38 @@ var UploadSessionToolInput = z56.object(UploadSessionToolInputShape).superRefine
15220
15295
  });
15221
15296
  }
15222
15297
  });
15223
- var UploadSessionResponse = z56.object({
15224
- sessionId: z56.string().uuid(),
15225
- uploadPageUrl: z56.string().url(),
15226
- mediaKind: z56.enum([
15298
+ var UploadSessionResponse = z57.object({
15299
+ sessionId: z57.string().uuid(),
15300
+ uploadPageUrl: z57.string().url(),
15301
+ mediaKind: z57.enum([
15227
15302
  "image",
15228
15303
  "video",
15229
15304
  "mixed"
15230
15305
  ]),
15231
- assetRole: z56.enum([
15306
+ assetRole: z57.enum([
15232
15307
  "media",
15233
15308
  "thumbnail"
15234
15309
  ]),
15235
- maxFiles: z56.number().int().positive(),
15236
- expiresAt: z56.string().datetime()
15310
+ maxFiles: z57.number().int().positive(),
15311
+ expiresAt: z57.string().datetime()
15237
15312
  });
15238
- var UploadStatusInput = z56.object({
15239
- sessionId: z56.string().uuid().describe("The sessionId returned by request_media_upload.")
15313
+ var UploadStatusInput = z57.object({
15314
+ sessionId: z57.string().uuid().describe("The sessionId returned by request_media_upload.")
15240
15315
  });
15241
- var UniversalUploadStatusResponse = z56.discriminatedUnion("status", [
15242
- z56.object({
15243
- status: z56.literal("pending"),
15244
- assets: z56.array(z56.never()).length(0)
15316
+ var UniversalUploadStatusResponse = z57.discriminatedUnion("status", [
15317
+ z57.object({
15318
+ status: z57.literal("pending"),
15319
+ assets: z57.array(z57.never()).length(0)
15245
15320
  }),
15246
- z56.object({
15247
- status: z56.literal("uploaded"),
15248
- assets: z56.array(z56.object({
15249
- assetId: z56.string().uuid(),
15250
- mediaKind: z56.enum([
15321
+ z57.object({
15322
+ status: z57.literal("uploaded"),
15323
+ assets: z57.array(z57.object({
15324
+ assetId: z57.string().uuid(),
15325
+ mediaKind: z57.enum([
15251
15326
  "image",
15252
15327
  "video"
15253
15328
  ]),
15254
- assetRole: z56.enum([
15329
+ assetRole: z57.enum([
15255
15330
  "media",
15256
15331
  "thumbnail"
15257
15332
  ])
@@ -15259,13 +15334,13 @@ var UniversalUploadStatusResponse = z56.discriminatedUnion("status", [
15259
15334
  })
15260
15335
  ]);
15261
15336
  var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
15262
- uploadPurpose: z56.enum([
15337
+ uploadPurpose: z57.enum([
15263
15338
  "product_reference",
15264
15339
  "creative",
15265
15340
  "generic"
15266
15341
  ]),
15267
- checkToolName: z56.literal("check_media_upload"),
15268
- resolveEndpoint: z56.string().url()
15342
+ checkToolName: z57.literal("check_media_upload"),
15343
+ resolveEndpoint: z57.string().url()
15269
15344
  });
15270
15345
  function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
15271
15346
  const url = new URL(uploadPageUrl);
@@ -15356,13 +15431,13 @@ function registerMediaUploadTools(server, api) {
15356
15431
  __name(registerMediaUploadTools, "registerMediaUploadTools");
15357
15432
 
15358
15433
  // 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.")
15434
+ import { z as z58 } from "zod";
15435
+ var MetaStatusInput = z58.object({
15436
+ campaignId: z58.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
15362
15437
  });
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.")
15438
+ var TikTokStatusInput = z58.object({
15439
+ campaignId: z58.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
15440
+ advertiserId: z58.string().min(1).describe("The same advertiserId used to publish the campaign.")
15366
15441
  });
15367
15442
  function registerCampaignTools(server, api) {
15368
15443
  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 +15534,10 @@ function renderTikTokStatusMarkdown(r) {
15459
15534
  __name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
15460
15535
 
15461
15536
  // ../../packages/product-economics/src/product-costing.ts
15462
- import { z as z59 } from "zod";
15537
+ import { z as z60 } from "zod";
15463
15538
 
15464
15539
  // ../../packages/product-economics/src/product-costing-countries.ts
15465
- import { z as z58 } from "zod";
15540
+ import { z as z59 } from "zod";
15466
15541
 
15467
15542
  // ../../packages/product-economics/src/product-costing-shipping-references.json
15468
15543
  var product_costing_shipping_references_default = {
@@ -15526,21 +15601,21 @@ var product_costing_shipping_references_default = {
15526
15601
  };
15527
15602
 
15528
15603
  // ../../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([
15604
+ var ShippingReferenceSchema = z59.object({
15605
+ reference: z59.number().positive(),
15606
+ min: z59.number().nonnegative(),
15607
+ max: z59.number().positive(),
15608
+ updatedAt: z59.string().date(),
15609
+ confidence: z59.enum([
15535
15610
  "high",
15536
15611
  "medium",
15537
15612
  "medium-low"
15538
15613
  ]),
15539
- sources: z58.array(z58.string().url().startsWith("https://")).min(1).max(3)
15614
+ sources: z59.array(z59.string().url().startsWith("https://")).min(1).max(3)
15540
15615
  }).superRefine(({ reference, min, max }, context) => {
15541
15616
  if (min > reference || reference > max) {
15542
15617
  context.addIssue({
15543
- code: z58.ZodIssueCode.custom,
15618
+ code: z59.ZodIssueCode.custom,
15544
15619
  message: "shipping_reference_outside_range",
15545
15620
  path: [
15546
15621
  "reference"
@@ -15548,7 +15623,7 @@ var ShippingReferenceSchema = z58.object({
15548
15623
  });
15549
15624
  }
15550
15625
  });
15551
- var SHIPPING_REFERENCES = z58.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
15626
+ var SHIPPING_REFERENCES = z59.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
15552
15627
  var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
15553
15628
  var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
15554
15629
  "MX",
@@ -15730,18 +15805,18 @@ function getProductCostingCountryName(country) {
15730
15805
  __name(getProductCostingCountryName, "getProductCostingCountryName");
15731
15806
 
15732
15807
  // ../../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")
15808
+ var ProductCostingInputSchema = z60.object({
15809
+ country: z60.string().refine(isProductCostingCountryCode, "unsupported_country"),
15810
+ supplierCost: z60.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
15811
+ shippingCost: z60.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
15812
+ returnRate: z60.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
15813
+ cancellationRate: z60.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
15814
+ adsManagerCpa: z60.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
15815
+ desiredMargin: z60.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
15741
15816
  }).superRefine(({ returnRate, cancellationRate }, context) => {
15742
15817
  if (returnRate + cancellationRate >= 1) {
15743
15818
  context.addIssue({
15744
- code: z59.ZodIssueCode.custom,
15819
+ code: z60.ZodIssueCode.custom,
15745
15820
  message: "delivery_rate_positive",
15746
15821
  path: [
15747
15822
  "cancellationRate"
@@ -15808,14 +15883,14 @@ function calculateProductCosting(rawInput) {
15808
15883
  __name(calculateProductCosting, "calculateProductCosting");
15809
15884
 
15810
15885
  // 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, {
15886
+ import { z as z61 } from "zod";
15887
+ var optionalAmount = /* @__PURE__ */ __name((description) => z61.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
15888
+ var optionalPercent = /* @__PURE__ */ __name((description) => z61.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
15889
+ var ProductCostingToolInput = z61.object({
15890
+ country: z61.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
15816
15891
  message: "Pa\xEDs no soportado por ProductMaker."
15817
15892
  }).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."),
15893
+ 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
15894
  supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
15820
15895
  shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
15821
15896
  shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
@@ -15947,7 +16022,7 @@ function formatPercent(value) {
15947
16022
  __name(formatPercent, "formatPercent");
15948
16023
 
15949
16024
  // src/tools/product-research.ts
15950
- import { z as z61 } from "zod";
16025
+ import { z as z62 } from "zod";
15951
16026
 
15952
16027
  // src/tools/product-research-idempotency.ts
15953
16028
  import { createHash as createHash3 } from "crypto";
@@ -16063,17 +16138,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
16063
16138
  ]);
16064
16139
  var POLL_INTERVAL_MS = 5e3;
16065
16140
  var MAX_WAIT_SECONDS = 120;
16066
- var FindInput = z61.object({
16141
+ var FindInput = z62.object({
16067
16142
  targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
16068
16143
  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.")
16144
+ 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.`),
16145
+ 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
16146
  });
16072
- var GetInput = z61.object({
16073
- runId: z61.string().uuid().describe("ID del run devuelto por find_winning_products.")
16147
+ var GetInput = z62.object({
16148
+ runId: z62.string().uuid().describe("ID del run devuelto por find_winning_products.")
16074
16149
  });
16075
- var ListInput = z61.object({
16076
- limit: z61.number().int().min(1).max(20).default(10)
16150
+ var ListInput = z62.object({
16151
+ limit: z62.number().int().min(1).max(20).default(10)
16077
16152
  });
16078
16153
  function textResult(text) {
16079
16154
  return {
@@ -16165,14 +16240,14 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
16165
16240
  __name(registerProductResearchTools, "registerProductResearchTools");
16166
16241
 
16167
16242
  // src/tools/dropshipping-projects.ts
16168
- import { z as z62 } from "zod";
16169
- var ProjectId = z62.string().uuid();
16170
- var DropshippingProjectStatus = z62.enum([
16243
+ import { z as z63 } from "zod";
16244
+ var ProjectId = z63.string().uuid();
16245
+ var DropshippingProjectStatus = z63.enum([
16171
16246
  "active",
16172
16247
  "completed",
16173
16248
  "archived"
16174
16249
  ]);
16175
- var DropshippingProjectPhase = z62.enum([
16250
+ var DropshippingProjectPhase = z63.enum([
16176
16251
  "research",
16177
16252
  "costing",
16178
16253
  "media",
@@ -16181,21 +16256,21 @@ var DropshippingProjectPhase = z62.enum([
16181
16256
  "advertising",
16182
16257
  "complete"
16183
16258
  ]);
16184
- var DropshippingRewardMilestone = z62.enum([
16259
+ var DropshippingRewardMilestone = z63.enum([
16185
16260
  "product_selected",
16186
16261
  "costing_saved",
16187
16262
  "product_media_ready",
16188
16263
  "creatives_completed",
16189
16264
  "campaign_created"
16190
16265
  ]);
16191
- var TargetCountry = z62.enum([
16266
+ var TargetCountry = z63.enum([
16192
16267
  "CO",
16193
16268
  "MX",
16194
16269
  "PE",
16195
16270
  "EC",
16196
16271
  "CL"
16197
16272
  ]);
16198
- var ResearchCategory = z62.enum([
16273
+ var ResearchCategory = z63.enum([
16199
16274
  "auto",
16200
16275
  "automotive",
16201
16276
  "kitchen",
@@ -16210,7 +16285,7 @@ var ResearchCategory = z62.enum([
16210
16285
  "garden",
16211
16286
  "cleaning"
16212
16287
  ]);
16213
- var HttpUrl3 = z62.string().url().max(2e3).refine((value) => {
16288
+ var HttpUrl3 = z63.string().url().max(2e3).refine((value) => {
16214
16289
  try {
16215
16290
  return [
16216
16291
  "http:",
@@ -16220,43 +16295,43 @@ var HttpUrl3 = z62.string().url().max(2e3).refine((value) => {
16220
16295
  return false;
16221
16296
  }
16222
16297
  }, "URL must use HTTP(S)");
16223
- var ResearchCandidateOrigin = z62.object({
16224
- type: z62.literal("research_candidate"),
16298
+ var ResearchCandidateOrigin = z63.object({
16299
+ type: z63.literal("research_candidate"),
16225
16300
  runId: ProjectId,
16226
- candidateSourceId: z62.string().min(1).max(160)
16301
+ candidateSourceId: z63.string().min(1).max(160)
16227
16302
  });
16228
- var TaskOrigin = z62.object({
16229
- type: z62.literal("task"),
16303
+ var TaskOrigin = z63.object({
16304
+ type: z63.literal("task"),
16230
16305
  taskId: ProjectId
16231
16306
  });
16232
- var ManualOrigin = z62.object({
16233
- type: z62.literal("manual"),
16307
+ var ManualOrigin = z63.object({
16308
+ type: z63.literal("manual"),
16234
16309
  clientRequestId: ProjectId,
16235
- country: z62.string().min(2).max(3).optional()
16310
+ country: z63.string().min(2).max(3).optional()
16236
16311
  });
16237
- var StartProjectInput = z62.object({
16238
- origin: z62.discriminatedUnion("type", [
16312
+ var StartProjectInput = z63.object({
16313
+ origin: z63.discriminatedUnion("type", [
16239
16314
  ResearchCandidateOrigin,
16240
16315
  TaskOrigin,
16241
16316
  ManualOrigin
16242
16317
  ]),
16243
- productName: z62.string().trim().min(1).max(240).optional(),
16318
+ productName: z63.string().trim().min(1).max(240).optional(),
16244
16319
  productUrl: HttpUrl3.optional(),
16245
- country: z62.string().min(2).max(3).optional(),
16246
- languageCode: z62.string().min(2).max(16).optional()
16320
+ country: z63.string().min(2).max(3).optional(),
16321
+ languageCode: z63.string().min(2).max(16).optional()
16247
16322
  }).strict();
16248
- var CostProjectInput = z62.object({
16323
+ var CostProjectInput = z63.object({
16249
16324
  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({
16325
+ version: z63.number().int().positive(),
16326
+ country: z63.string().trim().min(2).max(3),
16327
+ supplierCost: z63.number().finite().positive(),
16328
+ shippingCost: z63.number().finite().nonnegative(),
16329
+ returnRate: z63.number().finite().min(0).lt(1),
16330
+ cancellationRate: z63.number().finite().min(0).lt(1),
16331
+ adsManagerCpa: z63.number().finite().nonnegative(),
16332
+ desiredMargin: z63.number().finite().min(0).lt(1)
16333
+ });
16334
+ var GuideInput = z63.object({
16260
16335
  projectId: ProjectId.optional()
16261
16336
  }).strict();
16262
16337
  var NEXT_ACTION_KINDS = [
@@ -16274,29 +16349,29 @@ var NEXT_ACTION_KINDS = [
16274
16349
  "repair_meta_campaign",
16275
16350
  "review_paused_campaign"
16276
16351
  ];
16277
- var DropshippingProjectNextAction = z62.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z62.object({
16278
- kind: z62.literal(kind),
16279
- href: z62.string().min(1)
16352
+ var DropshippingProjectNextAction = z63.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z63.object({
16353
+ kind: z63.literal(kind),
16354
+ href: z63.string().min(1)
16280
16355
  })));
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)
16356
+ var CostingInputSchema = z63.object({
16357
+ country: z63.string().min(2).max(3),
16358
+ supplierCost: z63.number().finite().positive(),
16359
+ shippingCost: z63.number().finite().nonnegative(),
16360
+ returnRate: z63.number().finite().min(0).lt(1),
16361
+ cancellationRate: z63.number().finite().min(0).lt(1),
16362
+ adsManagerCpa: z63.number().finite().nonnegative(),
16363
+ desiredMargin: z63.number().finite().min(0).lt(1)
16289
16364
  }).superRefine(({ returnRate, cancellationRate }, context) => {
16290
16365
  if (returnRate + cancellationRate >= 1) context.addIssue({
16291
- code: z62.ZodIssueCode.custom,
16366
+ code: z63.ZodIssueCode.custom,
16292
16367
  path: [
16293
16368
  "cancellationRate"
16294
16369
  ]
16295
16370
  });
16296
16371
  });
16297
- var FiniteCostingNumber = z62.number().finite();
16298
- var CostingResultSchema = z62.object({
16299
- country: z62.string().min(2).max(3),
16372
+ var FiniteCostingNumber = z63.number().finite();
16373
+ var CostingResultSchema = z63.object({
16374
+ country: z63.string().min(2).max(3),
16300
16375
  deliveryRate: FiniteCostingNumber,
16301
16376
  adjustedShippingCost: FiniteCostingNumber,
16302
16377
  adjustedCpa: FiniteCostingNumber,
@@ -16309,44 +16384,44 @@ var CostingResultSchema = z62.object({
16309
16384
  estimatedProfit: FiniteCostingNumber,
16310
16385
  actualMargin: FiniteCostingNumber,
16311
16386
  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({
16387
+ wasPriceAutoAdjusted: z63.boolean(),
16388
+ profitabilityStatus: z63.literal("healthy")
16389
+ });
16390
+ var RewardProgressSchema = z63.object({
16391
+ campaignKey: z63.literal("dropshipping-launch-v1"),
16392
+ totalCredits: z63.number().int().positive(),
16393
+ earnedCredits: z63.number().int().nonnegative(),
16394
+ milestones: z63.array(z63.object({
16320
16395
  milestone: DropshippingRewardMilestone,
16321
- credits: z62.number().int().positive(),
16322
- available: z62.boolean().optional(),
16323
- earned: z62.boolean(),
16396
+ credits: z63.number().int().positive(),
16397
+ available: z63.boolean().optional(),
16398
+ earned: z63.boolean(),
16324
16399
  grantId: ProjectId.nullable(),
16325
- grantedAt: z62.string().datetime().nullable()
16400
+ grantedAt: z63.string().datetime().nullable()
16326
16401
  })).length(DropshippingRewardMilestone.options.length)
16327
16402
  });
16328
- var ProjectResponseSchema = z62.object({
16403
+ var ProjectResponseSchema = z63.object({
16329
16404
  id: ProjectId,
16330
16405
  taskId: ProjectId.nullable(),
16331
16406
  status: DropshippingProjectStatus,
16332
- originKey: z62.string().min(1),
16407
+ originKey: z63.string().min(1),
16333
16408
  researchRunId: ProjectId.nullable(),
16334
- candidateSourceId: z62.string().nullable(),
16335
- productName: z62.string().nullable(),
16409
+ candidateSourceId: z63.string().nullable(),
16410
+ productName: z63.string().nullable(),
16336
16411
  productUrl: HttpUrl3.nullable(),
16337
16412
  referenceImageUrl: HttpUrl3.nullable(),
16338
- targetCountry: z62.string().nullable(),
16339
- languageCode: z62.string().nullable(),
16340
- hasReferenceImage: z62.boolean(),
16413
+ targetCountry: z63.string().nullable(),
16414
+ languageCode: z63.string().nullable(),
16415
+ hasReferenceImage: z63.boolean(),
16341
16416
  costingInput: CostingInputSchema.nullable(),
16342
16417
  costingResult: CostingResultSchema.nullable(),
16343
- costingVersion: z62.number().int().positive().nullable(),
16344
- version: z62.number().int().positive(),
16418
+ costingVersion: z63.number().int().positive().nullable(),
16419
+ version: z63.number().int().positive(),
16345
16420
  phase: DropshippingProjectPhase,
16346
16421
  nextAction: DropshippingProjectNextAction.nullable(),
16347
16422
  rewards: RewardProgressSchema,
16348
- createdAt: z62.string().datetime(),
16349
- updatedAt: z62.string().datetime()
16423
+ createdAt: z63.string().datetime(),
16424
+ updatedAt: z63.string().datetime()
16350
16425
  }).passthrough();
16351
16426
  var NEXT_ACTION_GUIDANCE = {
16352
16427
  cost_product: "Llama `cost_dropshipping_project` con el costo real del proveedor. Nunca lo inventes: p\xEDdeselo al usuario.",