@productmaker/mcp 12.1.1 → 12.1.3

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.
package/dist/http.js CHANGED
@@ -2766,9 +2766,9 @@ var ClassicLandingSelectionSnapshotSchema = z18.object({
2766
2766
  }).strict().superRefine((snapshot, ctx) => {
2767
2767
  if (snapshot.images) {
2768
2768
  const selectedImages = snapshot.blocks.filter((block) => block.kind === "image");
2769
- const ids = snapshot.images.map((image) => classicLandingBlockId({
2769
+ const ids = snapshot.images.map((image2) => classicLandingBlockId({
2770
2770
  kind: "image",
2771
- ...image
2771
+ ...image2
2772
2772
  }));
2773
2773
  if (new Set(ids).size !== ids.length || ids.length !== selectedImages.length || selectedImages.some((block) => !ids.includes(classicLandingBlockId(block)))) ctx.addIssue({
2774
2774
  code: z18.ZodIssueCode.custom,
@@ -15716,9 +15716,9 @@ var MotionGraphicsVoiceDirectionSchema = z78.object({
15716
15716
  pace: z78.enum(MOTION_GRAPHICS_VOICE_PACES)
15717
15717
  }).strict();
15718
15718
  var AUDIO_TAG = /\[(?:sighs|laughs softly|short pause|emphatic|whispers|gasps|hesitant|warmly)\]/g;
15719
- function motionGraphicsTaggedSpeechMatches(text3, tagged) {
15719
+ function motionGraphicsTaggedSpeechMatches(text4, tagged) {
15720
15720
  const normalize = /* @__PURE__ */ __name((value) => value.normalize("NFC").replace(/\s+/g, " ").trim(), "normalize");
15721
- return normalize(tagged.replace(AUDIO_TAG, "")) === normalize(text3);
15721
+ return normalize(tagged.replace(AUDIO_TAG, "")) === normalize(text4);
15722
15722
  }
15723
15723
  __name(motionGraphicsTaggedSpeechMatches, "motionGraphicsTaggedSpeechMatches");
15724
15724
  var MotionGraphicsTaggedSpeechSchema = z78.string().trim().min(1).max(1200);
@@ -21890,10 +21890,10 @@ var GENDER_ALIASES = {
21890
21890
  };
21891
21891
  function matchAlias(raw, aliases) {
21892
21892
  if (typeof raw !== "string") return void 0;
21893
- const text3 = raw.trim().toLowerCase();
21894
- const exact = aliases[text3];
21893
+ const text4 = raw.trim().toLowerCase();
21894
+ const exact = aliases[text4];
21895
21895
  if (exact) return exact;
21896
- const words = new Set(text3.split(/[^a-z]+/).filter(Boolean));
21896
+ const words = new Set(text4.split(/[^a-z]+/).filter(Boolean));
21897
21897
  for (const [alias, value] of Object.entries(aliases)) {
21898
21898
  if (words.has(alias)) return value;
21899
21899
  }
@@ -23785,26 +23785,118 @@ var WebsiteCaptureResearchSchema = z116.object({
23785
23785
  });
23786
23786
 
23787
23787
  // ../../packages/types/src/demo-mode.ts
23788
- import { z as z118 } from "zod";
23788
+ import { z as z119 } from "zod";
23789
23789
 
23790
- // ../../packages/types/src/demo-mode-service-page-assets.ts
23790
+ // ../../packages/types/src/demo-mode-product.ts
23791
23791
  import { z as z117 } from "zod";
23792
- var DemoServicePageAssetSourceSchema = z117.object({
23793
- pageId: z117.string().uuid(),
23794
- ownerId: z117.string().min(1),
23795
- assets: z117.array(z117.object({
23796
- id: z117.string().uuid(),
23797
- storageKey: z117.string().min(1).max(1024),
23798
- mediaType: z117.enum([
23792
+ var text3 = z117.string().trim().min(1).max(2e5);
23793
+ var nullableText = z117.string().max(2e5).nullable();
23794
+ var image = z117.object({
23795
+ provider: text3,
23796
+ model: text3,
23797
+ prompt: z117.string().max(2e5),
23798
+ imageUrl: text3,
23799
+ width: z117.number().int().positive(),
23800
+ height: z117.number().int().positive(),
23801
+ adCopy: nullableText,
23802
+ rawResponse: z117.unknown()
23803
+ });
23804
+ var ProductDemoSnapshotSchema = z117.object({
23805
+ product: z117.object({
23806
+ title: text3,
23807
+ price: nullableText,
23808
+ country: nullableText,
23809
+ features: z117.array(text3).max(100),
23810
+ form: nullableText,
23811
+ details: z117.unknown(),
23812
+ isCombo: z117.boolean(),
23813
+ comboItems: z117.unknown(),
23814
+ images: z117.array(text3).min(1).max(50),
23815
+ cleanImages: z117.array(text3).max(50),
23816
+ cleanImagesMeta: z117.unknown()
23817
+ }),
23818
+ angles: z117.array(z117.object({
23819
+ content: text3,
23820
+ buyerPersona: nullableText,
23821
+ actor: nullableText,
23822
+ scriptNotes: nullableText
23823
+ })).min(1).max(10),
23824
+ videos: z117.array(z117.object({
23825
+ /** Present only for explicit multi-template packs; legacy arrays keep selection-order playback. */
23826
+ reviewAngleIndex: z117.number().int().min(0).max(9).optional(),
23827
+ provider: text3,
23828
+ model: text3,
23829
+ script: text3,
23830
+ prompt: z117.string().max(2e5),
23831
+ imageUrl: text3,
23832
+ durationSeconds: z117.number().int().positive().nullable(),
23833
+ format: VideoFormat,
23834
+ resultUrls: z117.array(text3).min(1).max(10),
23835
+ rawResponse: z117.unknown(),
23836
+ adCopy: nullableText
23837
+ })).min(1).max(10),
23838
+ landingImages: z117.array(z117.object({
23839
+ role: LandingRole,
23840
+ indexNum: z117.number().int().min(1),
23841
+ url: text3,
23842
+ width: z117.number().int().positive(),
23843
+ height: z117.number().int().positive(),
23844
+ notes: nullableText
23845
+ })).max(20),
23846
+ landingConfig: z117.unknown(),
23847
+ image,
23848
+ productUseSheet: z117.unknown(),
23849
+ productTruth: z117.unknown(),
23850
+ productReference: z117.object({
23851
+ referenceEvidenceVersion: z117.number().int().nonnegative(),
23852
+ planVersion: z117.number().int().positive(),
23853
+ baseReferenceSetHash: text3,
23854
+ referenceSet: z117.unknown(),
23855
+ preparationPlan: z117.unknown(),
23856
+ canonicalIdentityAnchors: z117.unknown()
23857
+ })
23858
+ });
23859
+ var ProductDemoPhaseSchema = z117.enum([
23860
+ "preparing",
23861
+ "angles",
23862
+ "preparing_scripts",
23863
+ "scripts",
23864
+ "generating",
23865
+ "done"
23866
+ ]);
23867
+ var ProductDemoJobPhaseSchema = z117.enum([
23868
+ "preparing",
23869
+ "scripts",
23870
+ "generating"
23871
+ ]);
23872
+ var ProductDemoTaskStateSchema = z117.object({
23873
+ admitted: z117.boolean().default(false),
23874
+ phase: ProductDemoPhaseSchema,
23875
+ waitMs: z117.number().int().positive(),
23876
+ snapshot: ProductDemoSnapshotSchema,
23877
+ selectedAngleIndices: z117.array(z117.number().int().min(0).max(9)).max(10),
23878
+ chargeCents: z117.number().int().min(0).max(1e5),
23879
+ maxCents: z117.number().int().min(0).optional()
23880
+ });
23881
+
23882
+ // ../../packages/types/src/demo-mode-service-page-assets.ts
23883
+ import { z as z118 } from "zod";
23884
+ var DemoServicePageAssetSourceSchema = z118.object({
23885
+ pageId: z118.string().uuid(),
23886
+ ownerId: z118.string().min(1),
23887
+ assets: z118.array(z118.object({
23888
+ id: z118.string().uuid(),
23889
+ storageKey: z118.string().min(1).max(1024),
23890
+ mediaType: z118.enum([
23799
23891
  "image/webp",
23800
23892
  "video/mp4"
23801
23893
  ]),
23802
- byteSize: z117.number().int().positive().max(32 * 1024 * 1024),
23803
- width: z117.number().int().positive().max(1920),
23804
- height: z117.number().int().positive().max(1920),
23805
- contentHash: z117.string().regex(/^[a-f0-9]{64}$/i),
23894
+ byteSize: z118.number().int().positive().max(32 * 1024 * 1024),
23895
+ width: z118.number().int().positive().max(1920),
23896
+ height: z118.number().int().positive().max(1920),
23897
+ contentHash: z118.string().regex(/^[a-f0-9]{64}$/i),
23806
23898
  sourceKind: ServicePageSourceKindSchema,
23807
- approvedAt: z117.string().datetime()
23899
+ approvedAt: z118.string().datetime()
23808
23900
  }).strict()).max(24)
23809
23901
  }).strict();
23810
23902
 
@@ -23813,9 +23905,10 @@ var DEMO_MODE_FLOWS = [
23813
23905
  "brand",
23814
23906
  "servicePage",
23815
23907
  "motion",
23816
- "image"
23908
+ "image",
23909
+ "product"
23817
23910
  ];
23818
- var DemoModeFlowSchema = z118.enum(DEMO_MODE_FLOWS);
23911
+ var DemoModeFlowSchema = z119.enum(DEMO_MODE_FLOWS);
23819
23912
  var DEMO_MODE_STEPS = [
23820
23913
  "running",
23821
23914
  "research",
@@ -23828,108 +23921,166 @@ var DEMO_MODE_STEPS = [
23828
23921
  "final",
23829
23922
  "watchdog"
23830
23923
  ];
23831
- var DemoModeStepSchema = z118.enum(DEMO_MODE_STEPS);
23924
+ var DemoModeStepSchema = z119.enum(DEMO_MODE_STEPS);
23832
23925
  var DEMO_MODE_WAIT_SECONDS = {
23833
23926
  min: 30,
23834
23927
  max: 450,
23835
23928
  default: 150
23836
23929
  };
23837
- var centsSchema = z118.number().int().min(0).max(1e5);
23838
- var emailSchema = z118.string().trim().toLowerCase().email();
23839
- var optionalTemplateId = z118.preprocess((value) => value === "" ? void 0 : value, z118.string().uuid().optional());
23840
- var DemoModeTemplatesSchema = z118.object({
23841
- brandId: z118.string().uuid(),
23842
- servicePageId: z118.string().uuid(),
23843
- motionTaskId: z118.string().uuid(),
23930
+ var DEMO_MODE_DEFAULT_CHARGE_CENTS = {
23931
+ brand: 100,
23932
+ servicePage: 300,
23933
+ motion: 1500,
23934
+ image: 200,
23935
+ product: 1500
23936
+ };
23937
+ var centsSchema = z119.number().int().min(0).max(1e5);
23938
+ var emailSchema = z119.string().trim().toLowerCase().email();
23939
+ var DEMO_MODE_OPTIONAL_MOTION_TEMPLATE_KEYS = [
23940
+ "motionVariantTaskId",
23941
+ "motionThirdTaskId"
23942
+ ];
23943
+ var DEMO_MODE_OPTIONAL_PRODUCT_VIDEO_TEMPLATE_KEYS = [
23944
+ "productVideoVariantTaskId",
23945
+ "productVideoThirdTaskId"
23946
+ ];
23947
+ var DEMO_MODE_PRODUCT_VIDEO_TEMPLATE_KEYS = [
23948
+ "productVideoTaskId",
23949
+ ...DEMO_MODE_OPTIONAL_PRODUCT_VIDEO_TEMPLATE_KEYS
23950
+ ];
23951
+ var DEMO_MODE_PRODUCT_TEMPLATE_KEYS = [
23952
+ "productLandingTaskId",
23953
+ "productVideoTaskId",
23954
+ "productImageTaskId"
23955
+ ];
23956
+ var DEMO_MODE_PRODUCT_ALL_TEMPLATE_KEYS = [
23957
+ ...DEMO_MODE_PRODUCT_TEMPLATE_KEYS,
23958
+ ...DEMO_MODE_OPTIONAL_PRODUCT_VIDEO_TEMPLATE_KEYS
23959
+ ];
23960
+ var DEMO_MODE_OPTIONAL_TEMPLATE_KEYS = [
23961
+ ...DEMO_MODE_OPTIONAL_MOTION_TEMPLATE_KEYS,
23962
+ ...DEMO_MODE_PRODUCT_ALL_TEMPLATE_KEYS
23963
+ ];
23964
+ var optionalTemplateId = z119.preprocess((value) => value === "" ? void 0 : value, z119.string().uuid().optional());
23965
+ var DemoModeTemplatesSchema = z119.object({
23966
+ brandId: z119.string().uuid(),
23967
+ servicePageId: z119.string().uuid(),
23968
+ motionTaskId: z119.string().uuid(),
23844
23969
  motionVariantTaskId: optionalTemplateId,
23845
23970
  motionThirdTaskId: optionalTemplateId,
23846
- imageTaskId: z118.string().uuid()
23847
- });
23848
- var DemoModeEditableSchema = z118.object({
23849
- enabled: z118.boolean(),
23850
- emails: z118.array(emailSchema).max(50).transform((list) => [
23971
+ imageTaskId: z119.string().uuid(),
23972
+ productLandingTaskId: optionalTemplateId,
23973
+ productVideoTaskId: optionalTemplateId,
23974
+ productVideoVariantTaskId: optionalTemplateId,
23975
+ productVideoThirdTaskId: optionalTemplateId,
23976
+ productImageTaskId: optionalTemplateId
23977
+ });
23978
+ var DemoModeEditableObjectSchema = z119.object({
23979
+ productsEnabled: z119.boolean().default(false),
23980
+ enabled: z119.boolean(),
23981
+ emails: z119.array(emailSchema).max(50).transform((list) => [
23851
23982
  ...new Set(list)
23852
23983
  ]),
23853
- waitSeconds: z118.number().int().min(DEMO_MODE_WAIT_SECONDS.min).max(DEMO_MODE_WAIT_SECONDS.max),
23854
- chargeCents: z118.object({
23984
+ waitSeconds: z119.number().int().min(DEMO_MODE_WAIT_SECONDS.min).max(DEMO_MODE_WAIT_SECONDS.max),
23985
+ chargeCents: z119.object({
23855
23986
  brand: centsSchema,
23856
23987
  servicePage: centsSchema,
23857
23988
  motion: centsSchema,
23858
- image: centsSchema
23989
+ image: centsSchema,
23990
+ product: centsSchema.default(DEMO_MODE_DEFAULT_CHARGE_CENTS.product)
23859
23991
  }),
23860
23992
  templates: DemoModeTemplatesSchema
23861
23993
  });
23862
- var nullableString = z118.string().nullable();
23863
- var DemoModeSnapshotSchema = z118.object({
23864
- brand: z118.object({
23994
+ var DemoModeEditableSchema = DemoModeEditableObjectSchema.superRefine((value, ctx) => {
23995
+ if (!value.productsEnabled) return;
23996
+ for (const key of DEMO_MODE_PRODUCT_TEMPLATE_KEYS) {
23997
+ if (!value.templates[key]) ctx.addIssue({
23998
+ code: z119.ZodIssueCode.custom,
23999
+ path: [
24000
+ "templates",
24001
+ key
24002
+ ],
24003
+ message: "Product demo requires all three templates"
24004
+ });
24005
+ }
24006
+ });
24007
+ var nullableString = z119.string().nullable();
24008
+ var DemoModeSnapshotSchema = z119.object({
24009
+ product: ProductDemoSnapshotSchema.optional(),
24010
+ brand: z119.object({
23865
24011
  /** Columnas de identidad de `Brand` listas para un `update` (sin id/userId/slug/estado/fechas). */
23866
- identity: z118.record(z118.unknown()),
23867
- productSamples: z118.array(z118.object({
23868
- name: z118.string(),
23869
- priceCents: z118.number().int().nullable(),
24012
+ identity: z119.record(z119.unknown()),
24013
+ productSamples: z119.array(z119.object({
24014
+ name: z119.string(),
24015
+ priceCents: z119.number().int().nullable(),
23870
24016
  currency: nullableString,
23871
- imageKey: z118.string(),
24017
+ imageKey: z119.string(),
23872
24018
  productUrl: nullableString,
23873
- position: z118.number().int()
24019
+ position: z119.number().int()
23874
24020
  })),
23875
- personas: z118.array(z118.object({
23876
- name: z118.string(),
24021
+ personas: z119.array(z119.object({
24022
+ name: z119.string(),
23877
24023
  demographics: nullableString,
23878
24024
  painPoints: nullableString,
23879
24025
  motivations: nullableString,
23880
24026
  objections: nullableString,
23881
24027
  gender: nullableString,
23882
- isDefault: z118.boolean()
24028
+ isDefault: z119.boolean()
23883
24029
  }))
23884
24030
  }),
23885
- servicePage: z118.object({
23886
- facts: z118.unknown(),
23887
- review: z118.unknown(),
23888
- artifact: z118.unknown(),
24031
+ servicePage: z119.object({
24032
+ facts: z119.unknown(),
24033
+ review: z119.unknown(),
24034
+ artifact: z119.unknown(),
23889
24035
  /** Optional only for snapshots saved before page-owned demo media. */
23890
24036
  assetSource: DemoServicePageAssetSourceSchema.optional()
23891
24037
  }),
23892
- motion: z118.object({
24038
+ motion: z119.object({
23893
24039
  outputs: MotionGraphicsOutputsSchema,
23894
24040
  /**
23895
24041
  * La captura REAL de la web de la plantilla (nunca una fabricada por la
23896
24042
  * demo). Null cuando la plantilla no tiene ninguna: la captura demo nunca
23897
24043
  * va live, así que el servicio usa `DEMO_MODE_PLACEHOLDER_CAPTURE`.
23898
24044
  */
23899
- capture: z118.object({
23900
- bundleKey: z118.string(),
23901
- sha256: z118.string(),
23902
- uploadBytes: z118.number().int().nullable(),
24045
+ capture: z119.object({
24046
+ bundleKey: z119.string(),
24047
+ sha256: z119.string(),
24048
+ uploadBytes: z119.number().int().nullable(),
23903
24049
  previewKey: nullableString
23904
24050
  }).nullable()
23905
24051
  }),
23906
- image: z118.object({
23907
- provider: z118.string(),
23908
- model: z118.string(),
23909
- prompt: z118.string(),
23910
- imageUrl: z118.string(),
23911
- width: z118.number().int(),
23912
- height: z118.number().int(),
24052
+ image: z119.object({
24053
+ provider: z119.string(),
24054
+ model: z119.string(),
24055
+ prompt: z119.string(),
24056
+ imageUrl: z119.string(),
24057
+ width: z119.number().int(),
24058
+ height: z119.number().int(),
23913
24059
  adCopy: nullableString,
23914
- rawResponse: z118.unknown()
24060
+ rawResponse: z119.unknown()
23915
24061
  })
23916
24062
  });
23917
- var DemoModeConfigSchema = DemoModeEditableSchema.extend({
24063
+ var DemoModeConfigSchema = DemoModeEditableObjectSchema.extend({
23918
24064
  snapshot: DemoModeSnapshotSchema.nullable(),
23919
- snapshotAt: z118.string().datetime().nullable()
24065
+ snapshotAt: z119.string().datetime().nullable()
23920
24066
  });
23921
- var DemoModeAdminViewSchema = DemoModeEditableSchema.extend({
24067
+ var DemoModeAdminViewSchema = DemoModeEditableObjectSchema.extend({
23922
24068
  // Sin configurar, la API devuelve ids vacíos ("" no es uuid): la vista los
23923
24069
  // admite; el PUT sí exige uuid (`DemoModeEditableSchema`).
23924
- templates: z118.object({
23925
- brandId: z118.string(),
23926
- servicePageId: z118.string(),
23927
- motionTaskId: z118.string(),
23928
- motionVariantTaskId: z118.string().optional(),
23929
- motionThirdTaskId: z118.string().optional(),
23930
- imageTaskId: z118.string()
24070
+ templates: z119.object({
24071
+ brandId: z119.string(),
24072
+ servicePageId: z119.string(),
24073
+ motionTaskId: z119.string(),
24074
+ motionVariantTaskId: z119.string().optional(),
24075
+ motionThirdTaskId: z119.string().optional(),
24076
+ imageTaskId: z119.string(),
24077
+ productLandingTaskId: z119.string().optional(),
24078
+ productVideoTaskId: z119.string().optional(),
24079
+ productVideoVariantTaskId: z119.string().optional(),
24080
+ productVideoThirdTaskId: z119.string().optional(),
24081
+ productImageTaskId: z119.string().optional()
23931
24082
  }),
23932
- snapshotAt: z118.string().nullable()
24083
+ snapshotAt: z119.string().nullable()
23933
24084
  });
23934
24085
  var DEMO_MODE_TEMPLATE_PROBLEMS = [
23935
24086
  "not_found",
@@ -23938,35 +24089,45 @@ var DEMO_MODE_TEMPLATE_PROBLEMS = [
23938
24089
  "artifact_invalid",
23939
24090
  "task_not_done",
23940
24091
  "no_video",
23941
- "no_creative"
24092
+ "no_creative",
24093
+ "product_invalid",
24094
+ "product_mismatch",
24095
+ "no_angles",
24096
+ "no_landing"
23942
24097
  ];
23943
- var DemoModeTemplateVerdictSchema = z118.discriminatedUnion("ok", [
23944
- z118.object({
23945
- ok: z118.literal(true)
24098
+ var DemoModeTemplateVerdictSchema = z119.discriminatedUnion("ok", [
24099
+ z119.object({
24100
+ ok: z119.literal(true)
23946
24101
  }),
23947
- z118.object({
23948
- ok: z118.literal(false),
23949
- problem: z118.enum(DEMO_MODE_TEMPLATE_PROBLEMS)
24102
+ z119.object({
24103
+ ok: z119.literal(false),
24104
+ problem: z119.enum(DEMO_MODE_TEMPLATE_PROBLEMS)
23950
24105
  })
23951
24106
  ]);
23952
- var DemoModeValidationSchema = z118.object({
24107
+ var DemoModeValidationSchema = z119.object({
23953
24108
  brandId: DemoModeTemplateVerdictSchema,
23954
24109
  servicePageId: DemoModeTemplateVerdictSchema,
23955
24110
  motionTaskId: DemoModeTemplateVerdictSchema,
23956
24111
  motionVariantTaskId: DemoModeTemplateVerdictSchema.optional(),
23957
24112
  motionThirdTaskId: DemoModeTemplateVerdictSchema.optional(),
23958
- imageTaskId: DemoModeTemplateVerdictSchema
23959
- });
23960
- var DemoModeJobSchema = z118.object({
24113
+ imageTaskId: DemoModeTemplateVerdictSchema,
24114
+ productLandingTaskId: DemoModeTemplateVerdictSchema.optional(),
24115
+ productVideoTaskId: DemoModeTemplateVerdictSchema.optional(),
24116
+ productVideoVariantTaskId: DemoModeTemplateVerdictSchema.optional(),
24117
+ productVideoThirdTaskId: DemoModeTemplateVerdictSchema.optional(),
24118
+ productImageTaskId: DemoModeTemplateVerdictSchema.optional()
24119
+ });
24120
+ var DemoModeJobSchema = z119.object({
23961
24121
  flow: DemoModeFlowSchema,
24122
+ productPhase: ProductDemoJobPhaseSchema.optional(),
23962
24123
  step: DemoModeStepSchema,
23963
24124
  /** brandId | servicePageOperationId | taskId según el flujo. */
23964
- targetId: z118.string().uuid(),
23965
- userId: z118.string().min(1),
24125
+ targetId: z119.string().uuid(),
24126
+ userId: z119.string().min(1),
23966
24127
  /** Solo marca: la generación de extracción que el guion completa. */
23967
- generation: z118.number().int().positive().optional(),
24128
+ generation: z119.number().int().positive().optional(),
23968
24129
  /** Solo `final`/`watchdog`: la parte del snapshot de ESTE flujo, congelada al empezar. */
23969
- result: z118.unknown().optional()
24130
+ result: z119.unknown().optional()
23970
24131
  });
23971
24132
 
23972
24133
  // src/http.ts
@@ -24144,8 +24305,8 @@ async function readResponseText(response, maxBytes) {
24144
24305
  }
24145
24306
  __name(readResponseText, "readResponseText");
24146
24307
  async function readResponseJson(response, maxBytes) {
24147
- const text3 = await readResponseText(response, maxBytes);
24148
- return JSON.parse(text3);
24308
+ const text4 = await readResponseText(response, maxBytes);
24309
+ return JSON.parse(text4);
24149
24310
  }
24150
24311
  __name(readResponseJson, "readResponseJson");
24151
24312
 
@@ -24478,23 +24639,23 @@ import { InsufficientScopeError, InvalidTokenError } from "@modelcontextprotocol
24478
24639
  import { createRemoteJWKSet as createRemoteJWKSet2, jwtVerify as jwtVerify2 } from "jose";
24479
24640
 
24480
24641
  // src/auth/oauth-config.ts
24481
- import { z as z119 } from "zod";
24642
+ import { z as z120 } from "zod";
24482
24643
  var MCP_RESOURCE = new URL("https://mcp.productmaker.app/mcp");
24483
24644
  var MCP_SCOPE = "mcp:access";
24484
24645
  var REFRESH_SCOPE = "offline_access";
24485
24646
  var STATIC_CLIENT_ISSUER = new URL(MCP_RESOURCE.origin);
24486
- var oauthEnvSchema = z119.object({
24487
- MCP_REMOTE_AUTH_MODE: z119.literal("oauth"),
24488
- MCP_AUTH0_ISSUER: z119.string().trim().min(1),
24489
- MCP_AUTH0_AUDIENCE: z119.string().trim().refine((value) => value === MCP_RESOURCE.href, {
24647
+ var oauthEnvSchema = z120.object({
24648
+ MCP_REMOTE_AUTH_MODE: z120.literal("oauth"),
24649
+ MCP_AUTH0_ISSUER: z120.string().trim().min(1),
24650
+ MCP_AUTH0_AUDIENCE: z120.string().trim().refine((value) => value === MCP_RESOURCE.href, {
24490
24651
  message: `must equal ${MCP_RESOURCE.href}`
24491
24652
  }),
24492
- MCP_AUTH0_CLIENT_ID: z119.string().trim().min(1),
24493
- MCP_AUTH0_CLIENT_SECRET: z119.string().trim().min(1),
24494
- PM_API_AUDIENCE: z119.string().trim().min(1),
24495
- AUTH0_AUDIENCE: z119.string().trim().min(1),
24496
- MCP_STATIC_CLIENT_ID: z119.string().trim().min(1).optional(),
24497
- MCP_STATIC_CLIENT_SECRET: z119.string().trim().min(1).optional()
24653
+ MCP_AUTH0_CLIENT_ID: z120.string().trim().min(1),
24654
+ MCP_AUTH0_CLIENT_SECRET: z120.string().trim().min(1),
24655
+ PM_API_AUDIENCE: z120.string().trim().min(1),
24656
+ AUTH0_AUDIENCE: z120.string().trim().min(1),
24657
+ MCP_STATIC_CLIENT_ID: z120.string().trim().min(1).optional(),
24658
+ MCP_STATIC_CLIENT_SECRET: z120.string().trim().min(1).optional()
24498
24659
  });
24499
24660
  function formatZodIssues(error) {
24500
24661
  return error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
@@ -25883,7 +26044,7 @@ var ApiClient = class {
25883
26044
  };
25884
26045
 
25885
26046
  // src/index.ts
25886
- var MCP_VERSION = "12.1.1";
26047
+ var MCP_VERSION = "12.1.3";
25887
26048
 
25888
26049
  // src/meta-upload-app.ts
25889
26050
  import { readFileSync } from "fs";
@@ -25980,12 +26141,12 @@ function buildTaskResultsView(media, proxyBaseUrl) {
25980
26141
  return null;
25981
26142
  }
25982
26143
  }, "safeUrl");
25983
- const images = media.images.flatMap((image, index) => {
25984
- const url = safeUrl(image.url);
26144
+ const images = media.images.flatMap((image2, index) => {
26145
+ const url = safeUrl(image2.url);
25985
26146
  return url ? [
25986
26147
  {
25987
26148
  url,
25988
- alt: image.alt?.slice(0, 160) ?? `ProductMaker image ${index + 1}`
26149
+ alt: image2.alt?.slice(0, 160) ?? `ProductMaker image ${index + 1}`
25989
26150
  }
25990
26151
  ] : [];
25991
26152
  });
@@ -26070,7 +26231,7 @@ function registerTaskResultsAppResource(server, proxyBaseUrl) {
26070
26231
  __name(registerTaskResultsAppResource, "registerTaskResultsAppResource");
26071
26232
 
26072
26233
  // src/tools/tasks.ts
26073
- import { z as z125 } from "zod";
26234
+ import { z as z126 } from "zod";
26074
26235
 
26075
26236
  // src/resolve-image.ts
26076
26237
  import { lookup as dnsLookup } from "dns/promises";
@@ -26631,9 +26792,9 @@ async function resolveMediaRef(ref, opts) {
26631
26792
  __name(resolveMediaRef, "resolveMediaRef");
26632
26793
 
26633
26794
  // src/tools/shared.ts
26634
- import { z as z120 } from "zod";
26635
- var Lang = z120.string().regex(/^[a-z]{2}(?:[-_][a-zA-Z]{2})?$/, "Usa un c\xF3digo de idioma BCP-47, por ejemplo es, en-US o pt-BR").max(10);
26636
- var Country = z120.string().min(2).max(3);
26795
+ import { z as z121 } from "zod";
26796
+ var Lang = z121.string().regex(/^[a-z]{2}(?:[-_][a-zA-Z]{2})?$/, "Usa un c\xF3digo de idioma BCP-47, por ejemplo es, en-US o pt-BR").max(10);
26797
+ var Country = z121.string().min(2).max(3);
26637
26798
  var LandingStrategyEnum = LandingStrategySchema;
26638
26799
  var LandingImageFormatEnum = LandingImageFormatSchema;
26639
26800
  var VideoPresetEnum = VideoPreset.extract([
@@ -26737,7 +26898,7 @@ function animationStyleApplies(videoPreset, angleNarratives) {
26737
26898
  return ANIMATED_VIDEO_PRESETS.has(videoPreset ?? "") || (angleNarratives ?? []).some((n) => ANIMATED_NARRATIVE_STYLES.has(n));
26738
26899
  }
26739
26900
  __name(animationStyleApplies, "animationStyleApplies");
26740
- var VideoTierEnum = z120.enum([
26901
+ var VideoTierEnum = z121.enum([
26741
26902
  "basic"
26742
26903
  ]);
26743
26904
  function resolveVideoTier(_tier) {
@@ -26795,10 +26956,10 @@ var ImageCreativeStyleEnum = ImageCreativeStyle;
26795
26956
  var ImageCreativeArchetypeEnum = ImageCreativeArchetype;
26796
26957
  var ImageCreativeVisualTreatmentEnum = ImageCreativeVisualTreatment;
26797
26958
  var ImageCreativeAspectRatioEnum = ImageCreativeAspectRatio;
26798
- var ImageRefSchema = z120.object({
26799
- url: z120.string().url().optional().describe('URL p\xFAblica HTTPS de la foto. Ej: una URL de Shopify CDN, Cloudinary, Imgur. \xDAsala cuando el usuario te diga "est\xE1 en X.com/foto.jpg" o cuando la foto ya est\xE9 hospedada.'),
26800
- path: z120.string().min(1).optional().describe('Ruta del archivo en el computador del usuario. Ej: "/Users/maria/Desktop/foto.jpg", "~/Pictures/camiseta.png", "C:\\Users\\Maria\\Desktop\\foto.jpg". El MCP local la lee del disco y la sube. SOLO funciona cuando el MCP corre local (stdio). NO funciona en mcp.productmaker.app (HTTP) \u2014 ah\xED usa `url`.'),
26801
- assetId: z120.string().uuid().optional().describe("ID opaco devuelto por check_media_upload. \xDAsalo para una imagen subida desde el MCP App; ProductMaker adopta el archivo directamente y el MCP nunca descarga sus bytes.")
26959
+ var ImageRefSchema = z121.object({
26960
+ url: z121.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.'),
26961
+ path: z121.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`.'),
26962
+ assetId: z121.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.")
26802
26963
  }).refine((v) => [
26803
26964
  v.url,
26804
26965
  v.path,
@@ -26806,18 +26967,18 @@ var ImageRefSchema = z120.object({
26806
26967
  ].filter(Boolean).length === 1, {
26807
26968
  message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
26808
26969
  });
26809
- var ImagesInput = z120.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
26810
- const assetCount = images.filter((image) => Boolean(image.assetId)).length;
26970
+ var ImagesInput = z121.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
26971
+ const assetCount = images.filter((image2) => Boolean(image2.assetId)).length;
26811
26972
  if (assetCount > 0 && assetCount !== images.length) {
26812
26973
  ctx.addIssue({
26813
- code: z120.ZodIssueCode.custom,
26974
+ code: z121.ZodIssueCode.custom,
26814
26975
  message: "all image entries must use assetId, or all must use URL/path sources"
26815
26976
  });
26816
26977
  }
26817
26978
  }).describe('1 a 5 fotos del MISMO producto. La PRIMERA es la principal (hero); las dem\xE1s son \xE1ngulos adicionales. NO mezcles productos distintos en una sola llamada.\n\nCada entrada tiene EXACTAMENTE uno de:\n\u2022 `url` \u2014 URL p\xFAblica HTTPS (Shopify CDN, Cloudinary). Prefi\xE9rela si la foto ya est\xE1 hospedada.\n\u2022 `path` \u2014 Ruta del archivo en el computador del usuario (ej. "/Users/maria/Desktop/foto.jpg", "~/Downloads/camiseta.png"). \xDAsala cuando el usuario te dijo d\xF3nde guard\xF3 la foto. Solo MCP local \u2014 el cliente web rechaza paths.\n\n\u2022 `assetId` \u2014 ID opaco devuelto por `check_media_upload`. En MCP remoto, si el usuario quiere usar una foto de su laptop, llama `request_media_upload` y no pidas una ruta local ni URL.\n\nNo mezcles assetId con URL/path en la misma llamada. Los paths se conservan solo para MCP local por stdio.');
26818
26979
  function uploadedAssetIds(images) {
26819
- if (!images.length || !images.every((image) => Boolean(image.assetId))) return null;
26820
- return images.map((image) => image.assetId);
26980
+ if (!images.length || !images.every((image2) => Boolean(image2.assetId))) return null;
26981
+ return images.map((image2) => image2.assetId);
26821
26982
  }
26822
26983
  __name(uploadedAssetIds, "uploadedAssetIds");
26823
26984
  function asText(value) {
@@ -26891,14 +27052,14 @@ async function submitCreative(api, opts) {
26891
27052
  });
26892
27053
  }
26893
27054
  __name(submitCreative, "submitCreative");
26894
- var ResearchTargetCountryEnum = z120.enum([
27055
+ var ResearchTargetCountryEnum = z121.enum([
26895
27056
  "CO",
26896
27057
  "MX",
26897
27058
  "PE",
26898
27059
  "EC",
26899
27060
  "CL"
26900
27061
  ]);
26901
- var ResearchCategoryEnum = z120.enum([
27062
+ var ResearchCategoryEnum = z121.enum([
26902
27063
  "auto",
26903
27064
  "automotive",
26904
27065
  "kitchen",
@@ -27693,7 +27854,7 @@ function approveRefusalMessage(reason) {
27693
27854
  __name(approveRefusalMessage, "approveRefusalMessage");
27694
27855
 
27695
27856
  // src/tools/task-outputs.ts
27696
- import { z as z121 } from "zod";
27857
+ import { z as z122 } from "zod";
27697
27858
 
27698
27859
  // src/tools/conversational-review-format.ts
27699
27860
  function escapeMarkdownText(value) {
@@ -27824,12 +27985,12 @@ function serviceVideoResultMedia(result) {
27824
27985
  };
27825
27986
  }
27826
27987
  __name(serviceVideoResultMedia, "serviceVideoResultMedia");
27827
- var CreativeVariantIdentity = z121.object({
27828
- variantTaskId: z121.string().uuid(),
27829
- sourceTaskId: z121.string().uuid(),
27988
+ var CreativeVariantIdentity = z122.object({
27989
+ variantTaskId: z122.string().uuid(),
27990
+ sourceTaskId: z122.string().uuid(),
27830
27991
  kind: TaskCreativeVariantKind,
27831
27992
  status: TaskStatusSchema,
27832
- error: z121.string().optional()
27993
+ error: z122.string().optional()
27833
27994
  });
27834
27995
  function proxifyOutputs(outputs, proxyBaseUrl) {
27835
27996
  if (!proxyBaseUrl || !isProxyEnabled()) return outputs;
@@ -28433,59 +28594,59 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
28433
28594
  __name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
28434
28595
 
28435
28596
  // src/tools/media-presentation.ts
28436
- import { z as z122 } from "zod";
28437
- var HttpsPresentationUrlSchema = z122.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
28597
+ import { z as z123 } from "zod";
28598
+ var HttpsPresentationUrlSchema = z123.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
28438
28599
  var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
28439
28600
  const hostname = new URL(value).hostname.toLowerCase();
28440
28601
  return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
28441
28602
  }, "preview URL must be owned by ProductMaker");
28442
- var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z122.number().int().positive().max(maximum), "positiveIntAtMost");
28443
- var PresentationImageSchema = z122.object({
28444
- kind: z122.literal("image"),
28603
+ var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z123.number().int().positive().max(maximum), "positiveIntAtMost");
28604
+ var PresentationImageSchema = z123.object({
28605
+ kind: z123.literal("image"),
28445
28606
  url: HttpsPresentationUrlSchema,
28446
- mimeType: z122.enum([
28607
+ mimeType: z123.enum([
28447
28608
  "image/jpeg",
28448
28609
  "image/png"
28449
28610
  ]),
28450
28611
  byteSize: positiveIntAtMost(5 * 1024 * 1024),
28451
28612
  width: positiveIntAtMost(16384),
28452
28613
  height: positiveIntAtMost(16384),
28453
- alt: z122.string().trim().min(1).max(240)
28614
+ alt: z123.string().trim().min(1).max(240)
28454
28615
  }).strict();
28455
28616
  var McpMediaPresentationSchema = PresentationImageSchema;
28456
- var GalleryImageSchema = z122.object({
28617
+ var GalleryImageSchema = z123.object({
28457
28618
  url: ProductMakerPreviewUrlSchema,
28458
- alt: z122.string().trim().min(1).max(240)
28619
+ alt: z123.string().trim().min(1).max(240)
28459
28620
  });
28460
28621
  var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
28461
- async function imageBlocks(image, transport) {
28622
+ async function imageBlocks(image2, transport) {
28462
28623
  const portableFallback = [
28463
28624
  {
28464
28625
  type: "resource_link",
28465
- uri: image.url,
28466
- name: image.alt,
28467
- ...image.mimeType ? {
28468
- mimeType: image.mimeType
28626
+ uri: image2.url,
28627
+ name: image2.alt,
28628
+ ...image2.mimeType ? {
28629
+ mimeType: image2.mimeType
28469
28630
  } : {},
28470
- ...image.byteSize ? {
28471
- size: image.byteSize
28631
+ ...image2.byteSize ? {
28632
+ size: image2.byteSize
28472
28633
  } : {}
28473
28634
  },
28474
28635
  {
28475
28636
  type: "text",
28476
- text: `Si no ves la imagen, \xE1brela aqu\xED: ${image.url}`
28637
+ text: `Si no ves la imagen, \xE1brela aqu\xED: ${image2.url}`
28477
28638
  }
28478
28639
  ];
28479
28640
  try {
28480
28641
  const [resolved] = await resolveImages([
28481
28642
  {
28482
- url: image.url
28643
+ url: image2.url
28483
28644
  }
28484
28645
  ], {
28485
28646
  transport,
28486
- maxBytes: image.byteSize ?? MCP_GALLERY_IMAGE_MAX_BYTES
28647
+ maxBytes: image2.byteSize ?? MCP_GALLERY_IMAGE_MAX_BYTES
28487
28648
  });
28488
- if (!resolved || image.mimeType && resolved.mimetype !== image.mimeType || resolved.buffer.byteLength > (image.byteSize ?? MCP_GALLERY_IMAGE_MAX_BYTES)) {
28649
+ if (!resolved || image2.mimeType && resolved.mimetype !== image2.mimeType || resolved.buffer.byteLength > (image2.byteSize ?? MCP_GALLERY_IMAGE_MAX_BYTES)) {
28489
28650
  return portableFallback;
28490
28651
  }
28491
28652
  return [
@@ -28512,12 +28673,12 @@ async function buildMcpMediaPresentationContent(rawPresentation, transport = "ht
28512
28673
  ];
28513
28674
  }
28514
28675
  __name(buildMcpMediaPresentationContent, "buildMcpMediaPresentationContent");
28515
- var OwnedImagePreviewSchema = z122.object({
28676
+ var OwnedImagePreviewSchema = z123.object({
28516
28677
  url: HttpsPresentationUrlSchema.refine((value) => {
28517
28678
  const url = new URL(value);
28518
28679
  return !url.username && !url.password && !isPrivateHost(url.hostname);
28519
28680
  }, "Preview URL must be public HTTPS without credentials"),
28520
- alt: z122.string().trim().min(1).max(240)
28681
+ alt: z123.string().trim().min(1).max(240)
28521
28682
  });
28522
28683
  async function buildMcpImagePreviewContent(rawPreview, transport = "http") {
28523
28684
  const preview2 = OwnedImagePreviewSchema.safeParse(rawPreview);
@@ -28593,24 +28754,24 @@ async function buildMcpImageGalleryContent(rawItems, transport = "http") {
28593
28754
  }
28594
28755
  ];
28595
28756
  }
28596
- const image = parsed.data;
28757
+ const image2 = parsed.data;
28597
28758
  const heading = {
28598
28759
  type: "text",
28599
- text: `Foto ${index + 1}: ${image.alt}`
28760
+ text: `Foto ${index + 1}: ${image2.alt}`
28600
28761
  };
28601
28762
  const fallback = {
28602
28763
  type: "resource_link",
28603
- uri: image.url,
28604
- name: `Abrir foto ${index + 1}: ${image.alt}`
28764
+ uri: image2.url,
28765
+ name: `Abrir foto ${index + 1}: ${image2.alt}`
28605
28766
  };
28606
28767
  const textFallback = {
28607
28768
  type: "text",
28608
- text: `Si no ves la foto ${index + 1}, \xE1brela aqu\xED: ${image.url}`
28769
+ text: `Si no ves la foto ${index + 1}, \xE1brela aqu\xED: ${image2.url}`
28609
28770
  };
28610
28771
  try {
28611
28772
  const [resolved] = await resolveImages([
28612
28773
  {
28613
- url: image.url
28774
+ url: image2.url
28614
28775
  }
28615
28776
  ], {
28616
28777
  transport,
@@ -28712,7 +28873,7 @@ async function observeMcpMediaDelivery(fingerprint, work) {
28712
28873
  __name(observeMcpMediaDelivery, "observeMcpMediaDelivery");
28713
28874
 
28714
28875
  // src/tools/animated-video.ts
28715
- import { z as z123 } from "zod";
28876
+ import { z as z124 } from "zod";
28716
28877
 
28717
28878
  // src/tools/paid-confirmation.ts
28718
28879
  function describeMarketStudyChoice(enabled) {
@@ -28961,30 +29122,30 @@ function hookVariantsLabel(count) {
28961
29122
  return count === 1 ? "1 versi\xF3n del gancho" : `${count} versiones del gancho`;
28962
29123
  }
28963
29124
  __name(hookVariantsLabel, "hookVariantsLabel");
28964
- var DurationInput = z123.union(MOTION_GRAPHICS_DURATIONS.map((d) => z123.literal(d)));
28965
- var CreateAnimatedVideoInput = z123.object({
28966
- action: z123.enum([
29125
+ var DurationInput = z124.union(MOTION_GRAPHICS_DURATIONS.map((d) => z124.literal(d)));
29126
+ var CreateAnimatedVideoInput = z124.object({
29127
+ action: z124.enum([
28967
29128
  "prepare",
28968
29129
  "status",
28969
29130
  "cancel",
28970
29131
  "generate"
28971
29132
  ]).default("prepare").describe("prepare inicia una captura gratuita; status consulta websiteCaptureId; cancel la cancela; generate requiere captura ready y confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrar vista previa y precio."),
28972
- brandId: z123.string().uuid().optional().describe("ID de un servicio propio y listo (de create_brand). Obligatorio al preparar y crear videos nuevos. Conserva el mismo brandId en reintentos; si recuperas una generaci\xF3n hist\xF3rica aceptada sin este campo, om\xEDtelo como en la petici\xF3n original. status/cancel no lo necesitan."),
28973
- websiteCaptureId: z123.string().uuid().optional().describe("ID de la captura preparada. Obligatorio para status/cancel/generate; no inventarlo."),
28974
- generationRequestId: z123.string().uuid().optional().describe("Identidad opcional de una generaci\xF3n confirmada. Repite el mismo UUID al recuperar una respuesta perdida; usa otro \xFAnicamente cuando el usuario pida y confirme otro video, nunca por un error de transporte."),
28975
- confirmed: z123.boolean().optional().describe("Solo true despu\xE9s de que el usuario confirme esta captura, formato, duraci\xF3n, idioma y precio. Obligatorio para generate; preparar no genera ni cobra."),
29133
+ brandId: z124.string().uuid().optional().describe("ID de un servicio propio y listo (de create_brand). Obligatorio al preparar y crear videos nuevos. Conserva el mismo brandId en reintentos; si recuperas una generaci\xF3n hist\xF3rica aceptada sin este campo, om\xEDtelo como en la petici\xF3n original. status/cancel no lo necesitan."),
29134
+ websiteCaptureId: z124.string().uuid().optional().describe("ID de la captura preparada. Obligatorio para status/cancel/generate; no inventarlo."),
29135
+ generationRequestId: z124.string().uuid().optional().describe("Identidad opcional de una generaci\xF3n confirmada. Repite el mismo UUID al recuperar una respuesta perdida; usa otro \xFAnicamente cuando el usuario pida y confirme otro video, nunca por un error de transporte."),
29136
+ confirmed: z124.boolean().optional().describe("Solo true despu\xE9s de que el usuario confirme esta captura, formato, duraci\xF3n, idioma y precio. Obligatorio para generate; preparar no genera ni cobra."),
28976
29137
  // Plain text, not `.url()`: users type «cal.com», and the web accepts it.
28977
29138
  // normalizeWebAddress (shared with the web) adds https:// and refuses
28978
29139
  // anything that is not a public http(s) address.
28979
- landingUrl: z123.string().trim().min(1).optional().describe("Enlace p\xFAblico de la p\xE1gina del servicio, como lo dio el usuario (\xABcal.com\xBB o \xABhttps://cal.com\xBB). El video sale de lo que muestra esa p\xE1gina: su marca, colores y mensajes."),
29140
+ landingUrl: z124.string().trim().min(1).optional().describe("Enlace p\xFAblico de la p\xE1gina del servicio, como lo dio el usuario (\xABcal.com\xBB o \xABhttps://cal.com\xBB). El video sale de lo que muestra esa p\xE1gina: su marca, colores y mensajes."),
28980
29141
  format: MotionGraphicsFormatSchema.optional().describe('Formato: "vertical" (9:16, Reels/TikTok), "square" (1:1, feed) u "horizontal" (16:9, YouTube/web). Si el usuario no lo dijo, PREG\xDANTALE.'),
28981
29142
  durationSec: DurationInput.optional().describe(`Duraci\xF3n en segundos: ${MOTION_GRAPHICS_DURATIONS.join(", ")}. Fija el precio (ver la descripci\xF3n de la herramienta). Si el usuario no la dijo, PREG\xDANTALE.`),
28982
29143
  language: MotionGraphicsLanguageSchema.optional().describe('Idioma de los textos del video: "es", "en" o "pt".'),
28983
29144
  videoQuality: MotionGraphicsVideoQualitySchema.default(DEFAULT_MOTION_GRAPHICS_VIDEO_QUALITY).describe('Calidad IA: "economy" (econ\xF3mica) o "pro" (alta, por defecto). Afecta el precio de los clips IA.'),
28984
29145
  videoResolution: MotionGraphicsVideoResolutionSchema.default(DEFAULT_MOTION_GRAPHICS_VIDEO_RESOLUTION).describe('Resoluci\xF3n: "480p" (por defecto), "720p" o "1080p". 1080p solo est\xE1 disponible con videoQuality="pro".'),
28985
- notes: z123.string().trim().max(MOTION_GRAPHICS_NOTES_MAX_CHARS).optional().describe("Opcional. Idea creativa, escenarios, acciones, di\xE1logo, voz o m\xFAsica en lenguaje natural. El director puede hacer solo motion graphics, escenas reales o escenas imposibles seg\xFAn la idea; las frases gu\xEDan el guion sin garantizar reproducci\xF3n exacta."),
29146
+ notes: z124.string().trim().max(MOTION_GRAPHICS_NOTES_MAX_CHARS).optional().describe("Opcional. Idea creativa, escenarios, acciones, di\xE1logo, voz o m\xFAsica en lenguaje natural. El director puede hacer solo motion graphics, escenas reales o escenas imposibles seg\xFAn la idea; las frases gu\xEDan el guion sin garantizar reproducci\xF3n exacta."),
28986
29147
  hookVariants: MotionGraphicsHookVariantsSchema.optional().describe(`Opcional. Cantidad de videos independientes, de 1 a ${MOTION_GRAPHICS_HOOK_VARIANTS_MAX} (por defecto 1). Cada uno tiene su propio \xE1ngulo, guion y estilo visual, respetando notes, y reserva el precio completo de un video (ver la descripci\xF3n); \xFAsalo solo si el usuario lo pide.`),
28987
- music: z123.boolean().optional().describe("Opcional. M\xFAsica y efectos dirigidos seg\xFAn el negocio y el video (por defecto true), con una copia adicional solo con voces. false entrega solo voces, sin m\xFAsica ni efectos a\xF1adidos ni el cargo de m\xFAsica. \xDAsalo solo si el usuario lo pide.")
29148
+ music: z124.boolean().optional().describe("Opcional. M\xFAsica y efectos dirigidos seg\xFAn el negocio y el video (por defecto true), con una copia adicional solo con voces. false entrega solo voces, sin m\xFAsica ni efectos a\xF1adidos ni el cargo de m\xFAsica. \xDAsalo solo si el usuario lo pide.")
28988
29149
  }).strict();
28989
29150
  function captureNextAction(capture) {
28990
29151
  if (capture.status === "ready") return "Muestra la vista previa al usuario y confirma formato, duraci\xF3n, idioma, calidad IA, resoluci\xF3n y precio. Solo despu\xE9s llama create_animated_video con action=generate, este websiteCaptureId y confirmed=true.";
@@ -29037,33 +29198,33 @@ var FORMAT_LABELS = {
29037
29198
  square: "cuadrado 1:1",
29038
29199
  horizontal: "horizontal 16:9"
29039
29200
  };
29040
- var AnimatedVideoResultSchema = z123.object({
29041
- status: z123.enum([
29201
+ var AnimatedVideoResultSchema = z124.object({
29202
+ status: z124.enum([
29042
29203
  "pending",
29043
29204
  "done",
29044
29205
  "error"
29045
29206
  ]),
29046
- serviceMode: z123.literal("motion_graphics"),
29047
- finalMp4Url: z123.string().optional(),
29048
- adCopy: z123.string().optional(),
29049
- adCopies: z123.array(z123.string()).optional(),
29050
- error: z123.string().optional(),
29051
- motionGraphics: z123.object({
29207
+ serviceMode: z124.literal("motion_graphics"),
29208
+ finalMp4Url: z124.string().optional(),
29209
+ adCopy: z124.string().optional(),
29210
+ adCopies: z124.array(z124.string()).optional(),
29211
+ error: z124.string().optional(),
29212
+ motionGraphics: z124.object({
29052
29213
  stage: MotionGraphicsStageSchema,
29053
29214
  format: MotionGraphicsFormatSchema,
29054
- durationSec: z123.number(),
29055
- width: z123.number().optional(),
29056
- height: z123.number().optional(),
29215
+ durationSec: z124.number(),
29216
+ width: z124.number().optional(),
29217
+ height: z124.number().optional(),
29057
29218
  language: MotionGraphicsLanguageSchema.optional(),
29058
29219
  videoQuality: MotionGraphicsVideoQualitySchema.optional().catch(void 0),
29059
29220
  videoResolution: MotionGraphicsVideoResolutionSchema.optional().catch(void 0),
29060
- creativeBatch: z123.object({
29221
+ creativeBatch: z124.object({
29061
29222
  index: MotionGraphicsHookVariantsSchema,
29062
29223
  count: MotionGraphicsHookVariantsSchema,
29063
- tasks: z123.array(z123.object({
29064
- taskId: z123.string().uuid(),
29224
+ tasks: z124.array(z124.object({
29225
+ taskId: z124.string().uuid(),
29065
29226
  index: MotionGraphicsHookVariantsSchema,
29066
- status: z123.enum([
29227
+ status: z124.enum([
29067
29228
  "queued",
29068
29229
  "processing",
29069
29230
  "done",
@@ -29071,29 +29232,29 @@ var AnimatedVideoResultSchema = z123.object({
29071
29232
  ])
29072
29233
  })).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX)
29073
29234
  }).optional().catch(void 0),
29074
- queuedAt: z123.string().optional(),
29075
- jobsAhead: z123.number().int().nonnegative().optional(),
29076
- stageStartedAt: z123.string().optional(),
29077
- renderProgress: z123.number().optional(),
29235
+ queuedAt: z124.string().optional(),
29236
+ jobsAhead: z124.number().int().nonnegative().optional(),
29237
+ stageStartedAt: z124.string().optional(),
29238
+ renderProgress: z124.number().optional(),
29078
29239
  // AI clip fields (absent on a video paid before clips, or from an API
29079
29240
  // that predates them). Lenient: an unreadable value is dropped
29080
29241
  // instead of hiding the status.
29081
- clipCount: z123.number().int().nonnegative().optional().catch(void 0),
29082
- clipsUsed: z123.number().int().nonnegative().optional().catch(void 0),
29083
- clipPriceCents: z123.number().finite().nonnegative().optional().catch(void 0),
29084
- clipsRefunded: z123.number().int().nonnegative().optional().catch(void 0),
29242
+ clipCount: z124.number().int().nonnegative().optional().catch(void 0),
29243
+ clipsUsed: z124.number().int().nonnegative().optional().catch(void 0),
29244
+ clipPriceCents: z124.number().finite().nonnegative().optional().catch(void 0),
29245
+ clipsRefunded: z124.number().int().nonnegative().optional().catch(void 0),
29085
29246
  // Hook versions (absent from an API or a video before them): the
29086
29247
  // count ordered and, once done, the signed URLs of the EXTRA versions
29087
29248
  // (hook 2, hook 3); `finalMp4Url` is hook 1.
29088
- hookVariants: z123.number().int().min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).optional().catch(void 0),
29089
- cleanVideoUrl: z123.string().url().optional().catch(void 0),
29090
- cleanVariantUrls: z123.array(z123.string().url()).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
29091
- variantUrls: z123.array(z123.string().min(1)).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
29249
+ hookVariants: z124.number().int().min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).optional().catch(void 0),
29250
+ cleanVideoUrl: z124.string().url().optional().catch(void 0),
29251
+ cleanVariantUrls: z124.array(z124.string().url()).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
29252
+ variantUrls: z124.array(z124.string().min(1)).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
29092
29253
  // Extra hook versions given back, as the task recorded it once the
29093
29254
  // refunds landed (absent until then, and from an API before it).
29094
- variantsRefunded: z123.number().int().nonnegative().optional().catch(void 0),
29095
- activity: z123.array(MotionGraphicsActivitySchema).optional().catch(void 0),
29096
- previewUrl: z123.string().optional()
29255
+ variantsRefunded: z124.number().int().nonnegative().optional().catch(void 0),
29256
+ activity: z124.array(MotionGraphicsActivitySchema).optional().catch(void 0),
29257
+ previewUrl: z124.string().optional()
29097
29258
  }).passthrough()
29098
29259
  }).passthrough();
29099
29260
  function parseAnimatedVideoResult(value) {
@@ -29146,10 +29307,10 @@ function toAgentFacingAnimatedVideo(result) {
29146
29307
  ...hasSiteText && activity ? {
29147
29308
  activity: activity.map((item) => {
29148
29309
  if (!SITE_TEXT_CODES.has(item.code) || !item.text) return item;
29149
- const { text: text3, ...rest } = item;
29310
+ const { text: text4, ...rest } = item;
29150
29311
  return {
29151
29312
  ...rest,
29152
- untrustedSiteText: text3
29313
+ untrustedSiteText: text4
29153
29314
  };
29154
29315
  })
29155
29316
  } : {}
@@ -29372,7 +29533,7 @@ function registerAnimatedVideoTools(server, api) {
29372
29533
  nowMs: 0
29373
29534
  })
29374
29535
  });
29375
- const parsedTaskIds = z123.array(z123.string().uuid()).min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).safeParse(created.taskIds);
29536
+ const parsedTaskIds = z124.array(z124.string().uuid()).min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).safeParse(created.taskIds);
29376
29537
  const taskIds = parsedTaskIds.success && parsedTaskIds.data[0] === created.taskId ? parsedTaskIds.data : void 0;
29377
29538
  const receipt = {
29378
29539
  taskId: created.taskId,
@@ -29414,10 +29575,10 @@ function registerAnimatedVideoTools(server, api) {
29414
29575
  __name(registerAnimatedVideoTools, "registerAnimatedVideoTools");
29415
29576
 
29416
29577
  // src/tools/winning-product-image.ts
29417
- import { z as z124 } from "zod";
29418
- var WinnerReferenceInput = z124.object({
29419
- runId: z124.string().uuid(),
29420
- candidateSourceId: z124.string().trim().min(1).max(160)
29578
+ import { z as z125 } from "zod";
29579
+ var WinnerReferenceInput = z125.object({
29580
+ runId: z125.string().uuid(),
29581
+ candidateSourceId: z125.string().trim().min(1).max(160)
29421
29582
  }).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
29422
29583
  async function resolveWinnerImages(api, winnerReference, images) {
29423
29584
  if (!winnerReference) return images;
@@ -29428,9 +29589,9 @@ async function resolveWinnerImages(api, winnerReference, images) {
29428
29589
  },
29429
29590
  ...images ?? []
29430
29591
  ];
29431
- const unique = combined.filter((image, index, all) => all.findIndex((candidate) => candidate.assetId === image.assetId) === index);
29592
+ const unique = combined.filter((image2, index, all) => all.findIndex((candidate) => candidate.assetId === image2.assetId) === index);
29432
29593
  if (unique.length > 5) throw new Error("M\xE1ximo 5 fotos del producto en total.");
29433
- if (!unique.every((image) => Boolean(image.assetId))) {
29594
+ if (!unique.every((image2) => Boolean(image2.assetId))) {
29434
29595
  throw new Error("Cuando reutilizas la foto encontrada, carga las fotos adicionales con request_media_upload.");
29435
29596
  }
29436
29597
  return unique;
@@ -29454,62 +29615,62 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
29454
29615
  var CREATE_SERVICE_VIDEO_ON_MCP = PRODUCTMAKER_MCP_CAPABILITY_NAMES.includes("create_service_video");
29455
29616
  var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
29456
29617
  var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
29457
- var CreateProductTaskInput = z125.object({
29618
+ var CreateProductTaskInput = z126.object({
29458
29619
  images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
29459
29620
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
29460
- projectId: z125.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
29461
- productUrl: z125.string().url().optional().describe("Opcional. URL de la p\xE1gina del producto (Shopify, AliExpress, Amazon, etc.) para enriquecer el contexto. Si se omite, la IA infiere todo desde la imagen."),
29621
+ projectId: z126.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
29622
+ productUrl: z126.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."),
29462
29623
  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.'),
29463
29624
  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.'),
29464
- price: z125.string().min(1).max(120).optional().describe('Precio que se mostrar\xE1 en la landing y video. Formato libre \u2014 ej. "$89.900", "USD 29.99", "MXN 599". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar. Si te dice "t\xFA elige", om\xEDtelo y el backend sugiere uno.'),
29465
- compareAtPrice: z125.string().min(1).max(120).optional().describe('Opcional. Precio anterior para comunicar un descuento real en landing e im\xE1genes. Ej. "$129.000" cuando price="$89.900".'),
29466
- offer: z125.string().min(1).max(240).optional().describe('Oferta o promoci\xF3n a destacar. Ej. "2x1", "Env\xEDo gratis hoy", "50% OFF". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar (es v\xE1lido que diga "sin oferta"). Si te dice "t\xFA elige", om\xEDtelo.'),
29467
- paymentMethods: z125.string().min(1).max(240).optional().describe('Opcional. M\xE9todos de pago que puede mostrar la landing. Ej. "Tarjeta, PSE, Nequi, Contraentrega". Si se omite, la landing no muestra m\xE9todos de pago.'),
29468
- productContext: z125.string().max(PRODUCT_CONTEXT_MAX_CHARS).optional().describe("Opcional. Informacion adicional del producto que la IA debe usar como contexto prioritario: uso real, comprador, restricciones, diferenciadores o direccion creativa. No reemplaza la investigacion de competencia; si hay competencia, guia el primer angulo y los outputs no deben contradecirlo."),
29469
- productLabel: z125.string().trim().max(80).optional().describe('Opcional. Qu\xE9 es el producto, en pocas palabras (ej. "quita pelusas para ropa"). Es AUTORITATIVO: si lo env\xEDas, la IA usa esta identidad y no la reemplaza por otra categor\xEDa. Si lo omites, la IA detecta el producto desde la imagen.'),
29625
+ price: z126.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.'),
29626
+ compareAtPrice: z126.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".'),
29627
+ offer: z126.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.'),
29628
+ paymentMethods: z126.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.'),
29629
+ productContext: z126.string().max(PRODUCT_CONTEXT_MAX_CHARS).optional().describe("Opcional. Informacion adicional del producto que la IA debe usar como contexto prioritario: uso real, comprador, restricciones, diferenciadores o direccion creativa. No reemplaza la investigacion de competencia; si hay competencia, guia el primer angulo y los outputs no deben contradecirlo."),
29630
+ productLabel: z126.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.'),
29470
29631
  videoPreset: VideoPresetEnum.default("auto").describe('Opcional. Tipo/narrativa del video \u2014 \xFAnico campo de "estilo" que el usuario controla. Default "auto" (la IA escoge tras analizar el producto). Todos los presets funcionan a 15s (single_call) y 30s (Multiescena); "problem_solution" en single_call abre sin el producto y el producto entra por referencia en su beat de soluci\xF3n. Opciones: "auto", "ugc_dynamic" (review con experiencia y prueba), "ugc_how_to" (tutorial con pasos y resultado visible), "ugc_unboxing_chaos" (apertura y primera prueba), "problem_solution" (problema concreto, producto como soluci\xF3n y CTA), "product_showcase" (producto ejecutando una funci\xF3n real), "wearable_showcase" (prenda o accesorio modelado), "cinematic" (TV spot con receta cinematogr\xE1fica), "wild_card" (idea imposible: un truco visual que en la vida real no podr\xEDa pasar, y al cierre la invitaci\xF3n a comprar), "pixar_problem" (problema animado 3D), "pixar_sassy" (producto que habla). Si el usuario pide algo fuera de esta lista, p\xEDdele una opci\xF3n v\xE1lida.'),
29471
29632
  animationStyle: AnimationStyleEnum.optional().describe('Opcional. Estilo visual SOLO para presets animados ("pixar_problem" o "pixar_sassy") \u2014 la API lo rechaza con cualquier otro preset. Opciones: "pixar_3d" (default, look 3D de pel\xEDcula animada), "claymation" (plastilina stop-motion artesanal), "wes_anderson" (tableau sim\xE9trico pastel), "sci_fi" (futurista con HUDs y ne\xF3n), "realista" (fotorrealista, fiel al producto). Si el usuario pide un look animado sin nombrar el estilo, omite el campo.'),
29472
- durationSeconds: z125.union([
29473
- z125.literal(15),
29474
- z125.literal(30)
29633
+ durationSeconds: z126.union([
29634
+ z126.literal(15),
29635
+ z126.literal(30)
29475
29636
  ]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
29476
- pauseForAngleReview: z125.boolean().optional().describe("Compatibilidad heredada. MCP deriva esta pausa de aiDecidesAll: manual siempre pausa y autom\xE1tico siempre la omite. No uses este campo para saltar reviews."),
29477
- aiDecidesAll: z125.boolean().optional().describe("Mapea el toggle web \u201CDejar que la IA decida todo\u201D. Si true, ProductMaker omite reviews. Act\xEDvalo \xFAnicamente cuando el usuario lo pida expl\xEDcitamente. Omitido/false = reviews conversacionales."),
29637
+ pauseForAngleReview: z126.boolean().optional().describe("Compatibilidad heredada. MCP deriva esta pausa de aiDecidesAll: manual siempre pausa y autom\xE1tico siempre la omite. No uses este campo para saltar reviews."),
29638
+ aiDecidesAll: z126.boolean().optional().describe("Mapea el toggle web \u201CDejar que la IA decida todo\u201D. Si true, ProductMaker omite reviews. Act\xEDvalo \xFAnicamente cuando el usuario lo pida expl\xEDcitamente. Omitido/false = reviews conversacionales."),
29478
29639
  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.'),
29479
29640
  videoStructure: VideoStructureEnum.default("single_take").describe('Opcional. Formato: "single_take" = Un solo clip (generado completo; puede incluir cambios de plano) o "multi_scene" = Multiescena. Default: single_take.'),
29480
29641
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
29481
29642
  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).'),
29482
- videoAngleCount: z125.number().int().min(1).max(3).optional().describe("Cantidad de videos a renderizar: 1, 2 o 3. REQUERIDO cuando outputs incluye video (o se omite outputs, cuyo default incluye video); om\xEDtelo s\xF3lo cuando no se generar\xE1 video. Preg\xFAntalo incluso con aiDecidesAll=true porque cambia el costo."),
29643
+ videoAngleCount: z126.number().int().min(1).max(3).optional().describe("Cantidad de videos a renderizar: 1, 2 o 3. REQUERIDO cuando outputs incluye video (o se omite outputs, cuyo default incluye video); om\xEDtelo s\xF3lo cuando no se generar\xE1 video. Preg\xFAntalo incluso con aiDecidesAll=true porque cambia el costo."),
29483
29644
  angleNarratives: PublicNarrativeStyleEnum.array().max(3).optional().describe('Opcional. Narrativa POR \xC1NGULO (posicional). Valores actuales: "review", "ugc_how_to", "ugc_unboxing_chaos", "problem_product_cta" (problema concreto, producto como soluci\xF3n y CTA), "product_showcase", "wearable_showcase", "cinematic", "wild_card", "animated_problem_pixar", "sassy_product_pixar", "market" (narrativa an\xE1lisis de mercado: adapta el video a los patrones ganadores estudiados de la competencia; requiere competitorScanEnabled: true). angleNarratives[i] fuerza la narrativa del \xE1ngulo i; las posiciones restantes las elige la IA. La lista no puede superar videoAngleCount.'),
29484
- outputs: z125.array(z125.enum([
29645
+ outputs: z126.array(z126.enum([
29485
29646
  "landing",
29486
29647
  "video",
29487
29648
  "image"
29488
29649
  ])).min(1).max(3).optional().describe(`Opcional. Qu\xE9 outputs generar. Default: todos ["landing","video","image"]. Para 2 outputs: ["landing","image"] (sin video), ["video","image"] (sin landing), ["landing","video"] (sin imagen). ${createProductTaskSingleOutputDescription}`),
29489
- includeInitialLandingGif: z125.boolean().optional().describe("Opcional. En nuevas landings cl\xE1sicas habilitadas, omitirlo incluye el primer GIF del producto y su coste en el total. Env\xEDa false si el usuario lo excluye: no se genera ni se reserva su coste. Conserva la elecci\xF3n al confirmar y al reintentar."),
29490
- competitorScanEnabled: z125.boolean().optional().describe("Opcional. Default false: omitirlo significa SIN estudio de mercado. Antes de crear, llama estimate_market_study_cost con kind=product_task, muestra al usuario el costo con y sin estudio y preg\xFAntale si lo quiere; env\xEDa true solo si lo acepta (o si solicita la narrativa an\xE1lisis de mercado). Si la tarea incluye video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico."),
29650
+ includeInitialLandingGif: z126.boolean().optional().describe("Opcional. En nuevas landings cl\xE1sicas habilitadas, omitirlo incluye el primer GIF del producto y su coste en el total. Env\xEDa false si el usuario lo excluye: no se genera ni se reserva su coste. Conserva la elecci\xF3n al confirmar y al reintentar."),
29651
+ competitorScanEnabled: z126.boolean().optional().describe("Opcional. Default false: omitirlo significa SIN estudio de mercado. Antes de crear, llama estimate_market_study_cost con kind=product_task, muestra al usuario el costo con y sin estudio y preg\xFAntale si lo quiere; env\xEDa true solo si lo acepta (o si solicita la narrativa an\xE1lisis de mercado). Si la tarea incluye video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico."),
29491
29652
  generateAiEdit: AiEditRequestSchema.optional().describe('Opcional. Pide la Edici\xF3n con IA: una pasada que a\xF1ade texto, efectos y m\xFAsica sobre cada video entregado (variante with_ai_edit; se cobra al entregar, por video). Nivel: "economy" (Econ\xF3mica, Sonnet 5.5, m\xE1s barata) o "pro" (Opus 5.5, mejor calidad, ~10 min). true equivale a "pro"; false/omitido = sin edici\xF3n.'),
29492
- replicateWinnerWhenFound: z125.boolean().optional().describe("Conserva la preferencia de copiar un ganador si existe. false estudia el mercado sin reemplazar un \xE1ngulo por el anuncio ganador. No a\xF1ade una pregunta obligatoria."),
29493
- brandId: z125.string().uuid().optional().describe("Opcional. ID de una marca del usuario; si se env\xEDa, el sistema usa su voz, colores y persona para enriquecer los outputs generados."),
29494
- actorId: z125.string().trim().min(1).max(120).optional().describe("Opcional. ID de un personaje guardado (usa list_actors para verlos). Si lo env\xEDas, su foto y su voz mandan sobre la descripci\xF3n de texto."),
29653
+ replicateWinnerWhenFound: z126.boolean().optional().describe("Conserva la preferencia de copiar un ganador si existe. false estudia el mercado sin reemplazar un \xE1ngulo por el anuncio ganador. No a\xF1ade una pregunta obligatoria."),
29654
+ brandId: z126.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."),
29655
+ actorId: z126.string().trim().min(1).max(120).optional().describe("Opcional. ID de un personaje guardado (usa list_actors para verlos). Si lo env\xEDas, su foto y su voz mandan sobre la descripci\xF3n de texto."),
29495
29656
  creativeGender: CreativeGenderEnum.optional().describe('Opcional. QUI\xC9N APARECE EN PANTALLA en todos los creativos de la task: el presentador del video, las personas fotografiadas en la landing y la persona del anuncio. NO es la voz. M\xE1ndalo en cuanto el usuario lo diga en cualquier momento de la conversaci\xF3n y con cualquier redacci\xF3n ("quiero una mujer", "que salga un hombre", "esto es para hombres"): si no lo mandas, el g\xE9nero lo inventa la IA y el usuario recibe lo contrario de lo que pidi\xF3 sin ning\xFAn aviso. "mixed" solo cuando pida expl\xEDcitamente ambos. Si adem\xE1s mandas actorId, el personaje guardado manda sobre este campo.'),
29496
- creativeDirection: z125.string().max(500).optional().describe('Opcional. Direcci\xF3n creativa en texto libre (colores, mood, estilo) que aplica a los outputs de IMAGEN y LANDING (no al video \u2014 el estilo/ambiente del video se dirige con scriptNotes). M\xC1XIMA PRIORIDAD: anula marca, colores y estilo por defecto. Ej. "amarillo y azul, minimalista". M\xE1x 500 caracteres.'),
29497
- headline: z125.string().max(120).optional().describe("Opcional. Titular EXACTO a renderizar. Se imprime tal cual: la IA no lo reescribe, no lo acorta y no lo traduce. Se aplica a las IM\xC1GENES y a la portada de la landing de esta task (el video no lo usa; para el video usa scriptNotes). \xDAsalo cuando el copy es de marca y no es negociable. M\xE1x 120 caracteres. Si lo omites, la IA escribe el titular."),
29498
- subheadline: z125.string().max(160).optional().describe("Opcional. Subt\xEDtulo EXACTO a renderizar, misma regla que headline. Independiente: puedes fijar solo el subt\xEDtulo. M\xE1x 160 caracteres."),
29657
+ creativeDirection: z126.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.'),
29658
+ headline: z126.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."),
29659
+ subheadline: z126.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."),
29499
29660
  landingStrategy: LandingStrategyEnum.optional().describe('Opcional. Estructura de la landing cl\xE1sica cuando landing est\xE1 entre outputs: "classic" (estructura original probada y recomendada; default del primer rollout), "auto" (la IA decide; experimental), "pain_solution", "social_proof" (Landing Viral: UGC, WhatsApp, Instagram y evidencia social), "benefits_clarity", "offer_value" o "lifestyle_identity". Default "classic".'),
29500
29661
  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".')
29501
29662
  }).strict();
29502
- var CreateServiceVideoInput = z125.object({
29503
- landingUrl: z125.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
29504
- additionalContext: z125.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
29663
+ var CreateServiceVideoInput = z126.object({
29664
+ landingUrl: z126.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
29665
+ additionalContext: z126.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
29505
29666
  language: Lang.describe("Idioma del video: es, en o pt."),
29506
- voiceId: z125.string().trim().min(1).pipe(VoiceId).optional().describe('Opcional. Voz para toda la narraci\xF3n. Usa "auto" para que la IA la alinee con el presentador. Las voces del banco compartido fueron retiradas.'),
29507
- brandId: z125.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
29508
- reviewMode: z125.enum([
29667
+ voiceId: z126.string().trim().min(1).pipe(VoiceId).optional().describe('Opcional. Voz para toda la narraci\xF3n. Usa "auto" para que la IA la alinee con el presentador. Las voces del banco compartido fueron retiradas.'),
29668
+ brandId: z126.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
29669
+ reviewMode: z126.enum([
29509
29670
  "automatic",
29510
29671
  "guided"
29511
29672
  ]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
29512
- videoPreset: z125.enum([
29673
+ videoPreset: z126.enum([
29513
29674
  "auto",
29514
29675
  "ugc_dynamic",
29515
29676
  "ugc_how_to",
@@ -29519,128 +29680,128 @@ var CreateServiceVideoInput = z125.object({
29519
29680
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
29520
29681
  videoResolution: VideoResolutionEnum.default("480p").describe('Opcional. Resoluci\xF3n: "480p" o "720p". 720p cuesta m\xE1s por segundo y solo est\xE1 disponible en "economy" y "pro" (Medio = 768P). Default: 480p.')
29521
29682
  }).strict();
29522
- var GetTaskStatusInput = z125.object({
29523
- taskId: z125.string().min(1),
29524
- waitSeconds: z125.number().int().min(0).max(120).optional()
29683
+ var GetTaskStatusInput = z126.object({
29684
+ taskId: z126.string().min(1),
29685
+ waitSeconds: z126.number().int().min(0).max(120).optional()
29525
29686
  });
29526
- var ListTasksInput = z125.object({
29527
- limit: z125.number().int().min(1).max(50).optional(),
29528
- offset: z125.number().int().min(0).optional(),
29529
- search: z125.string().optional()
29687
+ var ListTasksInput = z126.object({
29688
+ limit: z126.number().int().min(1).max(50).optional(),
29689
+ offset: z126.number().int().min(0).optional(),
29690
+ search: z126.string().optional()
29530
29691
  });
29531
29692
  var MCP_REVIEW_LIST_FIELD_MAX = IMAGE_WIZARD_LIST_FIELD_MAX;
29532
29693
  var MCP_REVIEW_FEATURE_ITEM_MAX = IMAGE_FEATURE_ITEM_MAX;
29533
- var EditTaskDraftInput = z125.object({
29534
- taskId: z125.string().min(1),
29535
- angleIndex: z125.number().int().min(0),
29536
- angle: z125.object({
29537
- angle: z125.string().min(1).max(480),
29538
- buyerPersona: z125.string().min(1).max(360),
29539
- actor: z125.string().min(1).max(360).optional(),
29540
- actorId: z125.string().trim().min(1).optional().describe("Opcional. ID de un personaje guardado (usa list_actors para verlos). Si lo env\xEDas, su foto y su voz mandan sobre la descripci\xF3n de texto."),
29541
- gender: z125.enum([
29694
+ var EditTaskDraftInput = z126.object({
29695
+ taskId: z126.string().min(1),
29696
+ angleIndex: z126.number().int().min(0),
29697
+ angle: z126.object({
29698
+ angle: z126.string().min(1).max(480),
29699
+ buyerPersona: z126.string().min(1).max(360),
29700
+ actor: z126.string().min(1).max(360).optional(),
29701
+ actorId: z126.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."),
29702
+ gender: z126.enum([
29542
29703
  "female",
29543
29704
  "male"
29544
29705
  ]).optional(),
29545
- scriptNotes: z125.string().max(2e3).optional()
29706
+ scriptNotes: z126.string().max(2e3).optional()
29546
29707
  })
29547
29708
  });
29548
- var PendingActionPayload = z125.discriminatedUnion("kind", [
29549
- z125.object({
29550
- kind: z125.literal("product_reference_set_approval"),
29709
+ var PendingActionPayload = z126.discriminatedUnion("kind", [
29710
+ z126.object({
29711
+ kind: z126.literal("product_reference_set_approval"),
29551
29712
  scope: ProductReferenceScopeEnum.optional(),
29552
- scopeKey: z125.string().min(1).max(120).optional(),
29553
- scopeSnapshotId: z125.string().uuid().optional(),
29554
- expectedScopeHash: z125.string().min(1).max(128).optional(),
29713
+ scopeKey: z126.string().min(1).max(120).optional(),
29714
+ scopeSnapshotId: z126.string().uuid().optional(),
29715
+ expectedScopeHash: z126.string().min(1).max(128).optional(),
29555
29716
  decision: ProductReferenceResolutionDecisionEnum,
29556
29717
  reason: ProductReferenceRejectionReasonEnum.optional(),
29557
- affectedRefKeys: z125.array(z125.string().min(1).max(200)).min(1).optional(),
29558
- affectedPhotoNumbers: z125.array(z125.number().int().positive()).min(1).optional(),
29559
- recoveryAction: z125.enum([
29718
+ affectedRefKeys: z126.array(z126.string().min(1).max(200)).min(1).optional(),
29719
+ affectedPhotoNumbers: z126.array(z126.number().int().positive()).min(1).optional(),
29720
+ recoveryAction: z126.enum([
29560
29721
  "remove",
29561
29722
  "replace",
29562
29723
  "upload",
29563
29724
  "return_to_selection"
29564
29725
  ]).optional()
29565
29726
  }),
29566
- z125.object({
29567
- kind: z125.literal("product_reference_confirmation"),
29568
- selectedPhotoNumbers: z125.array(z125.number().int().positive().max(5)).min(1).max(5).optional().describe("Opcional. N\xFAmeros visibles de las fotos que el usuario quiere conservar; las dem\xE1s se deseleccionan. Debe quedar al menos una."),
29727
+ z126.object({
29728
+ kind: z126.literal("product_reference_confirmation"),
29729
+ selectedPhotoNumbers: z126.array(z126.number().int().positive().max(5)).min(1).max(5).optional().describe("Opcional. N\xFAmeros visibles de las fotos que el usuario quiere conservar; las dem\xE1s se deseleccionan. Debe quedar al menos una."),
29569
29730
  userChoice: ProductReferenceUserChoiceEnum.optional(),
29570
- confirmedProductNames: z125.array(z125.string().min(1).max(120)).min(2).max(8).optional(),
29731
+ confirmedProductNames: z126.array(z126.string().min(1).max(120)).min(2).max(8).optional(),
29571
29732
  videoStructure: VideoStructureEnum.optional().describe("Opcional. Formato para reanudar el video: single_take (Un solo clip, generado completo; puede incluir cambios de plano) o multi_scene (Multiescena). El backend vuelve a validar que sea compatible con el agrupamiento confirmado."),
29572
29733
  videoQuality: VideoQualityEnum.optional().describe("Opcional. Calidad para reanudar el video: economy (Econ\xF3mico), medium (Medio) o pro. El proveedor se elige internamente y el backend vuelve a cotizar la ruta."),
29573
- useMultiSceneShowcase: z125.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
29734
+ useMultiSceneShowcase: z126.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
29574
29735
  }),
29575
- z125.object({
29576
- kind: z125.literal("angle_review_approval"),
29736
+ z126.object({
29737
+ kind: z126.literal("angle_review_approval"),
29577
29738
  // All edits are optional — empty action body just approves the
29578
29739
  // backend-generated draft as-is. Field shapes mirror the angle-review
29579
29740
  // request contracts in @packages/types/wizard.ts; the handler routes to
29580
29741
  // the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
29581
- customAngle: z125.string().min(1).max(480).optional(),
29742
+ customAngle: z126.string().min(1).max(480).optional(),
29582
29743
  // Keep the shared MCP action within the strictest downstream contract:
29583
29744
  // autopilot/image resume endpoints cap these fields at 1500 characters.
29584
- painPoints: z125.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
29585
- benefits: z125.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
29745
+ painPoints: z126.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
29746
+ benefits: z126.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
29586
29747
  // Same policy as the two fields above: the strictest downstream contract
29587
29748
  // wins. The image endpoint caps each feature at 240 while landing/video
29588
29749
  // accept 300, and this single action routes to whichever the task is — so
29589
29750
  // accepting 300 here turns a 250-character feature on an image task into
29590
29751
  // an opaque HTTP 400 after the model already believed it had been saved.
29591
- features: z125.array(z125.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
29592
- buyerPersona: z125.string().min(1).max(360).optional(),
29752
+ features: z126.array(z126.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
29753
+ buyerPersona: z126.string().min(1).max(360).optional(),
29593
29754
  narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n) funciona en ambos formatos \u2014 en Un solo clip abre sin producto y el producto entra por referencia en su beat. La familia storyteller ("animated_storyteller", "animated_inner_journey", "animated_object_soul", "animated_timeline") no est\xE1 disponible por ahora.'),
29594
- actor: z125.string().min(1).max(360).optional().describe("Nueva descripci\xF3n del presentador. Al enviarla sin actorId, se elimina autom\xE1ticamente cualquier actor guardado previo de esos \xE1ngulos."),
29595
- actorId: z125.string().max(120).nullable().optional(),
29596
- creativeDirection: z125.string().max(2e3).optional(),
29597
- selectedAngleNumbers: z125.array(z125.number().int().positive()).min(1).max(3).optional().describe("N\xFAmeros visibles (1-based) de los \xE1ngulos que el usuario quiere renderizar. Deben ser \xFAnicos, existir en la review y no superar el videoAngleCount autorizado."),
29598
- angleEdits: z125.array(z125.object({
29599
- angleNumber: z125.number().int().positive(),
29600
- narrativeSelection: z125.enum([
29755
+ actor: z126.string().min(1).max(360).optional().describe("Nueva descripci\xF3n del presentador. Al enviarla sin actorId, se elimina autom\xE1ticamente cualquier actor guardado previo de esos \xE1ngulos."),
29756
+ actorId: z126.string().max(120).nullable().optional(),
29757
+ creativeDirection: z126.string().max(2e3).optional(),
29758
+ selectedAngleNumbers: z126.array(z126.number().int().positive()).min(1).max(3).optional().describe("N\xFAmeros visibles (1-based) de los \xE1ngulos que el usuario quiere renderizar. Deben ser \xFAnicos, existir en la review y no superar el videoAngleCount autorizado."),
29759
+ angleEdits: z126.array(z126.object({
29760
+ angleNumber: z126.number().int().positive(),
29761
+ narrativeSelection: z126.enum([
29601
29762
  "market",
29602
29763
  "guided"
29603
29764
  ]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
29604
- angle: z125.string().min(1).max(480).optional(),
29605
- buyerPersona: z125.string().min(1).max(360).optional(),
29765
+ angle: z126.string().min(1).max(480).optional(),
29766
+ buyerPersona: z126.string().min(1).max(360).optional(),
29606
29767
  narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n) funciona en ambos formatos \u2014 en Un solo clip abre sin producto y el producto entra por referencia en su beat. La familia storyteller ("animated_storyteller", "animated_inner_journey", "animated_object_soul", "animated_timeline") no est\xE1 disponible por ahora.'),
29607
- actor: z125.string().min(1).max(360).optional(),
29608
- actorId: z125.string().max(120).nullable().optional(),
29609
- creativeDirection: z125.string().max(2e3).optional()
29768
+ actor: z126.string().min(1).max(360).optional(),
29769
+ actorId: z126.string().max(120).nullable().optional(),
29770
+ creativeDirection: z126.string().max(2e3).optional()
29610
29771
  }).strict()).max(3).optional().describe("Ediciones independientes por n\xFAmero visible de \xE1ngulo. S\xF3lo se aceptan para \xE1ngulos incluidos en selectedAngleNumbers (o en la selecci\xF3n por defecto)."),
29611
- gapDurationSeconds: z125.union([
29612
- z125.literal(15),
29613
- z125.literal(30)
29772
+ gapDurationSeconds: z126.union([
29773
+ z126.literal(15),
29774
+ z126.literal(30)
29614
29775
  ]).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.")
29615
29776
  }),
29616
- z125.object({
29617
- kind: z125.literal("service_angle_approval"),
29618
- angleId: z125.string().uuid().optional(),
29619
- angleNumber: z125.number().int().positive().optional(),
29620
- content: z125.string().min(1).max(480).optional(),
29621
- creativeDirection: z125.string().min(1).max(1500).optional(),
29622
- actor: z125.string().min(1).max(360).optional()
29777
+ z126.object({
29778
+ kind: z126.literal("service_angle_approval"),
29779
+ angleId: z126.string().uuid().optional(),
29780
+ angleNumber: z126.number().int().positive().optional(),
29781
+ content: z126.string().min(1).max(480).optional(),
29782
+ creativeDirection: z126.string().min(1).max(1500).optional(),
29783
+ actor: z126.string().min(1).max(360).optional()
29623
29784
  }),
29624
- z125.object({
29625
- kind: z125.literal("service_script_approval"),
29626
- voiceovers: z125.record(z125.string(), z125.string().min(1).max(600)).optional(),
29627
- visualDirections: z125.record(z125.string(), z125.string().min(1).max(1200)).optional(),
29628
- voiceoversByScene: z125.record(z125.string(), z125.string().min(1).max(600)).optional(),
29629
- visualDirectionsByScene: z125.record(z125.string(), z125.string().min(1).max(1200)).optional()
29785
+ z126.object({
29786
+ kind: z126.literal("service_script_approval"),
29787
+ voiceovers: z126.record(z126.string(), z126.string().min(1).max(600)).optional(),
29788
+ visualDirections: z126.record(z126.string(), z126.string().min(1).max(1200)).optional(),
29789
+ voiceoversByScene: z126.record(z126.string(), z126.string().min(1).max(600)).optional(),
29790
+ visualDirectionsByScene: z126.record(z126.string(), z126.string().min(1).max(1200)).optional()
29630
29791
  })
29631
29792
  ]);
29632
- var ResolvePendingActionInput = z125.object({
29633
- taskId: z125.string().min(1),
29793
+ var ResolvePendingActionInput = z126.object({
29794
+ taskId: z126.string().min(1),
29634
29795
  action: PendingActionPayload
29635
29796
  }).strict();
29636
29797
  function resolveVariantConfirmVideoTier(action) {
29637
29798
  return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
29638
29799
  }
29639
29800
  __name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
29640
- var StatusForResolveSchema = z125.object({
29801
+ var StatusForResolveSchema = z126.object({
29641
29802
  // Metadata used to select the backend resume contract. Older API responses
29642
29803
  // may omit these fields, so the resolver keeps the generic fallback.
29643
- kind: z125.enum([
29804
+ kind: z126.enum([
29644
29805
  "autopilot",
29645
29806
  "video",
29646
29807
  "image",
@@ -29648,18 +29809,18 @@ var StatusForResolveSchema = z125.object({
29648
29809
  "mix",
29649
29810
  "service"
29650
29811
  ]).optional(),
29651
- selectedOutputs: z125.array(z125.enum([
29812
+ selectedOutputs: z126.array(z126.enum([
29652
29813
  "landing",
29653
29814
  "video",
29654
29815
  "image"
29655
29816
  ])).optional(),
29656
- videoAngleCount: z125.number().int().min(1).max(3).optional(),
29657
- ugcFormat: z125.enum([
29817
+ videoAngleCount: z126.number().int().min(1).max(3).optional(),
29818
+ ugcFormat: z126.enum([
29658
29819
  "single_8s",
29659
29820
  "single_15s",
29660
29821
  "double_30s"
29661
29822
  ]).optional(),
29662
- videoStyle: z125.enum([
29823
+ videoStyle: z126.enum([
29663
29824
  "ugc",
29664
29825
  "cartoon_3d",
29665
29826
  "product_only",
@@ -29669,13 +29830,13 @@ var StatusForResolveSchema = z125.object({
29669
29830
  videoQuality: VideoQualityEnum.optional(),
29670
29831
  videoRouteId: VideoRouteIdEnum.optional(),
29671
29832
  videoModel: TaskVideoModelEnum.optional(),
29672
- videoTier: z125.enum([
29833
+ videoTier: z126.enum([
29673
29834
  "legacy",
29674
29835
  "standard",
29675
29836
  "pro",
29676
29837
  "single_call"
29677
29838
  ]).optional(),
29678
- videoResolution: z125.enum([
29839
+ videoResolution: z126.enum([
29679
29840
  "480p",
29680
29841
  "720p"
29681
29842
  ]).optional(),
@@ -29683,60 +29844,60 @@ var StatusForResolveSchema = z125.object({
29683
29844
  // A task created before a narrative was blocked/hidden must still parse,
29684
29845
  // or resolve_pending_action could never approve it.
29685
29846
  narrativeStyle: NarrativeStyle.optional(),
29686
- pauseForVideoScriptReview: z125.boolean().optional(),
29687
- pendingUserAction: z125.object({
29688
- kind: z125.string(),
29689
- candidateGrouping: z125.string().optional(),
29690
- selectedImageUrls: z125.array(z125.string()).optional(),
29691
- proposedProductNames: z125.array(z125.string()).optional(),
29847
+ pauseForVideoScriptReview: z126.boolean().optional(),
29848
+ pendingUserAction: z126.object({
29849
+ kind: z126.string(),
29850
+ candidateGrouping: z126.string().optional(),
29851
+ selectedImageUrls: z126.array(z126.string()).optional(),
29852
+ proposedProductNames: z126.array(z126.string()).optional(),
29692
29853
  // Adaptive reference questions are server-owned. Echo only the evidence
29693
29854
  // identity and the choices shown by the current snapshot; never accept a
29694
29855
  // client-supplied reference set as authorization.
29695
- options: z125.array(ProductReferenceUserChoiceEnum).max(4).optional(),
29696
- mode: z125.enum([
29856
+ options: z126.array(ProductReferenceUserChoiceEnum).max(4).optional(),
29857
+ mode: z126.enum([
29697
29858
  "question",
29698
29859
  "visual_recovery"
29699
29860
  ]).optional(),
29700
29861
  /** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
29701
- canKeepSelection: z125.boolean().optional(),
29702
- decisionKey: z125.string().optional(),
29703
- questionOrdinal: z125.number().int().min(1).max(5).optional(),
29704
- questionCeiling: z125.union([
29705
- z125.literal(3),
29706
- z125.literal(5)
29862
+ canKeepSelection: z126.boolean().optional(),
29863
+ decisionKey: z126.string().optional(),
29864
+ questionOrdinal: z126.number().int().min(1).max(5).optional(),
29865
+ questionCeiling: z126.union([
29866
+ z126.literal(3),
29867
+ z126.literal(5)
29707
29868
  ]).optional(),
29708
- referenceEvidenceVersion: z125.number().int().positive().optional(),
29709
- expectedEvidenceHash: z125.string().optional(),
29710
- question: z125.object({
29711
- prompt: z125.string().min(1).max(240),
29712
- helpText: z125.string().min(1).max(300).optional(),
29713
- options: z125.array(z125.object({
29869
+ referenceEvidenceVersion: z126.number().int().positive().optional(),
29870
+ expectedEvidenceHash: z126.string().optional(),
29871
+ question: z126.object({
29872
+ prompt: z126.string().min(1).max(240),
29873
+ helpText: z126.string().min(1).max(300).optional(),
29874
+ options: z126.array(z126.object({
29714
29875
  value: ProductReferenceUserChoiceEnum,
29715
- label: z125.string().min(1).max(120),
29716
- description: z125.string().min(1).max(240).optional()
29876
+ label: z126.string().min(1).max(120),
29877
+ description: z126.string().min(1).max(240).optional()
29717
29878
  })).min(2).max(4)
29718
29879
  }).optional(),
29719
29880
  scope: ProductReferenceScopeEnum.optional(),
29720
- scopeKey: z125.string().optional(),
29721
- scopeSnapshotId: z125.string().uuid().optional(),
29722
- scopeHash: z125.string().optional(),
29723
- baseReferenceSetHash: z125.string().optional(),
29724
- phase: z125.enum([
29881
+ scopeKey: z126.string().optional(),
29882
+ scopeSnapshotId: z126.string().uuid().optional(),
29883
+ scopeHash: z126.string().optional(),
29884
+ baseReferenceSetHash: z126.string().optional(),
29885
+ phase: z126.enum([
29725
29886
  "preparation",
29726
29887
  "final"
29727
29888
  ]).optional(),
29728
- selectedRefKeys: z125.array(z125.string().min(1).max(200)).optional(),
29729
- allowedDecisions: z125.array(ProductReferenceResolutionDecisionEnum).optional(),
29730
- previews: z125.array(z125.object({
29731
- refKey: z125.string().min(1).max(200)
29889
+ selectedRefKeys: z126.array(z126.string().min(1).max(200)).optional(),
29890
+ allowedDecisions: z126.array(ProductReferenceResolutionDecisionEnum).optional(),
29891
+ previews: z126.array(z126.object({
29892
+ refKey: z126.string().min(1).max(200)
29732
29893
  }).passthrough()).optional(),
29733
- customAngleDraft: z125.string().optional(),
29734
- painPointsDraft: z125.string().optional(),
29735
- benefitsDraft: z125.string().optional(),
29736
- featuresDraft: z125.array(z125.string()).optional(),
29737
- angleOptions: z125.array(z125.object({
29738
- index: z125.number().int().nonnegative(),
29739
- angle: z125.string().min(1)
29894
+ customAngleDraft: z126.string().optional(),
29895
+ painPointsDraft: z126.string().optional(),
29896
+ benefitsDraft: z126.string().optional(),
29897
+ featuresDraft: z126.array(z126.string()).optional(),
29898
+ angleOptions: z126.array(z126.object({
29899
+ index: z126.number().int().nonnegative(),
29900
+ angle: z126.string().min(1)
29740
29901
  }).passthrough()).min(1).max(5).optional(),
29741
29902
  // Recommendation consumed only when the caller explicitly sends
29742
29903
  // gapDurationSeconds: 30 in the angle approval action.
@@ -29746,17 +29907,17 @@ var StatusForResolveSchema = z125.object({
29746
29907
  // keys. `actorId` (the saved custom actor the picker stored) was silently
29747
29908
  // dropped here, so the approval handler below could not echo it back on the
29748
29909
  // PATCH — the selection looked accepted and reached no render.
29749
- angles: z125.array(z125.object({
29750
- id: z125.string().uuid(),
29751
- content: z125.string(),
29752
- creativeDirection: z125.string(),
29753
- actor: z125.string(),
29754
- actorId: z125.string().nullable().optional()
29910
+ angles: z126.array(z126.object({
29911
+ id: z126.string().uuid(),
29912
+ content: z126.string(),
29913
+ creativeDirection: z126.string(),
29914
+ actor: z126.string(),
29915
+ actorId: z126.string().nullable().optional()
29755
29916
  }).passthrough()).optional(),
29756
- panels: z125.array(z125.object({
29757
- beatId: z125.string(),
29758
- voiceover: z125.string(),
29759
- visualDirection: z125.string()
29917
+ panels: z126.array(z126.object({
29918
+ beatId: z126.string(),
29919
+ voiceover: z126.string(),
29920
+ visualDirection: z126.string()
29760
29921
  }).passthrough()).optional()
29761
29922
  }).optional()
29762
29923
  }).passthrough();
@@ -30109,8 +30270,8 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
30109
30270
  server.registerTool("verify_landing_commerce", {
30110
30271
  description: getProductMakerCapabilityModelGuidance("verify_landing_commerce").summary + " Verifica una correcci\xF3n manual de precios, tachados o packs de una landing editable existente. Solo relee Shopify y los recibos externos; no cambia precios, inventario, SKU ni compra una edici\xF3n. Pasa taskId y editId de la edici\xF3n ya conocida; nunca inventes IDs ni pidas repetir el cambio. Devuelve el estado can\xF3nico por proveedor: conserva el aviso pendiente hasta confirmar los valores reales. Solo despu\xE9s de confirmar todos los valores, el servidor puede volver a habilitar la compra. Web guardada no demuestra publicaci\xF3n p\xFAblica ni checkout; muestra las correcciones y enlaces pendientes sin c\xF3digos t\xE9cnicos. La disponibilidad del editor conserva sus permisos actuales.",
30111
30272
  inputSchema: {
30112
- taskId: z125.string().uuid(),
30113
- editId: z125.string().uuid()
30273
+ taskId: z126.string().uuid(),
30274
+ editId: z126.string().uuid()
30114
30275
  },
30115
30276
  annotations: OVERWRITES_EXTERNAL
30116
30277
  }, async (input) => {
@@ -30302,15 +30463,15 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
30302
30463
  const rawOutputs = await fetchTaskOutputs(api, input.taskId, {
30303
30464
  signal
30304
30465
  });
30305
- const imageContent = await buildMcpGeneratedImageContent(rawOutputs.images.map((image, i) => ({
30306
- url: image.url,
30466
+ const imageContent = await buildMcpGeneratedImageContent(rawOutputs.images.map((image2, i) => ({
30467
+ url: image2.url,
30307
30468
  alt: `Imagen ${i + 1}`
30308
30469
  })), transport);
30309
30470
  const outputs = proxifyOutputs(rawOutputs, proxyBaseUrl);
30310
30471
  const media = {
30311
30472
  images: [
30312
- ...outputs.images.map((image, i) => ({
30313
- url: image.url,
30473
+ ...outputs.images.map((image2, i) => ({
30474
+ url: image2.url,
30314
30475
  alt: `Imagen ${i + 1}`
30315
30476
  })),
30316
30477
  ...outputs.landing.sections.map((section) => ({
@@ -30381,16 +30542,16 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
30381
30542
  if (input.search) qs.set("search", input.search);
30382
30543
  const path3 = `/v1/tasks${qs.toString() ? "?" + qs.toString() : ""}`;
30383
30544
  const r = await api.getJson(path3);
30384
- const page = z125.object({
30385
- items: z125.array(z125.unknown())
30545
+ const page = z126.object({
30546
+ items: z126.array(z126.unknown())
30386
30547
  }).passthrough().safeParse(r);
30387
30548
  if (!page.success) return asText(r);
30388
30549
  return asText({
30389
30550
  ...page.data,
30390
30551
  items: page.data.items.map((item) => {
30391
- const servicePage = z125.object({
30392
- taskId: z125.string().uuid(),
30393
- resourceType: z125.literal("service_page")
30552
+ const servicePage = z126.object({
30553
+ taskId: z126.string().uuid(),
30554
+ resourceType: z126.literal("service_page")
30394
30555
  }).passthrough().safeParse(item);
30395
30556
  if (!servicePage.success) return item;
30396
30557
  return {
@@ -30880,28 +31041,28 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
30880
31041
  __name(registerTaskTools, "registerTaskTools");
30881
31042
 
30882
31043
  // src/tools/brands.ts
30883
- import { z as z126 } from "zod";
31044
+ import { z as z127 } from "zod";
30884
31045
  var guidance2 = getProductMakerCapabilityModelGuidance("create_brand");
30885
31046
  var BRAND_START_REPLAY_WINDOW_MS = 15 * 60 * 1e3;
30886
31047
  var BRAND_NOTES_MAX_CHARS = 2e4;
30887
31048
  var BRAND_AMBIGUOUS_REQUEST_RETENTION_MS = 24 * 60 * 60 * 1e3;
30888
31049
  var BRAND_CREATION_REQUEST_LIMIT = 500;
30889
31050
  var brandCreationRequests = /* @__PURE__ */ new Map();
30890
- var CreateBrandInput = z126.object({
30891
- action: z126.enum([
31051
+ var CreateBrandInput = z127.object({
31052
+ action: z127.enum([
30892
31053
  "start",
30893
31054
  "status",
30894
31055
  "list"
30895
31056
  ]).default("start").describe("start cotiza (sin confirmed) o inicia (confirmed=true) el an\xE1lisis; status consulta brandId hasta ready o failed; list muestra las marcas que el usuario ya tiene."),
30896
- sourceUrl: z126.string().trim().min(1).max(BRAND_SOURCE_URL_MAX_LENGTH).optional().describe("Instagram, Facebook, TikTok o web p\xFAblica del negocio, como la dio el usuario (\xAB@sanlucasbarberia\xBB, \xABinstagram.com/sanlucasbarberia\xBB, \xABmibarberia.com\xBB). Obligatorio para start."),
30897
- businessNotes: z126.string().trim().max(BRAND_NOTES_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cuente de su negocio en el chat (servicios y precios, WhatsApp, ciudad o zona, horarios). Se guarda como documento del negocio y llega tal cual a la marca y a su landing. Copia sus palabras; no inventes datos."),
30898
- language: z126.enum([
31057
+ sourceUrl: z127.string().trim().min(1).max(BRAND_SOURCE_URL_MAX_LENGTH).optional().describe("Instagram, Facebook, TikTok o web p\xFAblica del negocio, como la dio el usuario (\xAB@sanlucasbarberia\xBB, \xABinstagram.com/sanlucasbarberia\xBB, \xABmibarberia.com\xBB). Obligatorio para start."),
31058
+ businessNotes: z127.string().trim().max(BRAND_NOTES_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cuente de su negocio en el chat (servicios y precios, WhatsApp, ciudad o zona, horarios). Se guarda como documento del negocio y llega tal cual a la marca y a su landing. Copia sus palabras; no inventes datos."),
31059
+ language: z127.enum([
30899
31060
  "es",
30900
31061
  "en",
30901
31062
  "pt"
30902
31063
  ]).optional().describe("Idioma de la conversaci\xF3n. Solo se usa si la p\xE1gina del negocio no deja claro su idioma."),
30903
- confirmed: z126.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, start solo cotiza y no cobra."),
30904
- brandId: z126.string().uuid().optional().describe("ID de la marca. Obligatorio para status; no lo inventes.")
31064
+ confirmed: z127.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, start solo cotiza y no cobra."),
31065
+ brandId: z127.string().uuid().optional().describe("ID de la marca. Obligatorio para status; no lo inventes.")
30905
31066
  }).strict();
30906
31067
  function normalizeBrandSourceUrl(raw) {
30907
31068
  const value = raw.trim();
@@ -31185,31 +31346,31 @@ __name(registerBrandTools, "registerBrandTools");
31185
31346
 
31186
31347
  // src/tools/service-landing.ts
31187
31348
  import { createHash as createHash4, randomUUID } from "crypto";
31188
- import { z as z127 } from "zod";
31349
+ import { z as z128 } from "zod";
31189
31350
  var guidance3 = getProductMakerCapabilityModelGuidance("create_service_landing");
31190
31351
  var SERVICE_LANDING_KEY_NAMESPACE = "6f1d8c2a-3b4e-5f60-8a7b-9c0d1e2f3a4b";
31191
31352
  var SERVICE_LANDING_INFO_MAX_CHARS = 2e4;
31192
- var CreateServiceLandingInput = z127.object({
31193
- action: z127.enum([
31353
+ var CreateServiceLandingInput = z128.object({
31354
+ action: z128.enum([
31194
31355
  "prepare",
31195
31356
  "build",
31196
31357
  "status",
31197
31358
  "publish"
31198
31359
  ]).default("prepare").describe("prepare (gratis) crea o retoma la landing de la marca y da el precio; build (pagado, confirmed=true) genera la p\xE1gina directamente con la marca y los datos guardados; status sigue el avance; publish la publica y devuelve su enlace."),
31199
- brandId: z127.string().uuid().optional().describe("ID de la marca (de create_brand). Obligatorio para prepare. Nunca un taskId de producto."),
31200
- servicePageId: z127.string().uuid().optional().describe("ID de la landing que devolvi\xF3 prepare. Obligatorio para build, status y publish."),
31201
- businessInfo: z127.string().trim().max(SERVICE_LANDING_INFO_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cont\xF3 del negocio y no estaba en su marca: servicios y precios, WhatsApp o tel\xE9fono, ciudad o zona, horarios. Copia sus palabras; no inventes datos."),
31202
- confirmed: z127.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio total y que el usuario acepte. Obligatorio para build."),
31203
- maxCredits: z127.number().int().positive().optional().describe("El total en cr\xE9ditos que el usuario acept\xF3 (el que devolvi\xF3 prepare). Obligatorio para build: ninguna etapa se inicia si su precio supera este total."),
31204
- operationId: z127.string().uuid().optional().describe("Opcional en status: la operaci\xF3n que devolvi\xF3 build."),
31205
- slug: z127.string().trim().toLowerCase().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).max(64).optional().describe("Opcional en publish: la direcci\xF3n corta de la p\xE1gina (ej. sanlucas-barberia). Si falta se usa la sugerida desde el nombre del negocio.")
31360
+ brandId: z128.string().uuid().optional().describe("ID de la marca (de create_brand). Obligatorio para prepare. Nunca un taskId de producto."),
31361
+ servicePageId: z128.string().uuid().optional().describe("ID de la landing que devolvi\xF3 prepare. Obligatorio para build, status y publish."),
31362
+ businessInfo: z128.string().trim().max(SERVICE_LANDING_INFO_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cont\xF3 del negocio y no estaba en su marca: servicios y precios, WhatsApp o tel\xE9fono, ciudad o zona, horarios. Copia sus palabras; no inventes datos."),
31363
+ confirmed: z128.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio total y que el usuario acepte. Obligatorio para build."),
31364
+ maxCredits: z128.number().int().positive().optional().describe("El total en cr\xE9ditos que el usuario acept\xF3 (el que devolvi\xF3 prepare). Obligatorio para build: ninguna etapa se inicia si su precio supera este total."),
31365
+ operationId: z128.string().uuid().optional().describe("Opcional en status: la operaci\xF3n que devolvi\xF3 build."),
31366
+ slug: z128.string().trim().toLowerCase().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).max(64).optional().describe("Opcional en publish: la direcci\xF3n corta de la p\xE1gina (ej. sanlucas-barberia). Si falta se usa la sugerida desde el nombre del negocio.")
31206
31367
  }).strict();
31207
31368
  function serviceKey(...parts) {
31208
31369
  return deriveUuidV5(parts.join(":"), SERVICE_LANDING_KEY_NAMESPACE);
31209
31370
  }
31210
31371
  __name(serviceKey, "serviceKey");
31211
- function textHash(text3) {
31212
- return createHash4("sha256").update(text3, "utf8").digest("hex").slice(0, 16);
31372
+ function textHash(text4) {
31373
+ return createHash4("sha256").update(text4, "utf8").digest("hex").slice(0, 16);
31213
31374
  }
31214
31375
  __name(textHash, "textHash");
31215
31376
  function quoteRange(quote) {
@@ -31577,7 +31738,7 @@ function registerServiceLandingTools(server, api) {
31577
31738
  __name(registerServiceLandingTools, "registerServiceLandingTools");
31578
31739
 
31579
31740
  // src/tools/service-images.ts
31580
- import { z as z128 } from "zod";
31741
+ import { z as z129 } from "zod";
31581
31742
  var guidance4 = getProductMakerCapabilityModelGuidance("create_service_images");
31582
31743
  var SERVICE_IMAGE_FORMATS = [
31583
31744
  "4:5",
@@ -31590,23 +31751,23 @@ var LANGUAGE_TAGS = {
31590
31751
  en: "en-US",
31591
31752
  pt: "pt-BR"
31592
31753
  };
31593
- var CreateServiceImagesInput = z128.object({
31594
- brandId: z128.string().uuid().optional().describe("ID de un servicio propio y listo (de create_brand), obligatorio para cotizar y crear im\xE1genes nuevas. En un retry hist\xF3rico ya confirmado que originalmente no ten\xEDa este campo, conserva la petici\xF3n original. Nunca un taskId de producto."),
31595
- instruction: z128.string().trim().max(4e3).optional().describe("Opcional. Qu\xE9 servicio o promoci\xF3n mostrar, con las palabras del usuario (ej. \xABcorte + barba a $35.000 los martes\xBB). Si se omite, la IA propone la imagen usando la informaci\xF3n del servicio."),
31596
- delegateToAi: z128.boolean().optional().describe("true si el usuario prefiere que la IA elija qu\xE9 mostrar a partir de su servicio. Tambi\xE9n se delega cuando instruction est\xE1 vac\xEDo."),
31597
- format: z128.enum(SERVICE_IMAGE_FORMATS).optional().describe('Formato: "4:5" (feed, por defecto), "9:16" (historias/reels) o "1:1" (cuadrado).'),
31598
- count: z128.number().int().min(1).max(SERVICE_IMAGE_MAX_COUNT).optional().describe("Cu\xE1ntas im\xE1genes, de 1 a 3 (por defecto 1)."),
31599
- quality: z128.enum([
31754
+ var CreateServiceImagesInput = z129.object({
31755
+ brandId: z129.string().uuid().optional().describe("ID de un servicio propio y listo (de create_brand), obligatorio para cotizar y crear im\xE1genes nuevas. En un retry hist\xF3rico ya confirmado que originalmente no ten\xEDa este campo, conserva la petici\xF3n original. Nunca un taskId de producto."),
31756
+ instruction: z129.string().trim().max(4e3).optional().describe("Opcional. Qu\xE9 servicio o promoci\xF3n mostrar, con las palabras del usuario (ej. \xABcorte + barba a $35.000 los martes\xBB). Si se omite, la IA propone la imagen usando la informaci\xF3n del servicio."),
31757
+ delegateToAi: z129.boolean().optional().describe("true si el usuario prefiere que la IA elija qu\xE9 mostrar a partir de su servicio. Tambi\xE9n se delega cuando instruction est\xE1 vac\xEDo."),
31758
+ format: z129.enum(SERVICE_IMAGE_FORMATS).optional().describe('Formato: "4:5" (feed, por defecto), "9:16" (historias/reels) o "1:1" (cuadrado).'),
31759
+ count: z129.number().int().min(1).max(SERVICE_IMAGE_MAX_COUNT).optional().describe("Cu\xE1ntas im\xE1genes, de 1 a 3 (por defecto 1)."),
31760
+ quality: z129.enum([
31600
31761
  "standard",
31601
31762
  "high"
31602
31763
  ]).optional().describe('Calidad: "standard" (por defecto) o "high" (m\xE1s cara; no disponible en 4:5).'),
31603
- language: z128.enum([
31764
+ language: z129.enum([
31604
31765
  "es",
31605
31766
  "en",
31606
31767
  "pt"
31607
31768
  ]).optional().describe("Idioma de los textos de la imagen (por defecto es)."),
31608
- adCopy: z128.boolean().optional().describe("Compatibilidad con clientes anteriores: el copy para publicar siempre est\xE1 incluido en cada imagen de servicios."),
31609
- confirmed: z128.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, solo cotiza y no cobra.")
31769
+ adCopy: z129.boolean().optional().describe("Compatibilidad con clientes anteriores: el copy para publicar siempre est\xE1 incluido en cada imagen de servicios."),
31770
+ confirmed: z129.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, solo cotiza y no cobra.")
31610
31771
  }).strict();
31611
31772
  function serviceImageModel(quality) {
31612
31773
  return quality === "high" ? AD_CREATIVE_MODELS.PREMIUM : AD_CREATIVE_MODELS.STANDARD;
@@ -31723,7 +31884,7 @@ function registerServiceImageTools(server, api, options = {}) {
31723
31884
  nextAction: "Dile al usuario que est\xE1s creando sus im\xE1genes. Llama get_task_status con este taskId (waitSeconds=45) hasta done (trae las im\xE1genes reales de ProductMaker) o error. Muestra los recursos de imagen devueltos directamente en el chat. Nunca generes ni recrees una imagen sustituta con otra herramienta. Si la vista previa falla, explica el fallo y conserva los enlaces protegidos devueltos."
31724
31885
  });
31725
31886
  } catch (error) {
31726
- if (error instanceof z128.ZodError) throw invalidInputFromZod(error);
31887
+ if (error instanceof z129.ZodError) throw invalidInputFromZod(error);
31727
31888
  throw translateError(error);
31728
31889
  }
31729
31890
  });
@@ -31731,7 +31892,7 @@ function registerServiceImageTools(server, api, options = {}) {
31731
31892
  __name(registerServiceImageTools, "registerServiceImageTools");
31732
31893
 
31733
31894
  // src/tools/creatives.ts
31734
- import { z as z129 } from "zod";
31895
+ import { z as z130 } from "zod";
31735
31896
  var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
31736
31897
  var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
31737
31898
  var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
@@ -31742,72 +31903,72 @@ var CreativeRefs = {
31742
31903
  images: ImagesInput,
31743
31904
  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.'),
31744
31905
  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.'),
31745
- price: z129.string().min(1).max(120).optional().describe('Precio en formato libre \u2014 ej. "$89.900", "USD 29.99". Opcional pero MUY IMPACTANTE para conversi\xF3n: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar. Si el usuario te dice "t\xFA elige", omite el campo y la IA del backend sugiere uno.'),
31746
- offer: z129.string().min(1).max(240).optional().describe('Oferta a destacar \u2014 ej. "2x1", "Env\xEDo gratis", "50% OFF". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar (es v\xE1lido que diga "sin oferta"). Si el usuario te dice "t\xFA elige", omite el campo.'),
31747
- compareAtPrice: z129.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
31748
- productContext: z129.string().max(3e3).optional().describe("Opcional. Informacion adicional del producto que la IA debe usar como contexto prioritario: uso real, comprador, restricciones, diferenciadores o direccion creativa. No reemplaza la investigacion de competencia; si hay competencia, guia el primer angulo y los outputs no deben contradecirlo."),
31749
- productLabel: z129.string().trim().max(80).optional().describe('Opcional. Nombre o tipo del producto en pocas palabras (ej. "collar de oro", "quita pelusas para ropa"). Es AUTORITATIVO: la IA usa esta identidad y no la reemplaza por otra categor\xEDa. Si lo omites, la IA lo detecta desde la imagen. NO salta la extracci\xF3n.'),
31750
- buyerPersona: z129.string().optional().describe('Opcional. Descripci\xF3n del comprador objetivo. Ej. "Mujeres 35-50, profesionales urbanas". Si se omite, la IA infiere desde el \xE1ngulo y producto.'),
31751
- isCombo: z129.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
31752
- competitorScanEnabled: z129.boolean().optional().describe("Opcional. Default false: omitirlo significa SIN estudio de mercado. Antes de crear, llama estimate_market_study_cost, muestra al usuario el costo con y sin estudio y preg\xFAntale si lo quiere; env\xEDa true solo si lo acepta (o si solicita la narrativa an\xE1lisis de mercado). En video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico."),
31753
- brandId: z129.string().uuid().optional().describe("Opcional. ID de una marca del usuario; si se env\xEDa, el sistema usa su voz, colores y persona para enriquecer el creativo.")
31906
+ price: z130.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.'),
31907
+ offer: z130.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.'),
31908
+ compareAtPrice: z130.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
31909
+ productContext: z130.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."),
31910
+ productLabel: z130.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.'),
31911
+ buyerPersona: z130.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.'),
31912
+ isCombo: z130.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
31913
+ competitorScanEnabled: z130.boolean().optional().describe("Opcional. Default false: omitirlo significa SIN estudio de mercado. Antes de crear, llama estimate_market_study_cost, muestra al usuario el costo con y sin estudio y preg\xFAntale si lo quiere; env\xEDa true solo si lo acepta (o si solicita la narrativa an\xE1lisis de mercado). En video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico."),
31914
+ brandId: z130.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.")
31754
31915
  };
31755
- var VideoPresenter = z129.discriminatedUnion("mode", [
31756
- z129.object({
31757
- mode: z129.literal("none")
31916
+ var VideoPresenter = z130.discriminatedUnion("mode", [
31917
+ z130.object({
31918
+ mode: z130.literal("none")
31758
31919
  }).strict(),
31759
- z129.object({
31760
- mode: z129.literal("saved_actor"),
31761
- actorId: z129.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
31920
+ z130.object({
31921
+ mode: z130.literal("saved_actor"),
31922
+ actorId: z130.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
31762
31923
  }).strict(),
31763
- z129.object({
31764
- mode: z129.literal("described"),
31765
- description: z129.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
31924
+ z130.object({
31925
+ mode: z130.literal("described"),
31926
+ description: z130.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
31766
31927
  }).strict()
31767
31928
  ]);
31768
- var VideoCreativeSetup = z129.discriminatedUnion("mode", [
31769
- z129.object({
31770
- mode: z129.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
31929
+ var VideoCreativeSetup = z130.discriminatedUnion("mode", [
31930
+ z130.object({
31931
+ mode: z130.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
31771
31932
  }).strict(),
31772
- z129.object({
31773
- mode: z129.literal("guided"),
31933
+ z130.object({
31934
+ mode: z130.literal("guided"),
31774
31935
  videoPreset: VideoPresetEnum.default("auto").describe('Narrativa opcional. Con estudio de mercado no la preguntes: se usa "auto" y el estudio define la estructura. Sin estudio conserva la elecci\xF3n del usuario. Todas las narrativas funcionan en Un solo clip y Multiescena.'),
31775
- buyerPersona: z129.string().trim().min(1).max(360),
31936
+ buyerPersona: z130.string().trim().min(1).max(360),
31776
31937
  animationStyle: AnimationStyleEnum.optional().describe('Opcional. Estilo visual SOLO para presets animados ("pixar_problem" o "pixar_sassy") \u2014 la API lo rechaza con cualquier otro preset. Opciones: "pixar_3d" (default, look 3D de pel\xEDcula animada), "claymation" (plastilina stop-motion artesanal), "wes_anderson" (tableau sim\xE9trico pastel), "sci_fi" (futurista con HUDs y ne\xF3n), "realista" (fotorrealista, fiel al producto). Si el usuario pide un look animado sin nombrar el estilo, omite el campo.'),
31777
31938
  presenter: VideoPresenter,
31778
- creativeDirection: z129.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
31939
+ creativeDirection: z130.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
31779
31940
  }).strict()
31780
31941
  ]);
31781
- var VideoInput = z129.object({
31942
+ var VideoInput = z130.object({
31782
31943
  images: CreativeRefs.images.optional(),
31783
31944
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
31784
- title: z129.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
31785
- primaryAngle: z129.string().min(1).describe('\xC1ngulo de venta principal (frase del beneficio). Ej. "Reduce arrugas en 14 d\xEDas" o "Para quienes odian las cremas grasosas".'),
31945
+ title: z130.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
31946
+ primaryAngle: z130.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".'),
31786
31947
  language: CreativeRefs.language,
31787
31948
  country: CreativeRefs.country,
31788
- aspectRatio: z129.enum([
31949
+ aspectRatio: z130.enum([
31789
31950
  "9:16",
31790
31951
  "16:9",
31791
31952
  "Auto"
31792
31953
  ]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
31793
31954
  generateAiEdit: AiEditRequestSchema.optional().describe('Opcional. Pide la Edici\xF3n con IA: una pasada que a\xF1ade texto, efectos y m\xFAsica sobre cada video entregado (variante with_ai_edit; se cobra al entregar, por video). Nivel: "economy" (Econ\xF3mica, Sonnet 5.5, m\xE1s barata) o "pro" (Opus 5.5, mejor calidad, ~10 min). true equivale a "pro"; false/omitido = sin edici\xF3n.'),
31794
- durationSeconds: z129.number().int().min(4).max(30).default(15).describe("Opcional. Duraci\xF3n objetivo: Un solo clip Econ\xF3mico o Medio usa 15s; Un solo clip Pro usa 15s o 30s; Multiescena usa 15s o 30s totales. La combinaci\xF3n de formato y calidad determina la ruta y el costo."),
31795
- videoAngleCount: z129.number().int().min(1).max(3).describe("Cantidad de videos a renderizar: 1, 2 o 3. Es una decisi\xF3n de costo obligatoria: preg\xFAntala incluso cuando creativeSetup.mode=automatic."),
31955
+ durationSeconds: z130.number().int().min(4).max(30).default(15).describe("Opcional. Duraci\xF3n objetivo: Un solo clip Econ\xF3mico o Medio usa 15s; Un solo clip Pro usa 15s o 30s; Multiescena usa 15s o 30s totales. La combinaci\xF3n de formato y calidad determina la ruta y el costo."),
31956
+ videoAngleCount: z130.number().int().min(1).max(3).describe("Cantidad de videos a renderizar: 1, 2 o 3. Es una decisi\xF3n de costo obligatoria: preg\xFAntala incluso cuando creativeSetup.mode=automatic."),
31796
31957
  angleNarratives: PublicNarrativeStyleEnum.array().max(3).optional().describe('Opcional. Narrativa POR \xC1NGULO (posicional). Valores actuales: "review", "ugc_how_to", "ugc_unboxing_chaos", "problem_product_cta" (problema concreto, producto como soluci\xF3n y CTA), "product_showcase", "wearable_showcase", "cinematic", "wild_card", "animated_problem_pixar", "sassy_product_pixar", "market" (narrativa an\xE1lisis de mercado: adapta el video a los patrones ganadores estudiados de la competencia; requiere competitorScanEnabled: true). angleNarratives[i] fuerza la narrativa del \xE1ngulo i; las posiciones restantes las elige la IA. La lista no puede superar videoAngleCount.'),
31797
31958
  creativeSetup: VideoCreativeSetup.describe("Configuraci\xF3n creativa obligatoria. En guided pregunta narrativa, p\xFAblico, presentador y direcci\xF3n antes de confirmar. Usa automatic s\xF3lo si el usuario deleg\xF3 todo expl\xEDcitamente."),
31798
31959
  videoStructure: VideoStructureEnum.default("single_take").describe('Opcional. Formato: "single_take" = Un solo clip (generado completo; puede incluir cambios de plano) o "multi_scene" = Multiescena (varias tomas concatenadas). Default: single_take.'),
31799
31960
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
31800
31961
  videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render: "480p" o "720p". Si se omite, se usa 480p; elige 720p expl\xEDcitamente si necesitas m\xE1s nitidez.'),
31801
- features: z129.array(z129.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
31962
+ features: z130.array(z130.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
31802
31963
  price: CreativeRefs.price,
31803
31964
  offer: CreativeRefs.offer,
31804
31965
  productContext: CreativeRefs.productContext,
31805
31966
  productLabel: CreativeRefs.productLabel,
31806
- cta: z129.string().optional().describe('Opcional. Call-to-action final del video. Ej. "Compra ahora", "Pide el tuyo hoy", "Link en bio". Si se omite, la IA escribe uno.'),
31807
- scriptNotes: z129.string().optional().describe('Opcional. Notas/restricciones para el guion (la IA las usa al redactar). Ej. "No mencionar la marca X", "Tono divertido, no cl\xEDnico", "Mencionar 2x1". NO es el guion literal: creativeSetup.mode=guided activa siempre la revisi\xF3n palabra-por-palabra con get_video_script / approve_video_script.'),
31967
+ cta: z130.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.'),
31968
+ scriptNotes: z130.string().optional().describe('Opcional. Notas/restricciones para el guion (la IA las usa al redactar). Ej. "No mencionar la marca X", "Tono divertido, no cl\xEDnico", "Mencionar 2x1". NO es el guion literal: creativeSetup.mode=guided activa siempre la revisi\xF3n palabra-por-palabra con get_video_script / approve_video_script.'),
31808
31969
  creativeGender: CreativeGenderEnum.optional().describe('Opcional. QUI\xC9N APARECE EN PANTALLA en el video: mujer ("female"), hombre ("male") o ambos ("mixed"). NO es la voz; cuando se fija, la voz se alinea sola con el personaje. M\xE1ndalo en cuanto el usuario diga qui\xE9n debe SALIR en el video, con cualquier redacci\xF3n ("quiero una mujer", "que salga un hombre", "protagonista femenina"): si no lo mandas, el g\xE9nero lo inventa la IA y el usuario puede recibir lo contrario de lo que pidi\xF3 sin ning\xFAn aviso. NO lo mandes cuando hable del P\xDABLICO COMPRADOR ("esto es para hombres", "mi p\xFAblico son mujeres", "va dirigido a mam\xE1s"): eso es a qui\xE9n se le vende, no qui\xE9n act\xFAa, y fijarlo ah\xED pinea un protagonista que nadie pidi\xF3. "mixed" solo cuando pida expl\xEDcitamente ambos, y ten en cuenta que no garantiza una mezcla: no fija ning\xFAn g\xE9nero y cada creativo elige su protagonista. No lo preguntes como paso obligatorio. Si creativeSetup.presenter.mode="saved_actor", el personaje guardado manda sobre este campo.'),
31809
31970
  competitorScanEnabled: CreativeRefs.competitorScanEnabled,
31810
- replicateWinnerWhenFound: z129.boolean().optional().describe("Conserva la preferencia de copiar un ganador si existe. false permite estudiar el mercado sin reemplazar un \xE1ngulo por el anuncio ganador. No a\xF1adas una pregunta obligatoria para este campo."),
31971
+ replicateWinnerWhenFound: z130.boolean().optional().describe("Conserva la preferencia de copiar un ganador si existe. false permite estudiar el mercado sin reemplazar un \xE1ngulo por el anuncio ganador. No a\xF1adas una pregunta obligatoria para este campo."),
31811
31972
  brandId: CreativeRefs.brandId
31812
31973
  }).strict();
31813
31974
  var FreeVideoQualityEnum = VideoQualityEnum;
@@ -31825,7 +31986,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
31825
31986
  length: 29
31826
31987
  }, (_, index) => index + 2)
31827
31988
  };
31828
- var FreeVideoModelIdEnum = z129.enum([
31989
+ var FreeVideoModelIdEnum = z130.enum([
31829
31990
  "grok-imagine-video-1-5-preview",
31830
31991
  "minimax-h3/reference-to-video",
31831
31992
  "wan/3-0-video",
@@ -31836,66 +31997,66 @@ var FREE_SELECTABLE_MODEL_IDS = [
31836
31997
  "minimax-h3/reference-to-video",
31837
31998
  "wan/3-0-video"
31838
31999
  ];
31839
- var FreeVideoInput = z129.object({
32000
+ var FreeVideoInput = z130.object({
31840
32001
  images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
31841
- rawPrompt: z129.string().trim().min(1).max(2e3).describe("Prompt o guion exacto del video. Si activas subt\xEDtulos, este mismo texto se usa como guion de subt\xEDtulos."),
32002
+ rawPrompt: z130.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."),
31842
32003
  language: CreativeRefs.language,
31843
32004
  quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
31844
32005
  // Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
31845
32006
  // parsed ONLY so the handler can reject it with a message naming its
31846
32007
  // replacement — dropping it silently would turn a caller's explicit
31847
32008
  // Pro++ pick into a quiet fallback to Wan.
31848
- freeProModel: z129.enum([
32009
+ freeProModel: z130.enum([
31849
32010
  "wan",
31850
32011
  "seedance"
31851
32012
  ]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
31852
32013
  modelId: FreeVideoModelIdEnum.optional().describe('Opcional. Elige expl\xEDcitamente el modelo del registro en vez del default de la calidad: "grok-imagine-video-1-5-preview" (Grok 1.5), "minimax-h3/reference-to-video" (H3 Max) o "wan/3-0-video" (Wan 3.0). Om\xEDtelo para usar el modelo por defecto de la calidad elegida. El modelo determina la duraci\xF3n permitida (Grok 6/8/10/15s, H3 Max 4-15s, Wan 2-30s) y el precio. "bytedance/seedance-2-5" est\xE1 inactivo y se rechaza con un error claro, nunca un 500.'),
31853
- durationSeconds: z129.number().int().min(2).max(30).describe("Duraci\xF3n exacta. Econ\xF3mico: 6, 8, 10 o 15s; Medio: enteros de 4 a 15s; Pro Wan: 2 a 30s; Pro++ Seedance: 4 a 30s."),
32014
+ durationSeconds: z130.number().int().min(2).max(30).describe("Duraci\xF3n exacta. Econ\xF3mico: 6, 8, 10 o 15s; Medio: enteros de 4 a 15s; Pro Wan: 2 a 30s; Pro++ Seedance: 4 a 30s."),
31854
32015
  videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
31855
- generateAiMusic: z129.boolean().default(false).describe('Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false. Equivale a generateAiEdit (nivel "pro"): la Edici\xF3n con IA trae su propia m\xFAsica.'),
32016
+ generateAiMusic: z130.boolean().default(false).describe('Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false. Equivale a generateAiEdit (nivel "pro"): la Edici\xF3n con IA trae su propia m\xFAsica.'),
31856
32017
  generateAiEdit: AiEditRequestSchema.optional().describe('Opcional. Pide la Edici\xF3n con IA: una pasada que a\xF1ade texto, gr\xE1ficos y m\xFAsica sobre el video ya entregado (variante with_ai_edit; se cobra al entregar). Nivel: "economy" (Econ\xF3mica, Sonnet 5.5, m\xE1s barata) o "pro" (Opus 5.5, mejor calidad, ~10 min). true equivale a "pro". Default sin edici\xF3n.'),
31857
- addSubtitles: z129.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
31858
- idempotencyKey: z129.string().uuid().optional().describe("Opcional. Se acepta por compatibilidad pero se ignora: la identidad del reintento se deriva autom\xE1ticamente de los argumentos sem\xE1nticos, as\xED que un retry con los mismos argumentos ya es idempotente sin este campo.")
32018
+ addSubtitles: z130.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
32019
+ idempotencyKey: z130.string().uuid().optional().describe("Opcional. Se acepta por compatibilidad pero se ignora: la identidad del reintento se deriva autom\xE1ticamente de los argumentos sem\xE1nticos, as\xED que un retry con los mismos argumentos ya es idempotente sin este campo.")
31859
32020
  }).strict();
31860
32021
  var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
31861
- var ImageCreativeSetup = z129.discriminatedUnion("mode", [
31862
- z129.object({
31863
- mode: z129.literal("automatic")
32022
+ var ImageCreativeSetup = z130.discriminatedUnion("mode", [
32023
+ z130.object({
32024
+ mode: z130.literal("automatic")
31864
32025
  }).strict(),
31865
- z129.object({
31866
- mode: z129.literal("guided"),
31867
- creativeArchetype: z129.union([
32026
+ z130.object({
32027
+ mode: z130.literal("guided"),
32028
+ creativeArchetype: z130.union([
31868
32029
  ImageCreativeArchetypeEnum,
31869
- z129.literal("ai_decides")
32030
+ z130.literal("ai_decides")
31870
32031
  ]),
31871
- visualTreatment: z129.union([
32032
+ visualTreatment: z130.union([
31872
32033
  ImageCreativeVisualTreatmentEnum,
31873
- z129.literal("ai_decides")
32034
+ z130.literal("ai_decides")
31874
32035
  ]),
31875
32036
  aspectRatio: ImageCreativeAspectRatioEnum,
31876
- nVariants: z129.union([
31877
- z129.literal(1),
31878
- z129.literal(2),
31879
- z129.literal(3),
31880
- z129.literal(4),
31881
- z129.literal(6)
32037
+ nVariants: z130.union([
32038
+ z130.literal(1),
32039
+ z130.literal(2),
32040
+ z130.literal(3),
32041
+ z130.literal(4),
32042
+ z130.literal(6)
31882
32043
  ]),
31883
- imageModel: z129.enum(PUBLIC_IMAGE_QUALITY_INPUTS).describe('Calidad: "image:1k" (Est\xE1ndar) o "image:2k" (Premium). Los tokens gpt-image-2-5:{1k,2k} y gpt-image-2:{1k,2k} se siguen aceptando.'),
31884
- styleMix: z129.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
31885
- generateAdCopy: z129.boolean(),
31886
- competitorScanEnabled: z129.boolean(),
31887
- productContext: z129.string().trim().min(1).max(3e3).nullable(),
31888
- creativeDirection: z129.string().trim().min(1).max(500).nullable(),
31889
- brandColors: z129.string().trim().min(1).max(240).nullable().describe('Colores en lenguaje natural, igual que en el chat web. Ej. "Azul y Dorado". null significa sin colores espec\xEDficos.'),
31890
- headline: z129.string().trim().min(1).max(120).nullable(),
31891
- subheadline: z129.string().trim().min(1).max(160).nullable()
32044
+ imageModel: z130.enum(PUBLIC_IMAGE_QUALITY_INPUTS).describe('Calidad: "image:1k" (Est\xE1ndar) o "image:2k" (Premium). Los tokens gpt-image-2-5:{1k,2k} y gpt-image-2:{1k,2k} se siguen aceptando.'),
32045
+ styleMix: z130.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
32046
+ generateAdCopy: z130.boolean(),
32047
+ competitorScanEnabled: z130.boolean(),
32048
+ productContext: z130.string().trim().min(1).max(3e3).nullable(),
32049
+ creativeDirection: z130.string().trim().min(1).max(500).nullable(),
32050
+ brandColors: z130.string().trim().min(1).max(240).nullable().describe('Colores en lenguaje natural, igual que en el chat web. Ej. "Azul y Dorado". null significa sin colores espec\xEDficos.'),
32051
+ headline: z130.string().trim().min(1).max(120).nullable(),
32052
+ subheadline: z130.string().trim().min(1).max(160).nullable()
31892
32053
  }).strict()
31893
32054
  ]).superRefine((setup, context) => {
31894
32055
  if (setup.mode !== "guided") return;
31895
32056
  const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
31896
32057
  if (needsStyleMix && setup.styleMix === null) {
31897
32058
  context.addIssue({
31898
- code: z129.ZodIssueCode.custom,
32059
+ code: z130.ZodIssueCode.custom,
31899
32060
  path: [
31900
32061
  "styleMix"
31901
32062
  ],
@@ -31904,7 +32065,7 @@ var ImageCreativeSetup = z129.discriminatedUnion("mode", [
31904
32065
  }
31905
32066
  if (!needsStyleMix && setup.styleMix !== null) {
31906
32067
  context.addIssue({
31907
- code: z129.ZodIssueCode.custom,
32068
+ code: z130.ZodIssueCode.custom,
31908
32069
  path: [
31909
32070
  "styleMix"
31910
32071
  ],
@@ -31913,7 +32074,7 @@ var ImageCreativeSetup = z129.discriminatedUnion("mode", [
31913
32074
  }
31914
32075
  if (imageResolutionOf(setup.imageModel) === "2k" && setup.aspectRatio === "4:5") {
31915
32076
  context.addIssue({
31916
- code: z129.ZodIssueCode.custom,
32077
+ code: z130.ZodIssueCode.custom,
31917
32078
  path: [
31918
32079
  "aspectRatio"
31919
32080
  ],
@@ -31921,55 +32082,55 @@ var ImageCreativeSetup = z129.discriminatedUnion("mode", [
31921
32082
  });
31922
32083
  }
31923
32084
  });
31924
- var LandingCreativeSetup = z129.discriminatedUnion("mode", [
31925
- z129.object({
31926
- mode: z129.literal("automatic")
32085
+ var LandingCreativeSetup = z130.discriminatedUnion("mode", [
32086
+ z130.object({
32087
+ mode: z130.literal("automatic")
31927
32088
  }).strict(),
31928
- z129.object({
31929
- mode: z129.literal("guided"),
32089
+ z130.object({
32090
+ mode: z130.literal("guided"),
31930
32091
  landingStrategy: LandingStrategyEnum,
31931
32092
  landingImageFormat: LandingImageFormatEnum,
31932
- competitorScanEnabled: z129.boolean(),
31933
- paymentMethods: z129.string().trim().min(1).max(240).nullable(),
31934
- productContext: z129.string().trim().min(1).max(3e3).nullable(),
31935
- creativeDirection: z129.string().trim().min(1).max(500).nullable(),
31936
- headline: z129.string().trim().min(1).max(120).nullable(),
31937
- subheadline: z129.string().trim().min(1).max(160).nullable()
32093
+ competitorScanEnabled: z130.boolean(),
32094
+ paymentMethods: z130.string().trim().min(1).max(240).nullable(),
32095
+ productContext: z130.string().trim().min(1).max(3e3).nullable(),
32096
+ creativeDirection: z130.string().trim().min(1).max(500).nullable(),
32097
+ headline: z130.string().trim().min(1).max(120).nullable(),
32098
+ subheadline: z130.string().trim().min(1).max(160).nullable()
31938
32099
  }).strict()
31939
32100
  ]);
31940
- var ImageInput = z129.object({
32101
+ var ImageInput = z130.object({
31941
32102
  images: CreativeRefs.images.optional(),
31942
32103
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
31943
- productTitle: z129.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
31944
- primaryAngle: z129.string().min(1).optional().describe('Opcional. \xC1ngulo de venta principal. Si se omite, ProductMaker lo genera y creativeSetup.mode="guided" lo muestra para revisi\xF3n antes de crear las im\xE1genes.'),
32104
+ productTitle: z130.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
32105
+ primaryAngle: z130.string().min(1).optional().describe('Opcional. \xC1ngulo de venta principal. Si se omite, ProductMaker lo genera y creativeSetup.mode="guided" lo muestra para revisi\xF3n antes de crear las im\xE1genes.'),
31945
32106
  buyerPersona: CreativeRefs.buyerPersona,
31946
32107
  language: CreativeRefs.language,
31947
32108
  country: CreativeRefs.country,
31948
32109
  creativeSetup: ImageCreativeSetup.describe("Configuraci\xF3n obligatoria equivalente al wizard web. Usa guided salvo que el usuario delegue expl\xEDcitamente todo; presenta las decisiones guiadas en un \xFAnico checklist compacto."),
31949
32110
  imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
31950
- features: z129.array(z129.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
32111
+ features: z130.array(z130.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
31951
32112
  price: CreativeRefs.price,
31952
- omitPrice: z129.boolean().optional().describe("Pon true \xFAnicamente cuando el usuario pida expl\xEDcitamente una imagen sin precio. Evita que el backend reutilice un precio extra\xEDdo del producto. No lo combines con price ni compareAtPrice."),
32113
+ omitPrice: z130.boolean().optional().describe("Pon true \xFAnicamente cuando el usuario pida expl\xEDcitamente una imagen sin precio. Evita que el backend reutilice un precio extra\xEDdo del producto. No lo combines con price ni compareAtPrice."),
31953
32114
  compareAtPrice: CreativeRefs.compareAtPrice,
31954
32115
  offer: CreativeRefs.offer,
31955
32116
  productLabel: CreativeRefs.productLabel,
31956
32117
  isCombo: CreativeRefs.isCombo,
31957
32118
  brandId: CreativeRefs.brandId
31958
32119
  });
31959
- var EditImageCreativeInput = z129.object({
31960
- taskId: z129.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
31961
- variantIndex: z129.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
31962
- clientRequestId: z129.string().min(1).max(160).optional().describe("Identidad estable de esta correcci\xF3n; reutil\xEDzala al reconciliar una respuesta perdida, no para otra instrucci\xF3n."),
31963
- instruction: z129.string().min(1).max(1e3).describe('Qu\xE9 cambiar en esa imagen. Ej. "quita el badge de env\xEDo gratis", "cambia el fondo a blanco".')
32120
+ var EditImageCreativeInput = z130.object({
32121
+ taskId: z130.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
32122
+ variantIndex: z130.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
32123
+ clientRequestId: z130.string().min(1).max(160).optional().describe("Identidad estable de esta correcci\xF3n; reutil\xEDzala al reconciliar una respuesta perdida, no para otra instrucci\xF3n."),
32124
+ instruction: z130.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".')
31964
32125
  });
31965
- var LandingInput = z129.object({
31966
- includeInitialLandingGif: z129.boolean().optional().describe("Opcional. En nuevas landings cl\xE1sicas habilitadas, omitirlo incluye el primer GIF del producto y su coste en el total. Env\xEDa false si el usuario lo excluye: no se genera ni se reserva su coste. Conserva la elecci\xF3n al confirmar y al reintentar."),
32126
+ var LandingInput = z130.object({
32127
+ includeInitialLandingGif: z130.boolean().optional().describe("Opcional. En nuevas landings cl\xE1sicas habilitadas, omitirlo incluye el primer GIF del producto y su coste en el total. Env\xEDa false si el usuario lo excluye: no se genera ni se reserva su coste. Conserva la elecci\xF3n al confirmar y al reintentar."),
31967
32128
  images: CreativeRefs.images.optional(),
31968
32129
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
31969
32130
  language: CreativeRefs.language,
31970
32131
  country: CreativeRefs.country,
31971
32132
  creativeSetup: LandingCreativeSetup.describe("Configuraci\xF3n obligatoria de landing cl\xE1sica equivalente al wizard web. No expone landing editable/code mientras siga siendo admin-only."),
31972
- salesAngle: z129.string().optional().describe('Opcional. \xC1ngulo de venta principal. Ej. "Reduce arrugas en 14 d\xEDas". Si se omite, la IA lo deduce de la imagen.'),
32133
+ salesAngle: z130.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.'),
31973
32134
  buyerPersona: CreativeRefs.buyerPersona,
31974
32135
  price: CreativeRefs.price,
31975
32136
  compareAtPrice: CreativeRefs.compareAtPrice,
@@ -32251,8 +32412,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
32251
32412
  server.registerTool("get_image_edit_status", {
32252
32413
  description: imageEditStatusGuidance.summary,
32253
32414
  inputSchema: {
32254
- taskId: z129.string().uuid(),
32255
- operationId: z129.string().uuid()
32415
+ taskId: z130.string().uuid(),
32416
+ operationId: z130.string().uuid()
32256
32417
  },
32257
32418
  annotations: READS_INTERNAL
32258
32419
  }, async (input) => {
@@ -32309,10 +32470,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
32309
32470
  __name(registerCreativeTools, "registerCreativeTools");
32310
32471
 
32311
32472
  // src/tools/creative-variants.ts
32312
- import { z as z130 } from "zod";
32473
+ import { z as z131 } from "zod";
32313
32474
  var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
32314
32475
  var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
32315
- var LandingSectionKeyEnum = z130.enum([
32476
+ var LandingSectionKeyEnum = z131.enum([
32316
32477
  "problem_hook",
32317
32478
  "problem_cost",
32318
32479
  "solution_mechanism",
@@ -32352,24 +32513,24 @@ var LandingSectionKeyEnum = z130.enum([
32352
32513
  "lifestyle_fit",
32353
32514
  "join_lifestyle"
32354
32515
  ]);
32355
- var CreativeVariantKindEnum = z130.enum([
32516
+ var CreativeVariantKindEnum = z131.enum([
32356
32517
  "video",
32357
32518
  "image",
32358
32519
  "landing"
32359
32520
  ]);
32360
- var EstimateCreativeVariantInputBase = z130.object({
32361
- sourceTaskId: z130.string().uuid().describe("ID de la tarea original completada."),
32521
+ var EstimateCreativeVariantInputBase = z131.object({
32522
+ sourceTaskId: z131.string().uuid().describe("ID de la tarea original completada."),
32362
32523
  kind: CreativeVariantKindEnum,
32363
32524
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
32364
32525
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
32365
- nVariants: z130.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
32526
+ nVariants: z131.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
32366
32527
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
32367
- instructions: z130.string().trim().min(1).max(2e3).optional().describe("Opcional para landing. Si se env\xEDa sin sectionKey, el estimado suma la clasificaci\xF3n pagada con IA.")
32528
+ instructions: z131.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.")
32368
32529
  }).strict();
32369
32530
  var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
32370
32531
  if (input.kind === "video" && input.nVariants !== void 0) {
32371
32532
  ctx.addIssue({
32372
- code: z130.ZodIssueCode.custom,
32533
+ code: z131.ZodIssueCode.custom,
32373
32534
  path: [
32374
32535
  "nVariants"
32375
32536
  ],
@@ -32379,7 +32540,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
32379
32540
  if (input.kind !== "video") {
32380
32541
  if (input.videoPreset !== void 0) {
32381
32542
  ctx.addIssue({
32382
- code: z130.ZodIssueCode.custom,
32543
+ code: z131.ZodIssueCode.custom,
32383
32544
  path: [
32384
32545
  "videoPreset"
32385
32546
  ],
@@ -32388,7 +32549,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
32388
32549
  }
32389
32550
  if (input.videoResolution !== void 0) {
32390
32551
  ctx.addIssue({
32391
- code: z130.ZodIssueCode.custom,
32552
+ code: z131.ZodIssueCode.custom,
32392
32553
  path: [
32393
32554
  "videoResolution"
32394
32555
  ],
@@ -32398,7 +32559,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
32398
32559
  }
32399
32560
  if (input.kind !== "image" && input.nVariants !== void 0) {
32400
32561
  ctx.addIssue({
32401
- code: z130.ZodIssueCode.custom,
32562
+ code: z131.ZodIssueCode.custom,
32402
32563
  path: [
32403
32564
  "nVariants"
32404
32565
  ],
@@ -32408,7 +32569,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
32408
32569
  if (input.kind !== "landing") {
32409
32570
  if (input.sectionKey !== void 0) {
32410
32571
  ctx.addIssue({
32411
- code: z130.ZodIssueCode.custom,
32572
+ code: z131.ZodIssueCode.custom,
32412
32573
  path: [
32413
32574
  "sectionKey"
32414
32575
  ],
@@ -32417,7 +32578,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
32417
32578
  }
32418
32579
  if (input.instructions !== void 0) {
32419
32580
  ctx.addIssue({
32420
- code: z130.ZodIssueCode.custom,
32581
+ code: z131.ZodIssueCode.custom,
32421
32582
  path: [
32422
32583
  "instructions"
32423
32584
  ],
@@ -32426,31 +32587,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
32426
32587
  }
32427
32588
  }
32428
32589
  });
32429
- var CreateCreativeVariantInputBase = z130.object({
32430
- sourceTaskId: z130.string().uuid().describe("ID de la tarea original completada."),
32590
+ var CreateCreativeVariantInputBase = z131.object({
32591
+ sourceTaskId: z131.string().uuid().describe("ID de la tarea original completada."),
32431
32592
  kind: CreativeVariantKindEnum,
32432
- confirm: z130.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
32433
- clientRequestId: z130.string().uuid().describe("UUID estable para esta intenci\xF3n (obligatorio por compatibilidad de contrato; el servidor deriva la identidad real del request desde los argumentos sem\xE1nticos, as\xED que un UUID nuevo en un retry NO crea una variante duplicada). Si la API devuelve status=error, una nueva generaci\xF3n exige otra confirmaci\xF3n."),
32434
- angle: z130.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
32435
- buyerPersona: z130.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
32436
- scriptNotes: z130.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
32437
- creativeDirection: z130.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
32593
+ confirm: z131.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
32594
+ clientRequestId: z131.string().uuid().describe("UUID estable para esta intenci\xF3n (obligatorio por compatibilidad de contrato; el servidor deriva la identidad real del request desde los argumentos sem\xE1nticos, as\xED que un UUID nuevo en un retry NO crea una variante duplicada). Si la API devuelve status=error, una nueva generaci\xF3n exige otra confirmaci\xF3n."),
32595
+ angle: z131.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
32596
+ buyerPersona: z131.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
32597
+ scriptNotes: z131.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
32598
+ creativeDirection: z131.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
32438
32599
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
32439
32600
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
32440
- generateAiMusic: z130.boolean().optional().describe("Opcional para video."),
32441
- nVariants: z130.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
32601
+ generateAiMusic: z131.boolean().optional().describe("Opcional para video."),
32602
+ nVariants: z131.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
32442
32603
  imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
32443
32604
  creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
32444
32605
  visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
32445
32606
  aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
32446
- styleMix: z130.boolean().optional().describe("Opcional para imagen."),
32607
+ styleMix: z131.boolean().optional().describe("Opcional para imagen."),
32447
32608
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
32448
- instructions: z130.string().trim().min(1).max(2e3).optional().describe("Solicitud libre para una nueva secci\xF3n de landing. La IA la clasifica si no env\xEDas sectionKey.")
32609
+ instructions: z131.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.")
32449
32610
  }).strict();
32450
32611
  var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
32451
32612
  if ((input.kind === "video" || input.kind === "image") && !input.angle) {
32452
32613
  ctx.addIssue({
32453
- code: z130.ZodIssueCode.custom,
32614
+ code: z131.ZodIssueCode.custom,
32454
32615
  path: [
32455
32616
  "angle"
32456
32617
  ],
@@ -32459,7 +32620,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
32459
32620
  }
32460
32621
  if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
32461
32622
  ctx.addIssue({
32462
- code: z130.ZodIssueCode.custom,
32623
+ code: z131.ZodIssueCode.custom,
32463
32624
  path: [
32464
32625
  "instructions"
32465
32626
  ],
@@ -32505,7 +32666,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
32505
32666
  for (const field of fieldsByKind[input.kind]) {
32506
32667
  if (input[field] !== void 0) {
32507
32668
  ctx.addIssue({
32508
- code: z130.ZodIssueCode.custom,
32669
+ code: z131.ZodIssueCode.custom,
32509
32670
  path: [
32510
32671
  field
32511
32672
  ],
@@ -32663,13 +32824,13 @@ function registerCreativeVariantTools(server, api) {
32663
32824
  __name(registerCreativeVariantTools, "registerCreativeVariantTools");
32664
32825
 
32665
32826
  // src/tools/script-review.ts
32666
- import { z as z131 } from "zod";
32827
+ import { z as z132 } from "zod";
32667
32828
  var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
32668
32829
  var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
32669
32830
  var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
32670
- var GetVideoScriptInput = z131.object({
32671
- taskId: z131.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
32672
- angleKey: z131.string().min(1).optional().describe('Clave persistida del \xE1ngulo cuyo guion se quiere leer (formato "angle_0", "angle_1", ...). Usa exactamente el angleKey recibido en reviewNextAction.calls al aprobar \xE1ngulos, incluso si s\xF3lo elegiste uno. Si se omite, el backend resuelve a "angle_0" literal; elegir el segundo candidato no crea angle_0. No derives esta clave del n\xFAmero visible del candidato.')
32831
+ var GetVideoScriptInput = z132.object({
32832
+ taskId: z132.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
32833
+ angleKey: z132.string().min(1).optional().describe('Clave persistida del \xE1ngulo cuyo guion se quiere leer (formato "angle_0", "angle_1", ...). Usa exactamente el angleKey recibido en reviewNextAction.calls al aprobar \xE1ngulos, incluso si s\xF3lo elegiste uno. Si se omite, el backend resuelve a "angle_0" literal; elegir el segundo candidato no crea angle_0. No derives esta clave del n\xFAmero visible del candidato.')
32673
32834
  }).strict();
32674
32835
  var ApproveVideoScriptInput = ApproveVideoScriptCapabilityRequest;
32675
32836
  var RegenerateVideoScriptInput = RegenerateVideoScriptCapabilityRequest.extend({
@@ -32774,7 +32935,7 @@ Consulta get_task_status con esta tarea antes de reintentar. Si la tarea termin\
32774
32935
  __name(registerScriptReviewTools, "registerScriptReviewTools");
32775
32936
 
32776
32937
  // src/tools/connections.ts
32777
- import { z as z132 } from "zod";
32938
+ import { z as z133 } from "zod";
32778
32939
  var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
32779
32940
  var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
32780
32941
  var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
@@ -32783,7 +32944,7 @@ var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list
32783
32944
  function registerConnectionTools(server, api) {
32784
32945
  server.registerTool("list_shopify_shops", {
32785
32946
  description: listShopifyShopsGuidance.summary + " Si la lista est\xE1 vac\xEDa, dile al usuario que conecte una tienda en productmaker.app/integrations antes de intentar publicar.",
32786
- inputSchema: z132.object({}).shape,
32947
+ inputSchema: z133.object({}).shape,
32787
32948
  annotations: READS_INTERNAL
32788
32949
  }, async () => {
32789
32950
  try {
@@ -32795,10 +32956,10 @@ function registerConnectionTools(server, api) {
32795
32956
  });
32796
32957
  server.registerTool("list_shopify_products", {
32797
32958
  description: listShopifyProductsGuidance.summary + ' Usa el `id` devuelto junto con `publicationMode="existing"` en `publish_to_shopify`. Si `taskId` se proporciona, la respuesta tambi\xE9n indica el producto publicado actualmente para esa tarea y tienda. No modifica Shopify.',
32798
- inputSchema: z132.object({
32799
- shopDomain: z132.string().min(3).max(120),
32800
- query: z132.string().trim().max(120).optional(),
32801
- taskId: z132.string().uuid().optional()
32959
+ inputSchema: z133.object({
32960
+ shopDomain: z133.string().min(3).max(120),
32961
+ query: z133.string().trim().max(120).optional(),
32962
+ taskId: z133.string().uuid().optional()
32802
32963
  }).shape,
32803
32964
  annotations: READS_EXTERNAL
32804
32965
  }, async ({ shopDomain, query, taskId }) => {
@@ -32816,7 +32977,7 @@ function registerConnectionTools(server, api) {
32816
32977
  });
32817
32978
  server.registerTool("list_meta_ad_accounts", {
32818
32979
  description: listMetaAdAccountsGuidance.summary + " Para publicar, prefiere `list_meta_destinations`, que tambi\xE9n devuelve el portfolio y las p\xE1ginas disponibles. Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar Meta en productmaker.app/integrations.",
32819
- inputSchema: z132.object({}).shape,
32980
+ inputSchema: z133.object({}).shape,
32820
32981
  annotations: READS_EXTERNAL
32821
32982
  }, async () => {
32822
32983
  try {
@@ -32828,7 +32989,7 @@ function registerConnectionTools(server, api) {
32828
32989
  });
32829
32990
  server.registerTool("list_meta_destinations", {
32830
32991
  description: listMetaDestinationsGuidance.summary + " Es obligatorio llamar esta herramienta antes de publicar, mostrar las opciones y enviar al publicador el `portfolioId`, `adAccountId` y `pageId` elegidos; nunca elijas silenciosamente la primera p\xE1gina o cuenta. No modifica Meta.",
32831
- inputSchema: z132.object({}).shape,
32992
+ inputSchema: z133.object({}).shape,
32832
32993
  annotations: READS_EXTERNAL,
32833
32994
  _meta: {
32834
32995
  "openai/widgetAccessible": true
@@ -32843,7 +33004,7 @@ function registerConnectionTools(server, api) {
32843
33004
  });
32844
33005
  server.registerTool("list_tiktok_advertisers", {
32845
33006
  description: listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.",
32846
- inputSchema: z132.object({}).shape,
33007
+ inputSchema: z133.object({}).shape,
32847
33008
  annotations: READS_EXTERNAL
32848
33009
  }, async () => {
32849
33010
  try {
@@ -32857,7 +33018,7 @@ function registerConnectionTools(server, api) {
32857
33018
  __name(registerConnectionTools, "registerConnectionTools");
32858
33019
 
32859
33020
  // src/tools/actors.ts
32860
- import { z as z133 } from "zod";
33021
+ import { z as z134 } from "zod";
32861
33022
  var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
32862
33023
  var actorVoiceGuidance = {
32863
33024
  capabilities: getProductMakerCapabilityModelGuidance("get_actor_voice_capabilities"),
@@ -32897,7 +33058,7 @@ function sanitizeVoiceResult(value) {
32897
33058
  __name(sanitizeVoiceResult, "sanitizeVoiceResult");
32898
33059
  function registerActorTools(server, api) {
32899
33060
  const actor = {
32900
- actorId: z133.string().min(1).max(64)
33061
+ actorId: z134.string().min(1).max(64)
32901
33062
  };
32902
33063
  const safe = /* @__PURE__ */ __name(async (request) => {
32903
33064
  try {
@@ -32926,8 +33087,8 @@ function registerActorTools(server, api) {
32926
33087
  inputSchema: {
32927
33088
  ...actor,
32928
33089
  draft: ActorVoiceDraftSchema,
32929
- requestKey: z133.string().trim().min(1).max(128),
32930
- acceptedQuoteId: z133.string().trim().min(1).max(128)
33090
+ requestKey: z134.string().trim().min(1).max(128),
33091
+ acceptedQuoteId: z134.string().trim().min(1).max(128)
32931
33092
  },
32932
33093
  annotations: CREATES_PAID
32933
33094
  }, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/previews`, body)));
@@ -32935,7 +33096,7 @@ function registerActorTools(server, api) {
32935
33096
  description: actorVoiceGuidance.get.summary,
32936
33097
  inputSchema: {
32937
33098
  ...actor,
32938
- candidateId: z133.string().min(1).max(64)
33099
+ candidateId: z134.string().min(1).max(64)
32939
33100
  },
32940
33101
  // Polling can resume the first paid submission of an accepted quote.
32941
33102
  // The immutable candidate/operation key keeps recovery idempotent.
@@ -32948,16 +33109,16 @@ function registerActorTools(server, api) {
32948
33109
  description: actorVoiceGuidance.approve.summary,
32949
33110
  inputSchema: {
32950
33111
  ...actor,
32951
- candidateId: z133.string().min(1).max(64),
32952
- expectedRevision: z133.number().int().positive(),
32953
- expectedApprovedRevision: z133.number().int().positive().nullable().optional()
33112
+ candidateId: z134.string().min(1).max(64),
33113
+ expectedRevision: z134.number().int().positive(),
33114
+ expectedApprovedRevision: z134.number().int().positive().nullable().optional()
32954
33115
  },
32955
33116
  // Replaces the selected voice and withdraws the old catalog grants.
32956
33117
  annotations: OVERWRITES_INTERNAL
32957
33118
  }, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/approve`, body)));
32958
33119
  server.registerTool("list_actors", {
32959
33120
  description: listActorsGuidance.summary + " Devuelve id, nombre, descripci\xF3n, g\xE9nero y voz privada del personaje. Cuando el personaje tiene una voz personalizada, `voice.identityId` y `voice.revision` identifican la versi\xF3n aprobada \u2014 conserva la revisi\xF3n al llamar `approve_actor_voice` (expectedApprovedRevision) para reemplazarla. Los IDs de proveedor nunca se exponen por MCP. Usa el `id` como `actorId` al crear o editar una tarea. Solo aparecen los personajes listos para usar; si la lista est\xE1 vac\xEDa, dile al usuario que cree uno en productmaker.app antes de intentar asignarlo. No modifica nada.",
32960
- inputSchema: z133.object({}).shape,
33121
+ inputSchema: z134.object({}).shape,
32961
33122
  annotations: READS_INTERNAL
32962
33123
  }, async () => {
32963
33124
  try {
@@ -32990,7 +33151,7 @@ function registerActorTools(server, api) {
32990
33151
  __name(registerActorTools, "registerActorTools");
32991
33152
 
32992
33153
  // src/tools/publish.ts
32993
- import { z as z134 } from "zod";
33154
+ import { z as z135 } from "zod";
32994
33155
 
32995
33156
  // src/tools/meta-publish-attempt-id.ts
32996
33157
  var META_PUBLISH_NAMESPACE = "7b19c9ac-b4eb-4db1-970e-c2f24ce30b98";
@@ -33029,40 +33190,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
33029
33190
  var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
33030
33191
  var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
33031
33192
  var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
33032
- var ShopifyInput = z134.object({
33033
- taskId: z134.string().min(1),
33034
- shopDomain: z134.string().min(1),
33193
+ var ShopifyInput = z135.object({
33194
+ taskId: z135.string().min(1),
33195
+ shopDomain: z135.string().min(1),
33035
33196
  /** Override: number of landing images to include. Default = ALL images the
33036
33197
  * task generated (the MCP fetches /v1/results first to count). Bounded
33037
33198
  * generously here; the backend validates each index against
33038
33199
  * landing.images.length and rejects out-of-range. */
33039
- numLandingImages: z134.number().int().min(1).max(20).optional(),
33040
- variantIndex: z134.number().int().min(0).optional(),
33200
+ numLandingImages: z135.number().int().min(1).max(20).optional(),
33201
+ variantIndex: z135.number().int().min(0).optional(),
33041
33202
  /** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
33042
33203
  * When true, the landing renders variant-picker pills; when false, it ships
33043
33204
  * a single-option product page. Defaults to false. */
33044
- showVariantPicker: z134.boolean().optional(),
33205
+ showVariantPicker: z135.boolean().optional(),
33045
33206
  /** Default `auto` updates the product previously published for this task and
33046
33207
  * shop. Use `existing` with targetProductId to choose another product, or
33047
33208
  * `new` only when the user explicitly wants a duplicate/new listing. */
33048
- publicationMode: z134.enum([
33209
+ publicationMode: z135.enum([
33049
33210
  "auto",
33050
33211
  "existing",
33051
33212
  "new"
33052
33213
  ]).optional(),
33053
33214
  /** Shopify product GID, numeric id, or admin product URL. Required when
33054
33215
  * publicationMode is `existing`. */
33055
- targetProductId: z134.string().trim().min(1).max(300).optional(),
33216
+ targetProductId: z135.string().trim().min(1).max(300).optional(),
33056
33217
  /** Add an announcement bar text above add-to-cart (optional). */
33057
- announcementBarEnabled: z134.boolean().optional(),
33058
- announcementBarText: z134.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
33218
+ announcementBarEnabled: z135.boolean().optional(),
33219
+ announcementBarText: z135.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
33059
33220
  commerceCorrection: PublishCommerceCorrectionSchema.optional().describe("Complete seller-confirmed commerce values, with the revision and fingerprint returned in recovery. Never invent missing prices or convert currency."),
33060
- confirmed: z134.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
33221
+ confirmed: z135.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
33061
33222
  });
33062
33223
  var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
33063
33224
  if (value.commerceCorrection && value.confirmed !== true) {
33064
33225
  ctx.addIssue({
33065
- code: z134.ZodIssueCode.custom,
33226
+ code: z135.ZodIssueCode.custom,
33066
33227
  path: [
33067
33228
  "confirmed"
33068
33229
  ],
@@ -33071,7 +33232,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
33071
33232
  }
33072
33233
  if (value.announcementBarEnabled && !value.announcementBarText) {
33073
33234
  ctx.addIssue({
33074
- code: z134.ZodIssueCode.custom,
33235
+ code: z135.ZodIssueCode.custom,
33075
33236
  path: [
33076
33237
  "announcementBarText"
33077
33238
  ],
@@ -33080,7 +33241,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
33080
33241
  }
33081
33242
  if (!value.announcementBarEnabled && value.announcementBarText) {
33082
33243
  ctx.addIssue({
33083
- code: z134.ZodIssueCode.custom,
33244
+ code: z135.ZodIssueCode.custom,
33084
33245
  path: [
33085
33246
  "announcementBarText"
33086
33247
  ],
@@ -33094,90 +33255,90 @@ function parseShopifyInput(rawInput) {
33094
33255
  return parsed.data;
33095
33256
  }
33096
33257
  __name(parseShopifyInput, "parseShopifyInput");
33097
- var McpCampaignConfig = z134.object({
33258
+ var McpCampaignConfig = z135.object({
33098
33259
  /** Legacy USD amount. Meta retains its existing conversion; the TikTok
33099
33260
  * schema below restricts this input to USD advertiser accounts. */
33100
- dailyBudgetUsd: z134.number().positive().optional(),
33261
+ dailyBudgetUsd: z135.number().positive().optional(),
33101
33262
  /** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
33102
33263
  * normalizes at validation). Meta accepts max 1 (single-country ad set).
33103
33264
  * TikTok takes only the first entry. */
33104
- targetCountries: z134.array(CountryIso2Schema).max(1).optional(),
33105
- campaignName: z134.string().trim().min(1).max(100).optional()
33265
+ targetCountries: z135.array(CountryIso2Schema).max(1).optional(),
33266
+ campaignName: z135.string().trim().min(1).max(100).optional()
33106
33267
  });
33107
33268
  var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
33108
- var MetaInput = z134.object({
33109
- taskId: z134.string().min(1),
33269
+ var MetaInput = z135.object({
33270
+ taskId: z135.string().min(1),
33110
33271
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
33111
- portfolioId: z134.string().trim().min(1),
33272
+ portfolioId: z135.string().trim().min(1),
33112
33273
  /** Exact Facebook Page selected from `list_meta_destinations`. */
33113
- pageId: z134.string().trim().min(1),
33274
+ pageId: z135.string().trim().min(1),
33114
33275
  adAccountId: McpAdAccountId,
33115
- pixelId: z134.string().min(1).optional(),
33116
- landingUrl: z134.string().url().optional(),
33276
+ pixelId: z135.string().min(1).optional(),
33277
+ landingUrl: z135.string().url().optional(),
33117
33278
  /** Select which angles to publish by 0-based index. Omit to publish all
33118
33279
  * successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
33119
- angleIndexes: z134.array(z134.number().int().nonnegative()).optional(),
33280
+ angleIndexes: z135.array(z135.number().int().nonnegative()).optional(),
33120
33281
  campaignConfig: McpCampaignConfig.optional(),
33121
33282
  /** Override the ad's primary text (body copy). If omitted, ProductMaker
33122
33283
  * uses the auto-generated copy attached to the task. Capped at 500 chars
33123
33284
  * (Meta's primary-text limit). */
33124
- primaryText: z134.string().trim().min(1).max(500).optional(),
33285
+ primaryText: z135.string().trim().min(1).max(500).optional(),
33125
33286
  /** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
33126
33287
  * (wa.me) instead of a landing page. */
33127
- phoneNumber: z134.string().min(8).max(32).optional()
33288
+ phoneNumber: z135.string().min(8).max(32).optional()
33128
33289
  });
33129
- var GroupedTaskSource = z134.object({
33130
- type: z134.literal("task"),
33131
- taskId: z134.string().min(1),
33132
- angleIndex: z134.number().int().min(0).optional(),
33133
- videoVariant: z134.enum([
33290
+ var GroupedTaskSource = z135.object({
33291
+ type: z135.literal("task"),
33292
+ taskId: z135.string().min(1),
33293
+ angleIndex: z135.number().int().min(0).optional(),
33294
+ videoVariant: z135.enum([
33134
33295
  "with_subtitles",
33135
33296
  "without_subtitles"
33136
33297
  ]).optional(),
33137
- imageVariantIndex: z134.number().int().min(0).optional()
33138
- });
33139
- var GroupedMediaSource = z134.object({
33140
- type: z134.literal("media"),
33141
- url: z134.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
33142
- path: z134.string().min(1).optional().describe('Local file path only when this MCP runs over stdio. On the hosted MCP, call request_media_upload and then use source.type="asset".'),
33143
- thumbnailUrl: z134.string().url().optional(),
33144
- thumbnailPath: z134.string().min(1).optional()
33298
+ imageVariantIndex: z135.number().int().min(0).optional()
33299
+ });
33300
+ var GroupedMediaSource = z135.object({
33301
+ type: z135.literal("media"),
33302
+ url: z135.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
33303
+ path: z135.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".'),
33304
+ thumbnailUrl: z135.string().url().optional(),
33305
+ thumbnailPath: z135.string().min(1).optional()
33145
33306
  }).refine((value) => Boolean(value.url) !== Boolean(value.path), {
33146
33307
  message: "media source needs exactly one of `url` or `path`"
33147
33308
  }).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
33148
33309
  message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
33149
33310
  });
33150
- var GroupedUploadedAssetSource = z134.object({
33151
- type: z134.literal("asset"),
33311
+ var GroupedUploadedAssetSource = z135.object({
33312
+ type: z135.literal("asset"),
33152
33313
  /** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
33153
- assetId: z134.string().uuid(),
33154
- thumbnailAssetId: z134.string().uuid().optional()
33314
+ assetId: z135.string().uuid(),
33315
+ thumbnailAssetId: z135.string().uuid().optional()
33155
33316
  });
33156
- var GroupedCreative = z134.object({
33157
- type: z134.enum([
33317
+ var GroupedCreative = z135.object({
33318
+ type: z135.enum([
33158
33319
  "image",
33159
33320
  "video"
33160
33321
  ]),
33161
- source: z134.union([
33322
+ source: z135.union([
33162
33323
  GroupedTaskSource,
33163
33324
  GroupedMediaSource,
33164
33325
  GroupedUploadedAssetSource
33165
33326
  ]),
33166
- title: z134.string().max(120).optional(),
33167
- description: z134.string().max(500).optional(),
33327
+ title: z135.string().max(120).optional(),
33328
+ description: z135.string().max(500).optional(),
33168
33329
  cta: MetaCtaType.optional(),
33169
- creativeId: z134.string().min(1).optional()
33330
+ creativeId: z135.string().min(1).optional()
33170
33331
  });
33171
- var GroupedCampaignConfigBase = z134.object({
33332
+ var GroupedCampaignConfigBase = z135.object({
33172
33333
  campaignType: MetaCampaignType.default("sales"),
33173
33334
  optimizationMode: MetaOptimizationMode.default("advantage_plus"),
33174
33335
  budgetMode: MetaBudgetMode.optional(),
33175
- campaignDailyBudget: z134.number().int().positive().optional(),
33176
- adSets: z134.array(z134.object({
33177
- tempId: z134.string().min(1).max(80),
33178
- name: z134.string().min(1).max(100),
33179
- dailyBudget: z134.number().int().positive().optional(),
33180
- creativeIds: z134.array(z134.string().min(1)).min(1)
33336
+ campaignDailyBudget: z135.number().int().positive().optional(),
33337
+ adSets: z135.array(z135.object({
33338
+ tempId: z135.string().min(1).max(80),
33339
+ name: z135.string().min(1).max(100),
33340
+ dailyBudget: z135.number().int().positive().optional(),
33341
+ creativeIds: z135.array(z135.string().min(1)).min(1)
33181
33342
  })).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
33182
33343
  /**
33183
33344
  * Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
@@ -33185,17 +33346,17 @@ var GroupedCampaignConfigBase = z134.object({
33185
33346
  * opaque `invalid_literal` and made the WhatsApp destination — supported by
33186
33347
  * the API since #849 — unreachable from this tool.
33187
33348
  */
33188
- destination: z134.discriminatedUnion("type", [
33189
- z134.object({
33190
- type: z134.literal("landing"),
33191
- landingUrl: z134.string().url()
33349
+ destination: z135.discriminatedUnion("type", [
33350
+ z135.object({
33351
+ type: z135.literal("landing"),
33352
+ landingUrl: z135.string().url()
33192
33353
  }),
33193
- z134.object({
33194
- type: z134.literal("whatsapp"),
33195
- phoneNumber: z134.string().min(8).max(32)
33354
+ z135.object({
33355
+ type: z135.literal("whatsapp"),
33356
+ phoneNumber: z135.string().min(8).max(32)
33196
33357
  })
33197
33358
  ]),
33198
- saveAsDefault: z134.boolean().default(false),
33359
+ saveAsDefault: z135.boolean().default(false),
33199
33360
  budgetPolicy: MetaBudgetPolicy.optional()
33200
33361
  });
33201
33362
  function resolveBudgetMode(value) {
@@ -33209,7 +33370,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
33209
33370
  const budgetMode = resolveBudgetMode(value);
33210
33371
  if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
33211
33372
  ctx.addIssue({
33212
- code: z134.ZodIssueCode.custom,
33373
+ code: z135.ZodIssueCode.custom,
33213
33374
  path: [
33214
33375
  "campaignDailyBudget"
33215
33376
  ],
@@ -33220,7 +33381,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
33220
33381
  value.adSets.forEach((adSet, index) => {
33221
33382
  if (adSet.dailyBudget === void 0) {
33222
33383
  ctx.addIssue({
33223
- code: z134.ZodIssueCode.custom,
33384
+ code: z135.ZodIssueCode.custom,
33224
33385
  path: [
33225
33386
  "adSets",
33226
33387
  index,
@@ -33235,25 +33396,25 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
33235
33396
  ...value,
33236
33397
  budgetMode: resolveBudgetMode(value)
33237
33398
  }));
33238
- var PublishCreativesToMetaInputBase = z134.object({
33239
- creatives: z134.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
33399
+ var PublishCreativesToMetaInputBase = z135.object({
33400
+ creatives: z135.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
33240
33401
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
33241
- portfolioId: z134.string().trim().min(1),
33402
+ portfolioId: z135.string().trim().min(1),
33242
33403
  /** Exact Facebook Page selected from `list_meta_destinations`. */
33243
- pageId: z134.string().trim().min(1),
33404
+ pageId: z135.string().trim().min(1),
33244
33405
  adAccountId: McpAdAccountId,
33245
- pixelId: z134.string().min(1).optional(),
33406
+ pixelId: z135.string().min(1).optional(),
33246
33407
  /** Required unless `campaignConfig.destination` is whatsapp or a creative
33247
33408
  * comes from a task (the API then lands on the published service landing
33248
33409
  * of its service tasks) — see the superRefine below. Mirrors the API's
33249
33410
  * `FacebookCreateCampaignFromTasksBodySchema`. */
33250
- landingUrl: z134.string().url().optional(),
33411
+ landingUrl: z135.string().url().optional(),
33251
33412
  /** ISO-2 code or resolvable country name — mirrors the API contract
33252
33413
  * (CountryIso2Schema), which normalizes names to alpha-2 at validation.
33253
33414
  * Omitted: the brand country of its service tasks (the API answers
33254
33415
  * META_NO_TARGET_COUNTRY when it has none); "US" for products. */
33255
33416
  targetCountry: CountryIso2Schema.optional(),
33256
- campaignName: z134.string().trim().min(1).max(100),
33417
+ campaignName: z135.string().trim().min(1).max(100),
33257
33418
  campaignConfig: GroupedCampaignConfig.optional()
33258
33419
  });
33259
33420
  var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
@@ -33261,7 +33422,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
33261
33422
  const hasTaskCreative = value.creatives.some((creative) => creative.source.type === "task");
33262
33423
  if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl && !hasTaskCreative) {
33263
33424
  ctx.addIssue({
33264
- code: z134.ZodIssueCode.custom,
33425
+ code: z135.ZodIssueCode.custom,
33265
33426
  path: [
33266
33427
  "landingUrl"
33267
33428
  ],
@@ -33270,7 +33431,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
33270
33431
  }
33271
33432
  if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
33272
33433
  ctx.addIssue({
33273
- code: z134.ZodIssueCode.custom,
33434
+ code: z135.ZodIssueCode.custom,
33274
33435
  path: [
33275
33436
  "campaignConfig",
33276
33437
  "destination",
@@ -33289,16 +33450,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
33289
33450
  }
33290
33451
  return value;
33291
33452
  });
33292
- var PresignUploadResponseSchema = z134.object({
33293
- uploadUrl: z134.string().url().refine((value) => {
33453
+ var PresignUploadResponseSchema = z135.object({
33454
+ uploadUrl: z135.string().url().refine((value) => {
33294
33455
  const url = new URL(value);
33295
33456
  return !url.username && !url.password && url.protocol === "https:";
33296
33457
  }, "presigned upload URL must be HTTPS without embedded credentials"),
33297
- publicUrl: z134.string().url().refine((value) => {
33458
+ publicUrl: z135.string().url().refine((value) => {
33298
33459
  const url = new URL(value);
33299
33460
  return !url.username && !url.password;
33300
33461
  }, "public media URL must not contain embedded credentials"),
33301
- stagingAssetId: z134.string().uuid()
33462
+ stagingAssetId: z135.string().uuid()
33302
33463
  });
33303
33464
  async function uploadResolvedMedia(api, media, assetRole) {
33304
33465
  if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
@@ -33324,14 +33485,14 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
33324
33485
  }
33325
33486
  __name(resolveAndUploadMedia, "resolveAndUploadMedia");
33326
33487
  var TikTokMcpCampaignConfig = McpCampaignConfig.extend({
33327
- dailyBudgetUsd: z134.number().finite().positive().optional().describe("Legacy USD amount, supported only for USD advertiser accounts. No FX conversion."),
33328
- dailyBudget: z134.number().finite().positive().optional().describe("Daily budget in the selected advertiser currency major units; pass budgetCurrency together."),
33488
+ dailyBudgetUsd: z135.number().finite().positive().optional().describe("Legacy USD amount, supported only for USD advertiser accounts. No FX conversion."),
33489
+ dailyBudget: z135.number().finite().positive().optional().describe("Daily budget in the selected advertiser currency major units; pass budgetCurrency together."),
33329
33490
  budgetCurrency: TikTokBudgetCurrencySchema.optional(),
33330
33491
  destination: TikTokCampaignDestinationSchema.optional()
33331
33492
  }).superRefine((value, ctx) => {
33332
33493
  if (value.dailyBudgetUsd !== void 0 && (value.dailyBudget !== void 0 || value.budgetCurrency !== void 0)) {
33333
33494
  ctx.addIssue({
33334
- code: z134.ZodIssueCode.custom,
33495
+ code: z135.ZodIssueCode.custom,
33335
33496
  path: [
33336
33497
  "dailyBudgetUsd"
33337
33498
  ],
@@ -33340,7 +33501,7 @@ var TikTokMcpCampaignConfig = McpCampaignConfig.extend({
33340
33501
  }
33341
33502
  if (value.dailyBudget !== void 0 !== (value.budgetCurrency !== void 0)) {
33342
33503
  ctx.addIssue({
33343
- code: z134.ZodIssueCode.custom,
33504
+ code: z135.ZodIssueCode.custom,
33344
33505
  path: [
33345
33506
  "budgetCurrency"
33346
33507
  ],
@@ -33348,16 +33509,16 @@ var TikTokMcpCampaignConfig = McpCampaignConfig.extend({
33348
33509
  });
33349
33510
  }
33350
33511
  });
33351
- var TikTokInput = z134.object({
33352
- taskId: z134.string().min(1),
33353
- advertiserId: z134.string().min(1),
33354
- pixelId: z134.string().min(1).optional(),
33355
- landingUrl: z134.string().url().optional(),
33356
- angleIndexes: z134.array(z134.number().int().nonnegative()).optional(),
33512
+ var TikTokInput = z135.object({
33513
+ taskId: z135.string().min(1),
33514
+ advertiserId: z135.string().min(1),
33515
+ pixelId: z135.string().min(1).optional(),
33516
+ landingUrl: z135.string().url().optional(),
33517
+ angleIndexes: z135.array(z135.number().int().nonnegative()).optional(),
33357
33518
  campaignConfig: TikTokMcpCampaignConfig.optional(),
33358
33519
  /** Override the ad's description (TikTok's body copy). If omitted,
33359
33520
  * ProductMaker uses the auto-generated copy attached to the task. */
33360
- primaryText: z134.string().trim().min(1).max(500).optional()
33521
+ primaryText: z135.string().trim().min(1).max(500).optional()
33361
33522
  });
33362
33523
  function registerPublishTools(server, api, opts = {}) {
33363
33524
  const transport = opts.transport ?? "http";
@@ -33716,39 +33877,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
33716
33877
 
33717
33878
  // src/tools/meta-upload.ts
33718
33879
  import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
33719
- import { z as z135 } from "zod";
33880
+ import { z as z136 } from "zod";
33720
33881
  var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
33721
- var UploadSessionInputBase = z135.object({
33722
- mediaKind: z135.enum([
33882
+ var UploadSessionInputBase = z136.object({
33883
+ mediaKind: z136.enum([
33723
33884
  "image",
33724
33885
  "video",
33725
33886
  "mixed"
33726
33887
  ]).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."),
33727
- assetRole: z135.enum([
33888
+ assetRole: z136.enum([
33728
33889
  "media",
33729
33890
  "thumbnail"
33730
33891
  ]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
33731
- uploadPurpose: z135.enum([
33892
+ uploadPurpose: z136.enum([
33732
33893
  "product_reference",
33733
33894
  "creative",
33734
33895
  "generic"
33735
33896
  ]).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."),
33736
- maxFiles: z135.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
33897
+ maxFiles: z136.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
33737
33898
  });
33738
- var OpenAiFileReference = z135.object({
33739
- download_url: z135.string().url().describe("Required by ChatGPT's openai/fileParams schema. The App prefers getFileDownloadUrl(file_id) for a fresh URL, and the server never fetches this value."),
33740
- file_id: z135.string().min(1),
33741
- mime_type: z135.string().min(1).optional(),
33742
- file_name: z135.string().min(1).optional()
33899
+ var OpenAiFileReference = z136.object({
33900
+ download_url: z136.string().url().describe("Required by ChatGPT's openai/fileParams schema. The App prefers getFileDownloadUrl(file_id) for a fresh URL, and the server never fetches this value."),
33901
+ file_id: z136.string().min(1),
33902
+ mime_type: z136.string().min(1).optional(),
33903
+ file_name: z136.string().min(1).optional()
33743
33904
  });
33744
33905
  var UploadSessionToolInputShape = {
33745
33906
  ...UploadSessionInputBase.shape,
33746
- files: z135.array(OpenAiFileReference).max(10).optional().describe("Optional OpenAI-hosted file references provided by ChatGPT. They are only metadata for the UI bridge and are never forwarded to ProductMaker.")
33907
+ files: z136.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.")
33747
33908
  };
33748
- var UploadSessionToolInput = z135.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
33909
+ var UploadSessionToolInput = z136.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
33749
33910
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
33750
33911
  ctx.addIssue({
33751
- code: z135.ZodIssueCode.custom,
33912
+ code: z136.ZodIssueCode.custom,
33752
33913
  path: [
33753
33914
  "mediaKind"
33754
33915
  ],
@@ -33757,7 +33918,7 @@ var UploadSessionToolInput = z135.object(UploadSessionToolInputShape).superRefin
33757
33918
  }
33758
33919
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
33759
33920
  ctx.addIssue({
33760
- code: z135.ZodIssueCode.custom,
33921
+ code: z136.ZodIssueCode.custom,
33761
33922
  path: [
33762
33923
  "maxFiles"
33763
33924
  ],
@@ -33766,7 +33927,7 @@ var UploadSessionToolInput = z135.object(UploadSessionToolInputShape).superRefin
33766
33927
  }
33767
33928
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
33768
33929
  ctx.addIssue({
33769
- code: z135.ZodIssueCode.custom,
33930
+ code: z136.ZodIssueCode.custom,
33770
33931
  path: [
33771
33932
  "maxFiles"
33772
33933
  ],
@@ -33774,38 +33935,38 @@ var UploadSessionToolInput = z135.object(UploadSessionToolInputShape).superRefin
33774
33935
  });
33775
33936
  }
33776
33937
  });
33777
- var UploadSessionResponse = z135.object({
33778
- sessionId: z135.string().uuid(),
33779
- uploadPageUrl: z135.string().url(),
33780
- mediaKind: z135.enum([
33938
+ var UploadSessionResponse = z136.object({
33939
+ sessionId: z136.string().uuid(),
33940
+ uploadPageUrl: z136.string().url(),
33941
+ mediaKind: z136.enum([
33781
33942
  "image",
33782
33943
  "video",
33783
33944
  "mixed"
33784
33945
  ]),
33785
- assetRole: z135.enum([
33946
+ assetRole: z136.enum([
33786
33947
  "media",
33787
33948
  "thumbnail"
33788
33949
  ]),
33789
- maxFiles: z135.number().int().positive(),
33790
- expiresAt: z135.string().datetime()
33950
+ maxFiles: z136.number().int().positive(),
33951
+ expiresAt: z136.string().datetime()
33791
33952
  });
33792
- var UploadStatusInput = z135.object({
33793
- sessionId: z135.string().uuid().describe("The sessionId returned by request_media_upload.")
33953
+ var UploadStatusInput = z136.object({
33954
+ sessionId: z136.string().uuid().describe("The sessionId returned by request_media_upload.")
33794
33955
  });
33795
- var UniversalUploadStatusResponse = z135.discriminatedUnion("status", [
33796
- z135.object({
33797
- status: z135.literal("pending"),
33798
- assets: z135.array(z135.never()).length(0)
33956
+ var UniversalUploadStatusResponse = z136.discriminatedUnion("status", [
33957
+ z136.object({
33958
+ status: z136.literal("pending"),
33959
+ assets: z136.array(z136.never()).length(0)
33799
33960
  }),
33800
- z135.object({
33801
- status: z135.literal("uploaded"),
33802
- assets: z135.array(z135.object({
33803
- assetId: z135.string().uuid(),
33804
- mediaKind: z135.enum([
33961
+ z136.object({
33962
+ status: z136.literal("uploaded"),
33963
+ assets: z136.array(z136.object({
33964
+ assetId: z136.string().uuid(),
33965
+ mediaKind: z136.enum([
33805
33966
  "image",
33806
33967
  "video"
33807
33968
  ]),
33808
- assetRole: z135.enum([
33969
+ assetRole: z136.enum([
33809
33970
  "media",
33810
33971
  "thumbnail"
33811
33972
  ])
@@ -33813,13 +33974,13 @@ var UniversalUploadStatusResponse = z135.discriminatedUnion("status", [
33813
33974
  })
33814
33975
  ]);
33815
33976
  var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
33816
- uploadPurpose: z135.enum([
33977
+ uploadPurpose: z136.enum([
33817
33978
  "product_reference",
33818
33979
  "creative",
33819
33980
  "generic"
33820
33981
  ]),
33821
- checkToolName: z135.literal("check_media_upload"),
33822
- resolveEndpoint: z135.string().url()
33982
+ checkToolName: z136.literal("check_media_upload"),
33983
+ resolveEndpoint: z136.string().url()
33823
33984
  });
33824
33985
  function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
33825
33986
  const url = new URL(uploadPageUrl);
@@ -33910,15 +34071,15 @@ function registerMediaUploadTools(server, api) {
33910
34071
  __name(registerMediaUploadTools, "registerMediaUploadTools");
33911
34072
 
33912
34073
  // src/tools/campaigns.ts
33913
- import { z as z136 } from "zod";
34074
+ import { z as z137 } from "zod";
33914
34075
  var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
33915
34076
  var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
33916
- var MetaStatusInput = z136.object({
33917
- campaignId: z136.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
34077
+ var MetaStatusInput = z137.object({
34078
+ campaignId: z137.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
33918
34079
  });
33919
- var TikTokStatusInput = z136.object({
33920
- campaignId: z136.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
33921
- advertiserId: z136.string().min(1).describe("The same advertiserId used to publish the campaign.")
34080
+ var TikTokStatusInput = z137.object({
34081
+ campaignId: z137.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
34082
+ advertiserId: z137.string().min(1).describe("The same advertiserId used to publish the campaign.")
33922
34083
  });
33923
34084
  function registerCampaignTools(server, api) {
33924
34085
  server.registerTool("get_meta_campaign_status", {
@@ -34023,10 +34184,10 @@ function renderTikTokStatusMarkdown(r) {
34023
34184
  __name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
34024
34185
 
34025
34186
  // ../../packages/product-economics/src/product-costing.ts
34026
- import { z as z138 } from "zod";
34187
+ import { z as z139 } from "zod";
34027
34188
 
34028
34189
  // ../../packages/product-economics/src/product-costing-countries.ts
34029
- import { z as z137 } from "zod";
34190
+ import { z as z138 } from "zod";
34030
34191
 
34031
34192
  // ../../packages/product-economics/src/product-costing-shipping-references.json
34032
34193
  var product_costing_shipping_references_default = {
@@ -34090,21 +34251,21 @@ var product_costing_shipping_references_default = {
34090
34251
  };
34091
34252
 
34092
34253
  // ../../packages/product-economics/src/product-costing-countries.ts
34093
- var ShippingReferenceSchema = z137.object({
34094
- reference: z137.number().positive(),
34095
- min: z137.number().nonnegative(),
34096
- max: z137.number().positive(),
34097
- updatedAt: z137.string().date(),
34098
- confidence: z137.enum([
34254
+ var ShippingReferenceSchema = z138.object({
34255
+ reference: z138.number().positive(),
34256
+ min: z138.number().nonnegative(),
34257
+ max: z138.number().positive(),
34258
+ updatedAt: z138.string().date(),
34259
+ confidence: z138.enum([
34099
34260
  "high",
34100
34261
  "medium",
34101
34262
  "medium-low"
34102
34263
  ]),
34103
- sources: z137.array(z137.string().url().startsWith("https://")).min(1).max(3)
34264
+ sources: z138.array(z138.string().url().startsWith("https://")).min(1).max(3)
34104
34265
  }).superRefine(({ reference, min, max }, context) => {
34105
34266
  if (min > reference || reference > max) {
34106
34267
  context.addIssue({
34107
- code: z137.ZodIssueCode.custom,
34268
+ code: z138.ZodIssueCode.custom,
34108
34269
  message: "shipping_reference_outside_range",
34109
34270
  path: [
34110
34271
  "reference"
@@ -34112,7 +34273,7 @@ var ShippingReferenceSchema = z137.object({
34112
34273
  });
34113
34274
  }
34114
34275
  });
34115
- var SHIPPING_REFERENCES = z137.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
34276
+ var SHIPPING_REFERENCES = z138.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
34116
34277
  var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
34117
34278
  var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
34118
34279
  "MX",
@@ -34294,18 +34455,18 @@ function getProductCostingCountryName(country) {
34294
34455
  __name(getProductCostingCountryName, "getProductCostingCountryName");
34295
34456
 
34296
34457
  // ../../packages/product-economics/src/product-costing.ts
34297
- var ProductCostingInputSchema = z138.object({
34298
- country: z138.string().refine(isProductCostingCountryCode, "unsupported_country"),
34299
- supplierCost: z138.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
34300
- shippingCost: z138.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
34301
- returnRate: z138.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
34302
- cancellationRate: z138.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
34303
- adsManagerCpa: z138.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
34304
- desiredMargin: z138.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
34458
+ var ProductCostingInputSchema = z139.object({
34459
+ country: z139.string().refine(isProductCostingCountryCode, "unsupported_country"),
34460
+ supplierCost: z139.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
34461
+ shippingCost: z139.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
34462
+ returnRate: z139.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
34463
+ cancellationRate: z139.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
34464
+ adsManagerCpa: z139.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
34465
+ desiredMargin: z139.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
34305
34466
  }).superRefine(({ returnRate, cancellationRate }, context) => {
34306
34467
  if (returnRate + cancellationRate >= 1) {
34307
34468
  context.addIssue({
34308
- code: z138.ZodIssueCode.custom,
34469
+ code: z139.ZodIssueCode.custom,
34309
34470
  message: "delivery_rate_positive",
34310
34471
  path: [
34311
34472
  "cancellationRate"
@@ -34402,15 +34563,15 @@ function calculateProductCosting(rawInput) {
34402
34563
  __name(calculateProductCosting, "calculateProductCosting");
34403
34564
 
34404
34565
  // src/tools/product-costing.ts
34405
- import { z as z139 } from "zod";
34566
+ import { z as z140 } from "zod";
34406
34567
  var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
34407
- var optionalAmount = /* @__PURE__ */ __name((description) => z139.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
34408
- var optionalPercent = /* @__PURE__ */ __name((description) => z139.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
34409
- var ProductCostingToolInput = z139.object({
34410
- country: z139.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
34568
+ var optionalAmount = /* @__PURE__ */ __name((description) => z140.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
34569
+ var optionalPercent = /* @__PURE__ */ __name((description) => z140.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
34570
+ var ProductCostingToolInput = z140.object({
34571
+ country: z140.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
34411
34572
  message: "Pa\xEDs no soportado por ProductMaker."
34412
34573
  }).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
34413
- supplierCost: z139.number().finite().max(Number.MAX_SAFE_INTEGER).positive().optional().describe("Costo real de una unidad con el proveedor, en la moneda del pa\xEDs. Requerido salvo que uses supplierCostCop para Colombia."),
34574
+ supplierCost: z140.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."),
34414
34575
  supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
34415
34576
  shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
34416
34577
  shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
@@ -34573,7 +34734,7 @@ function formatPercent(value) {
34573
34734
  __name(formatPercent, "formatPercent");
34574
34735
 
34575
34736
  // src/tools/product-research.ts
34576
- import { z as z140 } from "zod";
34737
+ import { z as z141 } from "zod";
34577
34738
 
34578
34739
  // src/tools/product-research-idempotency.ts
34579
34740
  var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
@@ -34944,35 +35105,35 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
34944
35105
  ]);
34945
35106
  var POLL_INTERVAL_MS = 5e3;
34946
35107
  var MAX_WAIT_SECONDS = 120;
34947
- var FindInput = z140.object({
35108
+ var FindInput = z141.object({
34948
35109
  targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
34949
35110
  categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
34950
- confirmed: z140.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
34951
- waitSeconds: z140.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
35111
+ confirmed: z141.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
35112
+ waitSeconds: z141.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
34952
35113
  });
34953
- var GetInput = z140.object({
34954
- runId: z140.string().uuid().describe("ID del run devuelto por find_winning_products.")
35114
+ var GetInput = z141.object({
35115
+ runId: z141.string().uuid().describe("ID del run devuelto por find_winning_products.")
34955
35116
  });
34956
- var ListInput = z140.object({
34957
- limit: z140.number().int().min(1).max(20).default(10)
35117
+ var ListInput = z141.object({
35118
+ limit: z141.number().int().min(1).max(20).default(10)
34958
35119
  });
34959
- function textResult(text3) {
35120
+ function textResult(text4) {
34960
35121
  return {
34961
35122
  content: [
34962
35123
  {
34963
35124
  type: "text",
34964
- text: text3
35125
+ text: text4
34965
35126
  }
34966
35127
  ]
34967
35128
  };
34968
35129
  }
34969
35130
  __name(textResult, "textResult");
34970
- function researchResult(run, text3) {
35131
+ function researchResult(run, text4) {
34971
35132
  return {
34972
35133
  content: [
34973
35134
  {
34974
35135
  type: "text",
34975
- text: text3
35136
+ text: text4
34976
35137
  }
34977
35138
  ],
34978
35139
  structuredContent: run
@@ -35093,17 +35254,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
35093
35254
  __name(registerProductResearchTools, "registerProductResearchTools");
35094
35255
 
35095
35256
  // src/tools/dropshipping-projects.ts
35096
- import { z as z141 } from "zod";
35257
+ import { z as z142 } from "zod";
35097
35258
  var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
35098
35259
  var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
35099
35260
  var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
35100
- var ProjectId = z141.string().uuid();
35101
- var DropshippingProjectStatus = z141.enum([
35261
+ var ProjectId = z142.string().uuid();
35262
+ var DropshippingProjectStatus = z142.enum([
35102
35263
  "active",
35103
35264
  "completed",
35104
35265
  "archived"
35105
35266
  ]);
35106
- var DropshippingProjectPhase = z141.enum([
35267
+ var DropshippingProjectPhase = z142.enum([
35107
35268
  "research",
35108
35269
  "costing",
35109
35270
  "media",
@@ -35112,21 +35273,21 @@ var DropshippingProjectPhase = z141.enum([
35112
35273
  "advertising",
35113
35274
  "complete"
35114
35275
  ]);
35115
- var DropshippingRewardMilestone = z141.enum([
35276
+ var DropshippingRewardMilestone = z142.enum([
35116
35277
  "product_selected",
35117
35278
  "costing_saved",
35118
35279
  "product_media_ready",
35119
35280
  "creatives_completed",
35120
35281
  "campaign_created"
35121
35282
  ]);
35122
- var TargetCountry = z141.enum([
35283
+ var TargetCountry = z142.enum([
35123
35284
  "CO",
35124
35285
  "MX",
35125
35286
  "PE",
35126
35287
  "EC",
35127
35288
  "CL"
35128
35289
  ]);
35129
- var ResearchCategory = z141.enum([
35290
+ var ResearchCategory = z142.enum([
35130
35291
  "auto",
35131
35292
  "automotive",
35132
35293
  "kitchen",
@@ -35141,7 +35302,7 @@ var ResearchCategory = z141.enum([
35141
35302
  "garden",
35142
35303
  "cleaning"
35143
35304
  ]);
35144
- var HttpUrl3 = z141.string().url().max(2e3).refine((value) => {
35305
+ var HttpUrl3 = z142.string().url().max(2e3).refine((value) => {
35145
35306
  try {
35146
35307
  return [
35147
35308
  "http:",
@@ -35151,45 +35312,45 @@ var HttpUrl3 = z141.string().url().max(2e3).refine((value) => {
35151
35312
  return false;
35152
35313
  }
35153
35314
  }, "URL must use HTTP(S)");
35154
- var ResearchCandidateOrigin = z141.object({
35155
- type: z141.literal("research_candidate"),
35315
+ var ResearchCandidateOrigin = z142.object({
35316
+ type: z142.literal("research_candidate"),
35156
35317
  runId: ProjectId,
35157
- candidateSourceId: z141.string().min(1).max(160)
35318
+ candidateSourceId: z142.string().min(1).max(160)
35158
35319
  });
35159
- var TaskOrigin = z141.object({
35160
- type: z141.literal("task"),
35320
+ var TaskOrigin = z142.object({
35321
+ type: z142.literal("task"),
35161
35322
  taskId: ProjectId
35162
35323
  });
35163
- var ManualOrigin = z141.object({
35164
- type: z141.literal("manual"),
35324
+ var ManualOrigin = z142.object({
35325
+ type: z142.literal("manual"),
35165
35326
  clientRequestId: ProjectId,
35166
- country: z141.string().min(2).max(3).optional()
35327
+ country: z142.string().min(2).max(3).optional()
35167
35328
  });
35168
- var StartProjectInput = z141.object({
35169
- origin: z141.discriminatedUnion("type", [
35329
+ var StartProjectInput = z142.object({
35330
+ origin: z142.discriminatedUnion("type", [
35170
35331
  ResearchCandidateOrigin,
35171
35332
  TaskOrigin,
35172
35333
  ManualOrigin
35173
35334
  ]),
35174
- productName: z141.string().trim().min(1).max(240).optional(),
35335
+ productName: z142.string().trim().min(1).max(240).optional(),
35175
35336
  productUrl: HttpUrl3.optional(),
35176
- country: z141.string().min(2).max(3).optional(),
35177
- languageCode: z141.string().min(2).max(16).optional()
35337
+ country: z142.string().min(2).max(3).optional(),
35338
+ languageCode: z142.string().min(2).max(16).optional()
35178
35339
  }).strict();
35179
- var CostProjectInput = z141.object({
35340
+ var CostProjectInput = z142.object({
35180
35341
  projectId: ProjectId,
35181
- version: z141.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
35182
- country: z141.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
35342
+ version: z142.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
35343
+ country: z142.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
35183
35344
  message: "Pa\xEDs no soportado por ProductMaker."
35184
35345
  }).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
35185
- supplierCost: z141.number().finite().positive().describe("Costo real de una unidad con el proveedor, en la moneda del pa\xEDs. \xDANICO dato que debes pedirle al usuario: nunca lo inventes."),
35186
- shippingCost: z141.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
35187
- returnRate: z141.number().finite().min(0).lt(1).optional().describe("Fracci\xF3n de pedidos devueltos (0.25 = 25%). Omite para usar el valor gu\xEDa del pa\xEDs."),
35188
- cancellationRate: z141.number().finite().min(0).lt(1).optional().describe("Fracci\xF3n de pedidos cancelados (0.15 = 15%). Omite para usar el valor gu\xEDa del pa\xEDs."),
35189
- adsManagerCpa: z141.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
35190
- desiredMargin: z141.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
35191
- });
35192
- var GuideInput = z141.object({
35346
+ supplierCost: z142.number().finite().positive().describe("Costo real de una unidad con el proveedor, en la moneda del pa\xEDs. \xDANICO dato que debes pedirle al usuario: nunca lo inventes."),
35347
+ shippingCost: z142.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
35348
+ returnRate: z142.number().finite().min(0).lt(1).optional().describe("Fracci\xF3n de pedidos devueltos (0.25 = 25%). Omite para usar el valor gu\xEDa del pa\xEDs."),
35349
+ cancellationRate: z142.number().finite().min(0).lt(1).optional().describe("Fracci\xF3n de pedidos cancelados (0.15 = 15%). Omite para usar el valor gu\xEDa del pa\xEDs."),
35350
+ adsManagerCpa: z142.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
35351
+ desiredMargin: z142.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
35352
+ });
35353
+ var GuideInput = z142.object({
35193
35354
  projectId: ProjectId.optional()
35194
35355
  }).strict();
35195
35356
  var NEXT_ACTION_KINDS = [
@@ -35207,29 +35368,29 @@ var NEXT_ACTION_KINDS = [
35207
35368
  "repair_meta_campaign",
35208
35369
  "review_paused_campaign"
35209
35370
  ];
35210
- var DropshippingProjectNextAction = z141.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z141.object({
35211
- kind: z141.literal(kind),
35212
- href: z141.string().min(1)
35371
+ var DropshippingProjectNextAction = z142.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z142.object({
35372
+ kind: z142.literal(kind),
35373
+ href: z142.string().min(1)
35213
35374
  })));
35214
- var CostingInputSchema = z141.object({
35215
- country: z141.string().min(2).max(3),
35216
- supplierCost: z141.number().finite().positive(),
35217
- shippingCost: z141.number().finite().nonnegative(),
35218
- returnRate: z141.number().finite().min(0).lt(1),
35219
- cancellationRate: z141.number().finite().min(0).lt(1),
35220
- adsManagerCpa: z141.number().finite().nonnegative(),
35221
- desiredMargin: z141.number().finite().min(0).lt(1)
35375
+ var CostingInputSchema = z142.object({
35376
+ country: z142.string().min(2).max(3),
35377
+ supplierCost: z142.number().finite().positive(),
35378
+ shippingCost: z142.number().finite().nonnegative(),
35379
+ returnRate: z142.number().finite().min(0).lt(1),
35380
+ cancellationRate: z142.number().finite().min(0).lt(1),
35381
+ adsManagerCpa: z142.number().finite().nonnegative(),
35382
+ desiredMargin: z142.number().finite().min(0).lt(1)
35222
35383
  }).superRefine(({ returnRate, cancellationRate }, context) => {
35223
35384
  if (returnRate + cancellationRate >= 1) context.addIssue({
35224
- code: z141.ZodIssueCode.custom,
35385
+ code: z142.ZodIssueCode.custom,
35225
35386
  path: [
35226
35387
  "cancellationRate"
35227
35388
  ]
35228
35389
  });
35229
35390
  });
35230
- var FiniteCostingNumber = z141.number().finite();
35231
- var CostingResultSchema = z141.object({
35232
- country: z141.string().min(2).max(3),
35391
+ var FiniteCostingNumber = z142.number().finite();
35392
+ var CostingResultSchema = z142.object({
35393
+ country: z142.string().min(2).max(3),
35233
35394
  deliveryRate: FiniteCostingNumber,
35234
35395
  adjustedShippingCost: FiniteCostingNumber,
35235
35396
  adjustedCpa: FiniteCostingNumber,
@@ -35242,45 +35403,45 @@ var CostingResultSchema = z141.object({
35242
35403
  estimatedProfit: FiniteCostingNumber,
35243
35404
  actualMargin: FiniteCostingNumber,
35244
35405
  breakEvenAdsManagerCpa: FiniteCostingNumber,
35245
- wasPriceAutoAdjusted: z141.boolean(),
35246
- profitabilityStatus: z141.literal("healthy")
35247
- });
35248
- var RewardProgressSchema = z141.object({
35249
- campaignKey: z141.literal("dropshipping-launch-v1"),
35250
- totalCredits: z141.number().int().positive(),
35251
- earnedCredits: z141.number().int().nonnegative(),
35252
- milestones: z141.array(z141.object({
35406
+ wasPriceAutoAdjusted: z142.boolean(),
35407
+ profitabilityStatus: z142.literal("healthy")
35408
+ });
35409
+ var RewardProgressSchema = z142.object({
35410
+ campaignKey: z142.literal("dropshipping-launch-v1"),
35411
+ totalCredits: z142.number().int().positive(),
35412
+ earnedCredits: z142.number().int().nonnegative(),
35413
+ milestones: z142.array(z142.object({
35253
35414
  milestone: DropshippingRewardMilestone,
35254
- credits: z141.number().int().positive(),
35255
- available: z141.boolean().optional(),
35256
- earned: z141.boolean(),
35415
+ credits: z142.number().int().positive(),
35416
+ available: z142.boolean().optional(),
35417
+ earned: z142.boolean(),
35257
35418
  grantId: ProjectId.nullable(),
35258
- grantedAt: z141.string().datetime().nullable()
35419
+ grantedAt: z142.string().datetime().nullable()
35259
35420
  })).length(DropshippingRewardMilestone.options.length)
35260
35421
  });
35261
- var ProjectResponseSchema = z141.object({
35422
+ var ProjectResponseSchema = z142.object({
35262
35423
  id: ProjectId,
35263
35424
  taskId: ProjectId.nullable(),
35264
35425
  status: DropshippingProjectStatus,
35265
- originKey: z141.string().min(1),
35426
+ originKey: z142.string().min(1),
35266
35427
  researchRunId: ProjectId.nullable(),
35267
- candidateSourceId: z141.string().nullable(),
35268
- productName: z141.string().nullable(),
35428
+ candidateSourceId: z142.string().nullable(),
35429
+ productName: z142.string().nullable(),
35269
35430
  productUrl: HttpUrl3.nullable(),
35270
35431
  referenceImageUrl: HttpUrl3.nullable(),
35271
- targetCountry: z141.string().nullable(),
35272
- languageCode: z141.string().nullable(),
35273
- hasReferenceImage: z141.boolean(),
35274
- hasWinnerReferenceImage: z141.boolean(),
35432
+ targetCountry: z142.string().nullable(),
35433
+ languageCode: z142.string().nullable(),
35434
+ hasReferenceImage: z142.boolean(),
35435
+ hasWinnerReferenceImage: z142.boolean(),
35275
35436
  costingInput: CostingInputSchema.nullable(),
35276
35437
  costingResult: CostingResultSchema.nullable(),
35277
- costingVersion: z141.number().int().positive().nullable(),
35278
- version: z141.number().int().positive(),
35438
+ costingVersion: z142.number().int().positive().nullable(),
35439
+ version: z142.number().int().positive(),
35279
35440
  phase: DropshippingProjectPhase,
35280
35441
  nextAction: DropshippingProjectNextAction.nullable(),
35281
35442
  rewards: RewardProgressSchema,
35282
- createdAt: z141.string().datetime(),
35283
- updatedAt: z141.string().datetime()
35443
+ createdAt: z142.string().datetime(),
35444
+ updatedAt: z142.string().datetime()
35284
35445
  }).passthrough();
35285
35446
  var NEXT_ACTION_GUIDANCE = {
35286
35447
  cost_product: "Llama `cost_dropshipping_project` con el costo real del proveedor. Nunca lo inventes: p\xEDdeselo al usuario. Es el \xDANICO dato que debes pedirle: omite env\xEDo, devoluciones, cancelaciones, CPA y margen para que ProductMaker use los valores gu\xEDa del pa\xEDs, y luego dile al usuario cu\xE1les us\xF3 por si quiere corregirlos.",
@@ -35400,58 +35561,58 @@ function registerDropshippingProjectTools(server, api) {
35400
35561
  __name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
35401
35562
 
35402
35563
  // src/tools/daily-control.ts
35403
- import { z as z142 } from "zod";
35564
+ import { z as z143 } from "zod";
35404
35565
  var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
35405
35566
  var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
35406
35567
  var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
35407
- var ProviderCampaignIdentifier = z142.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
35408
- var DateOnly = z142.string().regex(/^\d{4}-\d{2}-\d{2}$/);
35409
- var DailyControlInput = z142.object({
35568
+ var ProviderCampaignIdentifier = z143.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
35569
+ var DateOnly = z143.string().regex(/^\d{4}-\d{2}-\d{2}$/);
35570
+ var DailyControlInput = z143.object({
35410
35571
  date: DateOnly.optional().describe("D\xEDa final de la ventana (YYYY-MM-DD). Si se omite, la ventana termina AYER en UTC \u2014 nunca hoy, porque el d\xEDa en curso est\xE1 incompleto \u2014 y el servidor puede correrla un d\xEDa m\xE1s atr\xE1s si en la zona horaria de la tienda ese d\xEDa todav\xEDa no ha cerrado."),
35411
- days: z142.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
35412
- projectId: z142.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
35572
+ days: z143.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
35573
+ projectId: z143.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
35413
35574
  }).strict();
35414
- var LinkCampaignInput = z142.object({
35415
- projectId: z142.string().uuid(),
35416
- provider: z142.enum([
35575
+ var LinkCampaignInput = z143.object({
35576
+ projectId: z143.string().uuid(),
35577
+ provider: z143.enum([
35417
35578
  "meta",
35418
35579
  "tiktok"
35419
35580
  ]),
35420
35581
  accountId: ProviderCampaignIdentifier.describe("Cuenta publicitaria del proveedor. Para Meta el servidor la IGNORA y deriva la cuenta real de la campa\xF1a \u2014 se sigue pidiendo aqu\xED solo porque TikTok s\xED la necesita para resolver la campa\xF1a."),
35421
35582
  campaignId: ProviderCampaignIdentifier
35422
35583
  }).strict();
35423
- var ReportReturnsInput = z142.object({
35424
- projectId: z142.string().uuid(),
35584
+ var ReportReturnsInput = z143.object({
35585
+ projectId: z143.string().uuid(),
35425
35586
  date: DateOnly,
35426
- returnedOrders: z142.number().int().min(0).max(1e5),
35427
- note: z142.string().trim().max(280).optional()
35428
- }).strict();
35429
- var DailyControlStatusMirror = DailyControlStatusEnum.or(z142.string());
35430
- var DailyControlLightMirror = DailyControlLightEnum.or(z142.string());
35431
- var DailyControlSourceMirror = DailyControlSourceEnum.or(z142.string());
35432
- var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z142.string());
35433
- var DailyControlDayMirror = z142.object({
35434
- date: z142.string(),
35435
- returnedOrders: z142.number(),
35587
+ returnedOrders: z143.number().int().min(0).max(1e5),
35588
+ note: z143.string().trim().max(280).optional()
35589
+ }).strict();
35590
+ var DailyControlStatusMirror = DailyControlStatusEnum.or(z143.string());
35591
+ var DailyControlLightMirror = DailyControlLightEnum.or(z143.string());
35592
+ var DailyControlSourceMirror = DailyControlSourceEnum.or(z143.string());
35593
+ var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z143.string());
35594
+ var DailyControlDayMirror = z143.object({
35595
+ date: z143.string(),
35596
+ returnedOrders: z143.number(),
35436
35597
  returnedSource: DailyControlSourceMirror,
35437
35598
  cancelledSource: DailyControlSourceMirror,
35438
- hasEstimates: z142.boolean(),
35599
+ hasEstimates: z143.boolean(),
35439
35600
  light: DailyControlLightMirror
35440
35601
  }).passthrough();
35441
- var DailyControlProductMirror = z142.object({
35442
- projectId: z142.string().uuid(),
35443
- productName: z142.string().nullable(),
35602
+ var DailyControlProductMirror = z143.object({
35603
+ projectId: z143.string().uuid(),
35604
+ productName: z143.string().nullable(),
35444
35605
  status: DailyControlStatusMirror,
35445
- statusMessage: z142.string().nullable(),
35446
- days: z142.array(DailyControlDayMirror),
35606
+ statusMessage: z143.string().nullable(),
35607
+ days: z143.array(DailyControlDayMirror),
35447
35608
  verdict: DailyControlVerdictMirror.nullable(),
35448
- rationale: z142.string().nullable()
35609
+ rationale: z143.string().nullable()
35449
35610
  }).passthrough();
35450
- var DailyControlResponseMirror = z142.object({
35451
- since: z142.string(),
35452
- until: z142.string(),
35453
- products: z142.array(DailyControlProductMirror),
35454
- archivedProjectSpend: z142.array(z142.unknown())
35611
+ var DailyControlResponseMirror = z143.object({
35612
+ since: z143.string(),
35613
+ until: z143.string(),
35614
+ products: z143.array(DailyControlProductMirror),
35615
+ archivedProjectSpend: z143.array(z143.unknown())
35455
35616
  }).passthrough();
35456
35617
  var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
35457
35618
  function withWarnings(response) {
@@ -35526,7 +35687,7 @@ __name(registerDailyControlTools, "registerDailyControlTools");
35526
35687
  // src/tools/product-control.ts
35527
35688
  import { readFile, stat } from "fs/promises";
35528
35689
  import { basename as basename2, isAbsolute, resolve as resolve3 } from "path";
35529
- import { z as z143 } from "zod";
35690
+ import { z as z144 } from "zod";
35530
35691
  var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
35531
35692
  var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
35532
35693
  var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
@@ -35539,36 +35700,36 @@ var createOperationGuidance = getProductMakerCapabilityModelGuidance("create_ope
35539
35700
  var mergeProductsGuidance = getProductMakerCapabilityModelGuidance("merge_products");
35540
35701
  var syncShopifyOrdersGuidance = getProductMakerCapabilityModelGuidance("sync_shopify_orders");
35541
35702
  var importOrdersFileGuidance = getProductMakerCapabilityModelGuidance("import_orders_file");
35542
- var DateOnly2 = z143.string().regex(/^\d{4}-\d{2}-\d{2}$/);
35703
+ var DateOnly2 = z144.string().regex(/^\d{4}-\d{2}-\d{2}$/);
35543
35704
  var IMPORT_BATCH_MAX2 = 50;
35544
- var ProductControlListInput = z143.object({
35545
- days: z143.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
35705
+ var ProductControlListInput = z144.object({
35706
+ days: z144.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
35546
35707
  date: DateOnly2.optional().describe("D\xEDa final de la ventana (YYYY-MM-DD). Si se omite, termina en el \xFAltimo d\xEDa cerrado \u2014 nunca hoy, que est\xE1 incompleto."),
35547
- shopDomain: z143.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
35708
+ shopDomain: z144.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
35548
35709
  }).strict();
35549
- var ImportableProductsInput = z143.object({
35550
- q: z143.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
35551
- after: z143.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
35552
- shopDomain: z143.string().min(1).optional()
35710
+ var ImportableProductsInput = z144.object({
35711
+ q: z144.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
35712
+ after: z144.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
35713
+ shopDomain: z144.string().min(1).optional()
35553
35714
  }).strict();
35554
- var ImportProductControlsInput = z143.object({
35555
- shopifyProductIds: z143.array(z143.string().min(1).max(64)).min(1).max(IMPORT_BATCH_MAX2).describe("Identificadores tal como vinieron de list_importable_products. NO los inventes ni los deduzcas del t\xEDtulo."),
35715
+ var ImportProductControlsInput = z144.object({
35716
+ shopifyProductIds: z144.array(z144.string().min(1).max(64)).min(1).max(IMPORT_BATCH_MAX2).describe("Identificadores tal como vinieron de list_importable_products. NO los inventes ni los deduzcas del t\xEDtulo."),
35556
35717
  // Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
35557
35718
  // sin decir a cuál archivaría el producto bajo la tienda equivocada.
35558
- shopDomain: z143.string().min(1)
35559
- }).strict();
35560
- var SetProductCostingInput = z143.object({
35561
- shopDomain: z143.string().min(1),
35562
- shopifyProductId: z143.string().min(1).max(64),
35563
- targetCountry: z143.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
35564
- supplierCost: z143.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
35565
- shippingCost: z143.number().finite().nonnegative(),
35566
- returnRate: z143.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
35567
- cancellationRate: z143.number().finite().min(0).lt(1)
35568
- }).strict();
35569
- var Count = z143.number().int().min(0).max(1e5).nullable().optional();
35570
- var ReportProductCountsInput = z143.object({
35571
- productControlId: z143.string().uuid().describe("El identificador que devuelve get_product_control."),
35719
+ shopDomain: z144.string().min(1)
35720
+ }).strict();
35721
+ var SetProductCostingInput = z144.object({
35722
+ shopDomain: z144.string().min(1),
35723
+ shopifyProductId: z144.string().min(1).max(64),
35724
+ targetCountry: z144.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
35725
+ supplierCost: z144.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
35726
+ shippingCost: z144.number().finite().nonnegative(),
35727
+ returnRate: z144.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
35728
+ cancellationRate: z144.number().finite().min(0).lt(1)
35729
+ }).strict();
35730
+ var Count = z144.number().int().min(0).max(1e5).nullable().optional();
35731
+ var ReportProductCountsInput = z144.object({
35732
+ productControlId: z144.string().uuid().describe("El identificador que devuelve get_product_control."),
35572
35733
  date: DateOnly2,
35573
35734
  orders: Count.describe("Pedidos que entraron ese d\xEDa."),
35574
35735
  cancelledOrders: Count,
@@ -35578,36 +35739,36 @@ var ReportProductCountsInput = z143.object({
35578
35739
  }).strict();
35579
35740
  var MAX_ORDERS_FILE_BYTES = 8 * 1024 * 1024;
35580
35741
  var SyncShopifyOrdersInput = SyncShopifyOrdersSchema;
35581
- var ImportOrdersFileInput = z143.object({
35742
+ var ImportOrdersFileInput = z144.object({
35582
35743
  /** Ruta ABSOLUTA en la máquina de quien usa el MCP. */
35583
- path: z143.string().min(1),
35584
- operationId: z143.string().uuid().optional(),
35744
+ path: z144.string().min(1),
35745
+ operationId: z144.string().uuid().optional(),
35585
35746
  /** Solo mirar: devuelve el resumen y no escribe nada. */
35586
- dryRun: z143.boolean().optional()
35747
+ dryRun: z144.boolean().optional()
35587
35748
  }).strict();
35588
- var CreateOperationInput = z143.object({
35589
- countryCode: z143.string().length(2),
35590
- label: z143.string().trim().min(1).max(60).optional()
35749
+ var CreateOperationInput = z144.object({
35750
+ countryCode: z144.string().length(2),
35751
+ label: z144.string().trim().min(1).max(60).optional()
35591
35752
  }).strict();
35592
- var MergeProductsInput = z143.object({
35593
- sourceId: z143.string().uuid(),
35594
- targetId: z143.string().uuid()
35753
+ var MergeProductsInput = z144.object({
35754
+ sourceId: z144.string().uuid(),
35755
+ targetId: z144.string().uuid()
35595
35756
  }).strict();
35596
- var SetMonthlyExpenseInput = z143.object({
35597
- month: z143.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
35757
+ var SetMonthlyExpenseInput = z144.object({
35758
+ month: z144.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
35598
35759
  label: SaveMonthlyExpenseSchema.shape.label,
35599
- amount: z143.number().finite().min(0),
35600
- operationId: z143.string().uuid().optional()
35760
+ amount: z144.number().finite().min(0),
35761
+ operationId: z144.string().uuid().optional()
35601
35762
  }).strict();
35602
- var SetAdSpendInput = z143.object({
35603
- month: z143.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
35604
- operationId: z143.string().uuid().optional(),
35763
+ var SetAdSpendInput = z144.object({
35764
+ month: z144.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
35765
+ operationId: z144.string().uuid().optional(),
35605
35766
  /** null RETIRA la corrección; cero afirma que no pautó. */
35606
- amount: z143.number().finite().min(0).nullable()
35767
+ amount: z144.number().finite().min(0).nullable()
35607
35768
  }).strict();
35608
- var GetFinancesInput = z143.object({
35609
- month: z143.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional().describe("Mes en YYYY-MM. Si se omite, el mes en curso. Solo mes calendario."),
35610
- operationId: z143.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
35769
+ var GetFinancesInput = z144.object({
35770
+ month: z144.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional().describe("Mes en YYYY-MM. Si se omite, el mes en curso. Solo mes calendario."),
35771
+ operationId: z144.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
35611
35772
  }).strict();
35612
35773
  function registerProductControlTools(server, api, { transport = "http" } = {}) {
35613
35774
  server.registerTool("get_product_control", {
@@ -35799,28 +35960,28 @@ function registerProductControlTools(server, api, { transport = "http" } = {}) {
35799
35960
  __name(registerProductControlTools, "registerProductControlTools");
35800
35961
 
35801
35962
  // src/tools/market-study-estimate.ts
35802
- import { z as z144 } from "zod";
35963
+ import { z as z145 } from "zod";
35803
35964
  var estimateMarketStudyGuidance = getProductMakerCapabilityModelGuidance("estimate_market_study_cost");
35804
- var ProductTaskOutputEnum = z144.enum([
35965
+ var ProductTaskOutputEnum = z145.enum([
35805
35966
  "landing",
35806
35967
  "video",
35807
35968
  "image"
35808
35969
  ]);
35809
- var EstimateMarketStudyInput = z144.object({
35810
- kind: z144.enum([
35970
+ var EstimateMarketStudyInput = z145.object({
35971
+ kind: z145.enum([
35811
35972
  "video",
35812
35973
  "product_task"
35813
35974
  ]).describe('"video" para generate_video_creative; "product_task" para create_product_task.'),
35814
- videoAngleCount: z144.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
35815
- durationSeconds: z144.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
35975
+ videoAngleCount: z145.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
35976
+ durationSeconds: z145.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
35816
35977
  videoStructure: VideoStructureEnum.default("single_take"),
35817
35978
  videoQuality: VideoQualityEnum.default("economy"),
35818
35979
  videoResolution: VideoResolutionEnum.default("480p"),
35819
- productImageCount: z144.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
35980
+ productImageCount: z145.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
35820
35981
  outputs: ProductTaskOutputEnum.array().min(1).max(3).optional().describe('Solo para kind="product_task": los mismos outputs de create_product_task. Default: todos.'),
35821
- generateAiMusic: z144.boolean().optional(),
35982
+ generateAiMusic: z145.boolean().optional(),
35822
35983
  generateAiEdit: AiEditRequestSchema.optional(),
35823
- replicateWinnerWhenFound: z144.boolean().optional().describe("La misma preferencia que enviar\xE1s al crear. false excluye la reserva de r\xE9plica del ganador de la cotizaci\xF3n con estudio.")
35984
+ replicateWinnerWhenFound: z145.boolean().optional().describe("La misma preferencia que enviar\xE1s al crear. false excluye la reserva de r\xE9plica del ganador de la cotizaci\xF3n con estudio.")
35824
35985
  }).strict();
35825
35986
  function buildMarketStudyEstimateRequests(input) {
35826
35987
  const quotesVideo = input.kind === "video" || (input.outputs ?? [