@productmaker/mcp 11.3.3 → 11.4.0

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/stdio.js CHANGED
@@ -9698,13 +9698,23 @@ var FacebookCreateCampaignFromTasksBodySchema = z51.object({
9698
9698
  portfolioId: z51.string().min(1),
9699
9699
  pageId: z51.string().min(1),
9700
9700
  pixelId: z51.string().optional(),
9701
+ /**
9702
+ * Omitted: a campaign with task creatives lands on the published service
9703
+ * landing of its service tasks (resolved server side, META_NO_LANDING_URL
9704
+ * when there is none); a media-only campaign must name it.
9705
+ */
9701
9706
  landingUrl: HttpUrl2.optional(),
9702
- targetCountry: CountryIso2Schema.default("US"),
9707
+ /**
9708
+ * Omitted: the brand country of its service tasks; a product-only campaign
9709
+ * keeps "US". Never a hardcoded country for a service (META_NO_TARGET_COUNTRY).
9710
+ */
9711
+ targetCountry: CountryIso2Schema.optional(),
9703
9712
  campaignName: z51.string().min(1).max(100),
9704
9713
  campaignConfig: MetaCampaignConfig.optional()
9705
9714
  }).superRefine((value, ctx) => {
9706
9715
  const isWhatsapp = value.campaignConfig?.destination?.type === "whatsapp";
9707
- if (!isWhatsapp && !value.landingUrl) {
9716
+ const hasTaskCreative = value.creatives.some((creative) => creative.source.type === "task");
9717
+ if (!isWhatsapp && !value.landingUrl && !hasTaskCreative) {
9708
9718
  ctx.addIssue({
9709
9719
  code: z51.ZodIssueCode.custom,
9710
9720
  path: [
@@ -18781,7 +18791,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
18781
18791
  ], [
18782
18792
  "tiktok_advertiser"
18783
18793
  ]),
18784
- defineCapability("publish_creatives_to_meta", "554d977e26e824490ffe3e027f34889b1e29d5969e6e9c0320f79e7c5a03584c", "external_mutation", "publishing", [
18794
+ defineCapability("publish_creatives_to_meta", "dff962c84ed7d0393444dcbe86cb6f4016b5928c1d0005f78ce9a365f1923ac3", "external_mutation", "publishing", [
18785
18795
  "external_mutation",
18786
18796
  "state_change"
18787
18797
  ], [
@@ -21877,19 +21887,37 @@ var ServiceImageContextSchema = z106.object({
21877
21887
  referenceKeys: z106.array(z106.string()).max(10)
21878
21888
  }).strict();
21879
21889
 
21880
- // ../../packages/types/src/service-website-capture.ts
21890
+ // ../../packages/types/src/task-ad-defaults.ts
21881
21891
  import { z as z107 } from "zod";
21892
+ var AD_HEADLINE_MAX_CHARS = 255;
21893
+ var TaskAdDefaultsSchema = z107.object({
21894
+ subjectKind: z107.enum([
21895
+ "product",
21896
+ "service"
21897
+ ]),
21898
+ landingUrl: z107.string().url().nullable(),
21899
+ landingSource: z107.enum([
21900
+ "shopify",
21901
+ "service_page"
21902
+ ]).nullable(),
21903
+ headline: z107.string().min(1).max(AD_HEADLINE_MAX_CHARS).nullable(),
21904
+ /** ISO 3166-1 alpha-2 when known. */
21905
+ country: z107.string().min(2).nullable()
21906
+ });
21907
+
21908
+ // ../../packages/types/src/service-website-capture.ts
21909
+ import { z as z108 } from "zod";
21882
21910
  var WEBSITE_CAPTURE_MAX_RESEARCH_BYTES = 1024 * 1024;
21883
21911
  var WEBSITE_CAPTURE_MAX_FILES = 100;
21884
21912
  var WEBSITE_CAPTURE_MAX_FILE_BYTES = 8 * 1024 * 1024;
21885
21913
  var WEBSITE_CAPTURE_MAX_BUNDLE_BYTES = 30 * 1024 * 1024;
21886
- var WebsiteCaptureCauseSchema = z107.enum([
21914
+ var WebsiteCaptureCauseSchema = z108.enum([
21887
21915
  "site_blocked",
21888
21916
  "site_unreachable",
21889
21917
  "not_enough_content",
21890
21918
  "internal"
21891
21919
  ]);
21892
- var WebsiteCaptureStatusSchema = z107.enum([
21920
+ var WebsiteCaptureStatusSchema = z108.enum([
21893
21921
  "queued",
21894
21922
  "capturing",
21895
21923
  "ready",
@@ -21911,143 +21939,143 @@ function normalizeWebsiteCaptureUrl(value) {
21911
21939
  }
21912
21940
  }
21913
21941
  __name(normalizeWebsiteCaptureUrl, "normalizeWebsiteCaptureUrl");
21914
- var WebsiteCaptureRequestSchema = z107.object({
21915
- url: z107.string().trim().max(2048).url().refine((value) => normalizeWebsiteCaptureUrl(value) !== null, "Use an HTTP(S) URL without credentials").transform((value) => normalizeWebsiteCaptureUrl(value)),
21942
+ var WebsiteCaptureRequestSchema = z108.object({
21943
+ url: z108.string().trim().max(2048).url().refine((value) => normalizeWebsiteCaptureUrl(value) !== null, "Use an HTTP(S) URL without credentials").transform((value) => normalizeWebsiteCaptureUrl(value)),
21916
21944
  language: MotionGraphicsLanguageSchema
21917
21945
  }).strict();
21918
- var WebsiteCaptureResponseSchema = z107.object({
21919
- captureId: z107.string().uuid(),
21946
+ var WebsiteCaptureResponseSchema = z108.object({
21947
+ captureId: z108.string().uuid(),
21920
21948
  status: WebsiteCaptureStatusSchema,
21921
- expiresAt: z107.string().datetime(),
21922
- previewUrl: z107.string().url().optional(),
21949
+ expiresAt: z108.string().datetime(),
21950
+ previewUrl: z108.string().url().optional(),
21923
21951
  cause: WebsiteCaptureCauseSchema.optional()
21924
21952
  });
21925
21953
  var WebsiteCaptureJobSchema = WebsiteCaptureRequestSchema.extend({
21926
- captureId: z107.string().uuid(),
21927
- attempt: z107.number().int().positive(),
21928
- leaseUntil: z107.string().datetime()
21954
+ captureId: z108.string().uuid(),
21955
+ attempt: z108.number().int().positive(),
21956
+ leaseUntil: z108.string().datetime()
21929
21957
  });
21930
- var WebsiteCaptureClaimResponseSchema = z107.object({
21958
+ var WebsiteCaptureClaimResponseSchema = z108.object({
21931
21959
  capture: WebsiteCaptureJobSchema.nullable()
21932
21960
  });
21933
21961
  var attempt = {
21934
- attempt: z107.number().int().positive()
21962
+ attempt: z108.number().int().positive()
21935
21963
  };
21936
- var digest = z107.string().regex(/^[a-f0-9]{64}$/);
21937
- var WebsiteCaptureUploadRequestSchema = z107.object({
21964
+ var digest = z108.string().regex(/^[a-f0-9]{64}$/);
21965
+ var WebsiteCaptureUploadRequestSchema = z108.object({
21938
21966
  ...attempt,
21939
- contentLength: z107.number().int().positive().max(WEBSITE_CAPTURE_MAX_BUNDLE_BYTES),
21967
+ contentLength: z108.number().int().positive().max(WEBSITE_CAPTURE_MAX_BUNDLE_BYTES),
21940
21968
  sha256: digest
21941
21969
  }).strict();
21942
- var WebsiteCaptureDoneRequestSchema = z107.object({
21970
+ var WebsiteCaptureDoneRequestSchema = z108.object({
21943
21971
  ...attempt,
21944
21972
  sha256: digest
21945
21973
  }).strict();
21946
- var WebsiteCaptureFailedRequestSchema = z107.object({
21974
+ var WebsiteCaptureFailedRequestSchema = z108.object({
21947
21975
  ...attempt,
21948
21976
  cause: WebsiteCaptureCauseSchema
21949
21977
  }).strict();
21950
- var WebsiteCaptureBundleSchema = z107.object({
21951
- version: z107.literal(1),
21952
- files: z107.array(z107.object({
21953
- path: z107.string().max(140).regex(/^research\/(?:page\.json|(?:desktop|mobile)-[1-9]\d*\.jpg|logo\.(?:png|svg)|image-[1-9]\d*\.(?:png|jpg|jpeg|webp|svg|avif)|font-[1-9]\d*\.(?:woff2?|ttf|otf))$/),
21954
- base64: z107.string().max(Math.ceil(WEBSITE_CAPTURE_MAX_FILE_BYTES / 3) * 4).regex(/^[A-Za-z0-9+/]*={0,2}$/).refine((value) => value.length % 4 === 0),
21978
+ var WebsiteCaptureBundleSchema = z108.object({
21979
+ version: z108.literal(1),
21980
+ files: z108.array(z108.object({
21981
+ path: z108.string().max(140).regex(/^research\/(?:page\.json|(?:desktop|mobile)-[1-9]\d*\.jpg|logo\.(?:png|svg)|image-[1-9]\d*\.(?:png|jpg|jpeg|webp|svg|avif)|font-[1-9]\d*\.(?:woff2?|ttf|otf))$/),
21982
+ base64: z108.string().max(Math.ceil(WEBSITE_CAPTURE_MAX_FILE_BYTES / 3) * 4).regex(/^[A-Za-z0-9+/]*={0,2}$/).refine((value) => value.length % 4 === 0),
21955
21983
  sha256: digest
21956
21984
  }).strict()).min(1).max(WEBSITE_CAPTURE_MAX_FILES)
21957
21985
  }).strict().refine((bundle) => new Set(bundle.files.map((file) => file.path)).size === bundle.files.length, "Duplicate capture file");
21958
- var WebsiteCaptureScreenshotSchema = z107.object({
21959
- file: z107.string(),
21960
- scrollTop: z107.number()
21961
- });
21962
- var WebsiteCaptureAccessSchema = z107.object({
21963
- publicContentText: z107.string().max(8e3),
21964
- passwordGate: z107.boolean(),
21965
- challengeGate: z107.boolean(),
21966
- blockingOverlay: z107.boolean(),
21986
+ var WebsiteCaptureScreenshotSchema = z108.object({
21987
+ file: z108.string(),
21988
+ scrollTop: z108.number()
21989
+ });
21990
+ var WebsiteCaptureAccessSchema = z108.object({
21991
+ publicContentText: z108.string().max(8e3),
21992
+ passwordGate: z108.boolean(),
21993
+ challengeGate: z108.boolean(),
21994
+ blockingOverlay: z108.boolean(),
21967
21995
  // Decoded, substantial images visible outside access walls and page chrome.
21968
21996
  // Optional for compatibility with already captured text-led research.
21969
- publicImageUrls: z107.array(z107.string().url().max(8192)).max(20).optional()
21970
- });
21971
- var WebsiteCaptureResearchSchema = z107.object({
21972
- requestedUrl: z107.string().url(),
21973
- capturedAt: z107.string().datetime(),
21974
- locale: z107.string(),
21975
- bodyTextTruncated: z107.boolean(),
21976
- finalUrl: z107.string().url(),
21977
- lang: z107.string().nullable(),
21978
- title: z107.string(),
21979
- description: z107.string(),
21980
- openGraph: z107.object({
21981
- title: z107.string(),
21982
- description: z107.string(),
21983
- image: z107.string(),
21984
- siteName: z107.string()
21997
+ publicImageUrls: z108.array(z108.string().url().max(8192)).max(20).optional()
21998
+ });
21999
+ var WebsiteCaptureResearchSchema = z108.object({
22000
+ requestedUrl: z108.string().url(),
22001
+ capturedAt: z108.string().datetime(),
22002
+ locale: z108.string(),
22003
+ bodyTextTruncated: z108.boolean(),
22004
+ finalUrl: z108.string().url(),
22005
+ lang: z108.string().nullable(),
22006
+ title: z108.string(),
22007
+ description: z108.string(),
22008
+ openGraph: z108.object({
22009
+ title: z108.string(),
22010
+ description: z108.string(),
22011
+ image: z108.string(),
22012
+ siteName: z108.string()
21985
22013
  }),
21986
- themeColor: z107.string(),
21987
- headings: z107.object({
21988
- h1: z107.array(z107.string()),
21989
- h2: z107.array(z107.string()),
21990
- h3: z107.array(z107.string())
22014
+ themeColor: z108.string(),
22015
+ headings: z108.object({
22016
+ h1: z108.array(z108.string()),
22017
+ h2: z108.array(z108.string()),
22018
+ h3: z108.array(z108.string())
21991
22019
  }),
21992
- callsToAction: z107.array(z107.string()),
21993
- listItems: z107.array(z107.string()),
21994
- bodyText: z107.string(),
22020
+ callsToAction: z108.array(z108.string()),
22021
+ listItems: z108.array(z108.string()),
22022
+ bodyText: z108.string(),
21995
22023
  access: WebsiteCaptureAccessSchema.optional(),
21996
- consent: z107.object({
21997
- pressed: z107.string().nullable(),
21998
- removed: z107.number().nonnegative()
22024
+ consent: z108.object({
22025
+ pressed: z108.string().nullable(),
22026
+ removed: z108.number().nonnegative()
21999
22027
  }).optional(),
22000
- overlaysDismissed: z107.number().int().nonnegative().optional(),
22001
- style: z107.object({
22002
- bodyBackground: z107.string(),
22003
- bodyColor: z107.string(),
22004
- bodyFont: z107.string(),
22005
- headingFont: z107.string().nullable(),
22006
- headingColor: z107.string().nullable(),
22007
- actionColors: z107.array(z107.object({
22008
- color: z107.string(),
22009
- uses: z107.number()
22028
+ overlaysDismissed: z108.number().int().nonnegative().optional(),
22029
+ style: z108.object({
22030
+ bodyBackground: z108.string(),
22031
+ bodyColor: z108.string(),
22032
+ bodyFont: z108.string(),
22033
+ headingFont: z108.string().nullable(),
22034
+ headingColor: z108.string().nullable(),
22035
+ actionColors: z108.array(z108.object({
22036
+ color: z108.string(),
22037
+ uses: z108.number()
22010
22038
  }))
22011
22039
  }),
22012
- images: z107.array(z107.object({
22013
- file: z107.string(),
22014
- src: z107.string(),
22015
- alt: z107.string(),
22016
- width: z107.number().nullable(),
22017
- height: z107.number().nullable(),
22018
- isOpenGraph: z107.boolean()
22040
+ images: z108.array(z108.object({
22041
+ file: z108.string(),
22042
+ src: z108.string(),
22043
+ alt: z108.string(),
22044
+ width: z108.number().nullable(),
22045
+ height: z108.number().nullable(),
22046
+ isOpenGraph: z108.boolean()
22019
22047
  })),
22020
- logo: z107.object({
22021
- file: z107.literal("logo.png"),
22022
- svg: z107.literal("logo.svg").optional(),
22023
- width: z107.number(),
22024
- height: z107.number()
22048
+ logo: z108.object({
22049
+ file: z108.literal("logo.png"),
22050
+ svg: z108.literal("logo.svg").optional(),
22051
+ width: z108.number(),
22052
+ height: z108.number()
22025
22053
  }).nullable(),
22026
- fonts: z107.array(z107.object({
22027
- family: z107.string(),
22028
- weight: z107.string(),
22029
- style: z107.string(),
22030
- unicodeRange: z107.string().nullable(),
22031
- file: z107.string().optional()
22054
+ fonts: z108.array(z108.object({
22055
+ family: z108.string(),
22056
+ weight: z108.string(),
22057
+ style: z108.string(),
22058
+ unicodeRange: z108.string().nullable(),
22059
+ file: z108.string().optional()
22032
22060
  }).transform((font) => ({
22033
22061
  ...font,
22034
22062
  file: font.file
22035
22063
  }))),
22036
- screenshots: z107.object({
22037
- desktop: z107.array(WebsiteCaptureScreenshotSchema),
22038
- mobile: z107.array(WebsiteCaptureScreenshotSchema)
22064
+ screenshots: z108.object({
22065
+ desktop: z108.array(WebsiteCaptureScreenshotSchema),
22066
+ mobile: z108.array(WebsiteCaptureScreenshotSchema)
22039
22067
  })
22040
22068
  });
22041
22069
 
22042
22070
  // ../../packages/types/src/demo-mode.ts
22043
- import { z as z108 } from "zod";
22071
+ import { z as z109 } from "zod";
22044
22072
  var DEMO_MODE_FLOWS = [
22045
22073
  "brand",
22046
22074
  "servicePage",
22047
22075
  "motion",
22048
22076
  "image"
22049
22077
  ];
22050
- var DemoModeFlowSchema = z108.enum(DEMO_MODE_FLOWS);
22078
+ var DemoModeFlowSchema = z109.enum(DEMO_MODE_FLOWS);
22051
22079
  var DEMO_MODE_STEPS = [
22052
22080
  "running",
22053
22081
  "research",
@@ -22060,27 +22088,27 @@ var DEMO_MODE_STEPS = [
22060
22088
  "final",
22061
22089
  "watchdog"
22062
22090
  ];
22063
- var DemoModeStepSchema = z108.enum(DEMO_MODE_STEPS);
22091
+ var DemoModeStepSchema = z109.enum(DEMO_MODE_STEPS);
22064
22092
  var DEMO_MODE_WAIT_SECONDS = {
22065
22093
  min: 30,
22066
22094
  max: 450,
22067
22095
  default: 150
22068
22096
  };
22069
- var centsSchema = z108.number().int().min(0).max(1e5);
22070
- var emailSchema = z108.string().trim().toLowerCase().email();
22071
- var DemoModeTemplatesSchema = z108.object({
22072
- brandId: z108.string().uuid(),
22073
- servicePageId: z108.string().uuid(),
22074
- motionTaskId: z108.string().uuid(),
22075
- imageTaskId: z108.string().uuid()
22076
- });
22077
- var DemoModeEditableSchema = z108.object({
22078
- enabled: z108.boolean(),
22079
- emails: z108.array(emailSchema).max(50).transform((list) => [
22097
+ var centsSchema = z109.number().int().min(0).max(1e5);
22098
+ var emailSchema = z109.string().trim().toLowerCase().email();
22099
+ var DemoModeTemplatesSchema = z109.object({
22100
+ brandId: z109.string().uuid(),
22101
+ servicePageId: z109.string().uuid(),
22102
+ motionTaskId: z109.string().uuid(),
22103
+ imageTaskId: z109.string().uuid()
22104
+ });
22105
+ var DemoModeEditableSchema = z109.object({
22106
+ enabled: z109.boolean(),
22107
+ emails: z109.array(emailSchema).max(50).transform((list) => [
22080
22108
  ...new Set(list)
22081
22109
  ]),
22082
- waitSeconds: z108.number().int().min(DEMO_MODE_WAIT_SECONDS.min).max(DEMO_MODE_WAIT_SECONDS.max),
22083
- chargeCents: z108.object({
22110
+ waitSeconds: z109.number().int().min(DEMO_MODE_WAIT_SECONDS.min).max(DEMO_MODE_WAIT_SECONDS.max),
22111
+ chargeCents: z109.object({
22084
22112
  brand: centsSchema,
22085
22113
  servicePage: centsSchema,
22086
22114
  motion: centsSchema,
@@ -22088,73 +22116,73 @@ var DemoModeEditableSchema = z108.object({
22088
22116
  }),
22089
22117
  templates: DemoModeTemplatesSchema
22090
22118
  });
22091
- var nullableString = z108.string().nullable();
22092
- var DemoModeSnapshotSchema = z108.object({
22093
- brand: z108.object({
22119
+ var nullableString = z109.string().nullable();
22120
+ var DemoModeSnapshotSchema = z109.object({
22121
+ brand: z109.object({
22094
22122
  /** Columnas de identidad de `Brand` listas para un `update` (sin id/userId/slug/estado/fechas). */
22095
- identity: z108.record(z108.unknown()),
22096
- productSamples: z108.array(z108.object({
22097
- name: z108.string(),
22098
- priceCents: z108.number().int().nullable(),
22123
+ identity: z109.record(z109.unknown()),
22124
+ productSamples: z109.array(z109.object({
22125
+ name: z109.string(),
22126
+ priceCents: z109.number().int().nullable(),
22099
22127
  currency: nullableString,
22100
- imageKey: z108.string(),
22128
+ imageKey: z109.string(),
22101
22129
  productUrl: nullableString,
22102
- position: z108.number().int()
22130
+ position: z109.number().int()
22103
22131
  })),
22104
- personas: z108.array(z108.object({
22105
- name: z108.string(),
22132
+ personas: z109.array(z109.object({
22133
+ name: z109.string(),
22106
22134
  demographics: nullableString,
22107
22135
  painPoints: nullableString,
22108
22136
  motivations: nullableString,
22109
22137
  objections: nullableString,
22110
22138
  gender: nullableString,
22111
- isDefault: z108.boolean()
22139
+ isDefault: z109.boolean()
22112
22140
  }))
22113
22141
  }),
22114
- servicePage: z108.object({
22115
- facts: z108.unknown(),
22116
- review: z108.unknown(),
22117
- artifact: z108.unknown()
22142
+ servicePage: z109.object({
22143
+ facts: z109.unknown(),
22144
+ review: z109.unknown(),
22145
+ artifact: z109.unknown()
22118
22146
  }),
22119
- motion: z108.object({
22147
+ motion: z109.object({
22120
22148
  outputs: MotionGraphicsOutputsSchema,
22121
22149
  /**
22122
22150
  * La captura REAL de la web de la plantilla (nunca una fabricada por la
22123
22151
  * demo). Null cuando la plantilla no tiene ninguna: la captura demo nunca
22124
22152
  * va live, así que el servicio usa `DEMO_MODE_PLACEHOLDER_CAPTURE`.
22125
22153
  */
22126
- capture: z108.object({
22127
- bundleKey: z108.string(),
22128
- sha256: z108.string(),
22129
- uploadBytes: z108.number().int().nullable(),
22154
+ capture: z109.object({
22155
+ bundleKey: z109.string(),
22156
+ sha256: z109.string(),
22157
+ uploadBytes: z109.number().int().nullable(),
22130
22158
  previewKey: nullableString
22131
22159
  }).nullable()
22132
22160
  }),
22133
- image: z108.object({
22134
- provider: z108.string(),
22135
- model: z108.string(),
22136
- prompt: z108.string(),
22137
- imageUrl: z108.string(),
22138
- width: z108.number().int(),
22139
- height: z108.number().int(),
22161
+ image: z109.object({
22162
+ provider: z109.string(),
22163
+ model: z109.string(),
22164
+ prompt: z109.string(),
22165
+ imageUrl: z109.string(),
22166
+ width: z109.number().int(),
22167
+ height: z109.number().int(),
22140
22168
  adCopy: nullableString,
22141
- rawResponse: z108.unknown()
22169
+ rawResponse: z109.unknown()
22142
22170
  })
22143
22171
  });
22144
22172
  var DemoModeConfigSchema = DemoModeEditableSchema.extend({
22145
22173
  snapshot: DemoModeSnapshotSchema.nullable(),
22146
- snapshotAt: z108.string().datetime().nullable()
22174
+ snapshotAt: z109.string().datetime().nullable()
22147
22175
  });
22148
22176
  var DemoModeAdminViewSchema = DemoModeEditableSchema.extend({
22149
22177
  // Sin configurar, la API devuelve ids vacíos ("" no es uuid): la vista los
22150
22178
  // admite; el PUT sí exige uuid (`DemoModeEditableSchema`).
22151
- templates: z108.object({
22152
- brandId: z108.string(),
22153
- servicePageId: z108.string(),
22154
- motionTaskId: z108.string(),
22155
- imageTaskId: z108.string()
22179
+ templates: z109.object({
22180
+ brandId: z109.string(),
22181
+ servicePageId: z109.string(),
22182
+ motionTaskId: z109.string(),
22183
+ imageTaskId: z109.string()
22156
22184
  }),
22157
- snapshotAt: z108.string().nullable()
22185
+ snapshotAt: z109.string().nullable()
22158
22186
  });
22159
22187
  var DEMO_MODE_TEMPLATE_PROBLEMS = [
22160
22188
  "not_found",
@@ -22165,31 +22193,31 @@ var DEMO_MODE_TEMPLATE_PROBLEMS = [
22165
22193
  "no_video",
22166
22194
  "no_creative"
22167
22195
  ];
22168
- var DemoModeTemplateVerdictSchema = z108.discriminatedUnion("ok", [
22169
- z108.object({
22170
- ok: z108.literal(true)
22196
+ var DemoModeTemplateVerdictSchema = z109.discriminatedUnion("ok", [
22197
+ z109.object({
22198
+ ok: z109.literal(true)
22171
22199
  }),
22172
- z108.object({
22173
- ok: z108.literal(false),
22174
- problem: z108.enum(DEMO_MODE_TEMPLATE_PROBLEMS)
22200
+ z109.object({
22201
+ ok: z109.literal(false),
22202
+ problem: z109.enum(DEMO_MODE_TEMPLATE_PROBLEMS)
22175
22203
  })
22176
22204
  ]);
22177
- var DemoModeValidationSchema = z108.object({
22205
+ var DemoModeValidationSchema = z109.object({
22178
22206
  brandId: DemoModeTemplateVerdictSchema,
22179
22207
  servicePageId: DemoModeTemplateVerdictSchema,
22180
22208
  motionTaskId: DemoModeTemplateVerdictSchema,
22181
22209
  imageTaskId: DemoModeTemplateVerdictSchema
22182
22210
  });
22183
- var DemoModeJobSchema = z108.object({
22211
+ var DemoModeJobSchema = z109.object({
22184
22212
  flow: DemoModeFlowSchema,
22185
22213
  step: DemoModeStepSchema,
22186
22214
  /** brandId | servicePageOperationId | taskId según el flujo. */
22187
- targetId: z108.string().uuid(),
22188
- userId: z108.string().min(1),
22215
+ targetId: z109.string().uuid(),
22216
+ userId: z109.string().min(1),
22189
22217
  /** Solo marca: la generación de extracción que el guion completa. */
22190
- generation: z108.number().int().positive().optional(),
22218
+ generation: z109.number().int().positive().optional(),
22191
22219
  /** Solo `final`/`watchdog`: la parte del snapshot de ESTE flujo, congelada al empezar. */
22192
- result: z108.unknown().optional()
22220
+ result: z109.unknown().optional()
22193
22221
  });
22194
22222
 
22195
22223
  // src/response-body.ts
@@ -22434,7 +22462,7 @@ var ApiClient = class {
22434
22462
  };
22435
22463
 
22436
22464
  // src/index.ts
22437
- var MCP_VERSION = "11.3.3";
22465
+ var MCP_VERSION = "11.4.0";
22438
22466
 
22439
22467
  // src/meta-upload-app.ts
22440
22468
  import { readFileSync } from "fs";
@@ -22506,7 +22534,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
22506
22534
  __name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
22507
22535
 
22508
22536
  // src/tools/tasks.ts
22509
- import { z as z113 } from "zod";
22537
+ import { z as z114 } from "zod";
22510
22538
 
22511
22539
  // src/resolve-image.ts
22512
22540
  import { lookup as dnsLookup } from "dns/promises";
@@ -23067,9 +23095,9 @@ async function resolveMediaRef(ref, opts) {
23067
23095
  __name(resolveMediaRef, "resolveMediaRef");
23068
23096
 
23069
23097
  // src/tools/shared.ts
23070
- import { z as z109 } from "zod";
23071
- var Lang = z109.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);
23072
- var Country = z109.string().min(2).max(3);
23098
+ import { z as z110 } from "zod";
23099
+ var Lang = z110.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);
23100
+ var Country = z110.string().min(2).max(3);
23073
23101
  var LandingStrategyEnum = LandingStrategySchema;
23074
23102
  var LandingImageFormatEnum = LandingImageFormatSchema;
23075
23103
  var VideoPresetEnum = VideoPreset.extract([
@@ -23173,7 +23201,7 @@ function animationStyleApplies(videoPreset, angleNarratives) {
23173
23201
  return ANIMATED_VIDEO_PRESETS.has(videoPreset ?? "") || (angleNarratives ?? []).some((n) => ANIMATED_NARRATIVE_STYLES.has(n));
23174
23202
  }
23175
23203
  __name(animationStyleApplies, "animationStyleApplies");
23176
- var VideoTierEnum = z109.enum([
23204
+ var VideoTierEnum = z110.enum([
23177
23205
  "basic"
23178
23206
  ]);
23179
23207
  function resolveVideoTier(_tier) {
@@ -23231,10 +23259,10 @@ var ImageCreativeStyleEnum = ImageCreativeStyle;
23231
23259
  var ImageCreativeArchetypeEnum = ImageCreativeArchetype;
23232
23260
  var ImageCreativeVisualTreatmentEnum = ImageCreativeVisualTreatment;
23233
23261
  var ImageCreativeAspectRatioEnum = ImageCreativeAspectRatio;
23234
- var ImageRefSchema = z109.object({
23235
- url: z109.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.'),
23236
- path: z109.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`.'),
23237
- assetId: z109.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.")
23262
+ var ImageRefSchema = z110.object({
23263
+ url: z110.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.'),
23264
+ path: z110.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`.'),
23265
+ assetId: z110.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.")
23238
23266
  }).refine((v) => [
23239
23267
  v.url,
23240
23268
  v.path,
@@ -23242,11 +23270,11 @@ var ImageRefSchema = z109.object({
23242
23270
  ].filter(Boolean).length === 1, {
23243
23271
  message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
23244
23272
  });
23245
- var ImagesInput = z109.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
23273
+ var ImagesInput = z110.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
23246
23274
  const assetCount = images.filter((image) => Boolean(image.assetId)).length;
23247
23275
  if (assetCount > 0 && assetCount !== images.length) {
23248
23276
  ctx.addIssue({
23249
- code: z109.ZodIssueCode.custom,
23277
+ code: z110.ZodIssueCode.custom,
23250
23278
  message: "all image entries must use assetId, or all must use URL/path sources"
23251
23279
  });
23252
23280
  }
@@ -23327,14 +23355,14 @@ async function submitCreative(api, opts) {
23327
23355
  });
23328
23356
  }
23329
23357
  __name(submitCreative, "submitCreative");
23330
- var ResearchTargetCountryEnum = z109.enum([
23358
+ var ResearchTargetCountryEnum = z110.enum([
23331
23359
  "CO",
23332
23360
  "MX",
23333
23361
  "PE",
23334
23362
  "EC",
23335
23363
  "CL"
23336
23364
  ]);
23337
- var ResearchCategoryEnum = z109.enum([
23365
+ var ResearchCategoryEnum = z110.enum([
23338
23366
  "auto",
23339
23367
  "automotive",
23340
23368
  "kitchen",
@@ -23464,6 +23492,7 @@ var McpErrorCode = {
23464
23492
  CAMPAIGN_NOT_FOUND: "CAMPAIGN_NOT_FOUND",
23465
23493
  CAMPAIGN_TASK_NOT_FOUND: "CAMPAIGN_TASK_NOT_FOUND",
23466
23494
  CAMPAIGN_MISSING_LANDING_URL: "CAMPAIGN_MISSING_LANDING_URL",
23495
+ CAMPAIGN_MISSING_TARGET_COUNTRY: "CAMPAIGN_MISSING_TARGET_COUNTRY",
23467
23496
  CAMPAIGN_NO_CREATIVES: "CAMPAIGN_NO_CREATIVES",
23468
23497
  CAMPAIGN_MISSING_THUMBNAILS: "CAMPAIGN_MISSING_THUMBNAILS",
23469
23498
  CAMPAIGN_RECONCILIATION_REQUIRED: "CAMPAIGN_RECONCILIATION_REQUIRED",
@@ -23503,6 +23532,7 @@ var McpErrorCode = {
23503
23532
  META_NO_ASSETS_READY: "META_NO_ASSETS_READY",
23504
23533
  META_NO_THUMBNAIL_SOURCE: "META_NO_THUMBNAIL_SOURCE",
23505
23534
  META_NO_LANDING_URL: "META_NO_LANDING_URL",
23535
+ META_NO_TARGET_COUNTRY: "META_NO_TARGET_COUNTRY",
23506
23536
  META_TASK_NOT_FOUND: "META_TASK_NOT_FOUND",
23507
23537
  META_INVALID_DATA: "META_INVALID_DATA",
23508
23538
  META_INVALID_AD_ACCOUNT: "META_INVALID_AD_ACCOUNT",
@@ -23590,7 +23620,8 @@ var CODE_MESSAGES = {
23590
23620
  META_NO_ADS_CREATED: "No ads could be created. Most likely: the Meta Ads account has no payment method, no Facebook Page is linked, or the Facebook app lost permissions. Verify all three at https://business.facebook.com.",
23591
23621
  META_NO_ASSETS_READY: "The task has no videos or ad creative ready to publish yet. Wait for generation to finish or regenerate the assets.",
23592
23622
  META_NO_THUMBNAIL_SOURCE: "No image is available to use as the video thumbnail. Upload a product image or generate the ad creative before publishing.",
23593
- META_NO_LANDING_URL: "Missing landing URL. Pass it in `landingUrl` or publish to Shopify first with `publish_to_shopify`.",
23623
+ META_NO_LANDING_URL: "Missing landing URL. Pass it in `landingUrl`, or publish first: a product to Shopify with `publish_to_shopify`, a service to its service landing.",
23624
+ META_NO_TARGET_COUNTRY: "This service ad has no target country (its brand sets none). Ask the user which country and pass it in `campaignConfig.targetCountries`; never assume one.",
23594
23625
  META_TASK_NOT_FOUND: "Task not found or does not belong to this user. Verify the `taskId`.",
23595
23626
  META_INVALID_DATA: "Meta rejected the request due to invalid data. Verify that `adAccountId` and `pixelId` are correct.",
23596
23627
  META_INVALID_AD_ACCOUNT: "Ad account not found or no access. Confirm the `adAccountId` with `list_meta_ad_accounts`.",
@@ -23629,7 +23660,8 @@ var CODE_MESSAGES = {
23629
23660
  // Campaign (shared)
23630
23661
  CAMPAIGN_NOT_FOUND: "Campaign not found or does not belong to this user. Verify the `campaignId`.",
23631
23662
  CAMPAIGN_TASK_NOT_FOUND: "Campaign task not found. Verify the `taskId`.",
23632
- CAMPAIGN_MISSING_LANDING_URL: "Missing landing URL for the campaign. Publish to Shopify first or pass `landingUrl` explicitly.",
23663
+ CAMPAIGN_MISSING_LANDING_URL: "Missing landing URL for the campaign. Publish first (a product to Shopify, a service to its service landing) or pass `landingUrl` explicitly.",
23664
+ CAMPAIGN_MISSING_TARGET_COUNTRY: "This service ad has no target country (its brand sets none). Ask the user which country and pass it in `campaignConfig.targetCountries`; never assume one.",
23633
23665
  CAMPAIGN_NO_CREATIVES: "The task has no creatives (video/image) ready for the campaign. Wait for generation to finish.",
23634
23666
  CAMPAIGN_MISSING_THUMBNAILS: "Missing thumbnails for the videos. Verify that image/video generation has finished.",
23635
23667
  CAMPAIGN_RECONCILIATION_REQUIRED: "A campaign may already have been created. Do not retry creation; reopen the project and reconcile it or contact support.",
@@ -23721,8 +23753,10 @@ var INVALID_PARAM_CODES = /* @__PURE__ */ new Set([
23721
23753
  McpErrorCode.TIKTOK_ADVERTISER_REQUIRED,
23722
23754
  McpErrorCode.TIKTOK_PIXEL_NOT_FOUND,
23723
23755
  McpErrorCode.CAMPAIGN_MISSING_LANDING_URL,
23756
+ McpErrorCode.CAMPAIGN_MISSING_TARGET_COUNTRY,
23724
23757
  McpErrorCode.CAMPAIGN_RECONCILIATION_REQUIRED,
23725
23758
  McpErrorCode.META_NO_LANDING_URL,
23759
+ McpErrorCode.META_NO_TARGET_COUNTRY,
23726
23760
  McpErrorCode.META_PORTFOLIO_MISMATCH,
23727
23761
  McpErrorCode.META_PAGE_SELECTION_REQUIRED,
23728
23762
  McpErrorCode.META_INVALID_PAGE,
@@ -23833,6 +23867,7 @@ var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
23833
23867
  McpErrorCode.META_NO_ASSETS_READY,
23834
23868
  McpErrorCode.META_NO_THUMBNAIL_SOURCE,
23835
23869
  McpErrorCode.META_NO_LANDING_URL,
23870
+ McpErrorCode.META_NO_TARGET_COUNTRY,
23836
23871
  McpErrorCode.META_TASK_NOT_FOUND,
23837
23872
  McpErrorCode.META_INVALID_DATA,
23838
23873
  McpErrorCode.META_INVALID_AD_ACCOUNT,
@@ -23880,6 +23915,7 @@ var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
23880
23915
  McpErrorCode.CAMPAIGN_NOT_FOUND,
23881
23916
  McpErrorCode.CAMPAIGN_TASK_NOT_FOUND,
23882
23917
  McpErrorCode.CAMPAIGN_MISSING_LANDING_URL,
23918
+ McpErrorCode.CAMPAIGN_MISSING_TARGET_COUNTRY,
23883
23919
  McpErrorCode.CAMPAIGN_NO_CREATIVES,
23884
23920
  McpErrorCode.CAMPAIGN_MISSING_THUMBNAILS,
23885
23921
  McpErrorCode.CAMPAIGN_RECONCILIATION_REQUIRED,
@@ -24699,29 +24735,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
24699
24735
  __name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
24700
24736
 
24701
24737
  // src/tools/media-presentation.ts
24702
- import { z as z110 } from "zod";
24703
- var HttpsPresentationUrlSchema = z110.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
24738
+ import { z as z111 } from "zod";
24739
+ var HttpsPresentationUrlSchema = z111.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
24704
24740
  var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
24705
24741
  const hostname = new URL(value).hostname.toLowerCase();
24706
24742
  return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
24707
24743
  }, "preview URL must be owned by ProductMaker");
24708
- var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z110.number().int().positive().max(maximum), "positiveIntAtMost");
24709
- var PresentationImageSchema = z110.object({
24710
- kind: z110.literal("image"),
24744
+ var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z111.number().int().positive().max(maximum), "positiveIntAtMost");
24745
+ var PresentationImageSchema = z111.object({
24746
+ kind: z111.literal("image"),
24711
24747
  url: HttpsPresentationUrlSchema,
24712
- mimeType: z110.enum([
24748
+ mimeType: z111.enum([
24713
24749
  "image/jpeg",
24714
24750
  "image/png"
24715
24751
  ]),
24716
24752
  byteSize: positiveIntAtMost(5 * 1024 * 1024),
24717
24753
  width: positiveIntAtMost(16384),
24718
24754
  height: positiveIntAtMost(16384),
24719
- alt: z110.string().trim().min(1).max(240)
24755
+ alt: z111.string().trim().min(1).max(240)
24720
24756
  }).strict();
24721
24757
  var McpMediaPresentationSchema = PresentationImageSchema;
24722
- var GalleryImageSchema = z110.object({
24758
+ var GalleryImageSchema = z111.object({
24723
24759
  url: ProductMakerPreviewUrlSchema,
24724
- alt: z110.string().trim().min(1).max(240)
24760
+ alt: z111.string().trim().min(1).max(240)
24725
24761
  });
24726
24762
  var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
24727
24763
  async function imageBlocks(image, transport) {
@@ -24778,12 +24814,12 @@ async function buildMcpMediaPresentationContent(rawPresentation, transport = "ht
24778
24814
  ];
24779
24815
  }
24780
24816
  __name(buildMcpMediaPresentationContent, "buildMcpMediaPresentationContent");
24781
- var OwnedImagePreviewSchema = z110.object({
24817
+ var OwnedImagePreviewSchema = z111.object({
24782
24818
  url: HttpsPresentationUrlSchema.refine((value) => {
24783
24819
  const url = new URL(value);
24784
24820
  return !url.username && !url.password && !isPrivateHost(url.hostname);
24785
24821
  }, "Preview URL must be public HTTPS without credentials"),
24786
- alt: z110.string().trim().min(1).max(240)
24822
+ alt: z111.string().trim().min(1).max(240)
24787
24823
  });
24788
24824
  async function buildMcpImagePreviewContent(rawPreview, transport = "http") {
24789
24825
  const preview2 = OwnedImagePreviewSchema.safeParse(rawPreview);
@@ -24866,7 +24902,7 @@ async function buildMcpImageGalleryContent(rawItems, transport = "http") {
24866
24902
  __name(buildMcpImageGalleryContent, "buildMcpImageGalleryContent");
24867
24903
 
24868
24904
  // src/tools/animated-video.ts
24869
- import { z as z111 } from "zod";
24905
+ import { z as z112 } from "zod";
24870
24906
 
24871
24907
  // src/tools/paid-confirmation.ts
24872
24908
  function describeMarketStudyChoice(enabled) {
@@ -25116,27 +25152,27 @@ function hookVariantsLabel(count) {
25116
25152
  return count === 1 ? "1 versi\xF3n del gancho" : `${count} versiones del gancho`;
25117
25153
  }
25118
25154
  __name(hookVariantsLabel, "hookVariantsLabel");
25119
- var DurationInput = z111.union(MOTION_GRAPHICS_DURATIONS.map((d) => z111.literal(d)));
25120
- var CreateAnimatedVideoInput = z111.object({
25121
- action: z111.enum([
25155
+ var DurationInput = z112.union(MOTION_GRAPHICS_DURATIONS.map((d) => z112.literal(d)));
25156
+ var CreateAnimatedVideoInput = z112.object({
25157
+ action: z112.enum([
25122
25158
  "prepare",
25123
25159
  "status",
25124
25160
  "cancel",
25125
25161
  "generate"
25126
25162
  ]).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."),
25127
- websiteCaptureId: z111.string().uuid().optional().describe("ID de la captura preparada. Obligatorio para status/cancel/generate; no inventarlo."),
25128
- generationRequestId: z111.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."),
25129
- confirmed: z111.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."),
25163
+ websiteCaptureId: z112.string().uuid().optional().describe("ID de la captura preparada. Obligatorio para status/cancel/generate; no inventarlo."),
25164
+ generationRequestId: z112.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."),
25165
+ confirmed: z112.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."),
25130
25166
  // Plain text, not `.url()`: users type «cal.com», and the web accepts it.
25131
25167
  // normalizeWebAddress (shared with the web) adds https:// and refuses
25132
25168
  // anything that is not a public http(s) address.
25133
- landingUrl: z111.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."),
25169
+ landingUrl: z112.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."),
25134
25170
  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.'),
25135
25171
  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.`),
25136
25172
  language: MotionGraphicsLanguageSchema.optional().describe('Idioma de los textos del video: "es", "en" o "pt".'),
25137
- notes: z111.string().trim().max(MOTION_GRAPHICS_NOTES_MAX_CHARS).optional().describe("Opcional. Indicaciones para el video en lenguaje natural (ej. enf\xF3cate en los precios, tono m\xE1s formal, menciona la prueba gratis)."),
25173
+ notes: z112.string().trim().max(MOTION_GRAPHICS_NOTES_MAX_CHARS).optional().describe("Opcional. Indicaciones para el video en lenguaje natural (ej. enf\xF3cate en los precios, tono m\xE1s formal, menciona la prueba gratis)."),
25138
25174
  hookVariants: MotionGraphicsHookVariantsSchema.optional().describe(`Opcional. Versiones del gancho: el mismo video con distintas aperturas para probar cu\xE1l funciona mejor, de 1 a ${MOTION_GRAPHICS_HOOK_VARIANTS_MAX} (por defecto 1). Cada versi\xF3n extra tiene precio (ver la descripci\xF3n de la herramienta); \xFAsalo solo si el usuario lo pide.`),
25139
- music: z111.boolean().optional().describe("Opcional. M\xFAsica de fondo (por defecto true). false hace el video sin m\xFAsica, m\xE1s crudo, estilo UGC: quedan la voz y los efectos de sonido. Mismo precio. \xDAsalo solo si el usuario lo pide.")
25175
+ music: z112.boolean().optional().describe("Opcional. M\xFAsica de fondo (por defecto true). false hace el video sin m\xFAsica, m\xE1s crudo, estilo UGC: quedan la voz y los efectos de sonido. Mismo precio. \xDAsalo solo si el usuario lo pide.")
25140
25176
  }).strict();
25141
25177
  function captureNextAction(capture) {
25142
25178
  if (capture.status === "ready") return "Muestra la vista previa al usuario y confirma formato, duraci\xF3n, idioma y precio. Solo despu\xE9s llama create_animated_video con action=generate, este websiteCaptureId y confirmed=true.";
@@ -25169,43 +25205,43 @@ var FORMAT_LABELS = {
25169
25205
  square: "cuadrado 1:1",
25170
25206
  horizontal: "horizontal 16:9"
25171
25207
  };
25172
- var AnimatedVideoResultSchema = z111.object({
25173
- status: z111.enum([
25208
+ var AnimatedVideoResultSchema = z112.object({
25209
+ status: z112.enum([
25174
25210
  "pending",
25175
25211
  "done",
25176
25212
  "error"
25177
25213
  ]),
25178
- serviceMode: z111.literal("motion_graphics"),
25179
- finalMp4Url: z111.string().optional(),
25180
- error: z111.string().optional(),
25181
- motionGraphics: z111.object({
25214
+ serviceMode: z112.literal("motion_graphics"),
25215
+ finalMp4Url: z112.string().optional(),
25216
+ error: z112.string().optional(),
25217
+ motionGraphics: z112.object({
25182
25218
  stage: MotionGraphicsStageSchema,
25183
25219
  format: MotionGraphicsFormatSchema,
25184
- durationSec: z111.number(),
25185
- width: z111.number().optional(),
25186
- height: z111.number().optional(),
25220
+ durationSec: z112.number(),
25221
+ width: z112.number().optional(),
25222
+ height: z112.number().optional(),
25187
25223
  language: MotionGraphicsLanguageSchema.optional(),
25188
- queuedAt: z111.string().optional(),
25189
- jobsAhead: z111.number().int().nonnegative().optional(),
25190
- stageStartedAt: z111.string().optional(),
25191
- renderProgress: z111.number().optional(),
25224
+ queuedAt: z112.string().optional(),
25225
+ jobsAhead: z112.number().int().nonnegative().optional(),
25226
+ stageStartedAt: z112.string().optional(),
25227
+ renderProgress: z112.number().optional(),
25192
25228
  // AI clip fields (absent on a video paid before clips, or from an API
25193
25229
  // that predates them). Lenient: an unreadable value is dropped
25194
25230
  // instead of hiding the status.
25195
- clipCount: z111.number().int().nonnegative().optional().catch(void 0),
25196
- clipsUsed: z111.number().int().nonnegative().optional().catch(void 0),
25197
- clipPriceCents: z111.number().finite().nonnegative().optional().catch(void 0),
25198
- clipsRefunded: z111.number().int().nonnegative().optional().catch(void 0),
25231
+ clipCount: z112.number().int().nonnegative().optional().catch(void 0),
25232
+ clipsUsed: z112.number().int().nonnegative().optional().catch(void 0),
25233
+ clipPriceCents: z112.number().finite().nonnegative().optional().catch(void 0),
25234
+ clipsRefunded: z112.number().int().nonnegative().optional().catch(void 0),
25199
25235
  // Hook versions (absent from an API or a video before them): the
25200
25236
  // count ordered and, once done, the signed URLs of the EXTRA versions
25201
25237
  // (hook 2, hook 3); `finalMp4Url` is hook 1.
25202
- hookVariants: z111.number().int().min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).optional().catch(void 0),
25203
- variantUrls: z111.array(z111.string().min(1)).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
25238
+ hookVariants: z112.number().int().min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).optional().catch(void 0),
25239
+ variantUrls: z112.array(z112.string().min(1)).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
25204
25240
  // Extra hook versions given back, as the task recorded it once the
25205
25241
  // refunds landed (absent until then, and from an API before it).
25206
- variantsRefunded: z111.number().int().nonnegative().optional().catch(void 0),
25207
- activity: z111.array(MotionGraphicsActivitySchema).optional().catch(void 0),
25208
- previewUrl: z111.string().optional()
25242
+ variantsRefunded: z112.number().int().nonnegative().optional().catch(void 0),
25243
+ activity: z112.array(MotionGraphicsActivitySchema).optional().catch(void 0),
25244
+ previewUrl: z112.string().optional()
25209
25245
  }).passthrough()
25210
25246
  }).passthrough();
25211
25247
  function parseAnimatedVideoResult(value) {
@@ -25461,10 +25497,10 @@ function registerAnimatedVideoTools(server, api) {
25461
25497
  __name(registerAnimatedVideoTools, "registerAnimatedVideoTools");
25462
25498
 
25463
25499
  // src/tools/winning-product-image.ts
25464
- import { z as z112 } from "zod";
25465
- var WinnerReferenceInput = z112.object({
25466
- runId: z112.string().uuid(),
25467
- candidateSourceId: z112.string().trim().min(1).max(160)
25500
+ import { z as z113 } from "zod";
25501
+ var WinnerReferenceInput = z113.object({
25502
+ runId: z113.string().uuid(),
25503
+ candidateSourceId: z113.string().trim().min(1).max(160)
25468
25504
  }).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
25469
25505
  async function resolveWinnerImages(api, winnerReference, images) {
25470
25506
  if (!winnerReference) return images;
@@ -25501,62 +25537,62 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
25501
25537
  var CREATE_SERVICE_VIDEO_ON_MCP = PRODUCTMAKER_MCP_CAPABILITY_NAMES.includes("create_service_video");
25502
25538
  var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
25503
25539
  var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
25504
- var CreateProductTaskInput = z113.object({
25540
+ var CreateProductTaskInput = z114.object({
25505
25541
  images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
25506
25542
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
25507
- projectId: z113.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
25508
- productUrl: z113.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."),
25543
+ projectId: z114.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
25544
+ productUrl: z114.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."),
25509
25545
  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.'),
25510
25546
  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.'),
25511
- price: z113.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.'),
25512
- compareAtPrice: z113.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".'),
25513
- offer: z113.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.'),
25514
- paymentMethods: z113.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.'),
25515
- productContext: z113.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."),
25516
- productLabel: z113.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.'),
25547
+ price: z114.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.'),
25548
+ compareAtPrice: z114.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".'),
25549
+ offer: z114.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.'),
25550
+ paymentMethods: z114.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.'),
25551
+ productContext: z114.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."),
25552
+ productLabel: z114.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.'),
25517
25553
  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.'),
25518
25554
  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.'),
25519
- durationSeconds: z113.union([
25520
- z113.literal(15),
25521
- z113.literal(30)
25555
+ durationSeconds: z114.union([
25556
+ z114.literal(15),
25557
+ z114.literal(30)
25522
25558
  ]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
25523
- pauseForAngleReview: z113.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."),
25524
- aiDecidesAll: z113.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."),
25559
+ pauseForAngleReview: z114.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."),
25560
+ aiDecidesAll: z114.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."),
25525
25561
  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.'),
25526
25562
  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.'),
25527
25563
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
25528
25564
  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).'),
25529
- videoAngleCount: z113.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."),
25565
+ videoAngleCount: z114.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."),
25530
25566
  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.'),
25531
- outputs: z113.array(z113.enum([
25567
+ outputs: z114.array(z114.enum([
25532
25568
  "landing",
25533
25569
  "video",
25534
25570
  "image"
25535
25571
  ])).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}`),
25536
- includeInitialLandingGif: z113.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."),
25537
- competitorScanEnabled: z113.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."),
25572
+ includeInitialLandingGif: z114.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."),
25573
+ competitorScanEnabled: z114.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."),
25538
25574
  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.'),
25539
- replicateWinnerWhenFound: z113.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."),
25540
- brandId: z113.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."),
25541
- actorId: z113.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."),
25575
+ replicateWinnerWhenFound: z114.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."),
25576
+ brandId: z114.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."),
25577
+ actorId: z114.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."),
25542
25578
  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.'),
25543
- creativeDirection: z113.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.'),
25544
- headline: z113.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."),
25545
- subheadline: z113.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."),
25579
+ creativeDirection: z114.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.'),
25580
+ headline: z114.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."),
25581
+ subheadline: z114.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."),
25546
25582
  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".'),
25547
25583
  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".')
25548
25584
  }).strict();
25549
- var CreateServiceVideoInput = z113.object({
25550
- landingUrl: z113.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
25551
- additionalContext: z113.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
25585
+ var CreateServiceVideoInput = z114.object({
25586
+ landingUrl: z114.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
25587
+ additionalContext: z114.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
25552
25588
  language: Lang.describe("Idioma del video: es, en o pt."),
25553
- voiceId: z113.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.'),
25554
- brandId: z113.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
25555
- reviewMode: z113.enum([
25589
+ voiceId: z114.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.'),
25590
+ brandId: z114.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
25591
+ reviewMode: z114.enum([
25556
25592
  "automatic",
25557
25593
  "guided"
25558
25594
  ]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
25559
- videoPreset: z113.enum([
25595
+ videoPreset: z114.enum([
25560
25596
  "auto",
25561
25597
  "ugc_dynamic",
25562
25598
  "ugc_how_to",
@@ -25566,128 +25602,128 @@ var CreateServiceVideoInput = z113.object({
25566
25602
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
25567
25603
  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.')
25568
25604
  }).strict();
25569
- var GetTaskStatusInput = z113.object({
25570
- taskId: z113.string().min(1),
25571
- waitSeconds: z113.number().int().min(0).max(120).optional()
25605
+ var GetTaskStatusInput = z114.object({
25606
+ taskId: z114.string().min(1),
25607
+ waitSeconds: z114.number().int().min(0).max(120).optional()
25572
25608
  });
25573
- var ListTasksInput = z113.object({
25574
- limit: z113.number().int().min(1).max(50).optional(),
25575
- offset: z113.number().int().min(0).optional(),
25576
- search: z113.string().optional()
25609
+ var ListTasksInput = z114.object({
25610
+ limit: z114.number().int().min(1).max(50).optional(),
25611
+ offset: z114.number().int().min(0).optional(),
25612
+ search: z114.string().optional()
25577
25613
  });
25578
25614
  var MCP_REVIEW_LIST_FIELD_MAX = IMAGE_WIZARD_LIST_FIELD_MAX;
25579
25615
  var MCP_REVIEW_FEATURE_ITEM_MAX = IMAGE_FEATURE_ITEM_MAX;
25580
- var EditTaskDraftInput = z113.object({
25581
- taskId: z113.string().min(1),
25582
- angleIndex: z113.number().int().min(0),
25583
- angle: z113.object({
25584
- angle: z113.string().min(1).max(480),
25585
- buyerPersona: z113.string().min(1).max(360),
25586
- actor: z113.string().min(1).max(360).optional(),
25587
- actorId: z113.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."),
25588
- gender: z113.enum([
25616
+ var EditTaskDraftInput = z114.object({
25617
+ taskId: z114.string().min(1),
25618
+ angleIndex: z114.number().int().min(0),
25619
+ angle: z114.object({
25620
+ angle: z114.string().min(1).max(480),
25621
+ buyerPersona: z114.string().min(1).max(360),
25622
+ actor: z114.string().min(1).max(360).optional(),
25623
+ actorId: z114.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."),
25624
+ gender: z114.enum([
25589
25625
  "female",
25590
25626
  "male"
25591
25627
  ]).optional(),
25592
- scriptNotes: z113.string().max(2e3).optional()
25628
+ scriptNotes: z114.string().max(2e3).optional()
25593
25629
  })
25594
25630
  });
25595
- var PendingActionPayload = z113.discriminatedUnion("kind", [
25596
- z113.object({
25597
- kind: z113.literal("product_reference_set_approval"),
25631
+ var PendingActionPayload = z114.discriminatedUnion("kind", [
25632
+ z114.object({
25633
+ kind: z114.literal("product_reference_set_approval"),
25598
25634
  scope: ProductReferenceScopeEnum.optional(),
25599
- scopeKey: z113.string().min(1).max(120).optional(),
25600
- scopeSnapshotId: z113.string().uuid().optional(),
25601
- expectedScopeHash: z113.string().min(1).max(128).optional(),
25635
+ scopeKey: z114.string().min(1).max(120).optional(),
25636
+ scopeSnapshotId: z114.string().uuid().optional(),
25637
+ expectedScopeHash: z114.string().min(1).max(128).optional(),
25602
25638
  decision: ProductReferenceResolutionDecisionEnum,
25603
25639
  reason: ProductReferenceRejectionReasonEnum.optional(),
25604
- affectedRefKeys: z113.array(z113.string().min(1).max(200)).min(1).optional(),
25605
- affectedPhotoNumbers: z113.array(z113.number().int().positive()).min(1).optional(),
25606
- recoveryAction: z113.enum([
25640
+ affectedRefKeys: z114.array(z114.string().min(1).max(200)).min(1).optional(),
25641
+ affectedPhotoNumbers: z114.array(z114.number().int().positive()).min(1).optional(),
25642
+ recoveryAction: z114.enum([
25607
25643
  "remove",
25608
25644
  "replace",
25609
25645
  "upload",
25610
25646
  "return_to_selection"
25611
25647
  ]).optional()
25612
25648
  }),
25613
- z113.object({
25614
- kind: z113.literal("product_reference_confirmation"),
25615
- selectedPhotoNumbers: z113.array(z113.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."),
25649
+ z114.object({
25650
+ kind: z114.literal("product_reference_confirmation"),
25651
+ selectedPhotoNumbers: z114.array(z114.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."),
25616
25652
  userChoice: ProductReferenceUserChoiceEnum.optional(),
25617
- confirmedProductNames: z113.array(z113.string().min(1).max(120)).min(2).max(8).optional(),
25653
+ confirmedProductNames: z114.array(z114.string().min(1).max(120)).min(2).max(8).optional(),
25618
25654
  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."),
25619
25655
  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."),
25620
- useMultiSceneShowcase: z113.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
25656
+ useMultiSceneShowcase: z114.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
25621
25657
  }),
25622
- z113.object({
25623
- kind: z113.literal("angle_review_approval"),
25658
+ z114.object({
25659
+ kind: z114.literal("angle_review_approval"),
25624
25660
  // All edits are optional — empty action body just approves the
25625
25661
  // backend-generated draft as-is. Field shapes mirror the angle-review
25626
25662
  // request contracts in @packages/types/wizard.ts; the handler routes to
25627
25663
  // the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
25628
- customAngle: z113.string().min(1).max(480).optional(),
25664
+ customAngle: z114.string().min(1).max(480).optional(),
25629
25665
  // Keep the shared MCP action within the strictest downstream contract:
25630
25666
  // autopilot/image resume endpoints cap these fields at 1500 characters.
25631
- painPoints: z113.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
25632
- benefits: z113.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
25667
+ painPoints: z114.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
25668
+ benefits: z114.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
25633
25669
  // Same policy as the two fields above: the strictest downstream contract
25634
25670
  // wins. The image endpoint caps each feature at 240 while landing/video
25635
25671
  // accept 300, and this single action routes to whichever the task is — so
25636
25672
  // accepting 300 here turns a 250-character feature on an image task into
25637
25673
  // an opaque HTTP 400 after the model already believed it had been saved.
25638
- features: z113.array(z113.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
25639
- buyerPersona: z113.string().min(1).max(360).optional(),
25674
+ features: z114.array(z114.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
25675
+ buyerPersona: z114.string().min(1).max(360).optional(),
25640
25676
  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.'),
25641
- actor: z113.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."),
25642
- actorId: z113.string().max(120).nullable().optional(),
25643
- creativeDirection: z113.string().max(2e3).optional(),
25644
- selectedAngleNumbers: z113.array(z113.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."),
25645
- angleEdits: z113.array(z113.object({
25646
- angleNumber: z113.number().int().positive(),
25647
- narrativeSelection: z113.enum([
25677
+ actor: z114.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."),
25678
+ actorId: z114.string().max(120).nullable().optional(),
25679
+ creativeDirection: z114.string().max(2e3).optional(),
25680
+ selectedAngleNumbers: z114.array(z114.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."),
25681
+ angleEdits: z114.array(z114.object({
25682
+ angleNumber: z114.number().int().positive(),
25683
+ narrativeSelection: z114.enum([
25648
25684
  "market",
25649
25685
  "guided"
25650
25686
  ]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
25651
- angle: z113.string().min(1).max(480).optional(),
25652
- buyerPersona: z113.string().min(1).max(360).optional(),
25687
+ angle: z114.string().min(1).max(480).optional(),
25688
+ buyerPersona: z114.string().min(1).max(360).optional(),
25653
25689
  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.'),
25654
- actor: z113.string().min(1).max(360).optional(),
25655
- actorId: z113.string().max(120).nullable().optional(),
25656
- creativeDirection: z113.string().max(2e3).optional()
25690
+ actor: z114.string().min(1).max(360).optional(),
25691
+ actorId: z114.string().max(120).nullable().optional(),
25692
+ creativeDirection: z114.string().max(2e3).optional()
25657
25693
  }).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)."),
25658
- gapDurationSeconds: z113.union([
25659
- z113.literal(15),
25660
- z113.literal(30)
25694
+ gapDurationSeconds: z114.union([
25695
+ z114.literal(15),
25696
+ z114.literal(30)
25661
25697
  ]).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.")
25662
25698
  }),
25663
- z113.object({
25664
- kind: z113.literal("service_angle_approval"),
25665
- angleId: z113.string().uuid().optional(),
25666
- angleNumber: z113.number().int().positive().optional(),
25667
- content: z113.string().min(1).max(480).optional(),
25668
- creativeDirection: z113.string().min(1).max(1500).optional(),
25669
- actor: z113.string().min(1).max(360).optional()
25699
+ z114.object({
25700
+ kind: z114.literal("service_angle_approval"),
25701
+ angleId: z114.string().uuid().optional(),
25702
+ angleNumber: z114.number().int().positive().optional(),
25703
+ content: z114.string().min(1).max(480).optional(),
25704
+ creativeDirection: z114.string().min(1).max(1500).optional(),
25705
+ actor: z114.string().min(1).max(360).optional()
25670
25706
  }),
25671
- z113.object({
25672
- kind: z113.literal("service_script_approval"),
25673
- voiceovers: z113.record(z113.string(), z113.string().min(1).max(600)).optional(),
25674
- visualDirections: z113.record(z113.string(), z113.string().min(1).max(1200)).optional(),
25675
- voiceoversByScene: z113.record(z113.string(), z113.string().min(1).max(600)).optional(),
25676
- visualDirectionsByScene: z113.record(z113.string(), z113.string().min(1).max(1200)).optional()
25707
+ z114.object({
25708
+ kind: z114.literal("service_script_approval"),
25709
+ voiceovers: z114.record(z114.string(), z114.string().min(1).max(600)).optional(),
25710
+ visualDirections: z114.record(z114.string(), z114.string().min(1).max(1200)).optional(),
25711
+ voiceoversByScene: z114.record(z114.string(), z114.string().min(1).max(600)).optional(),
25712
+ visualDirectionsByScene: z114.record(z114.string(), z114.string().min(1).max(1200)).optional()
25677
25713
  })
25678
25714
  ]);
25679
- var ResolvePendingActionInput = z113.object({
25680
- taskId: z113.string().min(1),
25715
+ var ResolvePendingActionInput = z114.object({
25716
+ taskId: z114.string().min(1),
25681
25717
  action: PendingActionPayload
25682
25718
  }).strict();
25683
25719
  function resolveVariantConfirmVideoTier(action) {
25684
25720
  return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
25685
25721
  }
25686
25722
  __name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
25687
- var StatusForResolveSchema = z113.object({
25723
+ var StatusForResolveSchema = z114.object({
25688
25724
  // Metadata used to select the backend resume contract. Older API responses
25689
25725
  // may omit these fields, so the resolver keeps the generic fallback.
25690
- kind: z113.enum([
25726
+ kind: z114.enum([
25691
25727
  "autopilot",
25692
25728
  "video",
25693
25729
  "image",
@@ -25695,18 +25731,18 @@ var StatusForResolveSchema = z113.object({
25695
25731
  "mix",
25696
25732
  "service"
25697
25733
  ]).optional(),
25698
- selectedOutputs: z113.array(z113.enum([
25734
+ selectedOutputs: z114.array(z114.enum([
25699
25735
  "landing",
25700
25736
  "video",
25701
25737
  "image"
25702
25738
  ])).optional(),
25703
- videoAngleCount: z113.number().int().min(1).max(3).optional(),
25704
- ugcFormat: z113.enum([
25739
+ videoAngleCount: z114.number().int().min(1).max(3).optional(),
25740
+ ugcFormat: z114.enum([
25705
25741
  "single_8s",
25706
25742
  "single_15s",
25707
25743
  "double_30s"
25708
25744
  ]).optional(),
25709
- videoStyle: z113.enum([
25745
+ videoStyle: z114.enum([
25710
25746
  "ugc",
25711
25747
  "cartoon_3d",
25712
25748
  "product_only",
@@ -25716,13 +25752,13 @@ var StatusForResolveSchema = z113.object({
25716
25752
  videoQuality: VideoQualityEnum.optional(),
25717
25753
  videoRouteId: VideoRouteIdEnum.optional(),
25718
25754
  videoModel: TaskVideoModelEnum.optional(),
25719
- videoTier: z113.enum([
25755
+ videoTier: z114.enum([
25720
25756
  "legacy",
25721
25757
  "standard",
25722
25758
  "pro",
25723
25759
  "single_call"
25724
25760
  ]).optional(),
25725
- videoResolution: z113.enum([
25761
+ videoResolution: z114.enum([
25726
25762
  "480p",
25727
25763
  "720p"
25728
25764
  ]).optional(),
@@ -25730,60 +25766,60 @@ var StatusForResolveSchema = z113.object({
25730
25766
  // A task created before a narrative was blocked/hidden must still parse,
25731
25767
  // or resolve_pending_action could never approve it.
25732
25768
  narrativeStyle: NarrativeStyle.optional(),
25733
- pauseForVideoScriptReview: z113.boolean().optional(),
25734
- pendingUserAction: z113.object({
25735
- kind: z113.string(),
25736
- candidateGrouping: z113.string().optional(),
25737
- selectedImageUrls: z113.array(z113.string()).optional(),
25738
- proposedProductNames: z113.array(z113.string()).optional(),
25769
+ pauseForVideoScriptReview: z114.boolean().optional(),
25770
+ pendingUserAction: z114.object({
25771
+ kind: z114.string(),
25772
+ candidateGrouping: z114.string().optional(),
25773
+ selectedImageUrls: z114.array(z114.string()).optional(),
25774
+ proposedProductNames: z114.array(z114.string()).optional(),
25739
25775
  // Adaptive reference questions are server-owned. Echo only the evidence
25740
25776
  // identity and the choices shown by the current snapshot; never accept a
25741
25777
  // client-supplied reference set as authorization.
25742
- options: z113.array(ProductReferenceUserChoiceEnum).max(4).optional(),
25743
- mode: z113.enum([
25778
+ options: z114.array(ProductReferenceUserChoiceEnum).max(4).optional(),
25779
+ mode: z114.enum([
25744
25780
  "question",
25745
25781
  "visual_recovery"
25746
25782
  ]).optional(),
25747
25783
  /** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
25748
- canKeepSelection: z113.boolean().optional(),
25749
- decisionKey: z113.string().optional(),
25750
- questionOrdinal: z113.number().int().min(1).max(5).optional(),
25751
- questionCeiling: z113.union([
25752
- z113.literal(3),
25753
- z113.literal(5)
25784
+ canKeepSelection: z114.boolean().optional(),
25785
+ decisionKey: z114.string().optional(),
25786
+ questionOrdinal: z114.number().int().min(1).max(5).optional(),
25787
+ questionCeiling: z114.union([
25788
+ z114.literal(3),
25789
+ z114.literal(5)
25754
25790
  ]).optional(),
25755
- referenceEvidenceVersion: z113.number().int().positive().optional(),
25756
- expectedEvidenceHash: z113.string().optional(),
25757
- question: z113.object({
25758
- prompt: z113.string().min(1).max(240),
25759
- helpText: z113.string().min(1).max(300).optional(),
25760
- options: z113.array(z113.object({
25791
+ referenceEvidenceVersion: z114.number().int().positive().optional(),
25792
+ expectedEvidenceHash: z114.string().optional(),
25793
+ question: z114.object({
25794
+ prompt: z114.string().min(1).max(240),
25795
+ helpText: z114.string().min(1).max(300).optional(),
25796
+ options: z114.array(z114.object({
25761
25797
  value: ProductReferenceUserChoiceEnum,
25762
- label: z113.string().min(1).max(120),
25763
- description: z113.string().min(1).max(240).optional()
25798
+ label: z114.string().min(1).max(120),
25799
+ description: z114.string().min(1).max(240).optional()
25764
25800
  })).min(2).max(4)
25765
25801
  }).optional(),
25766
25802
  scope: ProductReferenceScopeEnum.optional(),
25767
- scopeKey: z113.string().optional(),
25768
- scopeSnapshotId: z113.string().uuid().optional(),
25769
- scopeHash: z113.string().optional(),
25770
- baseReferenceSetHash: z113.string().optional(),
25771
- phase: z113.enum([
25803
+ scopeKey: z114.string().optional(),
25804
+ scopeSnapshotId: z114.string().uuid().optional(),
25805
+ scopeHash: z114.string().optional(),
25806
+ baseReferenceSetHash: z114.string().optional(),
25807
+ phase: z114.enum([
25772
25808
  "preparation",
25773
25809
  "final"
25774
25810
  ]).optional(),
25775
- selectedRefKeys: z113.array(z113.string().min(1).max(200)).optional(),
25776
- allowedDecisions: z113.array(ProductReferenceResolutionDecisionEnum).optional(),
25777
- previews: z113.array(z113.object({
25778
- refKey: z113.string().min(1).max(200)
25811
+ selectedRefKeys: z114.array(z114.string().min(1).max(200)).optional(),
25812
+ allowedDecisions: z114.array(ProductReferenceResolutionDecisionEnum).optional(),
25813
+ previews: z114.array(z114.object({
25814
+ refKey: z114.string().min(1).max(200)
25779
25815
  }).passthrough()).optional(),
25780
- customAngleDraft: z113.string().optional(),
25781
- painPointsDraft: z113.string().optional(),
25782
- benefitsDraft: z113.string().optional(),
25783
- featuresDraft: z113.array(z113.string()).optional(),
25784
- angleOptions: z113.array(z113.object({
25785
- index: z113.number().int().nonnegative(),
25786
- angle: z113.string().min(1)
25816
+ customAngleDraft: z114.string().optional(),
25817
+ painPointsDraft: z114.string().optional(),
25818
+ benefitsDraft: z114.string().optional(),
25819
+ featuresDraft: z114.array(z114.string()).optional(),
25820
+ angleOptions: z114.array(z114.object({
25821
+ index: z114.number().int().nonnegative(),
25822
+ angle: z114.string().min(1)
25787
25823
  }).passthrough()).min(1).max(5).optional(),
25788
25824
  // Recommendation consumed only when the caller explicitly sends
25789
25825
  // gapDurationSeconds: 30 in the angle approval action.
@@ -25793,17 +25829,17 @@ var StatusForResolveSchema = z113.object({
25793
25829
  // keys. `actorId` (the saved custom actor the picker stored) was silently
25794
25830
  // dropped here, so the approval handler below could not echo it back on the
25795
25831
  // PATCH — the selection looked accepted and reached no render.
25796
- angles: z113.array(z113.object({
25797
- id: z113.string().uuid(),
25798
- content: z113.string(),
25799
- creativeDirection: z113.string(),
25800
- actor: z113.string(),
25801
- actorId: z113.string().nullable().optional()
25832
+ angles: z114.array(z114.object({
25833
+ id: z114.string().uuid(),
25834
+ content: z114.string(),
25835
+ creativeDirection: z114.string(),
25836
+ actor: z114.string(),
25837
+ actorId: z114.string().nullable().optional()
25802
25838
  }).passthrough()).optional(),
25803
- panels: z113.array(z113.object({
25804
- beatId: z113.string(),
25805
- voiceover: z113.string(),
25806
- visualDirection: z113.string()
25839
+ panels: z114.array(z114.object({
25840
+ beatId: z114.string(),
25841
+ voiceover: z114.string(),
25842
+ visualDirection: z114.string()
25807
25843
  }).passthrough()).optional()
25808
25844
  }).optional()
25809
25845
  }).passthrough();
@@ -26155,8 +26191,8 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
26155
26191
  server.registerTool("verify_landing_commerce", {
26156
26192
  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.",
26157
26193
  inputSchema: {
26158
- taskId: z113.string().uuid(),
26159
- editId: z113.string().uuid()
26194
+ taskId: z114.string().uuid(),
26195
+ editId: z114.string().uuid()
26160
26196
  },
26161
26197
  annotations: OVERWRITES_EXTERNAL
26162
26198
  }, async (input) => {
@@ -26802,25 +26838,25 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
26802
26838
  __name(registerTaskTools, "registerTaskTools");
26803
26839
 
26804
26840
  // src/tools/brands.ts
26805
- import { z as z114 } from "zod";
26841
+ import { z as z115 } from "zod";
26806
26842
  var guidance2 = getProductMakerCapabilityModelGuidance("create_brand");
26807
26843
  var BRAND_START_REPLAY_WINDOW_MS = 15 * 60 * 1e3;
26808
26844
  var BRAND_NOTES_MAX_CHARS = 2e4;
26809
- var CreateBrandInput = z114.object({
26810
- action: z114.enum([
26845
+ var CreateBrandInput = z115.object({
26846
+ action: z115.enum([
26811
26847
  "start",
26812
26848
  "status",
26813
26849
  "list"
26814
26850
  ]).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."),
26815
- sourceUrl: z114.string().trim().min(1).max(500).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."),
26816
- businessNotes: z114.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."),
26817
- language: z114.enum([
26851
+ sourceUrl: z115.string().trim().min(1).max(500).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."),
26852
+ businessNotes: z115.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."),
26853
+ language: z115.enum([
26818
26854
  "es",
26819
26855
  "en",
26820
26856
  "pt"
26821
26857
  ]).optional().describe("Idioma de la conversaci\xF3n. Solo se usa si la p\xE1gina del negocio no deja claro su idioma."),
26822
- confirmed: z114.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, start solo cotiza y no cobra."),
26823
- brandId: z114.string().uuid().optional().describe("ID de la marca. Obligatorio para status; no lo inventes.")
26858
+ confirmed: z115.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, start solo cotiza y no cobra."),
26859
+ brandId: z115.string().uuid().optional().describe("ID de la marca. Obligatorio para status; no lo inventes.")
26824
26860
  }).strict();
26825
26861
  function normalizeBrandSourceUrl(raw) {
26826
26862
  const value = raw.trim();
@@ -27060,24 +27096,24 @@ __name(registerBrandTools, "registerBrandTools");
27060
27096
 
27061
27097
  // src/tools/service-landing.ts
27062
27098
  import { createHash as createHash3 } from "crypto";
27063
- import { z as z115 } from "zod";
27099
+ import { z as z116 } from "zod";
27064
27100
  var guidance3 = getProductMakerCapabilityModelGuidance("create_service_landing");
27065
27101
  var SERVICE_LANDING_KEY_NAMESPACE = "6f1d8c2a-3b4e-5f60-8a7b-9c0d1e2f3a4b";
27066
27102
  var SERVICE_LANDING_INFO_MAX_CHARS = 2e4;
27067
- var CreateServiceLandingInput = z115.object({
27068
- action: z115.enum([
27103
+ var CreateServiceLandingInput = z116.object({
27104
+ action: z116.enum([
27069
27105
  "prepare",
27070
27106
  "build",
27071
27107
  "status",
27072
27108
  "publish"
27073
27109
  ]).default("prepare").describe("prepare (gratis) crea o retoma la landing de la marca y da el precio; build (pagado, confirmed=true) lee los datos del negocio y luego crea la p\xE1gina; status sigue el avance; publish la publica y devuelve su enlace."),
27074
- brandId: z115.string().uuid().optional().describe("ID de la marca (de create_brand). Obligatorio para prepare. Nunca un taskId de producto."),
27075
- servicePageId: z115.string().uuid().optional().describe("ID de la landing que devolvi\xF3 prepare. Obligatorio para build, status y publish."),
27076
- businessInfo: z115.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."),
27077
- confirmed: z115.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio total y que el usuario acepte. Obligatorio para build."),
27078
- maxCredits: z115.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."),
27079
- operationId: z115.string().uuid().optional().describe("Opcional en status: la operaci\xF3n que devolvi\xF3 build."),
27080
- slug: z115.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.")
27110
+ brandId: z116.string().uuid().optional().describe("ID de la marca (de create_brand). Obligatorio para prepare. Nunca un taskId de producto."),
27111
+ servicePageId: z116.string().uuid().optional().describe("ID de la landing que devolvi\xF3 prepare. Obligatorio para build, status y publish."),
27112
+ businessInfo: z116.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."),
27113
+ confirmed: z116.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio total y que el usuario acepte. Obligatorio para build."),
27114
+ maxCredits: z116.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."),
27115
+ operationId: z116.string().uuid().optional().describe("Opcional en status: la operaci\xF3n que devolvi\xF3 build."),
27116
+ slug: z116.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.")
27081
27117
  }).strict();
27082
27118
  var SERVICE_LANDING_MAX_BUILD_ATTEMPTS = 10;
27083
27119
  function serviceKey(...parts) {
@@ -27410,7 +27446,7 @@ function registerServiceLandingTools(server, api) {
27410
27446
  __name(registerServiceLandingTools, "registerServiceLandingTools");
27411
27447
 
27412
27448
  // src/tools/service-images.ts
27413
- import { z as z116 } from "zod";
27449
+ import { z as z117 } from "zod";
27414
27450
  var guidance4 = getProductMakerCapabilityModelGuidance("create_service_images");
27415
27451
  var SERVICE_IMAGE_FORMATS = [
27416
27452
  "4:5",
@@ -27423,23 +27459,23 @@ var LANGUAGE_TAGS = {
27423
27459
  en: "en-US",
27424
27460
  pt: "pt-BR"
27425
27461
  };
27426
- var CreateServiceImagesInput = z116.object({
27427
- brandId: z116.string().uuid().optional().describe("ID de la marca (de create_brand). Recomendado: da nombre, colores, tono y servicios. Nunca un taskId de producto."),
27428
- instruction: z116.string().trim().max(4e3).optional().describe("Qu\xE9 servicio o promoci\xF3n mostrar, con las palabras del usuario (ej. \xABcorte + barba a $35.000 los martes\xBB). Si el usuario deja que la IA decida, om\xEDtelo y usa delegateToAi=true."),
27429
- delegateToAi: z116.boolean().optional().describe("true si el usuario prefiere que la IA elija qu\xE9 mostrar a partir de su marca."),
27430
- format: z116.enum(SERVICE_IMAGE_FORMATS).optional().describe('Formato: "4:5" (feed, por defecto), "9:16" (historias/reels) o "1:1" (cuadrado).'),
27431
- count: z116.number().int().min(1).max(SERVICE_IMAGE_MAX_COUNT).optional().describe("Cu\xE1ntas im\xE1genes, de 1 a 3 (por defecto 1)."),
27432
- quality: z116.enum([
27462
+ var CreateServiceImagesInput = z117.object({
27463
+ brandId: z117.string().uuid().optional().describe("ID de la marca (de create_brand). Recomendado: da nombre, colores, tono y servicios. Nunca un taskId de producto."),
27464
+ instruction: z117.string().trim().max(4e3).optional().describe("Qu\xE9 servicio o promoci\xF3n mostrar, con las palabras del usuario (ej. \xABcorte + barba a $35.000 los martes\xBB). Si el usuario deja que la IA decida, om\xEDtelo y usa delegateToAi=true."),
27465
+ delegateToAi: z117.boolean().optional().describe("true si el usuario prefiere que la IA elija qu\xE9 mostrar a partir de su marca."),
27466
+ format: z117.enum(SERVICE_IMAGE_FORMATS).optional().describe('Formato: "4:5" (feed, por defecto), "9:16" (historias/reels) o "1:1" (cuadrado).'),
27467
+ count: z117.number().int().min(1).max(SERVICE_IMAGE_MAX_COUNT).optional().describe("Cu\xE1ntas im\xE1genes, de 1 a 3 (por defecto 1)."),
27468
+ quality: z117.enum([
27433
27469
  "standard",
27434
27470
  "high"
27435
27471
  ]).optional().describe('Calidad: "standard" (por defecto) o "high" (m\xE1s cara; no disponible en 4:5).'),
27436
- language: z116.enum([
27472
+ language: z117.enum([
27437
27473
  "es",
27438
27474
  "en",
27439
27475
  "pt"
27440
27476
  ]).optional().describe("Idioma de los textos de la imagen (por defecto es)."),
27441
- adCopy: z116.boolean().optional().describe("Opcional. true agrega textos para el anuncio (titular y descripci\xF3n). Por defecto false."),
27442
- confirmed: z116.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, solo cotiza y no cobra.")
27477
+ adCopy: z117.boolean().optional().describe("Opcional. true agrega textos para el anuncio (titular y descripci\xF3n). Por defecto false."),
27478
+ confirmed: z117.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, solo cotiza y no cobra.")
27443
27479
  }).strict();
27444
27480
  function serviceImageModel(quality) {
27445
27481
  return quality === "high" ? AD_CREATIVE_MODELS.PREMIUM : AD_CREATIVE_MODELS.STANDARD;
@@ -27550,7 +27586,7 @@ function registerServiceImageTools(server, api, options = {}) {
27550
27586
  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) o error."
27551
27587
  });
27552
27588
  } catch (error) {
27553
- if (error instanceof z116.ZodError) throw invalidInputFromZod(error);
27589
+ if (error instanceof z117.ZodError) throw invalidInputFromZod(error);
27554
27590
  throw translateError(error);
27555
27591
  }
27556
27592
  });
@@ -27558,7 +27594,7 @@ function registerServiceImageTools(server, api, options = {}) {
27558
27594
  __name(registerServiceImageTools, "registerServiceImageTools");
27559
27595
 
27560
27596
  // src/tools/creatives.ts
27561
- import { z as z117 } from "zod";
27597
+ import { z as z118 } from "zod";
27562
27598
  var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
27563
27599
  var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
27564
27600
  var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
@@ -27569,72 +27605,72 @@ var CreativeRefs = {
27569
27605
  images: ImagesInput,
27570
27606
  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.'),
27571
27607
  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.'),
27572
- price: z117.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.'),
27573
- offer: z117.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.'),
27574
- compareAtPrice: z117.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
27575
- productContext: z117.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."),
27576
- productLabel: z117.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.'),
27577
- buyerPersona: z117.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.'),
27578
- isCombo: z117.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
27579
- competitorScanEnabled: z117.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."),
27580
- brandId: z117.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.")
27608
+ price: z118.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.'),
27609
+ offer: z118.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.'),
27610
+ compareAtPrice: z118.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
27611
+ productContext: z118.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."),
27612
+ productLabel: z118.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.'),
27613
+ buyerPersona: z118.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.'),
27614
+ isCombo: z118.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
27615
+ competitorScanEnabled: z118.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."),
27616
+ brandId: z118.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.")
27581
27617
  };
27582
- var VideoPresenter = z117.discriminatedUnion("mode", [
27583
- z117.object({
27584
- mode: z117.literal("none")
27618
+ var VideoPresenter = z118.discriminatedUnion("mode", [
27619
+ z118.object({
27620
+ mode: z118.literal("none")
27585
27621
  }).strict(),
27586
- z117.object({
27587
- mode: z117.literal("saved_actor"),
27588
- actorId: z117.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
27622
+ z118.object({
27623
+ mode: z118.literal("saved_actor"),
27624
+ actorId: z118.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
27589
27625
  }).strict(),
27590
- z117.object({
27591
- mode: z117.literal("described"),
27592
- description: z117.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
27626
+ z118.object({
27627
+ mode: z118.literal("described"),
27628
+ description: z118.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
27593
27629
  }).strict()
27594
27630
  ]);
27595
- var VideoCreativeSetup = z117.discriminatedUnion("mode", [
27596
- z117.object({
27597
- mode: z117.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
27631
+ var VideoCreativeSetup = z118.discriminatedUnion("mode", [
27632
+ z118.object({
27633
+ mode: z118.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
27598
27634
  }).strict(),
27599
- z117.object({
27600
- mode: z117.literal("guided"),
27635
+ z118.object({
27636
+ mode: z118.literal("guided"),
27601
27637
  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.'),
27602
- buyerPersona: z117.string().trim().min(1).max(360),
27638
+ buyerPersona: z118.string().trim().min(1).max(360),
27603
27639
  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.'),
27604
27640
  presenter: VideoPresenter,
27605
- creativeDirection: z117.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
27641
+ creativeDirection: z118.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
27606
27642
  }).strict()
27607
27643
  ]);
27608
- var VideoInput = z117.object({
27644
+ var VideoInput = z118.object({
27609
27645
  images: CreativeRefs.images.optional(),
27610
27646
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
27611
- title: z117.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
27612
- primaryAngle: z117.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".'),
27647
+ title: z118.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
27648
+ primaryAngle: z118.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".'),
27613
27649
  language: CreativeRefs.language,
27614
27650
  country: CreativeRefs.country,
27615
- aspectRatio: z117.enum([
27651
+ aspectRatio: z118.enum([
27616
27652
  "9:16",
27617
27653
  "16:9",
27618
27654
  "Auto"
27619
27655
  ]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
27620
27656
  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.'),
27621
- durationSeconds: z117.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."),
27622
- videoAngleCount: z117.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."),
27657
+ durationSeconds: z118.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."),
27658
+ videoAngleCount: z118.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."),
27623
27659
  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.'),
27624
27660
  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."),
27625
27661
  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.'),
27626
27662
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
27627
27663
  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.'),
27628
- features: z117.array(z117.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
27664
+ features: z118.array(z118.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
27629
27665
  price: CreativeRefs.price,
27630
27666
  offer: CreativeRefs.offer,
27631
27667
  productContext: CreativeRefs.productContext,
27632
27668
  productLabel: CreativeRefs.productLabel,
27633
- cta: z117.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.'),
27634
- scriptNotes: z117.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.'),
27669
+ cta: z118.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.'),
27670
+ scriptNotes: z118.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.'),
27635
27671
  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.'),
27636
27672
  competitorScanEnabled: CreativeRefs.competitorScanEnabled,
27637
- replicateWinnerWhenFound: z117.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."),
27673
+ replicateWinnerWhenFound: z118.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."),
27638
27674
  brandId: CreativeRefs.brandId
27639
27675
  }).strict();
27640
27676
  var FreeVideoQualityEnum = VideoQualityEnum;
@@ -27652,7 +27688,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
27652
27688
  length: 29
27653
27689
  }, (_, index) => index + 2)
27654
27690
  };
27655
- var FreeVideoModelIdEnum = z117.enum([
27691
+ var FreeVideoModelIdEnum = z118.enum([
27656
27692
  "grok-imagine-video-1-5-preview",
27657
27693
  "minimax-h3/reference-to-video",
27658
27694
  "wan/3-0-video",
@@ -27663,66 +27699,66 @@ var FREE_SELECTABLE_MODEL_IDS = [
27663
27699
  "minimax-h3/reference-to-video",
27664
27700
  "wan/3-0-video"
27665
27701
  ];
27666
- var FreeVideoInput = z117.object({
27702
+ var FreeVideoInput = z118.object({
27667
27703
  images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
27668
- rawPrompt: z117.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."),
27704
+ rawPrompt: z118.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."),
27669
27705
  language: CreativeRefs.language,
27670
27706
  quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
27671
27707
  // Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
27672
27708
  // parsed ONLY so the handler can reject it with a message naming its
27673
27709
  // replacement — dropping it silently would turn a caller's explicit
27674
27710
  // Pro++ pick into a quiet fallback to Wan.
27675
- freeProModel: z117.enum([
27711
+ freeProModel: z118.enum([
27676
27712
  "wan",
27677
27713
  "seedance"
27678
27714
  ]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
27679
27715
  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.'),
27680
- durationSeconds: z117.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."),
27716
+ durationSeconds: z118.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."),
27681
27717
  videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
27682
- generateAiMusic: z117.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.'),
27718
+ generateAiMusic: z118.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.'),
27683
27719
  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.'),
27684
- addSubtitles: z117.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
27685
- idempotencyKey: z117.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.")
27720
+ addSubtitles: z118.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
27721
+ idempotencyKey: z118.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.")
27686
27722
  }).strict();
27687
27723
  var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
27688
- var ImageCreativeSetup = z117.discriminatedUnion("mode", [
27689
- z117.object({
27690
- mode: z117.literal("automatic")
27724
+ var ImageCreativeSetup = z118.discriminatedUnion("mode", [
27725
+ z118.object({
27726
+ mode: z118.literal("automatic")
27691
27727
  }).strict(),
27692
- z117.object({
27693
- mode: z117.literal("guided"),
27694
- creativeArchetype: z117.union([
27728
+ z118.object({
27729
+ mode: z118.literal("guided"),
27730
+ creativeArchetype: z118.union([
27695
27731
  ImageCreativeArchetypeEnum,
27696
- z117.literal("ai_decides")
27732
+ z118.literal("ai_decides")
27697
27733
  ]),
27698
- visualTreatment: z117.union([
27734
+ visualTreatment: z118.union([
27699
27735
  ImageCreativeVisualTreatmentEnum,
27700
- z117.literal("ai_decides")
27736
+ z118.literal("ai_decides")
27701
27737
  ]),
27702
27738
  aspectRatio: ImageCreativeAspectRatioEnum,
27703
- nVariants: z117.union([
27704
- z117.literal(1),
27705
- z117.literal(2),
27706
- z117.literal(3),
27707
- z117.literal(4),
27708
- z117.literal(6)
27739
+ nVariants: z118.union([
27740
+ z118.literal(1),
27741
+ z118.literal(2),
27742
+ z118.literal(3),
27743
+ z118.literal(4),
27744
+ z118.literal(6)
27709
27745
  ]),
27710
- imageModel: z117.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.'),
27711
- styleMix: z117.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
27712
- generateAdCopy: z117.boolean(),
27713
- competitorScanEnabled: z117.boolean(),
27714
- productContext: z117.string().trim().min(1).max(3e3).nullable(),
27715
- creativeDirection: z117.string().trim().min(1).max(500).nullable(),
27716
- brandColors: z117.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.'),
27717
- headline: z117.string().trim().min(1).max(120).nullable(),
27718
- subheadline: z117.string().trim().min(1).max(160).nullable()
27746
+ imageModel: z118.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.'),
27747
+ styleMix: z118.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
27748
+ generateAdCopy: z118.boolean(),
27749
+ competitorScanEnabled: z118.boolean(),
27750
+ productContext: z118.string().trim().min(1).max(3e3).nullable(),
27751
+ creativeDirection: z118.string().trim().min(1).max(500).nullable(),
27752
+ brandColors: z118.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.'),
27753
+ headline: z118.string().trim().min(1).max(120).nullable(),
27754
+ subheadline: z118.string().trim().min(1).max(160).nullable()
27719
27755
  }).strict()
27720
27756
  ]).superRefine((setup, context) => {
27721
27757
  if (setup.mode !== "guided") return;
27722
27758
  const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
27723
27759
  if (needsStyleMix && setup.styleMix === null) {
27724
27760
  context.addIssue({
27725
- code: z117.ZodIssueCode.custom,
27761
+ code: z118.ZodIssueCode.custom,
27726
27762
  path: [
27727
27763
  "styleMix"
27728
27764
  ],
@@ -27731,7 +27767,7 @@ var ImageCreativeSetup = z117.discriminatedUnion("mode", [
27731
27767
  }
27732
27768
  if (!needsStyleMix && setup.styleMix !== null) {
27733
27769
  context.addIssue({
27734
- code: z117.ZodIssueCode.custom,
27770
+ code: z118.ZodIssueCode.custom,
27735
27771
  path: [
27736
27772
  "styleMix"
27737
27773
  ],
@@ -27740,7 +27776,7 @@ var ImageCreativeSetup = z117.discriminatedUnion("mode", [
27740
27776
  }
27741
27777
  if (imageResolutionOf(setup.imageModel) === "2k" && setup.aspectRatio === "4:5") {
27742
27778
  context.addIssue({
27743
- code: z117.ZodIssueCode.custom,
27779
+ code: z118.ZodIssueCode.custom,
27744
27780
  path: [
27745
27781
  "aspectRatio"
27746
27782
  ],
@@ -27748,55 +27784,55 @@ var ImageCreativeSetup = z117.discriminatedUnion("mode", [
27748
27784
  });
27749
27785
  }
27750
27786
  });
27751
- var LandingCreativeSetup = z117.discriminatedUnion("mode", [
27752
- z117.object({
27753
- mode: z117.literal("automatic")
27787
+ var LandingCreativeSetup = z118.discriminatedUnion("mode", [
27788
+ z118.object({
27789
+ mode: z118.literal("automatic")
27754
27790
  }).strict(),
27755
- z117.object({
27756
- mode: z117.literal("guided"),
27791
+ z118.object({
27792
+ mode: z118.literal("guided"),
27757
27793
  landingStrategy: LandingStrategyEnum,
27758
27794
  landingImageFormat: LandingImageFormatEnum,
27759
- competitorScanEnabled: z117.boolean(),
27760
- paymentMethods: z117.string().trim().min(1).max(240).nullable(),
27761
- productContext: z117.string().trim().min(1).max(3e3).nullable(),
27762
- creativeDirection: z117.string().trim().min(1).max(500).nullable(),
27763
- headline: z117.string().trim().min(1).max(120).nullable(),
27764
- subheadline: z117.string().trim().min(1).max(160).nullable()
27795
+ competitorScanEnabled: z118.boolean(),
27796
+ paymentMethods: z118.string().trim().min(1).max(240).nullable(),
27797
+ productContext: z118.string().trim().min(1).max(3e3).nullable(),
27798
+ creativeDirection: z118.string().trim().min(1).max(500).nullable(),
27799
+ headline: z118.string().trim().min(1).max(120).nullable(),
27800
+ subheadline: z118.string().trim().min(1).max(160).nullable()
27765
27801
  }).strict()
27766
27802
  ]);
27767
- var ImageInput = z117.object({
27803
+ var ImageInput = z118.object({
27768
27804
  images: CreativeRefs.images.optional(),
27769
27805
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
27770
- productTitle: z117.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
27771
- primaryAngle: z117.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.'),
27806
+ productTitle: z118.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
27807
+ primaryAngle: z118.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.'),
27772
27808
  buyerPersona: CreativeRefs.buyerPersona,
27773
27809
  language: CreativeRefs.language,
27774
27810
  country: CreativeRefs.country,
27775
27811
  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."),
27776
27812
  imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
27777
- features: z117.array(z117.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
27813
+ features: z118.array(z118.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
27778
27814
  price: CreativeRefs.price,
27779
- omitPrice: z117.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."),
27815
+ omitPrice: z118.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."),
27780
27816
  compareAtPrice: CreativeRefs.compareAtPrice,
27781
27817
  offer: CreativeRefs.offer,
27782
27818
  productLabel: CreativeRefs.productLabel,
27783
27819
  isCombo: CreativeRefs.isCombo,
27784
27820
  brandId: CreativeRefs.brandId
27785
27821
  });
27786
- var EditImageCreativeInput = z117.object({
27787
- taskId: z117.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
27788
- variantIndex: z117.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
27789
- clientRequestId: z117.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."),
27790
- instruction: z117.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".')
27822
+ var EditImageCreativeInput = z118.object({
27823
+ taskId: z118.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
27824
+ variantIndex: z118.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
27825
+ clientRequestId: z118.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."),
27826
+ instruction: z118.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".')
27791
27827
  });
27792
- var LandingInput = z117.object({
27793
- includeInitialLandingGif: z117.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."),
27828
+ var LandingInput = z118.object({
27829
+ includeInitialLandingGif: z118.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."),
27794
27830
  images: CreativeRefs.images.optional(),
27795
27831
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
27796
27832
  language: CreativeRefs.language,
27797
27833
  country: CreativeRefs.country,
27798
27834
  creativeSetup: LandingCreativeSetup.describe("Configuraci\xF3n obligatoria de landing cl\xE1sica equivalente al wizard web. No expone landing editable/code mientras siga siendo admin-only."),
27799
- salesAngle: z117.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.'),
27835
+ salesAngle: z118.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.'),
27800
27836
  buyerPersona: CreativeRefs.buyerPersona,
27801
27837
  price: CreativeRefs.price,
27802
27838
  compareAtPrice: CreativeRefs.compareAtPrice,
@@ -28078,8 +28114,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
28078
28114
  server.registerTool("get_image_edit_status", {
28079
28115
  description: imageEditStatusGuidance.summary,
28080
28116
  inputSchema: {
28081
- taskId: z117.string().uuid(),
28082
- operationId: z117.string().uuid()
28117
+ taskId: z118.string().uuid(),
28118
+ operationId: z118.string().uuid()
28083
28119
  },
28084
28120
  annotations: READS_INTERNAL
28085
28121
  }, async (input) => {
@@ -28136,10 +28172,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
28136
28172
  __name(registerCreativeTools, "registerCreativeTools");
28137
28173
 
28138
28174
  // src/tools/creative-variants.ts
28139
- import { z as z118 } from "zod";
28175
+ import { z as z119 } from "zod";
28140
28176
  var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
28141
28177
  var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
28142
- var LandingSectionKeyEnum = z118.enum([
28178
+ var LandingSectionKeyEnum = z119.enum([
28143
28179
  "problem_hook",
28144
28180
  "problem_cost",
28145
28181
  "solution_mechanism",
@@ -28179,24 +28215,24 @@ var LandingSectionKeyEnum = z118.enum([
28179
28215
  "lifestyle_fit",
28180
28216
  "join_lifestyle"
28181
28217
  ]);
28182
- var CreativeVariantKindEnum = z118.enum([
28218
+ var CreativeVariantKindEnum = z119.enum([
28183
28219
  "video",
28184
28220
  "image",
28185
28221
  "landing"
28186
28222
  ]);
28187
- var EstimateCreativeVariantInputBase = z118.object({
28188
- sourceTaskId: z118.string().uuid().describe("ID de la tarea original completada."),
28223
+ var EstimateCreativeVariantInputBase = z119.object({
28224
+ sourceTaskId: z119.string().uuid().describe("ID de la tarea original completada."),
28189
28225
  kind: CreativeVariantKindEnum,
28190
28226
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
28191
28227
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
28192
- nVariants: z118.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
28228
+ nVariants: z119.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
28193
28229
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
28194
- instructions: z118.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.")
28230
+ instructions: z119.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.")
28195
28231
  }).strict();
28196
28232
  var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
28197
28233
  if (input.kind === "video" && input.nVariants !== void 0) {
28198
28234
  ctx.addIssue({
28199
- code: z118.ZodIssueCode.custom,
28235
+ code: z119.ZodIssueCode.custom,
28200
28236
  path: [
28201
28237
  "nVariants"
28202
28238
  ],
@@ -28206,7 +28242,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
28206
28242
  if (input.kind !== "video") {
28207
28243
  if (input.videoPreset !== void 0) {
28208
28244
  ctx.addIssue({
28209
- code: z118.ZodIssueCode.custom,
28245
+ code: z119.ZodIssueCode.custom,
28210
28246
  path: [
28211
28247
  "videoPreset"
28212
28248
  ],
@@ -28215,7 +28251,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
28215
28251
  }
28216
28252
  if (input.videoResolution !== void 0) {
28217
28253
  ctx.addIssue({
28218
- code: z118.ZodIssueCode.custom,
28254
+ code: z119.ZodIssueCode.custom,
28219
28255
  path: [
28220
28256
  "videoResolution"
28221
28257
  ],
@@ -28225,7 +28261,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
28225
28261
  }
28226
28262
  if (input.kind !== "image" && input.nVariants !== void 0) {
28227
28263
  ctx.addIssue({
28228
- code: z118.ZodIssueCode.custom,
28264
+ code: z119.ZodIssueCode.custom,
28229
28265
  path: [
28230
28266
  "nVariants"
28231
28267
  ],
@@ -28235,7 +28271,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
28235
28271
  if (input.kind !== "landing") {
28236
28272
  if (input.sectionKey !== void 0) {
28237
28273
  ctx.addIssue({
28238
- code: z118.ZodIssueCode.custom,
28274
+ code: z119.ZodIssueCode.custom,
28239
28275
  path: [
28240
28276
  "sectionKey"
28241
28277
  ],
@@ -28244,7 +28280,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
28244
28280
  }
28245
28281
  if (input.instructions !== void 0) {
28246
28282
  ctx.addIssue({
28247
- code: z118.ZodIssueCode.custom,
28283
+ code: z119.ZodIssueCode.custom,
28248
28284
  path: [
28249
28285
  "instructions"
28250
28286
  ],
@@ -28253,31 +28289,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
28253
28289
  }
28254
28290
  }
28255
28291
  });
28256
- var CreateCreativeVariantInputBase = z118.object({
28257
- sourceTaskId: z118.string().uuid().describe("ID de la tarea original completada."),
28292
+ var CreateCreativeVariantInputBase = z119.object({
28293
+ sourceTaskId: z119.string().uuid().describe("ID de la tarea original completada."),
28258
28294
  kind: CreativeVariantKindEnum,
28259
- confirm: z118.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
28260
- clientRequestId: z118.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."),
28261
- angle: z118.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
28262
- buyerPersona: z118.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
28263
- scriptNotes: z118.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
28264
- creativeDirection: z118.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
28295
+ confirm: z119.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
28296
+ clientRequestId: z119.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."),
28297
+ angle: z119.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
28298
+ buyerPersona: z119.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
28299
+ scriptNotes: z119.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
28300
+ creativeDirection: z119.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
28265
28301
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
28266
28302
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
28267
- generateAiMusic: z118.boolean().optional().describe("Opcional para video."),
28268
- nVariants: z118.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
28303
+ generateAiMusic: z119.boolean().optional().describe("Opcional para video."),
28304
+ nVariants: z119.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
28269
28305
  imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
28270
28306
  creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
28271
28307
  visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
28272
28308
  aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
28273
- styleMix: z118.boolean().optional().describe("Opcional para imagen."),
28309
+ styleMix: z119.boolean().optional().describe("Opcional para imagen."),
28274
28310
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
28275
- instructions: z118.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.")
28311
+ instructions: z119.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.")
28276
28312
  }).strict();
28277
28313
  var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
28278
28314
  if ((input.kind === "video" || input.kind === "image") && !input.angle) {
28279
28315
  ctx.addIssue({
28280
- code: z118.ZodIssueCode.custom,
28316
+ code: z119.ZodIssueCode.custom,
28281
28317
  path: [
28282
28318
  "angle"
28283
28319
  ],
@@ -28286,7 +28322,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
28286
28322
  }
28287
28323
  if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
28288
28324
  ctx.addIssue({
28289
- code: z118.ZodIssueCode.custom,
28325
+ code: z119.ZodIssueCode.custom,
28290
28326
  path: [
28291
28327
  "instructions"
28292
28328
  ],
@@ -28332,7 +28368,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
28332
28368
  for (const field of fieldsByKind[input.kind]) {
28333
28369
  if (input[field] !== void 0) {
28334
28370
  ctx.addIssue({
28335
- code: z118.ZodIssueCode.custom,
28371
+ code: z119.ZodIssueCode.custom,
28336
28372
  path: [
28337
28373
  field
28338
28374
  ],
@@ -28465,13 +28501,13 @@ function registerCreativeVariantTools(server, api) {
28465
28501
  __name(registerCreativeVariantTools, "registerCreativeVariantTools");
28466
28502
 
28467
28503
  // src/tools/script-review.ts
28468
- import { z as z119 } from "zod";
28504
+ import { z as z120 } from "zod";
28469
28505
  var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
28470
28506
  var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
28471
28507
  var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
28472
- var GetVideoScriptInput = z119.object({
28473
- taskId: z119.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
28474
- angleKey: z119.string().min(1).optional().describe('Clave del \xE1ngulo cuyo guion se quiere leer (formato "angle_0", "angle_1", ...). REQUERIDO para tareas multi-angle: si se omite, el backend resuelve a "angle_0" LITERAL (no "el primer pendiente"), as\xED que en multi-angle donde angle_0 ya est\xE9 aprobado/saltado obtendr\xEDas status="approved" y nunca alcanzar\xEDas el \xE1ngulo realmente pendiente. Para single-angle puede omitirse.')
28508
+ var GetVideoScriptInput = z120.object({
28509
+ taskId: z120.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
28510
+ angleKey: z120.string().min(1).optional().describe('Clave del \xE1ngulo cuyo guion se quiere leer (formato "angle_0", "angle_1", ...). REQUERIDO para tareas multi-angle: si se omite, el backend resuelve a "angle_0" LITERAL (no "el primer pendiente"), as\xED que en multi-angle donde angle_0 ya est\xE9 aprobado/saltado obtendr\xEDas status="approved" y nunca alcanzar\xEDas el \xE1ngulo realmente pendiente. Para single-angle puede omitirse.')
28475
28511
  }).strict();
28476
28512
  var ApproveVideoScriptInput = ApproveVideoScriptCapabilityRequest;
28477
28513
  var RegenerateVideoScriptInput = RegenerateVideoScriptCapabilityRequest.extend({
@@ -28554,7 +28590,7 @@ function registerScriptReviewTools(server, api) {
28554
28590
  __name(registerScriptReviewTools, "registerScriptReviewTools");
28555
28591
 
28556
28592
  // src/tools/connections.ts
28557
- import { z as z120 } from "zod";
28593
+ import { z as z121 } from "zod";
28558
28594
  var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
28559
28595
  var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
28560
28596
  var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
@@ -28563,7 +28599,7 @@ var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list
28563
28599
  function registerConnectionTools(server, api) {
28564
28600
  server.registerTool("list_shopify_shops", {
28565
28601
  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.",
28566
- inputSchema: z120.object({}).shape,
28602
+ inputSchema: z121.object({}).shape,
28567
28603
  annotations: READS_INTERNAL
28568
28604
  }, async () => {
28569
28605
  try {
@@ -28575,10 +28611,10 @@ function registerConnectionTools(server, api) {
28575
28611
  });
28576
28612
  server.registerTool("list_shopify_products", {
28577
28613
  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.',
28578
- inputSchema: z120.object({
28579
- shopDomain: z120.string().min(3).max(120),
28580
- query: z120.string().trim().max(120).optional(),
28581
- taskId: z120.string().uuid().optional()
28614
+ inputSchema: z121.object({
28615
+ shopDomain: z121.string().min(3).max(120),
28616
+ query: z121.string().trim().max(120).optional(),
28617
+ taskId: z121.string().uuid().optional()
28582
28618
  }).shape,
28583
28619
  annotations: READS_EXTERNAL
28584
28620
  }, async ({ shopDomain, query, taskId }) => {
@@ -28596,7 +28632,7 @@ function registerConnectionTools(server, api) {
28596
28632
  });
28597
28633
  server.registerTool("list_meta_ad_accounts", {
28598
28634
  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.",
28599
- inputSchema: z120.object({}).shape,
28635
+ inputSchema: z121.object({}).shape,
28600
28636
  annotations: READS_EXTERNAL
28601
28637
  }, async () => {
28602
28638
  try {
@@ -28608,7 +28644,7 @@ function registerConnectionTools(server, api) {
28608
28644
  });
28609
28645
  server.registerTool("list_meta_destinations", {
28610
28646
  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.",
28611
- inputSchema: z120.object({}).shape,
28647
+ inputSchema: z121.object({}).shape,
28612
28648
  annotations: READS_EXTERNAL,
28613
28649
  _meta: {
28614
28650
  "openai/widgetAccessible": true
@@ -28623,7 +28659,7 @@ function registerConnectionTools(server, api) {
28623
28659
  });
28624
28660
  server.registerTool("list_tiktok_advertisers", {
28625
28661
  description: listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.",
28626
- inputSchema: z120.object({}).shape,
28662
+ inputSchema: z121.object({}).shape,
28627
28663
  annotations: READS_EXTERNAL
28628
28664
  }, async () => {
28629
28665
  try {
@@ -28637,7 +28673,7 @@ function registerConnectionTools(server, api) {
28637
28673
  __name(registerConnectionTools, "registerConnectionTools");
28638
28674
 
28639
28675
  // src/tools/actors.ts
28640
- import { z as z121 } from "zod";
28676
+ import { z as z122 } from "zod";
28641
28677
  var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
28642
28678
  var actorVoiceGuidance = {
28643
28679
  capabilities: getProductMakerCapabilityModelGuidance("get_actor_voice_capabilities"),
@@ -28677,7 +28713,7 @@ function sanitizeVoiceResult(value) {
28677
28713
  __name(sanitizeVoiceResult, "sanitizeVoiceResult");
28678
28714
  function registerActorTools(server, api) {
28679
28715
  const actor = {
28680
- actorId: z121.string().min(1).max(64)
28716
+ actorId: z122.string().min(1).max(64)
28681
28717
  };
28682
28718
  const safe = /* @__PURE__ */ __name(async (request) => {
28683
28719
  try {
@@ -28706,8 +28742,8 @@ function registerActorTools(server, api) {
28706
28742
  inputSchema: {
28707
28743
  ...actor,
28708
28744
  draft: ActorVoiceDraftSchema,
28709
- requestKey: z121.string().trim().min(1).max(128),
28710
- acceptedQuoteId: z121.string().trim().min(1).max(128)
28745
+ requestKey: z122.string().trim().min(1).max(128),
28746
+ acceptedQuoteId: z122.string().trim().min(1).max(128)
28711
28747
  },
28712
28748
  annotations: CREATES_PAID
28713
28749
  }, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/previews`, body)));
@@ -28715,7 +28751,7 @@ function registerActorTools(server, api) {
28715
28751
  description: actorVoiceGuidance.get.summary,
28716
28752
  inputSchema: {
28717
28753
  ...actor,
28718
- candidateId: z121.string().min(1).max(64)
28754
+ candidateId: z122.string().min(1).max(64)
28719
28755
  },
28720
28756
  // Polling can resume the first paid submission of an accepted quote.
28721
28757
  // The immutable candidate/operation key keeps recovery idempotent.
@@ -28728,16 +28764,16 @@ function registerActorTools(server, api) {
28728
28764
  description: actorVoiceGuidance.approve.summary,
28729
28765
  inputSchema: {
28730
28766
  ...actor,
28731
- candidateId: z121.string().min(1).max(64),
28732
- expectedRevision: z121.number().int().positive(),
28733
- expectedApprovedRevision: z121.number().int().positive().nullable().optional()
28767
+ candidateId: z122.string().min(1).max(64),
28768
+ expectedRevision: z122.number().int().positive(),
28769
+ expectedApprovedRevision: z122.number().int().positive().nullable().optional()
28734
28770
  },
28735
28771
  // Replaces the selected voice and withdraws the old catalog grants.
28736
28772
  annotations: OVERWRITES_INTERNAL
28737
28773
  }, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/approve`, body)));
28738
28774
  server.registerTool("list_actors", {
28739
28775
  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.",
28740
- inputSchema: z121.object({}).shape,
28776
+ inputSchema: z122.object({}).shape,
28741
28777
  annotations: READS_INTERNAL
28742
28778
  }, async () => {
28743
28779
  try {
@@ -28770,7 +28806,7 @@ function registerActorTools(server, api) {
28770
28806
  __name(registerActorTools, "registerActorTools");
28771
28807
 
28772
28808
  // src/tools/publish.ts
28773
- import { z as z122 } from "zod";
28809
+ import { z as z123 } from "zod";
28774
28810
 
28775
28811
  // src/tools/meta-publish-attempt-id.ts
28776
28812
  var META_PUBLISH_NAMESPACE = "7b19c9ac-b4eb-4db1-970e-c2f24ce30b98";
@@ -28809,40 +28845,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
28809
28845
  var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
28810
28846
  var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
28811
28847
  var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
28812
- var ShopifyInput = z122.object({
28813
- taskId: z122.string().min(1),
28814
- shopDomain: z122.string().min(1),
28848
+ var ShopifyInput = z123.object({
28849
+ taskId: z123.string().min(1),
28850
+ shopDomain: z123.string().min(1),
28815
28851
  /** Override: number of landing images to include. Default = ALL images the
28816
28852
  * task generated (the MCP fetches /v1/results first to count). Bounded
28817
28853
  * generously here; the backend validates each index against
28818
28854
  * landing.images.length and rejects out-of-range. */
28819
- numLandingImages: z122.number().int().min(1).max(20).optional(),
28820
- variantIndex: z122.number().int().min(0).optional(),
28855
+ numLandingImages: z123.number().int().min(1).max(20).optional(),
28856
+ variantIndex: z123.number().int().min(0).optional(),
28821
28857
  /** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
28822
28858
  * When true, the landing renders variant-picker pills; when false, it ships
28823
28859
  * a single-option product page. Defaults to false. */
28824
- showVariantPicker: z122.boolean().optional(),
28860
+ showVariantPicker: z123.boolean().optional(),
28825
28861
  /** Default `auto` updates the product previously published for this task and
28826
28862
  * shop. Use `existing` with targetProductId to choose another product, or
28827
28863
  * `new` only when the user explicitly wants a duplicate/new listing. */
28828
- publicationMode: z122.enum([
28864
+ publicationMode: z123.enum([
28829
28865
  "auto",
28830
28866
  "existing",
28831
28867
  "new"
28832
28868
  ]).optional(),
28833
28869
  /** Shopify product GID, numeric id, or admin product URL. Required when
28834
28870
  * publicationMode is `existing`. */
28835
- targetProductId: z122.string().trim().min(1).max(300).optional(),
28871
+ targetProductId: z123.string().trim().min(1).max(300).optional(),
28836
28872
  /** Add an announcement bar text above add-to-cart (optional). */
28837
- announcementBarEnabled: z122.boolean().optional(),
28838
- announcementBarText: z122.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
28873
+ announcementBarEnabled: z123.boolean().optional(),
28874
+ announcementBarText: z123.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
28839
28875
  commerceCorrection: PublishCommerceCorrectionSchema.optional().describe("Complete seller-confirmed commerce values, with the revision and fingerprint returned in recovery. Never invent missing prices or convert currency."),
28840
- confirmed: z122.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
28876
+ confirmed: z123.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
28841
28877
  });
28842
28878
  var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
28843
28879
  if (value.commerceCorrection && value.confirmed !== true) {
28844
28880
  ctx.addIssue({
28845
- code: z122.ZodIssueCode.custom,
28881
+ code: z123.ZodIssueCode.custom,
28846
28882
  path: [
28847
28883
  "confirmed"
28848
28884
  ],
@@ -28851,7 +28887,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
28851
28887
  }
28852
28888
  if (value.announcementBarEnabled && !value.announcementBarText) {
28853
28889
  ctx.addIssue({
28854
- code: z122.ZodIssueCode.custom,
28890
+ code: z123.ZodIssueCode.custom,
28855
28891
  path: [
28856
28892
  "announcementBarText"
28857
28893
  ],
@@ -28860,7 +28896,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
28860
28896
  }
28861
28897
  if (!value.announcementBarEnabled && value.announcementBarText) {
28862
28898
  ctx.addIssue({
28863
- code: z122.ZodIssueCode.custom,
28899
+ code: z123.ZodIssueCode.custom,
28864
28900
  path: [
28865
28901
  "announcementBarText"
28866
28902
  ],
@@ -28874,91 +28910,91 @@ function parseShopifyInput(rawInput) {
28874
28910
  return parsed.data;
28875
28911
  }
28876
28912
  __name(parseShopifyInput, "parseShopifyInput");
28877
- var McpCampaignConfig = z122.object({
28913
+ var McpCampaignConfig = z123.object({
28878
28914
  /** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
28879
28915
  * converts to the account currency server-side. Do NOT pre-convert: on a COP
28880
28916
  * account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
28881
- dailyBudgetUsd: z122.number().positive().optional(),
28917
+ dailyBudgetUsd: z123.number().positive().optional(),
28882
28918
  /** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
28883
28919
  * normalizes at validation). Meta accepts max 1 (single-country ad set).
28884
28920
  * TikTok takes only the first entry. */
28885
- targetCountries: z122.array(CountryIso2Schema).max(1).optional(),
28886
- campaignName: z122.string().trim().min(1).max(100).optional()
28921
+ targetCountries: z123.array(CountryIso2Schema).max(1).optional(),
28922
+ campaignName: z123.string().trim().min(1).max(100).optional()
28887
28923
  });
28888
28924
  var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
28889
- var MetaInput = z122.object({
28890
- taskId: z122.string().min(1),
28925
+ var MetaInput = z123.object({
28926
+ taskId: z123.string().min(1),
28891
28927
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
28892
- portfolioId: z122.string().trim().min(1),
28928
+ portfolioId: z123.string().trim().min(1),
28893
28929
  /** Exact Facebook Page selected from `list_meta_destinations`. */
28894
- pageId: z122.string().trim().min(1),
28930
+ pageId: z123.string().trim().min(1),
28895
28931
  adAccountId: McpAdAccountId,
28896
- pixelId: z122.string().min(1).optional(),
28897
- landingUrl: z122.string().url().optional(),
28932
+ pixelId: z123.string().min(1).optional(),
28933
+ landingUrl: z123.string().url().optional(),
28898
28934
  /** Select which angles to publish by 0-based index. Omit to publish all
28899
28935
  * successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
28900
- angleIndexes: z122.array(z122.number().int().nonnegative()).optional(),
28936
+ angleIndexes: z123.array(z123.number().int().nonnegative()).optional(),
28901
28937
  campaignConfig: McpCampaignConfig.optional(),
28902
28938
  /** Override the ad's primary text (body copy). If omitted, ProductMaker
28903
28939
  * uses the auto-generated copy attached to the task. Capped at 500 chars
28904
28940
  * (Meta's primary-text limit). */
28905
- primaryText: z122.string().trim().min(1).max(500).optional(),
28941
+ primaryText: z123.string().trim().min(1).max(500).optional(),
28906
28942
  /** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
28907
28943
  * (wa.me) instead of a landing page. */
28908
- phoneNumber: z122.string().min(8).max(32).optional()
28944
+ phoneNumber: z123.string().min(8).max(32).optional()
28909
28945
  });
28910
- var GroupedTaskSource = z122.object({
28911
- type: z122.literal("task"),
28912
- taskId: z122.string().min(1),
28913
- angleIndex: z122.number().int().min(0).optional(),
28914
- videoVariant: z122.enum([
28946
+ var GroupedTaskSource = z123.object({
28947
+ type: z123.literal("task"),
28948
+ taskId: z123.string().min(1),
28949
+ angleIndex: z123.number().int().min(0).optional(),
28950
+ videoVariant: z123.enum([
28915
28951
  "with_subtitles",
28916
28952
  "without_subtitles"
28917
28953
  ]).optional(),
28918
- imageVariantIndex: z122.number().int().min(0).optional()
28919
- });
28920
- var GroupedMediaSource = z122.object({
28921
- type: z122.literal("media"),
28922
- url: z122.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
28923
- path: z122.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".'),
28924
- thumbnailUrl: z122.string().url().optional(),
28925
- thumbnailPath: z122.string().min(1).optional()
28954
+ imageVariantIndex: z123.number().int().min(0).optional()
28955
+ });
28956
+ var GroupedMediaSource = z123.object({
28957
+ type: z123.literal("media"),
28958
+ url: z123.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
28959
+ path: z123.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".'),
28960
+ thumbnailUrl: z123.string().url().optional(),
28961
+ thumbnailPath: z123.string().min(1).optional()
28926
28962
  }).refine((value) => Boolean(value.url) !== Boolean(value.path), {
28927
28963
  message: "media source needs exactly one of `url` or `path`"
28928
28964
  }).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
28929
28965
  message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
28930
28966
  });
28931
- var GroupedUploadedAssetSource = z122.object({
28932
- type: z122.literal("asset"),
28967
+ var GroupedUploadedAssetSource = z123.object({
28968
+ type: z123.literal("asset"),
28933
28969
  /** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
28934
- assetId: z122.string().uuid(),
28935
- thumbnailAssetId: z122.string().uuid().optional()
28970
+ assetId: z123.string().uuid(),
28971
+ thumbnailAssetId: z123.string().uuid().optional()
28936
28972
  });
28937
- var GroupedCreative = z122.object({
28938
- type: z122.enum([
28973
+ var GroupedCreative = z123.object({
28974
+ type: z123.enum([
28939
28975
  "image",
28940
28976
  "video"
28941
28977
  ]),
28942
- source: z122.union([
28978
+ source: z123.union([
28943
28979
  GroupedTaskSource,
28944
28980
  GroupedMediaSource,
28945
28981
  GroupedUploadedAssetSource
28946
28982
  ]),
28947
- title: z122.string().max(120).optional(),
28948
- description: z122.string().max(500).optional(),
28983
+ title: z123.string().max(120).optional(),
28984
+ description: z123.string().max(500).optional(),
28949
28985
  cta: MetaCtaType.optional(),
28950
- creativeId: z122.string().min(1).optional()
28986
+ creativeId: z123.string().min(1).optional()
28951
28987
  });
28952
- var GroupedCampaignConfigBase = z122.object({
28988
+ var GroupedCampaignConfigBase = z123.object({
28953
28989
  campaignType: MetaCampaignType.default("sales"),
28954
28990
  optimizationMode: MetaOptimizationMode.default("advantage_plus"),
28955
28991
  budgetMode: MetaBudgetMode.optional(),
28956
- campaignDailyBudget: z122.number().int().positive().optional(),
28957
- adSets: z122.array(z122.object({
28958
- tempId: z122.string().min(1).max(80),
28959
- name: z122.string().min(1).max(100),
28960
- dailyBudget: z122.number().int().positive().optional(),
28961
- creativeIds: z122.array(z122.string().min(1)).min(1)
28992
+ campaignDailyBudget: z123.number().int().positive().optional(),
28993
+ adSets: z123.array(z123.object({
28994
+ tempId: z123.string().min(1).max(80),
28995
+ name: z123.string().min(1).max(100),
28996
+ dailyBudget: z123.number().int().positive().optional(),
28997
+ creativeIds: z123.array(z123.string().min(1)).min(1)
28962
28998
  })).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
28963
28999
  /**
28964
29000
  * Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
@@ -28966,17 +29002,17 @@ var GroupedCampaignConfigBase = z122.object({
28966
29002
  * opaque `invalid_literal` and made the WhatsApp destination — supported by
28967
29003
  * the API since #849 — unreachable from this tool.
28968
29004
  */
28969
- destination: z122.discriminatedUnion("type", [
28970
- z122.object({
28971
- type: z122.literal("landing"),
28972
- landingUrl: z122.string().url()
29005
+ destination: z123.discriminatedUnion("type", [
29006
+ z123.object({
29007
+ type: z123.literal("landing"),
29008
+ landingUrl: z123.string().url()
28973
29009
  }),
28974
- z122.object({
28975
- type: z122.literal("whatsapp"),
28976
- phoneNumber: z122.string().min(8).max(32)
29010
+ z123.object({
29011
+ type: z123.literal("whatsapp"),
29012
+ phoneNumber: z123.string().min(8).max(32)
28977
29013
  })
28978
29014
  ]),
28979
- saveAsDefault: z122.boolean().default(false),
29015
+ saveAsDefault: z123.boolean().default(false),
28980
29016
  budgetPolicy: MetaBudgetPolicy.optional()
28981
29017
  });
28982
29018
  function resolveBudgetMode(value) {
@@ -28990,7 +29026,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
28990
29026
  const budgetMode = resolveBudgetMode(value);
28991
29027
  if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
28992
29028
  ctx.addIssue({
28993
- code: z122.ZodIssueCode.custom,
29029
+ code: z123.ZodIssueCode.custom,
28994
29030
  path: [
28995
29031
  "campaignDailyBudget"
28996
29032
  ],
@@ -29001,7 +29037,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
29001
29037
  value.adSets.forEach((adSet, index) => {
29002
29038
  if (adSet.dailyBudget === void 0) {
29003
29039
  ctx.addIssue({
29004
- code: z122.ZodIssueCode.custom,
29040
+ code: z123.ZodIssueCode.custom,
29005
29041
  path: [
29006
29042
  "adSets",
29007
29043
  index,
@@ -29016,28 +29052,33 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
29016
29052
  ...value,
29017
29053
  budgetMode: resolveBudgetMode(value)
29018
29054
  }));
29019
- var PublishCreativesToMetaInputBase = z122.object({
29020
- creatives: z122.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
29055
+ var PublishCreativesToMetaInputBase = z123.object({
29056
+ creatives: z123.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
29021
29057
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
29022
- portfolioId: z122.string().trim().min(1),
29058
+ portfolioId: z123.string().trim().min(1),
29023
29059
  /** Exact Facebook Page selected from `list_meta_destinations`. */
29024
- pageId: z122.string().trim().min(1),
29060
+ pageId: z123.string().trim().min(1),
29025
29061
  adAccountId: McpAdAccountId,
29026
- pixelId: z122.string().min(1).optional(),
29027
- /** Required unless `campaignConfig.destination` is whatsapp — see the
29028
- * superRefine below. Mirrors the API's `FacebookCreateCampaignFromTasksBodySchema`. */
29029
- landingUrl: z122.string().url().optional(),
29062
+ pixelId: z123.string().min(1).optional(),
29063
+ /** Required unless `campaignConfig.destination` is whatsapp or a creative
29064
+ * comes from a task (the API then lands on the published service landing
29065
+ * of its service tasks) — see the superRefine below. Mirrors the API's
29066
+ * `FacebookCreateCampaignFromTasksBodySchema`. */
29067
+ landingUrl: z123.string().url().optional(),
29030
29068
  /** ISO-2 code or resolvable country name — mirrors the API contract
29031
- * (CountryIso2Schema), which normalizes names to alpha-2 at validation. */
29032
- targetCountry: CountryIso2Schema,
29033
- campaignName: z122.string().trim().min(1).max(100),
29069
+ * (CountryIso2Schema), which normalizes names to alpha-2 at validation.
29070
+ * Omitted: the brand country of its service tasks (the API answers
29071
+ * META_NO_TARGET_COUNTRY when it has none); "US" for products. */
29072
+ targetCountry: CountryIso2Schema.optional(),
29073
+ campaignName: z123.string().trim().min(1).max(100),
29034
29074
  campaignConfig: GroupedCampaignConfig.optional()
29035
29075
  });
29036
29076
  var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
29037
29077
  const destination = value.campaignConfig?.destination;
29038
- if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
29078
+ const hasTaskCreative = value.creatives.some((creative) => creative.source.type === "task");
29079
+ if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl && !hasTaskCreative) {
29039
29080
  ctx.addIssue({
29040
- code: z122.ZodIssueCode.custom,
29081
+ code: z123.ZodIssueCode.custom,
29041
29082
  path: [
29042
29083
  "landingUrl"
29043
29084
  ],
@@ -29046,7 +29087,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
29046
29087
  }
29047
29088
  if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
29048
29089
  ctx.addIssue({
29049
- code: z122.ZodIssueCode.custom,
29090
+ code: z123.ZodIssueCode.custom,
29050
29091
  path: [
29051
29092
  "campaignConfig",
29052
29093
  "destination",
@@ -29065,16 +29106,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
29065
29106
  }
29066
29107
  return value;
29067
29108
  });
29068
- var PresignUploadResponseSchema = z122.object({
29069
- uploadUrl: z122.string().url().refine((value) => {
29109
+ var PresignUploadResponseSchema = z123.object({
29110
+ uploadUrl: z123.string().url().refine((value) => {
29070
29111
  const url = new URL(value);
29071
29112
  return !url.username && !url.password && url.protocol === "https:";
29072
29113
  }, "presigned upload URL must be HTTPS without embedded credentials"),
29073
- publicUrl: z122.string().url().refine((value) => {
29114
+ publicUrl: z123.string().url().refine((value) => {
29074
29115
  const url = new URL(value);
29075
29116
  return !url.username && !url.password;
29076
29117
  }, "public media URL must not contain embedded credentials"),
29077
- stagingAssetId: z122.string().uuid()
29118
+ stagingAssetId: z123.string().uuid()
29078
29119
  });
29079
29120
  async function uploadResolvedMedia(api, media, assetRole) {
29080
29121
  if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
@@ -29099,16 +29140,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
29099
29140
  return uploadResolvedMedia(api, media, assetRole);
29100
29141
  }
29101
29142
  __name(resolveAndUploadMedia, "resolveAndUploadMedia");
29102
- var TikTokInput = z122.object({
29103
- taskId: z122.string().min(1),
29104
- advertiserId: z122.string().min(1),
29105
- pixelId: z122.string().min(1).optional(),
29106
- landingUrl: z122.string().url().optional(),
29107
- angleIndexes: z122.array(z122.number().int().nonnegative()).optional(),
29143
+ var TikTokInput = z123.object({
29144
+ taskId: z123.string().min(1),
29145
+ advertiserId: z123.string().min(1),
29146
+ pixelId: z123.string().min(1).optional(),
29147
+ landingUrl: z123.string().url().optional(),
29148
+ angleIndexes: z123.array(z123.number().int().nonnegative()).optional(),
29108
29149
  campaignConfig: McpCampaignConfig.optional(),
29109
29150
  /** Override the ad's description (TikTok's body copy). If omitted,
29110
29151
  * ProductMaker uses the auto-generated copy attached to the task. */
29111
- primaryText: z122.string().trim().min(1).max(500).optional()
29152
+ primaryText: z123.string().trim().min(1).max(500).optional()
29112
29153
  });
29113
29154
  function registerPublishTools(server, api, opts = {}) {
29114
29155
  const transport = opts.transport ?? "http";
@@ -29230,7 +29271,7 @@ function registerPublishTools(server, api, opts = {}) {
29230
29271
  }
29231
29272
  });
29232
29273
  server.registerTool("publish_creatives_to_meta", {
29233
- description: publishCreativesToMetaGuidance.summary + ' Publica tus creativos en Meta sin gastar cr\xE9ditos de ProductMaker. El presupuesto de anuncios se paga directamente desde tu cuenta de Meta. Crear creativos o copy con IA sigue usando cr\xE9ditos. Si la petici\xF3n natural adjunta o menciona archivos locales, llama primero `request_media_upload`; tras OK usa cada resultado como `source.type="asset"` con su `assetId` y el `type` que coincide con `mediaKind`. No pidas path ni URL. Despu\xE9s llama `list_meta_destinations` y pregunta en el chat por el `portfolioId`, `adAccountId` y `pageId` exactos; el App es solo para archivos. Si la carga fue parcial, conserva los assets confirmados, procesa s\xF3lo los pendientes y publica \xFAnicamente assets confirmados; nunca inventes assets ni superes diez creativos. Las rutas locales s\xF3lo funcionan con MCP stdio. Los medios propios se eliminan despu\xE9s de publicar correctamente; si falla antes de enviar una mutaci\xF3n a Meta, quedan durante el TTL. Para videos la miniatura es opcional y ProductMaker puede generarla con FFmpeg. `campaignConfig.destination` acepta landing o WhatsApp. Para landing basta `campaignConfig.destination.landingUrl`; no dupliques la URL arriba. Si omites `budgetMode`, se infiere `ad_set` cuando cada ad set trae `dailyBudget`, o `campaign` cuando env\xEDas `campaignDailyBudget`. No actives la campa\xF1a autom\xE1ticamente. Si el resultado es ambiguo, NO reenv\xEDes: revisa Meta Ads Manager.',
29274
+ description: publishCreativesToMetaGuidance.summary + ' Publica tus creativos en Meta sin gastar cr\xE9ditos de ProductMaker. El presupuesto de anuncios se paga directamente desde tu cuenta de Meta. Crear creativos o copy con IA sigue usando cr\xE9ditos. Si la petici\xF3n natural adjunta o menciona archivos locales, llama primero `request_media_upload`; tras OK usa cada resultado como `source.type="asset"` con su `assetId` y el `type` que coincide con `mediaKind`. No pidas path ni URL. Despu\xE9s llama `list_meta_destinations` y pregunta en el chat por el `portfolioId`, `adAccountId` y `pageId` exactos; el App es solo para archivos. Si la carga fue parcial, conserva los assets confirmados, procesa s\xF3lo los pendientes y publica \xFAnicamente assets confirmados; nunca inventes assets ni superes diez creativos. Las rutas locales s\xF3lo funcionan con MCP stdio. Los medios propios se eliminan despu\xE9s de publicar correctamente; si falla antes de enviar una mutaci\xF3n a Meta, quedan durante el TTL. Para videos la miniatura es opcional y ProductMaker puede generarla con FFmpeg. `campaignConfig.destination` acepta landing o WhatsApp. Para landing basta `campaignConfig.destination.landingUrl`; no dupliques la URL arriba. Con creativos de tarea de servicio puedes omitir `landingUrl` y `targetCountry`: se usan su landing de servicio publicada y el pa\xEDs de su marca; si falta alguno, pregunta al usuario (nunca asumas un pa\xEDs). Si omites `budgetMode`, se infiere `ad_set` cuando cada ad set trae `dailyBudget`, o `campaign` cuando env\xEDas `campaignDailyBudget`. No actives la campa\xF1a autom\xE1ticamente. Si el resultado es ambiguo, NO reenv\xEDes: revisa Meta Ads Manager.',
29234
29275
  inputSchema: PublishCreativesToMetaInputBase.shape,
29235
29276
  annotations: CREATES_EXTERNAL
29236
29277
  }, async (rawInput, extra) => {
@@ -29460,39 +29501,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
29460
29501
 
29461
29502
  // src/tools/meta-upload.ts
29462
29503
  import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
29463
- import { z as z123 } from "zod";
29504
+ import { z as z124 } from "zod";
29464
29505
  var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
29465
- var UploadSessionInputBase = z123.object({
29466
- mediaKind: z123.enum([
29506
+ var UploadSessionInputBase = z124.object({
29507
+ mediaKind: z124.enum([
29467
29508
  "image",
29468
29509
  "video",
29469
29510
  "mixed"
29470
29511
  ]).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."),
29471
- assetRole: z123.enum([
29512
+ assetRole: z124.enum([
29472
29513
  "media",
29473
29514
  "thumbnail"
29474
29515
  ]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
29475
- uploadPurpose: z123.enum([
29516
+ uploadPurpose: z124.enum([
29476
29517
  "product_reference",
29477
29518
  "creative",
29478
29519
  "generic"
29479
29520
  ]).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."),
29480
- maxFiles: z123.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
29521
+ maxFiles: z124.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
29481
29522
  });
29482
- var OpenAiFileReference = z123.object({
29483
- download_url: z123.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."),
29484
- file_id: z123.string().min(1),
29485
- mime_type: z123.string().min(1).optional(),
29486
- file_name: z123.string().min(1).optional()
29523
+ var OpenAiFileReference = z124.object({
29524
+ download_url: z124.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."),
29525
+ file_id: z124.string().min(1),
29526
+ mime_type: z124.string().min(1).optional(),
29527
+ file_name: z124.string().min(1).optional()
29487
29528
  });
29488
29529
  var UploadSessionToolInputShape = {
29489
29530
  ...UploadSessionInputBase.shape,
29490
- files: z123.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.")
29531
+ files: z124.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.")
29491
29532
  };
29492
- var UploadSessionToolInput = z123.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
29533
+ var UploadSessionToolInput = z124.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
29493
29534
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
29494
29535
  ctx.addIssue({
29495
- code: z123.ZodIssueCode.custom,
29536
+ code: z124.ZodIssueCode.custom,
29496
29537
  path: [
29497
29538
  "mediaKind"
29498
29539
  ],
@@ -29501,7 +29542,7 @@ var UploadSessionToolInput = z123.object(UploadSessionToolInputShape).superRefin
29501
29542
  }
29502
29543
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
29503
29544
  ctx.addIssue({
29504
- code: z123.ZodIssueCode.custom,
29545
+ code: z124.ZodIssueCode.custom,
29505
29546
  path: [
29506
29547
  "maxFiles"
29507
29548
  ],
@@ -29510,7 +29551,7 @@ var UploadSessionToolInput = z123.object(UploadSessionToolInputShape).superRefin
29510
29551
  }
29511
29552
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
29512
29553
  ctx.addIssue({
29513
- code: z123.ZodIssueCode.custom,
29554
+ code: z124.ZodIssueCode.custom,
29514
29555
  path: [
29515
29556
  "maxFiles"
29516
29557
  ],
@@ -29518,38 +29559,38 @@ var UploadSessionToolInput = z123.object(UploadSessionToolInputShape).superRefin
29518
29559
  });
29519
29560
  }
29520
29561
  });
29521
- var UploadSessionResponse = z123.object({
29522
- sessionId: z123.string().uuid(),
29523
- uploadPageUrl: z123.string().url(),
29524
- mediaKind: z123.enum([
29562
+ var UploadSessionResponse = z124.object({
29563
+ sessionId: z124.string().uuid(),
29564
+ uploadPageUrl: z124.string().url(),
29565
+ mediaKind: z124.enum([
29525
29566
  "image",
29526
29567
  "video",
29527
29568
  "mixed"
29528
29569
  ]),
29529
- assetRole: z123.enum([
29570
+ assetRole: z124.enum([
29530
29571
  "media",
29531
29572
  "thumbnail"
29532
29573
  ]),
29533
- maxFiles: z123.number().int().positive(),
29534
- expiresAt: z123.string().datetime()
29574
+ maxFiles: z124.number().int().positive(),
29575
+ expiresAt: z124.string().datetime()
29535
29576
  });
29536
- var UploadStatusInput = z123.object({
29537
- sessionId: z123.string().uuid().describe("The sessionId returned by request_media_upload.")
29577
+ var UploadStatusInput = z124.object({
29578
+ sessionId: z124.string().uuid().describe("The sessionId returned by request_media_upload.")
29538
29579
  });
29539
- var UniversalUploadStatusResponse = z123.discriminatedUnion("status", [
29540
- z123.object({
29541
- status: z123.literal("pending"),
29542
- assets: z123.array(z123.never()).length(0)
29580
+ var UniversalUploadStatusResponse = z124.discriminatedUnion("status", [
29581
+ z124.object({
29582
+ status: z124.literal("pending"),
29583
+ assets: z124.array(z124.never()).length(0)
29543
29584
  }),
29544
- z123.object({
29545
- status: z123.literal("uploaded"),
29546
- assets: z123.array(z123.object({
29547
- assetId: z123.string().uuid(),
29548
- mediaKind: z123.enum([
29585
+ z124.object({
29586
+ status: z124.literal("uploaded"),
29587
+ assets: z124.array(z124.object({
29588
+ assetId: z124.string().uuid(),
29589
+ mediaKind: z124.enum([
29549
29590
  "image",
29550
29591
  "video"
29551
29592
  ]),
29552
- assetRole: z123.enum([
29593
+ assetRole: z124.enum([
29553
29594
  "media",
29554
29595
  "thumbnail"
29555
29596
  ])
@@ -29557,13 +29598,13 @@ var UniversalUploadStatusResponse = z123.discriminatedUnion("status", [
29557
29598
  })
29558
29599
  ]);
29559
29600
  var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
29560
- uploadPurpose: z123.enum([
29601
+ uploadPurpose: z124.enum([
29561
29602
  "product_reference",
29562
29603
  "creative",
29563
29604
  "generic"
29564
29605
  ]),
29565
- checkToolName: z123.literal("check_media_upload"),
29566
- resolveEndpoint: z123.string().url()
29606
+ checkToolName: z124.literal("check_media_upload"),
29607
+ resolveEndpoint: z124.string().url()
29567
29608
  });
29568
29609
  function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
29569
29610
  const url = new URL(uploadPageUrl);
@@ -29654,15 +29695,15 @@ function registerMediaUploadTools(server, api) {
29654
29695
  __name(registerMediaUploadTools, "registerMediaUploadTools");
29655
29696
 
29656
29697
  // src/tools/campaigns.ts
29657
- import { z as z124 } from "zod";
29698
+ import { z as z125 } from "zod";
29658
29699
  var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
29659
29700
  var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
29660
- var MetaStatusInput = z124.object({
29661
- campaignId: z124.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
29701
+ var MetaStatusInput = z125.object({
29702
+ campaignId: z125.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
29662
29703
  });
29663
- var TikTokStatusInput = z124.object({
29664
- campaignId: z124.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
29665
- advertiserId: z124.string().min(1).describe("The same advertiserId used to publish the campaign.")
29704
+ var TikTokStatusInput = z125.object({
29705
+ campaignId: z125.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
29706
+ advertiserId: z125.string().min(1).describe("The same advertiserId used to publish the campaign.")
29666
29707
  });
29667
29708
  function registerCampaignTools(server, api) {
29668
29709
  server.registerTool("get_meta_campaign_status", {
@@ -29767,10 +29808,10 @@ function renderTikTokStatusMarkdown(r) {
29767
29808
  __name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
29768
29809
 
29769
29810
  // ../../packages/product-economics/src/product-costing.ts
29770
- import { z as z126 } from "zod";
29811
+ import { z as z127 } from "zod";
29771
29812
 
29772
29813
  // ../../packages/product-economics/src/product-costing-countries.ts
29773
- import { z as z125 } from "zod";
29814
+ import { z as z126 } from "zod";
29774
29815
 
29775
29816
  // ../../packages/product-economics/src/product-costing-shipping-references.json
29776
29817
  var product_costing_shipping_references_default = {
@@ -29834,21 +29875,21 @@ var product_costing_shipping_references_default = {
29834
29875
  };
29835
29876
 
29836
29877
  // ../../packages/product-economics/src/product-costing-countries.ts
29837
- var ShippingReferenceSchema = z125.object({
29838
- reference: z125.number().positive(),
29839
- min: z125.number().nonnegative(),
29840
- max: z125.number().positive(),
29841
- updatedAt: z125.string().date(),
29842
- confidence: z125.enum([
29878
+ var ShippingReferenceSchema = z126.object({
29879
+ reference: z126.number().positive(),
29880
+ min: z126.number().nonnegative(),
29881
+ max: z126.number().positive(),
29882
+ updatedAt: z126.string().date(),
29883
+ confidence: z126.enum([
29843
29884
  "high",
29844
29885
  "medium",
29845
29886
  "medium-low"
29846
29887
  ]),
29847
- sources: z125.array(z125.string().url().startsWith("https://")).min(1).max(3)
29888
+ sources: z126.array(z126.string().url().startsWith("https://")).min(1).max(3)
29848
29889
  }).superRefine(({ reference, min, max }, context) => {
29849
29890
  if (min > reference || reference > max) {
29850
29891
  context.addIssue({
29851
- code: z125.ZodIssueCode.custom,
29892
+ code: z126.ZodIssueCode.custom,
29852
29893
  message: "shipping_reference_outside_range",
29853
29894
  path: [
29854
29895
  "reference"
@@ -29856,7 +29897,7 @@ var ShippingReferenceSchema = z125.object({
29856
29897
  });
29857
29898
  }
29858
29899
  });
29859
- var SHIPPING_REFERENCES = z125.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
29900
+ var SHIPPING_REFERENCES = z126.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
29860
29901
  var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
29861
29902
  var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
29862
29903
  "MX",
@@ -30038,18 +30079,18 @@ function getProductCostingCountryName(country) {
30038
30079
  __name(getProductCostingCountryName, "getProductCostingCountryName");
30039
30080
 
30040
30081
  // ../../packages/product-economics/src/product-costing.ts
30041
- var ProductCostingInputSchema = z126.object({
30042
- country: z126.string().refine(isProductCostingCountryCode, "unsupported_country"),
30043
- supplierCost: z126.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
30044
- shippingCost: z126.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
30045
- returnRate: z126.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
30046
- cancellationRate: z126.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
30047
- adsManagerCpa: z126.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
30048
- desiredMargin: z126.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
30082
+ var ProductCostingInputSchema = z127.object({
30083
+ country: z127.string().refine(isProductCostingCountryCode, "unsupported_country"),
30084
+ supplierCost: z127.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
30085
+ shippingCost: z127.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
30086
+ returnRate: z127.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
30087
+ cancellationRate: z127.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
30088
+ adsManagerCpa: z127.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
30089
+ desiredMargin: z127.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
30049
30090
  }).superRefine(({ returnRate, cancellationRate }, context) => {
30050
30091
  if (returnRate + cancellationRate >= 1) {
30051
30092
  context.addIssue({
30052
- code: z126.ZodIssueCode.custom,
30093
+ code: z127.ZodIssueCode.custom,
30053
30094
  message: "delivery_rate_positive",
30054
30095
  path: [
30055
30096
  "cancellationRate"
@@ -30146,15 +30187,15 @@ function calculateProductCosting(rawInput) {
30146
30187
  __name(calculateProductCosting, "calculateProductCosting");
30147
30188
 
30148
30189
  // src/tools/product-costing.ts
30149
- import { z as z127 } from "zod";
30190
+ import { z as z128 } from "zod";
30150
30191
  var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
30151
- var optionalAmount = /* @__PURE__ */ __name((description) => z127.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
30152
- var optionalPercent = /* @__PURE__ */ __name((description) => z127.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
30153
- var ProductCostingToolInput = z127.object({
30154
- country: z127.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
30192
+ var optionalAmount = /* @__PURE__ */ __name((description) => z128.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
30193
+ var optionalPercent = /* @__PURE__ */ __name((description) => z128.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
30194
+ var ProductCostingToolInput = z128.object({
30195
+ country: z128.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
30155
30196
  message: "Pa\xEDs no soportado por ProductMaker."
30156
30197
  }).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
30157
- supplierCost: z127.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."),
30198
+ supplierCost: z128.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."),
30158
30199
  supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
30159
30200
  shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
30160
30201
  shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
@@ -30317,7 +30358,7 @@ function formatPercent(value) {
30317
30358
  __name(formatPercent, "formatPercent");
30318
30359
 
30319
30360
  // src/tools/product-research.ts
30320
- import { z as z128 } from "zod";
30361
+ import { z as z129 } from "zod";
30321
30362
 
30322
30363
  // src/tools/product-research-idempotency.ts
30323
30364
  var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
@@ -30688,17 +30729,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
30688
30729
  ]);
30689
30730
  var POLL_INTERVAL_MS = 5e3;
30690
30731
  var MAX_WAIT_SECONDS = 120;
30691
- var FindInput = z128.object({
30732
+ var FindInput = z129.object({
30692
30733
  targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
30693
30734
  categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
30694
- confirmed: z128.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
30695
- waitSeconds: z128.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
30735
+ confirmed: z129.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
30736
+ waitSeconds: z129.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
30696
30737
  });
30697
- var GetInput = z128.object({
30698
- runId: z128.string().uuid().describe("ID del run devuelto por find_winning_products.")
30738
+ var GetInput = z129.object({
30739
+ runId: z129.string().uuid().describe("ID del run devuelto por find_winning_products.")
30699
30740
  });
30700
- var ListInput = z128.object({
30701
- limit: z128.number().int().min(1).max(20).default(10)
30741
+ var ListInput = z129.object({
30742
+ limit: z129.number().int().min(1).max(20).default(10)
30702
30743
  });
30703
30744
  function textResult(text2) {
30704
30745
  return {
@@ -30837,17 +30878,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
30837
30878
  __name(registerProductResearchTools, "registerProductResearchTools");
30838
30879
 
30839
30880
  // src/tools/dropshipping-projects.ts
30840
- import { z as z129 } from "zod";
30881
+ import { z as z130 } from "zod";
30841
30882
  var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
30842
30883
  var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
30843
30884
  var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
30844
- var ProjectId = z129.string().uuid();
30845
- var DropshippingProjectStatus = z129.enum([
30885
+ var ProjectId = z130.string().uuid();
30886
+ var DropshippingProjectStatus = z130.enum([
30846
30887
  "active",
30847
30888
  "completed",
30848
30889
  "archived"
30849
30890
  ]);
30850
- var DropshippingProjectPhase = z129.enum([
30891
+ var DropshippingProjectPhase = z130.enum([
30851
30892
  "research",
30852
30893
  "costing",
30853
30894
  "media",
@@ -30856,21 +30897,21 @@ var DropshippingProjectPhase = z129.enum([
30856
30897
  "advertising",
30857
30898
  "complete"
30858
30899
  ]);
30859
- var DropshippingRewardMilestone = z129.enum([
30900
+ var DropshippingRewardMilestone = z130.enum([
30860
30901
  "product_selected",
30861
30902
  "costing_saved",
30862
30903
  "product_media_ready",
30863
30904
  "creatives_completed",
30864
30905
  "campaign_created"
30865
30906
  ]);
30866
- var TargetCountry = z129.enum([
30907
+ var TargetCountry = z130.enum([
30867
30908
  "CO",
30868
30909
  "MX",
30869
30910
  "PE",
30870
30911
  "EC",
30871
30912
  "CL"
30872
30913
  ]);
30873
- var ResearchCategory = z129.enum([
30914
+ var ResearchCategory = z130.enum([
30874
30915
  "auto",
30875
30916
  "automotive",
30876
30917
  "kitchen",
@@ -30885,7 +30926,7 @@ var ResearchCategory = z129.enum([
30885
30926
  "garden",
30886
30927
  "cleaning"
30887
30928
  ]);
30888
- var HttpUrl3 = z129.string().url().max(2e3).refine((value) => {
30929
+ var HttpUrl3 = z130.string().url().max(2e3).refine((value) => {
30889
30930
  try {
30890
30931
  return [
30891
30932
  "http:",
@@ -30895,45 +30936,45 @@ var HttpUrl3 = z129.string().url().max(2e3).refine((value) => {
30895
30936
  return false;
30896
30937
  }
30897
30938
  }, "URL must use HTTP(S)");
30898
- var ResearchCandidateOrigin = z129.object({
30899
- type: z129.literal("research_candidate"),
30939
+ var ResearchCandidateOrigin = z130.object({
30940
+ type: z130.literal("research_candidate"),
30900
30941
  runId: ProjectId,
30901
- candidateSourceId: z129.string().min(1).max(160)
30942
+ candidateSourceId: z130.string().min(1).max(160)
30902
30943
  });
30903
- var TaskOrigin = z129.object({
30904
- type: z129.literal("task"),
30944
+ var TaskOrigin = z130.object({
30945
+ type: z130.literal("task"),
30905
30946
  taskId: ProjectId
30906
30947
  });
30907
- var ManualOrigin = z129.object({
30908
- type: z129.literal("manual"),
30948
+ var ManualOrigin = z130.object({
30949
+ type: z130.literal("manual"),
30909
30950
  clientRequestId: ProjectId,
30910
- country: z129.string().min(2).max(3).optional()
30951
+ country: z130.string().min(2).max(3).optional()
30911
30952
  });
30912
- var StartProjectInput = z129.object({
30913
- origin: z129.discriminatedUnion("type", [
30953
+ var StartProjectInput = z130.object({
30954
+ origin: z130.discriminatedUnion("type", [
30914
30955
  ResearchCandidateOrigin,
30915
30956
  TaskOrigin,
30916
30957
  ManualOrigin
30917
30958
  ]),
30918
- productName: z129.string().trim().min(1).max(240).optional(),
30959
+ productName: z130.string().trim().min(1).max(240).optional(),
30919
30960
  productUrl: HttpUrl3.optional(),
30920
- country: z129.string().min(2).max(3).optional(),
30921
- languageCode: z129.string().min(2).max(16).optional()
30961
+ country: z130.string().min(2).max(3).optional(),
30962
+ languageCode: z130.string().min(2).max(16).optional()
30922
30963
  }).strict();
30923
- var CostProjectInput = z129.object({
30964
+ var CostProjectInput = z130.object({
30924
30965
  projectId: ProjectId,
30925
- version: z129.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
30926
- country: z129.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
30966
+ version: z130.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
30967
+ country: z130.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
30927
30968
  message: "Pa\xEDs no soportado por ProductMaker."
30928
30969
  }).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
30929
- supplierCost: z129.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."),
30930
- shippingCost: z129.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
30931
- returnRate: z129.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."),
30932
- cancellationRate: z129.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."),
30933
- adsManagerCpa: z129.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
30934
- desiredMargin: z129.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
30935
- });
30936
- var GuideInput = z129.object({
30970
+ supplierCost: z130.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."),
30971
+ shippingCost: z130.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
30972
+ returnRate: z130.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."),
30973
+ cancellationRate: z130.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."),
30974
+ adsManagerCpa: z130.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
30975
+ desiredMargin: z130.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
30976
+ });
30977
+ var GuideInput = z130.object({
30937
30978
  projectId: ProjectId.optional()
30938
30979
  }).strict();
30939
30980
  var NEXT_ACTION_KINDS = [
@@ -30951,29 +30992,29 @@ var NEXT_ACTION_KINDS = [
30951
30992
  "repair_meta_campaign",
30952
30993
  "review_paused_campaign"
30953
30994
  ];
30954
- var DropshippingProjectNextAction = z129.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z129.object({
30955
- kind: z129.literal(kind),
30956
- href: z129.string().min(1)
30995
+ var DropshippingProjectNextAction = z130.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z130.object({
30996
+ kind: z130.literal(kind),
30997
+ href: z130.string().min(1)
30957
30998
  })));
30958
- var CostingInputSchema = z129.object({
30959
- country: z129.string().min(2).max(3),
30960
- supplierCost: z129.number().finite().positive(),
30961
- shippingCost: z129.number().finite().nonnegative(),
30962
- returnRate: z129.number().finite().min(0).lt(1),
30963
- cancellationRate: z129.number().finite().min(0).lt(1),
30964
- adsManagerCpa: z129.number().finite().nonnegative(),
30965
- desiredMargin: z129.number().finite().min(0).lt(1)
30999
+ var CostingInputSchema = z130.object({
31000
+ country: z130.string().min(2).max(3),
31001
+ supplierCost: z130.number().finite().positive(),
31002
+ shippingCost: z130.number().finite().nonnegative(),
31003
+ returnRate: z130.number().finite().min(0).lt(1),
31004
+ cancellationRate: z130.number().finite().min(0).lt(1),
31005
+ adsManagerCpa: z130.number().finite().nonnegative(),
31006
+ desiredMargin: z130.number().finite().min(0).lt(1)
30966
31007
  }).superRefine(({ returnRate, cancellationRate }, context) => {
30967
31008
  if (returnRate + cancellationRate >= 1) context.addIssue({
30968
- code: z129.ZodIssueCode.custom,
31009
+ code: z130.ZodIssueCode.custom,
30969
31010
  path: [
30970
31011
  "cancellationRate"
30971
31012
  ]
30972
31013
  });
30973
31014
  });
30974
- var FiniteCostingNumber = z129.number().finite();
30975
- var CostingResultSchema = z129.object({
30976
- country: z129.string().min(2).max(3),
31015
+ var FiniteCostingNumber = z130.number().finite();
31016
+ var CostingResultSchema = z130.object({
31017
+ country: z130.string().min(2).max(3),
30977
31018
  deliveryRate: FiniteCostingNumber,
30978
31019
  adjustedShippingCost: FiniteCostingNumber,
30979
31020
  adjustedCpa: FiniteCostingNumber,
@@ -30986,45 +31027,45 @@ var CostingResultSchema = z129.object({
30986
31027
  estimatedProfit: FiniteCostingNumber,
30987
31028
  actualMargin: FiniteCostingNumber,
30988
31029
  breakEvenAdsManagerCpa: FiniteCostingNumber,
30989
- wasPriceAutoAdjusted: z129.boolean(),
30990
- profitabilityStatus: z129.literal("healthy")
30991
- });
30992
- var RewardProgressSchema = z129.object({
30993
- campaignKey: z129.literal("dropshipping-launch-v1"),
30994
- totalCredits: z129.number().int().positive(),
30995
- earnedCredits: z129.number().int().nonnegative(),
30996
- milestones: z129.array(z129.object({
31030
+ wasPriceAutoAdjusted: z130.boolean(),
31031
+ profitabilityStatus: z130.literal("healthy")
31032
+ });
31033
+ var RewardProgressSchema = z130.object({
31034
+ campaignKey: z130.literal("dropshipping-launch-v1"),
31035
+ totalCredits: z130.number().int().positive(),
31036
+ earnedCredits: z130.number().int().nonnegative(),
31037
+ milestones: z130.array(z130.object({
30997
31038
  milestone: DropshippingRewardMilestone,
30998
- credits: z129.number().int().positive(),
30999
- available: z129.boolean().optional(),
31000
- earned: z129.boolean(),
31039
+ credits: z130.number().int().positive(),
31040
+ available: z130.boolean().optional(),
31041
+ earned: z130.boolean(),
31001
31042
  grantId: ProjectId.nullable(),
31002
- grantedAt: z129.string().datetime().nullable()
31043
+ grantedAt: z130.string().datetime().nullable()
31003
31044
  })).length(DropshippingRewardMilestone.options.length)
31004
31045
  });
31005
- var ProjectResponseSchema = z129.object({
31046
+ var ProjectResponseSchema = z130.object({
31006
31047
  id: ProjectId,
31007
31048
  taskId: ProjectId.nullable(),
31008
31049
  status: DropshippingProjectStatus,
31009
- originKey: z129.string().min(1),
31050
+ originKey: z130.string().min(1),
31010
31051
  researchRunId: ProjectId.nullable(),
31011
- candidateSourceId: z129.string().nullable(),
31012
- productName: z129.string().nullable(),
31052
+ candidateSourceId: z130.string().nullable(),
31053
+ productName: z130.string().nullable(),
31013
31054
  productUrl: HttpUrl3.nullable(),
31014
31055
  referenceImageUrl: HttpUrl3.nullable(),
31015
- targetCountry: z129.string().nullable(),
31016
- languageCode: z129.string().nullable(),
31017
- hasReferenceImage: z129.boolean(),
31018
- hasWinnerReferenceImage: z129.boolean(),
31056
+ targetCountry: z130.string().nullable(),
31057
+ languageCode: z130.string().nullable(),
31058
+ hasReferenceImage: z130.boolean(),
31059
+ hasWinnerReferenceImage: z130.boolean(),
31019
31060
  costingInput: CostingInputSchema.nullable(),
31020
31061
  costingResult: CostingResultSchema.nullable(),
31021
- costingVersion: z129.number().int().positive().nullable(),
31022
- version: z129.number().int().positive(),
31062
+ costingVersion: z130.number().int().positive().nullable(),
31063
+ version: z130.number().int().positive(),
31023
31064
  phase: DropshippingProjectPhase,
31024
31065
  nextAction: DropshippingProjectNextAction.nullable(),
31025
31066
  rewards: RewardProgressSchema,
31026
- createdAt: z129.string().datetime(),
31027
- updatedAt: z129.string().datetime()
31067
+ createdAt: z130.string().datetime(),
31068
+ updatedAt: z130.string().datetime()
31028
31069
  }).passthrough();
31029
31070
  var NEXT_ACTION_GUIDANCE = {
31030
31071
  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.",
@@ -31144,58 +31185,58 @@ function registerDropshippingProjectTools(server, api) {
31144
31185
  __name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
31145
31186
 
31146
31187
  // src/tools/daily-control.ts
31147
- import { z as z130 } from "zod";
31188
+ import { z as z131 } from "zod";
31148
31189
  var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
31149
31190
  var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
31150
31191
  var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
31151
- var ProviderCampaignIdentifier = z130.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
31152
- var DateOnly = z130.string().regex(/^\d{4}-\d{2}-\d{2}$/);
31153
- var DailyControlInput = z130.object({
31192
+ var ProviderCampaignIdentifier = z131.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
31193
+ var DateOnly = z131.string().regex(/^\d{4}-\d{2}-\d{2}$/);
31194
+ var DailyControlInput = z131.object({
31154
31195
  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."),
31155
- days: z130.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
31156
- projectId: z130.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
31196
+ days: z131.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
31197
+ projectId: z131.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
31157
31198
  }).strict();
31158
- var LinkCampaignInput = z130.object({
31159
- projectId: z130.string().uuid(),
31160
- provider: z130.enum([
31199
+ var LinkCampaignInput = z131.object({
31200
+ projectId: z131.string().uuid(),
31201
+ provider: z131.enum([
31161
31202
  "meta",
31162
31203
  "tiktok"
31163
31204
  ]),
31164
31205
  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."),
31165
31206
  campaignId: ProviderCampaignIdentifier
31166
31207
  }).strict();
31167
- var ReportReturnsInput = z130.object({
31168
- projectId: z130.string().uuid(),
31208
+ var ReportReturnsInput = z131.object({
31209
+ projectId: z131.string().uuid(),
31169
31210
  date: DateOnly,
31170
- returnedOrders: z130.number().int().min(0).max(1e5),
31171
- note: z130.string().trim().max(280).optional()
31211
+ returnedOrders: z131.number().int().min(0).max(1e5),
31212
+ note: z131.string().trim().max(280).optional()
31172
31213
  }).strict();
31173
- var DailyControlStatusMirror = DailyControlStatusEnum.or(z130.string());
31174
- var DailyControlLightMirror = DailyControlLightEnum.or(z130.string());
31175
- var DailyControlSourceMirror = DailyControlSourceEnum.or(z130.string());
31176
- var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z130.string());
31177
- var DailyControlDayMirror = z130.object({
31178
- date: z130.string(),
31179
- returnedOrders: z130.number(),
31214
+ var DailyControlStatusMirror = DailyControlStatusEnum.or(z131.string());
31215
+ var DailyControlLightMirror = DailyControlLightEnum.or(z131.string());
31216
+ var DailyControlSourceMirror = DailyControlSourceEnum.or(z131.string());
31217
+ var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z131.string());
31218
+ var DailyControlDayMirror = z131.object({
31219
+ date: z131.string(),
31220
+ returnedOrders: z131.number(),
31180
31221
  returnedSource: DailyControlSourceMirror,
31181
31222
  cancelledSource: DailyControlSourceMirror,
31182
- hasEstimates: z130.boolean(),
31223
+ hasEstimates: z131.boolean(),
31183
31224
  light: DailyControlLightMirror
31184
31225
  }).passthrough();
31185
- var DailyControlProductMirror = z130.object({
31186
- projectId: z130.string().uuid(),
31187
- productName: z130.string().nullable(),
31226
+ var DailyControlProductMirror = z131.object({
31227
+ projectId: z131.string().uuid(),
31228
+ productName: z131.string().nullable(),
31188
31229
  status: DailyControlStatusMirror,
31189
- statusMessage: z130.string().nullable(),
31190
- days: z130.array(DailyControlDayMirror),
31230
+ statusMessage: z131.string().nullable(),
31231
+ days: z131.array(DailyControlDayMirror),
31191
31232
  verdict: DailyControlVerdictMirror.nullable(),
31192
- rationale: z130.string().nullable()
31233
+ rationale: z131.string().nullable()
31193
31234
  }).passthrough();
31194
- var DailyControlResponseMirror = z130.object({
31195
- since: z130.string(),
31196
- until: z130.string(),
31197
- products: z130.array(DailyControlProductMirror),
31198
- archivedProjectSpend: z130.array(z130.unknown())
31235
+ var DailyControlResponseMirror = z131.object({
31236
+ since: z131.string(),
31237
+ until: z131.string(),
31238
+ products: z131.array(DailyControlProductMirror),
31239
+ archivedProjectSpend: z131.array(z131.unknown())
31199
31240
  }).passthrough();
31200
31241
  var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
31201
31242
  function withWarnings(response) {
@@ -31270,7 +31311,7 @@ __name(registerDailyControlTools, "registerDailyControlTools");
31270
31311
  // src/tools/product-control.ts
31271
31312
  import { readFile, stat } from "fs/promises";
31272
31313
  import { basename as basename2, isAbsolute, resolve as resolve3 } from "path";
31273
- import { z as z131 } from "zod";
31314
+ import { z as z132 } from "zod";
31274
31315
  var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
31275
31316
  var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
31276
31317
  var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
@@ -31283,36 +31324,36 @@ var createOperationGuidance = getProductMakerCapabilityModelGuidance("create_ope
31283
31324
  var mergeProductsGuidance = getProductMakerCapabilityModelGuidance("merge_products");
31284
31325
  var syncShopifyOrdersGuidance = getProductMakerCapabilityModelGuidance("sync_shopify_orders");
31285
31326
  var importOrdersFileGuidance = getProductMakerCapabilityModelGuidance("import_orders_file");
31286
- var DateOnly2 = z131.string().regex(/^\d{4}-\d{2}-\d{2}$/);
31327
+ var DateOnly2 = z132.string().regex(/^\d{4}-\d{2}-\d{2}$/);
31287
31328
  var IMPORT_BATCH_MAX2 = 50;
31288
- var ProductControlListInput = z131.object({
31289
- days: z131.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
31329
+ var ProductControlListInput = z132.object({
31330
+ days: z132.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
31290
31331
  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."),
31291
- shopDomain: z131.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
31332
+ shopDomain: z132.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
31292
31333
  }).strict();
31293
- var ImportableProductsInput = z131.object({
31294
- q: z131.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
31295
- after: z131.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
31296
- shopDomain: z131.string().min(1).optional()
31334
+ var ImportableProductsInput = z132.object({
31335
+ q: z132.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
31336
+ after: z132.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
31337
+ shopDomain: z132.string().min(1).optional()
31297
31338
  }).strict();
31298
- var ImportProductControlsInput = z131.object({
31299
- shopifyProductIds: z131.array(z131.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."),
31339
+ var ImportProductControlsInput = z132.object({
31340
+ shopifyProductIds: z132.array(z132.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."),
31300
31341
  // Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
31301
31342
  // sin decir a cuál archivaría el producto bajo la tienda equivocada.
31302
- shopDomain: z131.string().min(1)
31343
+ shopDomain: z132.string().min(1)
31303
31344
  }).strict();
31304
- var SetProductCostingInput = z131.object({
31305
- shopDomain: z131.string().min(1),
31306
- shopifyProductId: z131.string().min(1).max(64),
31307
- targetCountry: z131.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
31308
- supplierCost: z131.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
31309
- shippingCost: z131.number().finite().nonnegative(),
31310
- returnRate: z131.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
31311
- cancellationRate: z131.number().finite().min(0).lt(1)
31345
+ var SetProductCostingInput = z132.object({
31346
+ shopDomain: z132.string().min(1),
31347
+ shopifyProductId: z132.string().min(1).max(64),
31348
+ targetCountry: z132.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
31349
+ supplierCost: z132.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
31350
+ shippingCost: z132.number().finite().nonnegative(),
31351
+ returnRate: z132.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
31352
+ cancellationRate: z132.number().finite().min(0).lt(1)
31312
31353
  }).strict();
31313
- var Count = z131.number().int().min(0).max(1e5).nullable().optional();
31314
- var ReportProductCountsInput = z131.object({
31315
- productControlId: z131.string().uuid().describe("El identificador que devuelve get_product_control."),
31354
+ var Count = z132.number().int().min(0).max(1e5).nullable().optional();
31355
+ var ReportProductCountsInput = z132.object({
31356
+ productControlId: z132.string().uuid().describe("El identificador que devuelve get_product_control."),
31316
31357
  date: DateOnly2,
31317
31358
  orders: Count.describe("Pedidos que entraron ese d\xEDa."),
31318
31359
  cancelledOrders: Count,
@@ -31322,36 +31363,36 @@ var ReportProductCountsInput = z131.object({
31322
31363
  }).strict();
31323
31364
  var MAX_ORDERS_FILE_BYTES = 8 * 1024 * 1024;
31324
31365
  var SyncShopifyOrdersInput = SyncShopifyOrdersSchema;
31325
- var ImportOrdersFileInput = z131.object({
31366
+ var ImportOrdersFileInput = z132.object({
31326
31367
  /** Ruta ABSOLUTA en la máquina de quien usa el MCP. */
31327
- path: z131.string().min(1),
31328
- operationId: z131.string().uuid().optional(),
31368
+ path: z132.string().min(1),
31369
+ operationId: z132.string().uuid().optional(),
31329
31370
  /** Solo mirar: devuelve el resumen y no escribe nada. */
31330
- dryRun: z131.boolean().optional()
31371
+ dryRun: z132.boolean().optional()
31331
31372
  }).strict();
31332
- var CreateOperationInput = z131.object({
31333
- countryCode: z131.string().length(2),
31334
- label: z131.string().trim().min(1).max(60).optional()
31373
+ var CreateOperationInput = z132.object({
31374
+ countryCode: z132.string().length(2),
31375
+ label: z132.string().trim().min(1).max(60).optional()
31335
31376
  }).strict();
31336
- var MergeProductsInput = z131.object({
31337
- sourceId: z131.string().uuid(),
31338
- targetId: z131.string().uuid()
31377
+ var MergeProductsInput = z132.object({
31378
+ sourceId: z132.string().uuid(),
31379
+ targetId: z132.string().uuid()
31339
31380
  }).strict();
31340
- var SetMonthlyExpenseInput = z131.object({
31341
- month: z131.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
31381
+ var SetMonthlyExpenseInput = z132.object({
31382
+ month: z132.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
31342
31383
  label: SaveMonthlyExpenseSchema.shape.label,
31343
- amount: z131.number().finite().min(0),
31344
- operationId: z131.string().uuid().optional()
31384
+ amount: z132.number().finite().min(0),
31385
+ operationId: z132.string().uuid().optional()
31345
31386
  }).strict();
31346
- var SetAdSpendInput = z131.object({
31347
- month: z131.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
31348
- operationId: z131.string().uuid().optional(),
31387
+ var SetAdSpendInput = z132.object({
31388
+ month: z132.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
31389
+ operationId: z132.string().uuid().optional(),
31349
31390
  /** null RETIRA la corrección; cero afirma que no pautó. */
31350
- amount: z131.number().finite().min(0).nullable()
31391
+ amount: z132.number().finite().min(0).nullable()
31351
31392
  }).strict();
31352
- var GetFinancesInput = z131.object({
31353
- month: z131.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."),
31354
- operationId: z131.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
31393
+ var GetFinancesInput = z132.object({
31394
+ month: z132.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."),
31395
+ operationId: z132.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
31355
31396
  }).strict();
31356
31397
  function registerProductControlTools(server, api, { transport = "http" } = {}) {
31357
31398
  server.registerTool("get_product_control", {
@@ -31543,28 +31584,28 @@ function registerProductControlTools(server, api, { transport = "http" } = {}) {
31543
31584
  __name(registerProductControlTools, "registerProductControlTools");
31544
31585
 
31545
31586
  // src/tools/market-study-estimate.ts
31546
- import { z as z132 } from "zod";
31587
+ import { z as z133 } from "zod";
31547
31588
  var estimateMarketStudyGuidance = getProductMakerCapabilityModelGuidance("estimate_market_study_cost");
31548
- var ProductTaskOutputEnum = z132.enum([
31589
+ var ProductTaskOutputEnum = z133.enum([
31549
31590
  "landing",
31550
31591
  "video",
31551
31592
  "image"
31552
31593
  ]);
31553
- var EstimateMarketStudyInput = z132.object({
31554
- kind: z132.enum([
31594
+ var EstimateMarketStudyInput = z133.object({
31595
+ kind: z133.enum([
31555
31596
  "video",
31556
31597
  "product_task"
31557
31598
  ]).describe('"video" para generate_video_creative; "product_task" para create_product_task.'),
31558
- videoAngleCount: z132.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
31559
- durationSeconds: z132.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
31599
+ videoAngleCount: z133.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
31600
+ durationSeconds: z133.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
31560
31601
  videoStructure: VideoStructureEnum.default("single_take"),
31561
31602
  videoQuality: VideoQualityEnum.default("economy"),
31562
31603
  videoResolution: VideoResolutionEnum.default("480p"),
31563
- productImageCount: z132.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
31604
+ productImageCount: z133.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
31564
31605
  outputs: ProductTaskOutputEnum.array().min(1).max(3).optional().describe('Solo para kind="product_task": los mismos outputs de create_product_task. Default: todos.'),
31565
- generateAiMusic: z132.boolean().optional(),
31606
+ generateAiMusic: z133.boolean().optional(),
31566
31607
  generateAiEdit: AiEditRequestSchema.optional(),
31567
- replicateWinnerWhenFound: z132.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.")
31608
+ replicateWinnerWhenFound: z133.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.")
31568
31609
  }).strict();
31569
31610
  function buildMarketStudyEstimateRequests(input) {
31570
31611
  const quotesVideo = input.kind === "video" || (input.outputs ?? [