@productmaker/mcp 12.1.0 → 12.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/http.js CHANGED
@@ -5326,6 +5326,7 @@ var ImageCreativeArchetype = z24.enum([
5326
5326
  "problem_solution",
5327
5327
  "lifestyle_identity"
5328
5328
  ]);
5329
+ var MAX_IMAGE_CREATIVE_VARIANTS = 6;
5329
5330
  var ImageCreativeVisualTreatment = z24.enum([
5330
5331
  "performance_product_ad",
5331
5332
  "premium_dtc_carousel"
@@ -23784,14 +23785,37 @@ var WebsiteCaptureResearchSchema = z116.object({
23784
23785
  });
23785
23786
 
23786
23787
  // ../../packages/types/src/demo-mode.ts
23788
+ import { z as z118 } from "zod";
23789
+
23790
+ // ../../packages/types/src/demo-mode-service-page-assets.ts
23787
23791
  import { z as z117 } from "zod";
23792
+ var DemoServicePageAssetSourceSchema = z117.object({
23793
+ pageId: z117.string().uuid(),
23794
+ ownerId: z117.string().min(1),
23795
+ assets: z117.array(z117.object({
23796
+ id: z117.string().uuid(),
23797
+ storageKey: z117.string().min(1).max(1024),
23798
+ mediaType: z117.enum([
23799
+ "image/webp",
23800
+ "video/mp4"
23801
+ ]),
23802
+ byteSize: z117.number().int().positive().max(32 * 1024 * 1024),
23803
+ width: z117.number().int().positive().max(1920),
23804
+ height: z117.number().int().positive().max(1920),
23805
+ contentHash: z117.string().regex(/^[a-f0-9]{64}$/i),
23806
+ sourceKind: ServicePageSourceKindSchema,
23807
+ approvedAt: z117.string().datetime()
23808
+ }).strict()).max(24)
23809
+ }).strict();
23810
+
23811
+ // ../../packages/types/src/demo-mode.ts
23788
23812
  var DEMO_MODE_FLOWS = [
23789
23813
  "brand",
23790
23814
  "servicePage",
23791
23815
  "motion",
23792
23816
  "image"
23793
23817
  ];
23794
- var DemoModeFlowSchema = z117.enum(DEMO_MODE_FLOWS);
23818
+ var DemoModeFlowSchema = z118.enum(DEMO_MODE_FLOWS);
23795
23819
  var DEMO_MODE_STEPS = [
23796
23820
  "running",
23797
23821
  "research",
@@ -23804,27 +23828,30 @@ var DEMO_MODE_STEPS = [
23804
23828
  "final",
23805
23829
  "watchdog"
23806
23830
  ];
23807
- var DemoModeStepSchema = z117.enum(DEMO_MODE_STEPS);
23831
+ var DemoModeStepSchema = z118.enum(DEMO_MODE_STEPS);
23808
23832
  var DEMO_MODE_WAIT_SECONDS = {
23809
23833
  min: 30,
23810
23834
  max: 450,
23811
23835
  default: 150
23812
23836
  };
23813
- var centsSchema = z117.number().int().min(0).max(1e5);
23814
- var emailSchema = z117.string().trim().toLowerCase().email();
23815
- var DemoModeTemplatesSchema = z117.object({
23816
- brandId: z117.string().uuid(),
23817
- servicePageId: z117.string().uuid(),
23818
- motionTaskId: z117.string().uuid(),
23819
- imageTaskId: z117.string().uuid()
23820
- });
23821
- var DemoModeEditableSchema = z117.object({
23822
- enabled: z117.boolean(),
23823
- emails: z117.array(emailSchema).max(50).transform((list) => [
23837
+ var centsSchema = z118.number().int().min(0).max(1e5);
23838
+ var emailSchema = z118.string().trim().toLowerCase().email();
23839
+ var optionalTemplateId = z118.preprocess((value) => value === "" ? void 0 : value, z118.string().uuid().optional());
23840
+ var DemoModeTemplatesSchema = z118.object({
23841
+ brandId: z118.string().uuid(),
23842
+ servicePageId: z118.string().uuid(),
23843
+ motionTaskId: z118.string().uuid(),
23844
+ motionVariantTaskId: optionalTemplateId,
23845
+ motionThirdTaskId: optionalTemplateId,
23846
+ imageTaskId: z118.string().uuid()
23847
+ });
23848
+ var DemoModeEditableSchema = z118.object({
23849
+ enabled: z118.boolean(),
23850
+ emails: z118.array(emailSchema).max(50).transform((list) => [
23824
23851
  ...new Set(list)
23825
23852
  ]),
23826
- waitSeconds: z117.number().int().min(DEMO_MODE_WAIT_SECONDS.min).max(DEMO_MODE_WAIT_SECONDS.max),
23827
- chargeCents: z117.object({
23853
+ waitSeconds: z118.number().int().min(DEMO_MODE_WAIT_SECONDS.min).max(DEMO_MODE_WAIT_SECONDS.max),
23854
+ chargeCents: z118.object({
23828
23855
  brand: centsSchema,
23829
23856
  servicePage: centsSchema,
23830
23857
  motion: centsSchema,
@@ -23832,73 +23859,77 @@ var DemoModeEditableSchema = z117.object({
23832
23859
  }),
23833
23860
  templates: DemoModeTemplatesSchema
23834
23861
  });
23835
- var nullableString = z117.string().nullable();
23836
- var DemoModeSnapshotSchema = z117.object({
23837
- brand: z117.object({
23862
+ var nullableString = z118.string().nullable();
23863
+ var DemoModeSnapshotSchema = z118.object({
23864
+ brand: z118.object({
23838
23865
  /** Columnas de identidad de `Brand` listas para un `update` (sin id/userId/slug/estado/fechas). */
23839
- identity: z117.record(z117.unknown()),
23840
- productSamples: z117.array(z117.object({
23841
- name: z117.string(),
23842
- priceCents: z117.number().int().nullable(),
23866
+ identity: z118.record(z118.unknown()),
23867
+ productSamples: z118.array(z118.object({
23868
+ name: z118.string(),
23869
+ priceCents: z118.number().int().nullable(),
23843
23870
  currency: nullableString,
23844
- imageKey: z117.string(),
23871
+ imageKey: z118.string(),
23845
23872
  productUrl: nullableString,
23846
- position: z117.number().int()
23873
+ position: z118.number().int()
23847
23874
  })),
23848
- personas: z117.array(z117.object({
23849
- name: z117.string(),
23875
+ personas: z118.array(z118.object({
23876
+ name: z118.string(),
23850
23877
  demographics: nullableString,
23851
23878
  painPoints: nullableString,
23852
23879
  motivations: nullableString,
23853
23880
  objections: nullableString,
23854
23881
  gender: nullableString,
23855
- isDefault: z117.boolean()
23882
+ isDefault: z118.boolean()
23856
23883
  }))
23857
23884
  }),
23858
- servicePage: z117.object({
23859
- facts: z117.unknown(),
23860
- review: z117.unknown(),
23861
- artifact: z117.unknown()
23885
+ servicePage: z118.object({
23886
+ facts: z118.unknown(),
23887
+ review: z118.unknown(),
23888
+ artifact: z118.unknown(),
23889
+ /** Optional only for snapshots saved before page-owned demo media. */
23890
+ assetSource: DemoServicePageAssetSourceSchema.optional()
23862
23891
  }),
23863
- motion: z117.object({
23892
+ motion: z118.object({
23864
23893
  outputs: MotionGraphicsOutputsSchema,
23865
23894
  /**
23866
23895
  * La captura REAL de la web de la plantilla (nunca una fabricada por la
23867
23896
  * demo). Null cuando la plantilla no tiene ninguna: la captura demo nunca
23868
23897
  * va live, así que el servicio usa `DEMO_MODE_PLACEHOLDER_CAPTURE`.
23869
23898
  */
23870
- capture: z117.object({
23871
- bundleKey: z117.string(),
23872
- sha256: z117.string(),
23873
- uploadBytes: z117.number().int().nullable(),
23899
+ capture: z118.object({
23900
+ bundleKey: z118.string(),
23901
+ sha256: z118.string(),
23902
+ uploadBytes: z118.number().int().nullable(),
23874
23903
  previewKey: nullableString
23875
23904
  }).nullable()
23876
23905
  }),
23877
- image: z117.object({
23878
- provider: z117.string(),
23879
- model: z117.string(),
23880
- prompt: z117.string(),
23881
- imageUrl: z117.string(),
23882
- width: z117.number().int(),
23883
- height: z117.number().int(),
23906
+ image: z118.object({
23907
+ provider: z118.string(),
23908
+ model: z118.string(),
23909
+ prompt: z118.string(),
23910
+ imageUrl: z118.string(),
23911
+ width: z118.number().int(),
23912
+ height: z118.number().int(),
23884
23913
  adCopy: nullableString,
23885
- rawResponse: z117.unknown()
23914
+ rawResponse: z118.unknown()
23886
23915
  })
23887
23916
  });
23888
23917
  var DemoModeConfigSchema = DemoModeEditableSchema.extend({
23889
23918
  snapshot: DemoModeSnapshotSchema.nullable(),
23890
- snapshotAt: z117.string().datetime().nullable()
23919
+ snapshotAt: z118.string().datetime().nullable()
23891
23920
  });
23892
23921
  var DemoModeAdminViewSchema = DemoModeEditableSchema.extend({
23893
23922
  // Sin configurar, la API devuelve ids vacíos ("" no es uuid): la vista los
23894
23923
  // admite; el PUT sí exige uuid (`DemoModeEditableSchema`).
23895
- templates: z117.object({
23896
- brandId: z117.string(),
23897
- servicePageId: z117.string(),
23898
- motionTaskId: z117.string(),
23899
- imageTaskId: z117.string()
23924
+ templates: z118.object({
23925
+ brandId: z118.string(),
23926
+ servicePageId: z118.string(),
23927
+ motionTaskId: z118.string(),
23928
+ motionVariantTaskId: z118.string().optional(),
23929
+ motionThirdTaskId: z118.string().optional(),
23930
+ imageTaskId: z118.string()
23900
23931
  }),
23901
- snapshotAt: z117.string().nullable()
23932
+ snapshotAt: z118.string().nullable()
23902
23933
  });
23903
23934
  var DEMO_MODE_TEMPLATE_PROBLEMS = [
23904
23935
  "not_found",
@@ -23909,31 +23940,33 @@ var DEMO_MODE_TEMPLATE_PROBLEMS = [
23909
23940
  "no_video",
23910
23941
  "no_creative"
23911
23942
  ];
23912
- var DemoModeTemplateVerdictSchema = z117.discriminatedUnion("ok", [
23913
- z117.object({
23914
- ok: z117.literal(true)
23943
+ var DemoModeTemplateVerdictSchema = z118.discriminatedUnion("ok", [
23944
+ z118.object({
23945
+ ok: z118.literal(true)
23915
23946
  }),
23916
- z117.object({
23917
- ok: z117.literal(false),
23918
- problem: z117.enum(DEMO_MODE_TEMPLATE_PROBLEMS)
23947
+ z118.object({
23948
+ ok: z118.literal(false),
23949
+ problem: z118.enum(DEMO_MODE_TEMPLATE_PROBLEMS)
23919
23950
  })
23920
23951
  ]);
23921
- var DemoModeValidationSchema = z117.object({
23952
+ var DemoModeValidationSchema = z118.object({
23922
23953
  brandId: DemoModeTemplateVerdictSchema,
23923
23954
  servicePageId: DemoModeTemplateVerdictSchema,
23924
23955
  motionTaskId: DemoModeTemplateVerdictSchema,
23956
+ motionVariantTaskId: DemoModeTemplateVerdictSchema.optional(),
23957
+ motionThirdTaskId: DemoModeTemplateVerdictSchema.optional(),
23925
23958
  imageTaskId: DemoModeTemplateVerdictSchema
23926
23959
  });
23927
- var DemoModeJobSchema = z117.object({
23960
+ var DemoModeJobSchema = z118.object({
23928
23961
  flow: DemoModeFlowSchema,
23929
23962
  step: DemoModeStepSchema,
23930
23963
  /** brandId | servicePageOperationId | taskId según el flujo. */
23931
- targetId: z117.string().uuid(),
23932
- userId: z117.string().min(1),
23964
+ targetId: z118.string().uuid(),
23965
+ userId: z118.string().min(1),
23933
23966
  /** Solo marca: la generación de extracción que el guion completa. */
23934
- generation: z117.number().int().positive().optional(),
23967
+ generation: z118.number().int().positive().optional(),
23935
23968
  /** Solo `final`/`watchdog`: la parte del snapshot de ESTE flujo, congelada al empezar. */
23936
- result: z117.unknown().optional()
23969
+ result: z118.unknown().optional()
23937
23970
  });
23938
23971
 
23939
23972
  // src/http.ts
@@ -24445,23 +24478,23 @@ import { InsufficientScopeError, InvalidTokenError } from "@modelcontextprotocol
24445
24478
  import { createRemoteJWKSet as createRemoteJWKSet2, jwtVerify as jwtVerify2 } from "jose";
24446
24479
 
24447
24480
  // src/auth/oauth-config.ts
24448
- import { z as z118 } from "zod";
24481
+ import { z as z119 } from "zod";
24449
24482
  var MCP_RESOURCE = new URL("https://mcp.productmaker.app/mcp");
24450
24483
  var MCP_SCOPE = "mcp:access";
24451
24484
  var REFRESH_SCOPE = "offline_access";
24452
24485
  var STATIC_CLIENT_ISSUER = new URL(MCP_RESOURCE.origin);
24453
- var oauthEnvSchema = z118.object({
24454
- MCP_REMOTE_AUTH_MODE: z118.literal("oauth"),
24455
- MCP_AUTH0_ISSUER: z118.string().trim().min(1),
24456
- MCP_AUTH0_AUDIENCE: z118.string().trim().refine((value) => value === MCP_RESOURCE.href, {
24486
+ var oauthEnvSchema = z119.object({
24487
+ MCP_REMOTE_AUTH_MODE: z119.literal("oauth"),
24488
+ MCP_AUTH0_ISSUER: z119.string().trim().min(1),
24489
+ MCP_AUTH0_AUDIENCE: z119.string().trim().refine((value) => value === MCP_RESOURCE.href, {
24457
24490
  message: `must equal ${MCP_RESOURCE.href}`
24458
24491
  }),
24459
- MCP_AUTH0_CLIENT_ID: z118.string().trim().min(1),
24460
- MCP_AUTH0_CLIENT_SECRET: z118.string().trim().min(1),
24461
- PM_API_AUDIENCE: z118.string().trim().min(1),
24462
- AUTH0_AUDIENCE: z118.string().trim().min(1),
24463
- MCP_STATIC_CLIENT_ID: z118.string().trim().min(1).optional(),
24464
- MCP_STATIC_CLIENT_SECRET: z118.string().trim().min(1).optional()
24492
+ MCP_AUTH0_CLIENT_ID: z119.string().trim().min(1),
24493
+ MCP_AUTH0_CLIENT_SECRET: z119.string().trim().min(1),
24494
+ PM_API_AUDIENCE: z119.string().trim().min(1),
24495
+ AUTH0_AUDIENCE: z119.string().trim().min(1),
24496
+ MCP_STATIC_CLIENT_ID: z119.string().trim().min(1).optional(),
24497
+ MCP_STATIC_CLIENT_SECRET: z119.string().trim().min(1).optional()
24465
24498
  });
24466
24499
  function formatZodIssues(error) {
24467
24500
  return error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
@@ -24644,7 +24677,7 @@ var Auth0TokenVerifier = class {
24644
24677
  }
24645
24678
  };
24646
24679
 
24647
- // src/oauth-analytics.ts
24680
+ // src/analytics.ts
24648
24681
  import { PostHog } from "posthog-node";
24649
24682
  var DEFAULT_POSTHOG_HOST = "https://us.i.posthog.com";
24650
24683
  var REDACTED = "[REDACTED]";
@@ -24664,12 +24697,6 @@ var SENSITIVE_KEYS = /* @__PURE__ */ new Set([
24664
24697
  var SENSITIVE_ASSIGNMENT_PATTERN = /(\b(?:access[_-]?token|authorization|client[_-]?secret|subject[_-]?token|refresh[_-]?token|id[_-]?token|api[_-]?key|token|secret|password|code)\b\s*[:=]\s*)(?:(bearer)\s+)?(?:(['"])(.*?)\3|([^\s,;&}"']+))/gi;
24665
24698
  var BEARER_TOKEN_PATTERN = /\b(bearer\s+)([A-Za-z0-9._~+/=-]+)/gi;
24666
24699
  var client = null;
24667
- var KNOWN_MCP_OAUTH_ANALYTICS_EVENTS = [
24668
- MCP_OAUTH_ANALYTICS_EVENTS.STARTED,
24669
- MCP_OAUTH_ANALYTICS_EVENTS.CONNECTED,
24670
- MCP_OAUTH_ANALYTICS_EVENTS.FAILED,
24671
- MCP_OAUTH_ANALYTICS_EVENTS.SAFE_VARIANT
24672
- ];
24673
24700
  function getPostHogClient() {
24674
24701
  if (client) return client;
24675
24702
  const apiKey = process.env.POSTHOG_API_KEY;
@@ -24722,18 +24749,7 @@ function sanitizeValue(value) {
24722
24749
  return value.map((entry) => sanitizeValue(entry));
24723
24750
  }
24724
24751
  if (value && typeof value === "object") {
24725
- return Object.fromEntries(Object.entries(value).map(([key, entry]) => {
24726
- if (isSensitiveKey(key)) {
24727
- return [
24728
- key,
24729
- REDACTED
24730
- ];
24731
- }
24732
- return [
24733
- key,
24734
- sanitizeValue(entry)
24735
- ];
24736
- }));
24752
+ return sanitizeProperties(value);
24737
24753
  }
24738
24754
  if (typeof value === "string") {
24739
24755
  return sanitizeString(value);
@@ -24741,21 +24757,40 @@ function sanitizeValue(value) {
24741
24757
  return value;
24742
24758
  }
24743
24759
  __name(sanitizeValue, "sanitizeValue");
24760
+ function sanitizeProperties(value) {
24761
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [
24762
+ key,
24763
+ isSensitiveKey(key) ? REDACTED : sanitizeValue(entry)
24764
+ ]));
24765
+ }
24766
+ __name(sanitizeProperties, "sanitizeProperties");
24767
+ function captureMcpAnalytics(event, subject, properties) {
24768
+ try {
24769
+ const posthog = getPostHogClient();
24770
+ if (!posthog) return;
24771
+ posthog.capture({
24772
+ distinctId: subject ?? "mcp_oauth_aggregate",
24773
+ event,
24774
+ properties: properties ? sanitizeProperties(properties) : void 0
24775
+ });
24776
+ } catch {
24777
+ }
24778
+ }
24779
+ __name(captureMcpAnalytics, "captureMcpAnalytics");
24780
+
24781
+ // src/oauth-analytics.ts
24782
+ var KNOWN_MCP_OAUTH_ANALYTICS_EVENTS = [
24783
+ MCP_OAUTH_ANALYTICS_EVENTS.STARTED,
24784
+ MCP_OAUTH_ANALYTICS_EVENTS.CONNECTED,
24785
+ MCP_OAUTH_ANALYTICS_EVENTS.FAILED,
24786
+ MCP_OAUTH_ANALYTICS_EVENTS.SAFE_VARIANT
24787
+ ];
24744
24788
  var OAuthAnalytics = class {
24745
24789
  static {
24746
24790
  __name(this, "OAuthAnalytics");
24747
24791
  }
24748
24792
  capture(event, subject, properties) {
24749
- const posthog = getPostHogClient();
24750
- if (!posthog) return;
24751
- try {
24752
- posthog.capture({
24753
- distinctId: subject ?? "mcp_oauth_aggregate",
24754
- event,
24755
- properties: sanitizeValue(properties)
24756
- });
24757
- } catch {
24758
- }
24793
+ captureMcpAnalytics(event, subject, properties);
24759
24794
  }
24760
24795
  };
24761
24796
 
@@ -25848,7 +25883,7 @@ var ApiClient = class {
25848
25883
  };
25849
25884
 
25850
25885
  // src/index.ts
25851
- var MCP_VERSION = "12.1.0";
25886
+ var MCP_VERSION = "12.1.1";
25852
25887
 
25853
25888
  // src/meta-upload-app.ts
25854
25889
  import { readFileSync } from "fs";
@@ -25919,8 +25954,123 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
25919
25954
  }
25920
25955
  __name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
25921
25956
 
25957
+ // src/task-results-app.ts
25958
+ import { readFileSync as readFileSync2 } from "fs";
25959
+ import { registerAppResource as registerAppResource2, RESOURCE_MIME_TYPE as RESOURCE_MIME_TYPE2 } from "@modelcontextprotocol/ext-apps/server";
25960
+ var TASK_RESULTS_APP_RESOURCE_URI = "ui://task-results/v1.html";
25961
+ var HTML_URL = new URL("./ui/task-results-app.html", import.meta.url);
25962
+ function assetOrigin(value) {
25963
+ if (!value) return null;
25964
+ try {
25965
+ const url = new URL(value);
25966
+ return url.protocol === "https:" && !url.username && !url.password ? url.origin : null;
25967
+ } catch {
25968
+ return null;
25969
+ }
25970
+ }
25971
+ __name(assetOrigin, "assetOrigin");
25972
+ function buildTaskResultsView(media, proxyBaseUrl) {
25973
+ const origin = assetOrigin(proxyBaseUrl);
25974
+ const safeUrl = /* @__PURE__ */ __name((value) => {
25975
+ if (!origin) return null;
25976
+ try {
25977
+ const url = new URL(value);
25978
+ return url.protocol === "https:" && url.origin === origin && url.pathname.startsWith("/assets/") && url.pathname.length > "/assets/".length && !url.username && !url.password ? url.href : null;
25979
+ } catch {
25980
+ return null;
25981
+ }
25982
+ }, "safeUrl");
25983
+ const images = media.images.flatMap((image, index) => {
25984
+ const url = safeUrl(image.url);
25985
+ return url ? [
25986
+ {
25987
+ url,
25988
+ alt: image.alt?.slice(0, 160) ?? `ProductMaker image ${index + 1}`
25989
+ }
25990
+ ] : [];
25991
+ });
25992
+ const videos = media.videos.flatMap((video) => {
25993
+ const url = safeUrl(video.url);
25994
+ return url ? [
25995
+ {
25996
+ url,
25997
+ ...video.label ? {
25998
+ label: video.label.slice(0, 120)
25999
+ } : {},
26000
+ ...video.scriptRewritten === true ? {
26001
+ scriptRewritten: true
26002
+ } : {}
26003
+ }
26004
+ ] : [];
26005
+ });
26006
+ const links = media.links.flatMap((link) => {
26007
+ const url = safeUrl(link.url);
26008
+ return url ? [
26009
+ {
26010
+ url,
26011
+ label: link.label?.slice(0, 120) ?? "Open result"
26012
+ }
26013
+ ] : [];
26014
+ });
26015
+ return {
26016
+ state: images.length || videos.length || links.length ? "ready" : "empty",
26017
+ images,
26018
+ videos,
26019
+ links
26020
+ };
26021
+ }
26022
+ __name(buildTaskResultsView, "buildTaskResultsView");
26023
+ function taskResultsToolMeta() {
26024
+ return {
26025
+ ui: {
26026
+ resourceUri: TASK_RESULTS_APP_RESOURCE_URI
26027
+ },
26028
+ "openai/outputTemplate": TASK_RESULTS_APP_RESOURCE_URI
26029
+ };
26030
+ }
26031
+ __name(taskResultsToolMeta, "taskResultsToolMeta");
26032
+ function renderTaskResultsAppHtml(proxyBaseUrl) {
26033
+ return readFileSync2(HTML_URL, "utf8").replace("__PRODUCTMAKER_ASSET_ORIGIN__", JSON.stringify(assetOrigin(proxyBaseUrl)).replaceAll("<", "\\u003c"));
26034
+ }
26035
+ __name(renderTaskResultsAppHtml, "renderTaskResultsAppHtml");
26036
+ function registerTaskResultsAppResource(server, proxyBaseUrl) {
26037
+ const origin = assetOrigin(proxyBaseUrl);
26038
+ const resourceDomains = origin ? [
26039
+ origin
26040
+ ] : [];
26041
+ const html = renderTaskResultsAppHtml(proxyBaseUrl);
26042
+ const meta = {
26043
+ ui: {
26044
+ csp: {
26045
+ resourceDomains,
26046
+ connectDomains: []
26047
+ }
26048
+ },
26049
+ "openai/widgetCSP": {
26050
+ resource_domains: resourceDomains,
26051
+ connect_domains: []
26052
+ },
26053
+ "openai/widgetDescription": "Displays the actual ProductMaker images and videos with playback controls and download links."
26054
+ };
26055
+ registerAppResource2(server, "ProductMaker task results", TASK_RESULTS_APP_RESOURCE_URI, {
26056
+ title: "Your creative",
26057
+ mimeType: RESOURCE_MIME_TYPE2,
26058
+ _meta: meta
26059
+ }, async () => ({
26060
+ contents: [
26061
+ {
26062
+ uri: TASK_RESULTS_APP_RESOURCE_URI,
26063
+ mimeType: RESOURCE_MIME_TYPE2,
26064
+ text: html,
26065
+ _meta: meta
26066
+ }
26067
+ ]
26068
+ }));
26069
+ }
26070
+ __name(registerTaskResultsAppResource, "registerTaskResultsAppResource");
26071
+
25922
26072
  // src/tools/tasks.ts
25923
- import { z as z124 } from "zod";
26073
+ import { z as z125 } from "zod";
25924
26074
 
25925
26075
  // src/resolve-image.ts
25926
26076
  import { lookup as dnsLookup } from "dns/promises";
@@ -26481,9 +26631,9 @@ async function resolveMediaRef(ref, opts) {
26481
26631
  __name(resolveMediaRef, "resolveMediaRef");
26482
26632
 
26483
26633
  // src/tools/shared.ts
26484
- import { z as z119 } from "zod";
26485
- var Lang = z119.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);
26486
- var Country = z119.string().min(2).max(3);
26634
+ import { z as z120 } from "zod";
26635
+ var Lang = z120.string().regex(/^[a-z]{2}(?:[-_][a-zA-Z]{2})?$/, "Usa un c\xF3digo de idioma BCP-47, por ejemplo es, en-US o pt-BR").max(10);
26636
+ var Country = z120.string().min(2).max(3);
26487
26637
  var LandingStrategyEnum = LandingStrategySchema;
26488
26638
  var LandingImageFormatEnum = LandingImageFormatSchema;
26489
26639
  var VideoPresetEnum = VideoPreset.extract([
@@ -26587,7 +26737,7 @@ function animationStyleApplies(videoPreset, angleNarratives) {
26587
26737
  return ANIMATED_VIDEO_PRESETS.has(videoPreset ?? "") || (angleNarratives ?? []).some((n) => ANIMATED_NARRATIVE_STYLES.has(n));
26588
26738
  }
26589
26739
  __name(animationStyleApplies, "animationStyleApplies");
26590
- var VideoTierEnum = z119.enum([
26740
+ var VideoTierEnum = z120.enum([
26591
26741
  "basic"
26592
26742
  ]);
26593
26743
  function resolveVideoTier(_tier) {
@@ -26645,10 +26795,10 @@ var ImageCreativeStyleEnum = ImageCreativeStyle;
26645
26795
  var ImageCreativeArchetypeEnum = ImageCreativeArchetype;
26646
26796
  var ImageCreativeVisualTreatmentEnum = ImageCreativeVisualTreatment;
26647
26797
  var ImageCreativeAspectRatioEnum = ImageCreativeAspectRatio;
26648
- var ImageRefSchema = z119.object({
26649
- url: z119.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.'),
26650
- path: z119.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`.'),
26651
- assetId: z119.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.")
26798
+ var ImageRefSchema = z120.object({
26799
+ url: z120.string().url().optional().describe('URL p\xFAblica HTTPS de la foto. Ej: una URL de Shopify CDN, Cloudinary, Imgur. \xDAsala cuando el usuario te diga "est\xE1 en X.com/foto.jpg" o cuando la foto ya est\xE9 hospedada.'),
26800
+ path: z120.string().min(1).optional().describe('Ruta del archivo en el computador del usuario. Ej: "/Users/maria/Desktop/foto.jpg", "~/Pictures/camiseta.png", "C:\\Users\\Maria\\Desktop\\foto.jpg". El MCP local la lee del disco y la sube. SOLO funciona cuando el MCP corre local (stdio). NO funciona en mcp.productmaker.app (HTTP) \u2014 ah\xED usa `url`.'),
26801
+ assetId: z120.string().uuid().optional().describe("ID opaco devuelto por check_media_upload. \xDAsalo para una imagen subida desde el MCP App; ProductMaker adopta el archivo directamente y el MCP nunca descarga sus bytes.")
26652
26802
  }).refine((v) => [
26653
26803
  v.url,
26654
26804
  v.path,
@@ -26656,11 +26806,11 @@ var ImageRefSchema = z119.object({
26656
26806
  ].filter(Boolean).length === 1, {
26657
26807
  message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
26658
26808
  });
26659
- var ImagesInput = z119.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
26809
+ var ImagesInput = z120.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
26660
26810
  const assetCount = images.filter((image) => Boolean(image.assetId)).length;
26661
26811
  if (assetCount > 0 && assetCount !== images.length) {
26662
26812
  ctx.addIssue({
26663
- code: z119.ZodIssueCode.custom,
26813
+ code: z120.ZodIssueCode.custom,
26664
26814
  message: "all image entries must use assetId, or all must use URL/path sources"
26665
26815
  });
26666
26816
  }
@@ -26741,14 +26891,14 @@ async function submitCreative(api, opts) {
26741
26891
  });
26742
26892
  }
26743
26893
  __name(submitCreative, "submitCreative");
26744
- var ResearchTargetCountryEnum = z119.enum([
26894
+ var ResearchTargetCountryEnum = z120.enum([
26745
26895
  "CO",
26746
26896
  "MX",
26747
26897
  "PE",
26748
26898
  "EC",
26749
26899
  "CL"
26750
26900
  ]);
26751
- var ResearchCategoryEnum = z119.enum([
26901
+ var ResearchCategoryEnum = z120.enum([
26752
26902
  "auto",
26753
26903
  "automotive",
26754
26904
  "kitchen",
@@ -27543,7 +27693,7 @@ function approveRefusalMessage(reason) {
27543
27693
  __name(approveRefusalMessage, "approveRefusalMessage");
27544
27694
 
27545
27695
  // src/tools/task-outputs.ts
27546
- import { z as z120 } from "zod";
27696
+ import { z as z121 } from "zod";
27547
27697
 
27548
27698
  // src/tools/conversational-review-format.ts
27549
27699
  function escapeMarkdownText(value) {
@@ -27596,12 +27746,90 @@ __name(formatCredits, "formatCredits");
27596
27746
 
27597
27747
  // src/tools/task-outputs.ts
27598
27748
  var WEBAPP_BASE = "https://productmaker.app";
27599
- var CreativeVariantIdentity = z120.object({
27600
- variantTaskId: z120.string().uuid(),
27601
- sourceTaskId: z120.string().uuid(),
27749
+ function proxifyServiceVideoResult(result, proxyBaseUrl) {
27750
+ if (!proxyBaseUrl || !isProxyEnabled()) return result;
27751
+ const rewrite = /* @__PURE__ */ __name((url, filename) => buildProxyUrl({
27752
+ r2Url: url,
27753
+ filename,
27754
+ proxyBaseUrl
27755
+ }) ?? url, "rewrite");
27756
+ const mg = result.motionGraphics;
27757
+ return {
27758
+ ...result,
27759
+ ...result.finalMp4Url ? {
27760
+ finalMp4Url: rewrite(result.finalMp4Url, "video-final.mp4")
27761
+ } : {},
27762
+ ...result.concatMp4Url ? {
27763
+ concatMp4Url: rewrite(result.concatMp4Url, "video-voices.mp4")
27764
+ } : {},
27765
+ ...mg ? {
27766
+ motionGraphics: {
27767
+ ...mg,
27768
+ ...Array.isArray(mg.variantUrls) ? {
27769
+ variantUrls: mg.variantUrls.map((url, i) => rewrite(url, `video-variant-${i + 2}.mp4`))
27770
+ } : {},
27771
+ ...mg.cleanVideoUrl ? {
27772
+ cleanVideoUrl: rewrite(mg.cleanVideoUrl, "video-clean.mp4")
27773
+ } : {},
27774
+ ...Array.isArray(mg.cleanVariantUrls) ? {
27775
+ cleanVariantUrls: mg.cleanVariantUrls.map((url, i) => rewrite(url, `video-clean-variant-${i + 2}.mp4`))
27776
+ } : {},
27777
+ ...mg.previewUrl ? {
27778
+ previewUrl: rewrite(mg.previewUrl, "service-preview.png")
27779
+ } : {}
27780
+ }
27781
+ } : {}
27782
+ };
27783
+ }
27784
+ __name(proxifyServiceVideoResult, "proxifyServiceVideoResult");
27785
+ function serviceVideoResultMedia(result) {
27786
+ const mg = result.motionGraphics;
27787
+ const candidates = [
27788
+ {
27789
+ url: result.finalMp4Url,
27790
+ label: "Video final"
27791
+ },
27792
+ {
27793
+ url: result.concatMp4Url,
27794
+ label: "Video solo voces"
27795
+ },
27796
+ ...(Array.isArray(mg?.variantUrls) ? mg.variantUrls : []).map((url, i) => ({
27797
+ url,
27798
+ label: `Versi\xF3n ${i + 2}`
27799
+ })),
27800
+ {
27801
+ url: mg?.cleanVideoUrl,
27802
+ label: "Video limpio"
27803
+ },
27804
+ ...(Array.isArray(mg?.cleanVariantUrls) ? mg.cleanVariantUrls : []).map((url, i) => ({
27805
+ url,
27806
+ label: `Versi\xF3n limpia ${i + 2}`
27807
+ }))
27808
+ ];
27809
+ const seen = /* @__PURE__ */ new Set();
27810
+ const videos = candidates.flatMap(({ url, label }) => {
27811
+ if (!url || seen.has(url)) return [];
27812
+ seen.add(url);
27813
+ return [
27814
+ {
27815
+ url,
27816
+ label
27817
+ }
27818
+ ];
27819
+ });
27820
+ return {
27821
+ images: [],
27822
+ videos,
27823
+ links: videos
27824
+ };
27825
+ }
27826
+ __name(serviceVideoResultMedia, "serviceVideoResultMedia");
27827
+ var CreativeVariantIdentity = z121.object({
27828
+ variantTaskId: z121.string().uuid(),
27829
+ sourceTaskId: z121.string().uuid(),
27602
27830
  kind: TaskCreativeVariantKind,
27603
27831
  status: TaskStatusSchema,
27604
- error: z120.string().optional()
27832
+ error: z121.string().optional()
27605
27833
  });
27606
27834
  function proxifyOutputs(outputs, proxyBaseUrl) {
27607
27835
  if (!proxyBaseUrl || !isProxyEnabled()) return outputs;
@@ -28205,29 +28433,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
28205
28433
  __name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
28206
28434
 
28207
28435
  // src/tools/media-presentation.ts
28208
- import { z as z121 } from "zod";
28209
- var HttpsPresentationUrlSchema = z121.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
28436
+ import { z as z122 } from "zod";
28437
+ var HttpsPresentationUrlSchema = z122.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
28210
28438
  var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
28211
28439
  const hostname = new URL(value).hostname.toLowerCase();
28212
28440
  return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
28213
28441
  }, "preview URL must be owned by ProductMaker");
28214
- var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z121.number().int().positive().max(maximum), "positiveIntAtMost");
28215
- var PresentationImageSchema = z121.object({
28216
- kind: z121.literal("image"),
28442
+ var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z122.number().int().positive().max(maximum), "positiveIntAtMost");
28443
+ var PresentationImageSchema = z122.object({
28444
+ kind: z122.literal("image"),
28217
28445
  url: HttpsPresentationUrlSchema,
28218
- mimeType: z121.enum([
28446
+ mimeType: z122.enum([
28219
28447
  "image/jpeg",
28220
28448
  "image/png"
28221
28449
  ]),
28222
28450
  byteSize: positiveIntAtMost(5 * 1024 * 1024),
28223
28451
  width: positiveIntAtMost(16384),
28224
28452
  height: positiveIntAtMost(16384),
28225
- alt: z121.string().trim().min(1).max(240)
28453
+ alt: z122.string().trim().min(1).max(240)
28226
28454
  }).strict();
28227
28455
  var McpMediaPresentationSchema = PresentationImageSchema;
28228
- var GalleryImageSchema = z121.object({
28456
+ var GalleryImageSchema = z122.object({
28229
28457
  url: ProductMakerPreviewUrlSchema,
28230
- alt: z121.string().trim().min(1).max(240)
28458
+ alt: z122.string().trim().min(1).max(240)
28231
28459
  });
28232
28460
  var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
28233
28461
  async function imageBlocks(image, transport) {
@@ -28284,12 +28512,12 @@ async function buildMcpMediaPresentationContent(rawPresentation, transport = "ht
28284
28512
  ];
28285
28513
  }
28286
28514
  __name(buildMcpMediaPresentationContent, "buildMcpMediaPresentationContent");
28287
- var OwnedImagePreviewSchema = z121.object({
28515
+ var OwnedImagePreviewSchema = z122.object({
28288
28516
  url: HttpsPresentationUrlSchema.refine((value) => {
28289
28517
  const url = new URL(value);
28290
28518
  return !url.username && !url.password && !isPrivateHost(url.hostname);
28291
28519
  }, "Preview URL must be public HTTPS without credentials"),
28292
- alt: z121.string().trim().min(1).max(240)
28520
+ alt: z122.string().trim().min(1).max(240)
28293
28521
  });
28294
28522
  async function buildMcpImagePreviewContent(rawPreview, transport = "http") {
28295
28523
  const preview2 = OwnedImagePreviewSchema.safeParse(rawPreview);
@@ -28304,6 +28532,53 @@ async function buildMcpImagePreviewContent(rawPreview, transport = "http") {
28304
28532
  return imageBlocks(preview2.data, transport);
28305
28533
  }
28306
28534
  __name(buildMcpImagePreviewContent, "buildMcpImagePreviewContent");
28535
+ async function buildMcpGeneratedImageContent(rawItems, transport = "http") {
28536
+ const blocks = await Promise.all(rawItems.slice(0, MAX_IMAGE_CREATIVE_VARIANTS).map(async (rawItem, index) => {
28537
+ const preview2 = OwnedImagePreviewSchema.safeParse(rawItem);
28538
+ if (!preview2.success) {
28539
+ return [
28540
+ {
28541
+ type: "text",
28542
+ text: `Imagen ${index + 1}: vista previa bloqueada por seguridad. No generes ni recrees una imagen sustituta.`
28543
+ }
28544
+ ];
28545
+ }
28546
+ const heading = {
28547
+ type: "text",
28548
+ text: `Imagen ${index + 1} de ProductMaker: ${preview2.data.alt}`
28549
+ };
28550
+ try {
28551
+ const [resolved] = await resolveImages([
28552
+ {
28553
+ url: preview2.data.url
28554
+ }
28555
+ ], {
28556
+ transport,
28557
+ maxBytes: MCP_GALLERY_IMAGE_MAX_BYTES
28558
+ });
28559
+ if (resolved) {
28560
+ return [
28561
+ heading,
28562
+ {
28563
+ type: "image",
28564
+ data: resolved.buffer.toString("base64"),
28565
+ mimeType: resolved.mimetype
28566
+ }
28567
+ ];
28568
+ }
28569
+ } catch {
28570
+ }
28571
+ return [
28572
+ heading,
28573
+ {
28574
+ type: "text",
28575
+ text: `Imagen ${index + 1}: no se pudo mostrar la imagen original de ProductMaker en este resultado. No generes ni recrees una imagen sustituta; usa el enlace protegido devuelto para esta imagen.`
28576
+ }
28577
+ ];
28578
+ }));
28579
+ return blocks.flat();
28580
+ }
28581
+ __name(buildMcpGeneratedImageContent, "buildMcpGeneratedImageContent");
28307
28582
  async function buildMcpImageGalleryContent(rawItems, transport = "http") {
28308
28583
  const items = rawItems.slice(0, 5).map((rawItem, index) => ({
28309
28584
  index,
@@ -28371,8 +28646,73 @@ async function buildMcpImageGalleryContent(rawItems, transport = "http") {
28371
28646
  }
28372
28647
  __name(buildMcpImageGalleryContent, "buildMcpImageGalleryContent");
28373
28648
 
28649
+ // src/media-delivery-analytics.ts
28650
+ var MCP_MEDIA_DELIVERY_ANALYTICS_EVENTS = {
28651
+ STARTED: "mcp_media_delivery_started",
28652
+ RESPONSE_DELIVERED: "mcp_media_response_delivered",
28653
+ FAILED: "mcp_media_delivery_failed",
28654
+ SAFE_VARIANT: "mcp_media_delivery_variant"
28655
+ };
28656
+ var RESPONSE_STATES = [
28657
+ "ready",
28658
+ "empty",
28659
+ "pending",
28660
+ "awaiting_review",
28661
+ "error"
28662
+ ];
28663
+ var isRecord4 = /* @__PURE__ */ __name((value) => value !== null && typeof value === "object" && !Array.isArray(value), "isRecord");
28664
+ function deliveryProperties(result) {
28665
+ const view = result._meta?.taskResults;
28666
+ const data = isRecord4(view) ? view : {};
28667
+ const responseState = RESPONSE_STATES.find((state) => state === data.state) ?? "unknown";
28668
+ const nativeImageCount = result.content.filter((block) => block.type === "image").length;
28669
+ const viewerImageCount = Array.isArray(data.images) ? data.images.length : 0;
28670
+ const viewerVideoCount = Array.isArray(data.videos) ? data.videos.length : 0;
28671
+ const imageFallbackCount = result.content.filter((block) => block.type === "text" && /^Imagen \d+: (?:no se pudo mostrar|vista previa bloqueada por seguridad)/.test(block.text)).length;
28672
+ const hasImages = nativeImageCount > 0 || viewerImageCount > 0 || imageFallbackCount > 0;
28673
+ return {
28674
+ measurement: "response_delivery",
28675
+ responseState,
28676
+ mediaKind: hasImages ? viewerVideoCount ? "mixed" : "image" : viewerVideoCount ? "video" : "none",
28677
+ nativeImageCount,
28678
+ viewerImageCount,
28679
+ viewerVideoCount,
28680
+ imageFallbackCount
28681
+ };
28682
+ }
28683
+ __name(deliveryProperties, "deliveryProperties");
28684
+ async function observeMcpMediaDelivery(fingerprint, work) {
28685
+ const subject = /^[a-f0-9]{32}$/.test(fingerprint) ? `mcp_credential_${fingerprint}` : "mcp_media_aggregate";
28686
+ const events = MCP_MEDIA_DELIVERY_ANALYTICS_EVENTS;
28687
+ captureMcpAnalytics(events.STARTED, subject, {
28688
+ measurement: "response_delivery"
28689
+ });
28690
+ let result;
28691
+ try {
28692
+ result = await work();
28693
+ } catch (error) {
28694
+ captureMcpAnalytics(events.FAILED, subject, {
28695
+ measurement: "response_delivery",
28696
+ reason: "exception"
28697
+ });
28698
+ throw error;
28699
+ }
28700
+ const properties = deliveryProperties(result);
28701
+ captureMcpAnalytics(events.SAFE_VARIANT, subject, properties);
28702
+ if (result.isError || properties.responseState === "error") {
28703
+ captureMcpAnalytics(events.FAILED, subject, {
28704
+ ...properties,
28705
+ reason: result.isError ? "tool_error" : "delivery_error"
28706
+ });
28707
+ } else {
28708
+ captureMcpAnalytics(events.RESPONSE_DELIVERED, subject, properties);
28709
+ }
28710
+ return result;
28711
+ }
28712
+ __name(observeMcpMediaDelivery, "observeMcpMediaDelivery");
28713
+
28374
28714
  // src/tools/animated-video.ts
28375
- import { z as z122 } from "zod";
28715
+ import { z as z123 } from "zod";
28376
28716
 
28377
28717
  // src/tools/paid-confirmation.ts
28378
28718
  function describeMarketStudyChoice(enabled) {
@@ -28485,17 +28825,17 @@ function sortCanonical(items) {
28485
28825
  });
28486
28826
  }
28487
28827
  __name(sortCanonical, "sortCanonical");
28488
- function isRecord4(value) {
28828
+ function isRecord5(value) {
28489
28829
  return typeof value === "object" && value !== null && !Array.isArray(value);
28490
28830
  }
28491
- __name(isRecord4, "isRecord");
28831
+ __name(isRecord5, "isRecord");
28492
28832
  function collectLanguageCodes(value, out) {
28493
28833
  if (Array.isArray(value)) {
28494
28834
  const items = value;
28495
28835
  for (const item of items) collectLanguageCodes(item, out);
28496
28836
  return out;
28497
28837
  }
28498
- if (!isRecord4(value)) return out;
28838
+ if (!isRecord5(value)) return out;
28499
28839
  for (const [key, entry] of Object.entries(value)) {
28500
28840
  if (LANGUAGE_FIELDS.has(key) && typeof entry === "string") {
28501
28841
  const base = entry.trim().split(/[-_]/)[0]?.toLowerCase();
@@ -28541,7 +28881,7 @@ function normalizeForKey(value, languages) {
28541
28881
  const items = value;
28542
28882
  return items.map((item) => normalizeForKey(item, languages));
28543
28883
  }
28544
- if (!isRecord4(value)) return value;
28884
+ if (!isRecord5(value)) return value;
28545
28885
  const out = {};
28546
28886
  for (const [key, entry] of Object.entries(value)) {
28547
28887
  if (PARAPHRASE_PRONE_FIELDS.has(key)) {
@@ -28621,30 +28961,30 @@ function hookVariantsLabel(count) {
28621
28961
  return count === 1 ? "1 versi\xF3n del gancho" : `${count} versiones del gancho`;
28622
28962
  }
28623
28963
  __name(hookVariantsLabel, "hookVariantsLabel");
28624
- var DurationInput = z122.union(MOTION_GRAPHICS_DURATIONS.map((d) => z122.literal(d)));
28625
- var CreateAnimatedVideoInput = z122.object({
28626
- action: z122.enum([
28964
+ var DurationInput = z123.union(MOTION_GRAPHICS_DURATIONS.map((d) => z123.literal(d)));
28965
+ var CreateAnimatedVideoInput = z123.object({
28966
+ action: z123.enum([
28627
28967
  "prepare",
28628
28968
  "status",
28629
28969
  "cancel",
28630
28970
  "generate"
28631
28971
  ]).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."),
28632
- brandId: z122.string().uuid().optional().describe("ID de un servicio propio y listo (de create_brand). Obligatorio al preparar y crear videos nuevos. Conserva el mismo brandId en reintentos; si recuperas una generaci\xF3n hist\xF3rica aceptada sin este campo, om\xEDtelo como en la petici\xF3n original. status/cancel no lo necesitan."),
28633
- websiteCaptureId: z122.string().uuid().optional().describe("ID de la captura preparada. Obligatorio para status/cancel/generate; no inventarlo."),
28634
- generationRequestId: z122.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."),
28635
- confirmed: z122.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."),
28972
+ brandId: z123.string().uuid().optional().describe("ID de un servicio propio y listo (de create_brand). Obligatorio al preparar y crear videos nuevos. Conserva el mismo brandId en reintentos; si recuperas una generaci\xF3n hist\xF3rica aceptada sin este campo, om\xEDtelo como en la petici\xF3n original. status/cancel no lo necesitan."),
28973
+ websiteCaptureId: z123.string().uuid().optional().describe("ID de la captura preparada. Obligatorio para status/cancel/generate; no inventarlo."),
28974
+ generationRequestId: z123.string().uuid().optional().describe("Identidad opcional de una generaci\xF3n confirmada. Repite el mismo UUID al recuperar una respuesta perdida; usa otro \xFAnicamente cuando el usuario pida y confirme otro video, nunca por un error de transporte."),
28975
+ confirmed: z123.boolean().optional().describe("Solo true despu\xE9s de que el usuario confirme esta captura, formato, duraci\xF3n, idioma y precio. Obligatorio para generate; preparar no genera ni cobra."),
28636
28976
  // Plain text, not `.url()`: users type «cal.com», and the web accepts it.
28637
28977
  // normalizeWebAddress (shared with the web) adds https:// and refuses
28638
28978
  // anything that is not a public http(s) address.
28639
- landingUrl: z122.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."),
28979
+ landingUrl: z123.string().trim().min(1).optional().describe("Enlace p\xFAblico de la p\xE1gina del servicio, como lo dio el usuario (\xABcal.com\xBB o \xABhttps://cal.com\xBB). El video sale de lo que muestra esa p\xE1gina: su marca, colores y mensajes."),
28640
28980
  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.'),
28641
28981
  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.`),
28642
28982
  language: MotionGraphicsLanguageSchema.optional().describe('Idioma de los textos del video: "es", "en" o "pt".'),
28643
28983
  videoQuality: MotionGraphicsVideoQualitySchema.default(DEFAULT_MOTION_GRAPHICS_VIDEO_QUALITY).describe('Calidad IA: "economy" (econ\xF3mica) o "pro" (alta, por defecto). Afecta el precio de los clips IA.'),
28644
28984
  videoResolution: MotionGraphicsVideoResolutionSchema.default(DEFAULT_MOTION_GRAPHICS_VIDEO_RESOLUTION).describe('Resoluci\xF3n: "480p" (por defecto), "720p" o "1080p". 1080p solo est\xE1 disponible con videoQuality="pro".'),
28645
- notes: z122.string().trim().max(MOTION_GRAPHICS_NOTES_MAX_CHARS).optional().describe("Opcional. Idea creativa, escenarios, acciones, di\xE1logo, voz o m\xFAsica en lenguaje natural. El director puede hacer solo motion graphics, escenas reales o escenas imposibles seg\xFAn la idea; las frases gu\xEDan el guion sin garantizar reproducci\xF3n exacta."),
28985
+ notes: z123.string().trim().max(MOTION_GRAPHICS_NOTES_MAX_CHARS).optional().describe("Opcional. Idea creativa, escenarios, acciones, di\xE1logo, voz o m\xFAsica en lenguaje natural. El director puede hacer solo motion graphics, escenas reales o escenas imposibles seg\xFAn la idea; las frases gu\xEDan el guion sin garantizar reproducci\xF3n exacta."),
28646
28986
  hookVariants: MotionGraphicsHookVariantsSchema.optional().describe(`Opcional. Cantidad de videos independientes, de 1 a ${MOTION_GRAPHICS_HOOK_VARIANTS_MAX} (por defecto 1). Cada uno tiene su propio \xE1ngulo, guion y estilo visual, respetando notes, y reserva el precio completo de un video (ver la descripci\xF3n); \xFAsalo solo si el usuario lo pide.`),
28647
- music: z122.boolean().optional().describe("Opcional. M\xFAsica y efectos dirigidos seg\xFAn el negocio y el video (por defecto true), con una copia adicional solo con voces. false entrega solo voces, sin m\xFAsica ni efectos a\xF1adidos ni el cargo de m\xFAsica. \xDAsalo solo si el usuario lo pide.")
28987
+ music: z123.boolean().optional().describe("Opcional. M\xFAsica y efectos dirigidos seg\xFAn el negocio y el video (por defecto true), con una copia adicional solo con voces. false entrega solo voces, sin m\xFAsica ni efectos a\xF1adidos ni el cargo de m\xFAsica. \xDAsalo solo si el usuario lo pide.")
28648
28988
  }).strict();
28649
28989
  function captureNextAction(capture) {
28650
28990
  if (capture.status === "ready") return "Muestra la vista previa al usuario y confirma formato, duraci\xF3n, idioma, calidad IA, resoluci\xF3n y precio. Solo despu\xE9s llama create_animated_video con action=generate, este websiteCaptureId y confirmed=true.";
@@ -28697,33 +29037,33 @@ var FORMAT_LABELS = {
28697
29037
  square: "cuadrado 1:1",
28698
29038
  horizontal: "horizontal 16:9"
28699
29039
  };
28700
- var AnimatedVideoResultSchema = z122.object({
28701
- status: z122.enum([
29040
+ var AnimatedVideoResultSchema = z123.object({
29041
+ status: z123.enum([
28702
29042
  "pending",
28703
29043
  "done",
28704
29044
  "error"
28705
29045
  ]),
28706
- serviceMode: z122.literal("motion_graphics"),
28707
- finalMp4Url: z122.string().optional(),
28708
- adCopy: z122.string().optional(),
28709
- adCopies: z122.array(z122.string()).optional(),
28710
- error: z122.string().optional(),
28711
- motionGraphics: z122.object({
29046
+ serviceMode: z123.literal("motion_graphics"),
29047
+ finalMp4Url: z123.string().optional(),
29048
+ adCopy: z123.string().optional(),
29049
+ adCopies: z123.array(z123.string()).optional(),
29050
+ error: z123.string().optional(),
29051
+ motionGraphics: z123.object({
28712
29052
  stage: MotionGraphicsStageSchema,
28713
29053
  format: MotionGraphicsFormatSchema,
28714
- durationSec: z122.number(),
28715
- width: z122.number().optional(),
28716
- height: z122.number().optional(),
29054
+ durationSec: z123.number(),
29055
+ width: z123.number().optional(),
29056
+ height: z123.number().optional(),
28717
29057
  language: MotionGraphicsLanguageSchema.optional(),
28718
29058
  videoQuality: MotionGraphicsVideoQualitySchema.optional().catch(void 0),
28719
29059
  videoResolution: MotionGraphicsVideoResolutionSchema.optional().catch(void 0),
28720
- creativeBatch: z122.object({
29060
+ creativeBatch: z123.object({
28721
29061
  index: MotionGraphicsHookVariantsSchema,
28722
29062
  count: MotionGraphicsHookVariantsSchema,
28723
- tasks: z122.array(z122.object({
28724
- taskId: z122.string().uuid(),
29063
+ tasks: z123.array(z123.object({
29064
+ taskId: z123.string().uuid(),
28725
29065
  index: MotionGraphicsHookVariantsSchema,
28726
- status: z122.enum([
29066
+ status: z123.enum([
28727
29067
  "queued",
28728
29068
  "processing",
28729
29069
  "done",
@@ -28731,29 +29071,29 @@ var AnimatedVideoResultSchema = z122.object({
28731
29071
  ])
28732
29072
  })).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX)
28733
29073
  }).optional().catch(void 0),
28734
- queuedAt: z122.string().optional(),
28735
- jobsAhead: z122.number().int().nonnegative().optional(),
28736
- stageStartedAt: z122.string().optional(),
28737
- renderProgress: z122.number().optional(),
29074
+ queuedAt: z123.string().optional(),
29075
+ jobsAhead: z123.number().int().nonnegative().optional(),
29076
+ stageStartedAt: z123.string().optional(),
29077
+ renderProgress: z123.number().optional(),
28738
29078
  // AI clip fields (absent on a video paid before clips, or from an API
28739
29079
  // that predates them). Lenient: an unreadable value is dropped
28740
29080
  // instead of hiding the status.
28741
- clipCount: z122.number().int().nonnegative().optional().catch(void 0),
28742
- clipsUsed: z122.number().int().nonnegative().optional().catch(void 0),
28743
- clipPriceCents: z122.number().finite().nonnegative().optional().catch(void 0),
28744
- clipsRefunded: z122.number().int().nonnegative().optional().catch(void 0),
29081
+ clipCount: z123.number().int().nonnegative().optional().catch(void 0),
29082
+ clipsUsed: z123.number().int().nonnegative().optional().catch(void 0),
29083
+ clipPriceCents: z123.number().finite().nonnegative().optional().catch(void 0),
29084
+ clipsRefunded: z123.number().int().nonnegative().optional().catch(void 0),
28745
29085
  // Hook versions (absent from an API or a video before them): the
28746
29086
  // count ordered and, once done, the signed URLs of the EXTRA versions
28747
29087
  // (hook 2, hook 3); `finalMp4Url` is hook 1.
28748
- hookVariants: z122.number().int().min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).optional().catch(void 0),
28749
- cleanVideoUrl: z122.string().url().optional().catch(void 0),
28750
- cleanVariantUrls: z122.array(z122.string().url()).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
28751
- variantUrls: z122.array(z122.string().min(1)).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
29088
+ hookVariants: z123.number().int().min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).optional().catch(void 0),
29089
+ cleanVideoUrl: z123.string().url().optional().catch(void 0),
29090
+ cleanVariantUrls: z123.array(z123.string().url()).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
29091
+ variantUrls: z123.array(z123.string().min(1)).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
28752
29092
  // Extra hook versions given back, as the task recorded it once the
28753
29093
  // refunds landed (absent until then, and from an API before it).
28754
- variantsRefunded: z122.number().int().nonnegative().optional().catch(void 0),
28755
- activity: z122.array(MotionGraphicsActivitySchema).optional().catch(void 0),
28756
- previewUrl: z122.string().optional()
29094
+ variantsRefunded: z123.number().int().nonnegative().optional().catch(void 0),
29095
+ activity: z123.array(MotionGraphicsActivitySchema).optional().catch(void 0),
29096
+ previewUrl: z123.string().optional()
28757
29097
  }).passthrough()
28758
29098
  }).passthrough();
28759
29099
  function parseAnimatedVideoResult(value) {
@@ -29032,7 +29372,7 @@ function registerAnimatedVideoTools(server, api) {
29032
29372
  nowMs: 0
29033
29373
  })
29034
29374
  });
29035
- const parsedTaskIds = z122.array(z122.string().uuid()).min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).safeParse(created.taskIds);
29375
+ const parsedTaskIds = z123.array(z123.string().uuid()).min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).safeParse(created.taskIds);
29036
29376
  const taskIds = parsedTaskIds.success && parsedTaskIds.data[0] === created.taskId ? parsedTaskIds.data : void 0;
29037
29377
  const receipt = {
29038
29378
  taskId: created.taskId,
@@ -29074,10 +29414,10 @@ function registerAnimatedVideoTools(server, api) {
29074
29414
  __name(registerAnimatedVideoTools, "registerAnimatedVideoTools");
29075
29415
 
29076
29416
  // src/tools/winning-product-image.ts
29077
- import { z as z123 } from "zod";
29078
- var WinnerReferenceInput = z123.object({
29079
- runId: z123.string().uuid(),
29080
- candidateSourceId: z123.string().trim().min(1).max(160)
29417
+ import { z as z124 } from "zod";
29418
+ var WinnerReferenceInput = z124.object({
29419
+ runId: z124.string().uuid(),
29420
+ candidateSourceId: z124.string().trim().min(1).max(160)
29081
29421
  }).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
29082
29422
  async function resolveWinnerImages(api, winnerReference, images) {
29083
29423
  if (!winnerReference) return images;
@@ -29114,62 +29454,62 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
29114
29454
  var CREATE_SERVICE_VIDEO_ON_MCP = PRODUCTMAKER_MCP_CAPABILITY_NAMES.includes("create_service_video");
29115
29455
  var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
29116
29456
  var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
29117
- var CreateProductTaskInput = z124.object({
29457
+ var CreateProductTaskInput = z125.object({
29118
29458
  images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
29119
29459
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
29120
- projectId: z124.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
29121
- productUrl: z124.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."),
29460
+ projectId: z125.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
29461
+ productUrl: z125.string().url().optional().describe("Opcional. URL de la p\xE1gina del producto (Shopify, AliExpress, Amazon, etc.) para enriquecer el contexto. Si se omite, la IA infiere todo desde la imagen."),
29122
29462
  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.'),
29123
29463
  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.'),
29124
- price: z124.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.'),
29125
- compareAtPrice: z124.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".'),
29126
- offer: z124.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.'),
29127
- paymentMethods: z124.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.'),
29128
- productContext: z124.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."),
29129
- productLabel: z124.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.'),
29464
+ price: z125.string().min(1).max(120).optional().describe('Precio que se mostrar\xE1 en la landing y video. Formato libre \u2014 ej. "$89.900", "USD 29.99", "MXN 599". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar. Si te dice "t\xFA elige", om\xEDtelo y el backend sugiere uno.'),
29465
+ compareAtPrice: z125.string().min(1).max(120).optional().describe('Opcional. Precio anterior para comunicar un descuento real en landing e im\xE1genes. Ej. "$129.000" cuando price="$89.900".'),
29466
+ offer: z125.string().min(1).max(240).optional().describe('Oferta o promoci\xF3n a destacar. Ej. "2x1", "Env\xEDo gratis hoy", "50% OFF". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar (es v\xE1lido que diga "sin oferta"). Si te dice "t\xFA elige", om\xEDtelo.'),
29467
+ paymentMethods: z125.string().min(1).max(240).optional().describe('Opcional. M\xE9todos de pago que puede mostrar la landing. Ej. "Tarjeta, PSE, Nequi, Contraentrega". Si se omite, la landing no muestra m\xE9todos de pago.'),
29468
+ productContext: z125.string().max(PRODUCT_CONTEXT_MAX_CHARS).optional().describe("Opcional. Informacion adicional del producto que la IA debe usar como contexto prioritario: uso real, comprador, restricciones, diferenciadores o direccion creativa. No reemplaza la investigacion de competencia; si hay competencia, guia el primer angulo y los outputs no deben contradecirlo."),
29469
+ productLabel: z125.string().trim().max(80).optional().describe('Opcional. Qu\xE9 es el producto, en pocas palabras (ej. "quita pelusas para ropa"). Es AUTORITATIVO: si lo env\xEDas, la IA usa esta identidad y no la reemplaza por otra categor\xEDa. Si lo omites, la IA detecta el producto desde la imagen.'),
29130
29470
  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.'),
29131
29471
  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.'),
29132
- durationSeconds: z124.union([
29133
- z124.literal(15),
29134
- z124.literal(30)
29472
+ durationSeconds: z125.union([
29473
+ z125.literal(15),
29474
+ z125.literal(30)
29135
29475
  ]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
29136
- pauseForAngleReview: z124.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."),
29137
- aiDecidesAll: z124.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."),
29476
+ pauseForAngleReview: z125.boolean().optional().describe("Compatibilidad heredada. MCP deriva esta pausa de aiDecidesAll: manual siempre pausa y autom\xE1tico siempre la omite. No uses este campo para saltar reviews."),
29477
+ aiDecidesAll: z125.boolean().optional().describe("Mapea el toggle web \u201CDejar que la IA decida todo\u201D. Si true, ProductMaker omite reviews. Act\xEDvalo \xFAnicamente cuando el usuario lo pida expl\xEDcitamente. Omitido/false = reviews conversacionales."),
29138
29478
  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.'),
29139
29479
  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.'),
29140
29480
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
29141
29481
  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).'),
29142
- videoAngleCount: z124.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."),
29482
+ videoAngleCount: z125.number().int().min(1).max(3).optional().describe("Cantidad de videos a renderizar: 1, 2 o 3. REQUERIDO cuando outputs incluye video (o se omite outputs, cuyo default incluye video); om\xEDtelo s\xF3lo cuando no se generar\xE1 video. Preg\xFAntalo incluso con aiDecidesAll=true porque cambia el costo."),
29143
29483
  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.'),
29144
- outputs: z124.array(z124.enum([
29484
+ outputs: z125.array(z125.enum([
29145
29485
  "landing",
29146
29486
  "video",
29147
29487
  "image"
29148
29488
  ])).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}`),
29149
- includeInitialLandingGif: z124.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."),
29150
- competitorScanEnabled: z124.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."),
29489
+ includeInitialLandingGif: z125.boolean().optional().describe("Opcional. En nuevas landings cl\xE1sicas habilitadas, omitirlo incluye el primer GIF del producto y su coste en el total. Env\xEDa false si el usuario lo excluye: no se genera ni se reserva su coste. Conserva la elecci\xF3n al confirmar y al reintentar."),
29490
+ competitorScanEnabled: z125.boolean().optional().describe("Opcional. Default false: omitirlo significa SIN estudio de mercado. Antes de crear, llama estimate_market_study_cost con kind=product_task, muestra al usuario el costo con y sin estudio y preg\xFAntale si lo quiere; env\xEDa true solo si lo acepta (o si solicita la narrativa an\xE1lisis de mercado). Si la tarea incluye video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico."),
29151
29491
  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.'),
29152
- replicateWinnerWhenFound: z124.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."),
29153
- brandId: z124.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."),
29154
- actorId: z124.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."),
29492
+ replicateWinnerWhenFound: z125.boolean().optional().describe("Conserva la preferencia de copiar un ganador si existe. false estudia el mercado sin reemplazar un \xE1ngulo por el anuncio ganador. No a\xF1ade una pregunta obligatoria."),
29493
+ brandId: z125.string().uuid().optional().describe("Opcional. ID de una marca del usuario; si se env\xEDa, el sistema usa su voz, colores y persona para enriquecer los outputs generados."),
29494
+ actorId: z125.string().trim().min(1).max(120).optional().describe("Opcional. ID de un personaje guardado (usa list_actors para verlos). Si lo env\xEDas, su foto y su voz mandan sobre la descripci\xF3n de texto."),
29155
29495
  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.'),
29156
- creativeDirection: z124.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.'),
29157
- headline: z124.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."),
29158
- subheadline: z124.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."),
29496
+ creativeDirection: z125.string().max(500).optional().describe('Opcional. Direcci\xF3n creativa en texto libre (colores, mood, estilo) que aplica a los outputs de IMAGEN y LANDING (no al video \u2014 el estilo/ambiente del video se dirige con scriptNotes). M\xC1XIMA PRIORIDAD: anula marca, colores y estilo por defecto. Ej. "amarillo y azul, minimalista". M\xE1x 500 caracteres.'),
29497
+ headline: z125.string().max(120).optional().describe("Opcional. Titular EXACTO a renderizar. Se imprime tal cual: la IA no lo reescribe, no lo acorta y no lo traduce. Se aplica a las IM\xC1GENES y a la portada de la landing de esta task (el video no lo usa; para el video usa scriptNotes). \xDAsalo cuando el copy es de marca y no es negociable. M\xE1x 120 caracteres. Si lo omites, la IA escribe el titular."),
29498
+ subheadline: z125.string().max(160).optional().describe("Opcional. Subt\xEDtulo EXACTO a renderizar, misma regla que headline. Independiente: puedes fijar solo el subt\xEDtulo. M\xE1x 160 caracteres."),
29159
29499
  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".'),
29160
29500
  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".')
29161
29501
  }).strict();
29162
- var CreateServiceVideoInput = z124.object({
29163
- landingUrl: z124.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
29164
- additionalContext: z124.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
29502
+ var CreateServiceVideoInput = z125.object({
29503
+ landingUrl: z125.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
29504
+ additionalContext: z125.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
29165
29505
  language: Lang.describe("Idioma del video: es, en o pt."),
29166
- voiceId: z124.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.'),
29167
- brandId: z124.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
29168
- reviewMode: z124.enum([
29506
+ voiceId: z125.string().trim().min(1).pipe(VoiceId).optional().describe('Opcional. Voz para toda la narraci\xF3n. Usa "auto" para que la IA la alinee con el presentador. Las voces del banco compartido fueron retiradas.'),
29507
+ brandId: z125.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
29508
+ reviewMode: z125.enum([
29169
29509
  "automatic",
29170
29510
  "guided"
29171
29511
  ]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
29172
- videoPreset: z124.enum([
29512
+ videoPreset: z125.enum([
29173
29513
  "auto",
29174
29514
  "ugc_dynamic",
29175
29515
  "ugc_how_to",
@@ -29179,128 +29519,128 @@ var CreateServiceVideoInput = z124.object({
29179
29519
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
29180
29520
  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.')
29181
29521
  }).strict();
29182
- var GetTaskStatusInput = z124.object({
29183
- taskId: z124.string().min(1),
29184
- waitSeconds: z124.number().int().min(0).max(120).optional()
29522
+ var GetTaskStatusInput = z125.object({
29523
+ taskId: z125.string().min(1),
29524
+ waitSeconds: z125.number().int().min(0).max(120).optional()
29185
29525
  });
29186
- var ListTasksInput = z124.object({
29187
- limit: z124.number().int().min(1).max(50).optional(),
29188
- offset: z124.number().int().min(0).optional(),
29189
- search: z124.string().optional()
29526
+ var ListTasksInput = z125.object({
29527
+ limit: z125.number().int().min(1).max(50).optional(),
29528
+ offset: z125.number().int().min(0).optional(),
29529
+ search: z125.string().optional()
29190
29530
  });
29191
29531
  var MCP_REVIEW_LIST_FIELD_MAX = IMAGE_WIZARD_LIST_FIELD_MAX;
29192
29532
  var MCP_REVIEW_FEATURE_ITEM_MAX = IMAGE_FEATURE_ITEM_MAX;
29193
- var EditTaskDraftInput = z124.object({
29194
- taskId: z124.string().min(1),
29195
- angleIndex: z124.number().int().min(0),
29196
- angle: z124.object({
29197
- angle: z124.string().min(1).max(480),
29198
- buyerPersona: z124.string().min(1).max(360),
29199
- actor: z124.string().min(1).max(360).optional(),
29200
- actorId: z124.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."),
29201
- gender: z124.enum([
29533
+ var EditTaskDraftInput = z125.object({
29534
+ taskId: z125.string().min(1),
29535
+ angleIndex: z125.number().int().min(0),
29536
+ angle: z125.object({
29537
+ angle: z125.string().min(1).max(480),
29538
+ buyerPersona: z125.string().min(1).max(360),
29539
+ actor: z125.string().min(1).max(360).optional(),
29540
+ actorId: z125.string().trim().min(1).optional().describe("Opcional. ID de un personaje guardado (usa list_actors para verlos). Si lo env\xEDas, su foto y su voz mandan sobre la descripci\xF3n de texto."),
29541
+ gender: z125.enum([
29202
29542
  "female",
29203
29543
  "male"
29204
29544
  ]).optional(),
29205
- scriptNotes: z124.string().max(2e3).optional()
29545
+ scriptNotes: z125.string().max(2e3).optional()
29206
29546
  })
29207
29547
  });
29208
- var PendingActionPayload = z124.discriminatedUnion("kind", [
29209
- z124.object({
29210
- kind: z124.literal("product_reference_set_approval"),
29548
+ var PendingActionPayload = z125.discriminatedUnion("kind", [
29549
+ z125.object({
29550
+ kind: z125.literal("product_reference_set_approval"),
29211
29551
  scope: ProductReferenceScopeEnum.optional(),
29212
- scopeKey: z124.string().min(1).max(120).optional(),
29213
- scopeSnapshotId: z124.string().uuid().optional(),
29214
- expectedScopeHash: z124.string().min(1).max(128).optional(),
29552
+ scopeKey: z125.string().min(1).max(120).optional(),
29553
+ scopeSnapshotId: z125.string().uuid().optional(),
29554
+ expectedScopeHash: z125.string().min(1).max(128).optional(),
29215
29555
  decision: ProductReferenceResolutionDecisionEnum,
29216
29556
  reason: ProductReferenceRejectionReasonEnum.optional(),
29217
- affectedRefKeys: z124.array(z124.string().min(1).max(200)).min(1).optional(),
29218
- affectedPhotoNumbers: z124.array(z124.number().int().positive()).min(1).optional(),
29219
- recoveryAction: z124.enum([
29557
+ affectedRefKeys: z125.array(z125.string().min(1).max(200)).min(1).optional(),
29558
+ affectedPhotoNumbers: z125.array(z125.number().int().positive()).min(1).optional(),
29559
+ recoveryAction: z125.enum([
29220
29560
  "remove",
29221
29561
  "replace",
29222
29562
  "upload",
29223
29563
  "return_to_selection"
29224
29564
  ]).optional()
29225
29565
  }),
29226
- z124.object({
29227
- kind: z124.literal("product_reference_confirmation"),
29228
- selectedPhotoNumbers: z124.array(z124.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."),
29566
+ z125.object({
29567
+ kind: z125.literal("product_reference_confirmation"),
29568
+ selectedPhotoNumbers: z125.array(z125.number().int().positive().max(5)).min(1).max(5).optional().describe("Opcional. N\xFAmeros visibles de las fotos que el usuario quiere conservar; las dem\xE1s se deseleccionan. Debe quedar al menos una."),
29229
29569
  userChoice: ProductReferenceUserChoiceEnum.optional(),
29230
- confirmedProductNames: z124.array(z124.string().min(1).max(120)).min(2).max(8).optional(),
29570
+ confirmedProductNames: z125.array(z125.string().min(1).max(120)).min(2).max(8).optional(),
29231
29571
  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."),
29232
29572
  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."),
29233
- useMultiSceneShowcase: z124.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
29573
+ useMultiSceneShowcase: z125.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
29234
29574
  }),
29235
- z124.object({
29236
- kind: z124.literal("angle_review_approval"),
29575
+ z125.object({
29576
+ kind: z125.literal("angle_review_approval"),
29237
29577
  // All edits are optional — empty action body just approves the
29238
29578
  // backend-generated draft as-is. Field shapes mirror the angle-review
29239
29579
  // request contracts in @packages/types/wizard.ts; the handler routes to
29240
29580
  // the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
29241
- customAngle: z124.string().min(1).max(480).optional(),
29581
+ customAngle: z125.string().min(1).max(480).optional(),
29242
29582
  // Keep the shared MCP action within the strictest downstream contract:
29243
29583
  // autopilot/image resume endpoints cap these fields at 1500 characters.
29244
- painPoints: z124.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
29245
- benefits: z124.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
29584
+ painPoints: z125.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
29585
+ benefits: z125.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
29246
29586
  // Same policy as the two fields above: the strictest downstream contract
29247
29587
  // wins. The image endpoint caps each feature at 240 while landing/video
29248
29588
  // accept 300, and this single action routes to whichever the task is — so
29249
29589
  // accepting 300 here turns a 250-character feature on an image task into
29250
29590
  // an opaque HTTP 400 after the model already believed it had been saved.
29251
- features: z124.array(z124.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
29252
- buyerPersona: z124.string().min(1).max(360).optional(),
29591
+ features: z125.array(z125.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
29592
+ buyerPersona: z125.string().min(1).max(360).optional(),
29253
29593
  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.'),
29254
- actor: z124.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."),
29255
- actorId: z124.string().max(120).nullable().optional(),
29256
- creativeDirection: z124.string().max(2e3).optional(),
29257
- selectedAngleNumbers: z124.array(z124.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."),
29258
- angleEdits: z124.array(z124.object({
29259
- angleNumber: z124.number().int().positive(),
29260
- narrativeSelection: z124.enum([
29594
+ actor: z125.string().min(1).max(360).optional().describe("Nueva descripci\xF3n del presentador. Al enviarla sin actorId, se elimina autom\xE1ticamente cualquier actor guardado previo de esos \xE1ngulos."),
29595
+ actorId: z125.string().max(120).nullable().optional(),
29596
+ creativeDirection: z125.string().max(2e3).optional(),
29597
+ selectedAngleNumbers: z125.array(z125.number().int().positive()).min(1).max(3).optional().describe("N\xFAmeros visibles (1-based) de los \xE1ngulos que el usuario quiere renderizar. Deben ser \xFAnicos, existir en la review y no superar el videoAngleCount autorizado."),
29598
+ angleEdits: z125.array(z125.object({
29599
+ angleNumber: z125.number().int().positive(),
29600
+ narrativeSelection: z125.enum([
29261
29601
  "market",
29262
29602
  "guided"
29263
29603
  ]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
29264
- angle: z124.string().min(1).max(480).optional(),
29265
- buyerPersona: z124.string().min(1).max(360).optional(),
29604
+ angle: z125.string().min(1).max(480).optional(),
29605
+ buyerPersona: z125.string().min(1).max(360).optional(),
29266
29606
  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.'),
29267
- actor: z124.string().min(1).max(360).optional(),
29268
- actorId: z124.string().max(120).nullable().optional(),
29269
- creativeDirection: z124.string().max(2e3).optional()
29607
+ actor: z125.string().min(1).max(360).optional(),
29608
+ actorId: z125.string().max(120).nullable().optional(),
29609
+ creativeDirection: z125.string().max(2e3).optional()
29270
29610
  }).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)."),
29271
- gapDurationSeconds: z124.union([
29272
- z124.literal(15),
29273
- z124.literal(30)
29611
+ gapDurationSeconds: z125.union([
29612
+ z125.literal(15),
29613
+ z125.literal(30)
29274
29614
  ]).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.")
29275
29615
  }),
29276
- z124.object({
29277
- kind: z124.literal("service_angle_approval"),
29278
- angleId: z124.string().uuid().optional(),
29279
- angleNumber: z124.number().int().positive().optional(),
29280
- content: z124.string().min(1).max(480).optional(),
29281
- creativeDirection: z124.string().min(1).max(1500).optional(),
29282
- actor: z124.string().min(1).max(360).optional()
29616
+ z125.object({
29617
+ kind: z125.literal("service_angle_approval"),
29618
+ angleId: z125.string().uuid().optional(),
29619
+ angleNumber: z125.number().int().positive().optional(),
29620
+ content: z125.string().min(1).max(480).optional(),
29621
+ creativeDirection: z125.string().min(1).max(1500).optional(),
29622
+ actor: z125.string().min(1).max(360).optional()
29283
29623
  }),
29284
- z124.object({
29285
- kind: z124.literal("service_script_approval"),
29286
- voiceovers: z124.record(z124.string(), z124.string().min(1).max(600)).optional(),
29287
- visualDirections: z124.record(z124.string(), z124.string().min(1).max(1200)).optional(),
29288
- voiceoversByScene: z124.record(z124.string(), z124.string().min(1).max(600)).optional(),
29289
- visualDirectionsByScene: z124.record(z124.string(), z124.string().min(1).max(1200)).optional()
29624
+ z125.object({
29625
+ kind: z125.literal("service_script_approval"),
29626
+ voiceovers: z125.record(z125.string(), z125.string().min(1).max(600)).optional(),
29627
+ visualDirections: z125.record(z125.string(), z125.string().min(1).max(1200)).optional(),
29628
+ voiceoversByScene: z125.record(z125.string(), z125.string().min(1).max(600)).optional(),
29629
+ visualDirectionsByScene: z125.record(z125.string(), z125.string().min(1).max(1200)).optional()
29290
29630
  })
29291
29631
  ]);
29292
- var ResolvePendingActionInput = z124.object({
29293
- taskId: z124.string().min(1),
29632
+ var ResolvePendingActionInput = z125.object({
29633
+ taskId: z125.string().min(1),
29294
29634
  action: PendingActionPayload
29295
29635
  }).strict();
29296
29636
  function resolveVariantConfirmVideoTier(action) {
29297
29637
  return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
29298
29638
  }
29299
29639
  __name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
29300
- var StatusForResolveSchema = z124.object({
29640
+ var StatusForResolveSchema = z125.object({
29301
29641
  // Metadata used to select the backend resume contract. Older API responses
29302
29642
  // may omit these fields, so the resolver keeps the generic fallback.
29303
- kind: z124.enum([
29643
+ kind: z125.enum([
29304
29644
  "autopilot",
29305
29645
  "video",
29306
29646
  "image",
@@ -29308,18 +29648,18 @@ var StatusForResolveSchema = z124.object({
29308
29648
  "mix",
29309
29649
  "service"
29310
29650
  ]).optional(),
29311
- selectedOutputs: z124.array(z124.enum([
29651
+ selectedOutputs: z125.array(z125.enum([
29312
29652
  "landing",
29313
29653
  "video",
29314
29654
  "image"
29315
29655
  ])).optional(),
29316
- videoAngleCount: z124.number().int().min(1).max(3).optional(),
29317
- ugcFormat: z124.enum([
29656
+ videoAngleCount: z125.number().int().min(1).max(3).optional(),
29657
+ ugcFormat: z125.enum([
29318
29658
  "single_8s",
29319
29659
  "single_15s",
29320
29660
  "double_30s"
29321
29661
  ]).optional(),
29322
- videoStyle: z124.enum([
29662
+ videoStyle: z125.enum([
29323
29663
  "ugc",
29324
29664
  "cartoon_3d",
29325
29665
  "product_only",
@@ -29329,13 +29669,13 @@ var StatusForResolveSchema = z124.object({
29329
29669
  videoQuality: VideoQualityEnum.optional(),
29330
29670
  videoRouteId: VideoRouteIdEnum.optional(),
29331
29671
  videoModel: TaskVideoModelEnum.optional(),
29332
- videoTier: z124.enum([
29672
+ videoTier: z125.enum([
29333
29673
  "legacy",
29334
29674
  "standard",
29335
29675
  "pro",
29336
29676
  "single_call"
29337
29677
  ]).optional(),
29338
- videoResolution: z124.enum([
29678
+ videoResolution: z125.enum([
29339
29679
  "480p",
29340
29680
  "720p"
29341
29681
  ]).optional(),
@@ -29343,60 +29683,60 @@ var StatusForResolveSchema = z124.object({
29343
29683
  // A task created before a narrative was blocked/hidden must still parse,
29344
29684
  // or resolve_pending_action could never approve it.
29345
29685
  narrativeStyle: NarrativeStyle.optional(),
29346
- pauseForVideoScriptReview: z124.boolean().optional(),
29347
- pendingUserAction: z124.object({
29348
- kind: z124.string(),
29349
- candidateGrouping: z124.string().optional(),
29350
- selectedImageUrls: z124.array(z124.string()).optional(),
29351
- proposedProductNames: z124.array(z124.string()).optional(),
29686
+ pauseForVideoScriptReview: z125.boolean().optional(),
29687
+ pendingUserAction: z125.object({
29688
+ kind: z125.string(),
29689
+ candidateGrouping: z125.string().optional(),
29690
+ selectedImageUrls: z125.array(z125.string()).optional(),
29691
+ proposedProductNames: z125.array(z125.string()).optional(),
29352
29692
  // Adaptive reference questions are server-owned. Echo only the evidence
29353
29693
  // identity and the choices shown by the current snapshot; never accept a
29354
29694
  // client-supplied reference set as authorization.
29355
- options: z124.array(ProductReferenceUserChoiceEnum).max(4).optional(),
29356
- mode: z124.enum([
29695
+ options: z125.array(ProductReferenceUserChoiceEnum).max(4).optional(),
29696
+ mode: z125.enum([
29357
29697
  "question",
29358
29698
  "visual_recovery"
29359
29699
  ]).optional(),
29360
29700
  /** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
29361
- canKeepSelection: z124.boolean().optional(),
29362
- decisionKey: z124.string().optional(),
29363
- questionOrdinal: z124.number().int().min(1).max(5).optional(),
29364
- questionCeiling: z124.union([
29365
- z124.literal(3),
29366
- z124.literal(5)
29701
+ canKeepSelection: z125.boolean().optional(),
29702
+ decisionKey: z125.string().optional(),
29703
+ questionOrdinal: z125.number().int().min(1).max(5).optional(),
29704
+ questionCeiling: z125.union([
29705
+ z125.literal(3),
29706
+ z125.literal(5)
29367
29707
  ]).optional(),
29368
- referenceEvidenceVersion: z124.number().int().positive().optional(),
29369
- expectedEvidenceHash: z124.string().optional(),
29370
- question: z124.object({
29371
- prompt: z124.string().min(1).max(240),
29372
- helpText: z124.string().min(1).max(300).optional(),
29373
- options: z124.array(z124.object({
29708
+ referenceEvidenceVersion: z125.number().int().positive().optional(),
29709
+ expectedEvidenceHash: z125.string().optional(),
29710
+ question: z125.object({
29711
+ prompt: z125.string().min(1).max(240),
29712
+ helpText: z125.string().min(1).max(300).optional(),
29713
+ options: z125.array(z125.object({
29374
29714
  value: ProductReferenceUserChoiceEnum,
29375
- label: z124.string().min(1).max(120),
29376
- description: z124.string().min(1).max(240).optional()
29715
+ label: z125.string().min(1).max(120),
29716
+ description: z125.string().min(1).max(240).optional()
29377
29717
  })).min(2).max(4)
29378
29718
  }).optional(),
29379
29719
  scope: ProductReferenceScopeEnum.optional(),
29380
- scopeKey: z124.string().optional(),
29381
- scopeSnapshotId: z124.string().uuid().optional(),
29382
- scopeHash: z124.string().optional(),
29383
- baseReferenceSetHash: z124.string().optional(),
29384
- phase: z124.enum([
29720
+ scopeKey: z125.string().optional(),
29721
+ scopeSnapshotId: z125.string().uuid().optional(),
29722
+ scopeHash: z125.string().optional(),
29723
+ baseReferenceSetHash: z125.string().optional(),
29724
+ phase: z125.enum([
29385
29725
  "preparation",
29386
29726
  "final"
29387
29727
  ]).optional(),
29388
- selectedRefKeys: z124.array(z124.string().min(1).max(200)).optional(),
29389
- allowedDecisions: z124.array(ProductReferenceResolutionDecisionEnum).optional(),
29390
- previews: z124.array(z124.object({
29391
- refKey: z124.string().min(1).max(200)
29728
+ selectedRefKeys: z125.array(z125.string().min(1).max(200)).optional(),
29729
+ allowedDecisions: z125.array(ProductReferenceResolutionDecisionEnum).optional(),
29730
+ previews: z125.array(z125.object({
29731
+ refKey: z125.string().min(1).max(200)
29392
29732
  }).passthrough()).optional(),
29393
- customAngleDraft: z124.string().optional(),
29394
- painPointsDraft: z124.string().optional(),
29395
- benefitsDraft: z124.string().optional(),
29396
- featuresDraft: z124.array(z124.string()).optional(),
29397
- angleOptions: z124.array(z124.object({
29398
- index: z124.number().int().nonnegative(),
29399
- angle: z124.string().min(1)
29733
+ customAngleDraft: z125.string().optional(),
29734
+ painPointsDraft: z125.string().optional(),
29735
+ benefitsDraft: z125.string().optional(),
29736
+ featuresDraft: z125.array(z125.string()).optional(),
29737
+ angleOptions: z125.array(z125.object({
29738
+ index: z125.number().int().nonnegative(),
29739
+ angle: z125.string().min(1)
29400
29740
  }).passthrough()).min(1).max(5).optional(),
29401
29741
  // Recommendation consumed only when the caller explicitly sends
29402
29742
  // gapDurationSeconds: 30 in the angle approval action.
@@ -29406,17 +29746,17 @@ var StatusForResolveSchema = z124.object({
29406
29746
  // keys. `actorId` (the saved custom actor the picker stored) was silently
29407
29747
  // dropped here, so the approval handler below could not echo it back on the
29408
29748
  // PATCH — the selection looked accepted and reached no render.
29409
- angles: z124.array(z124.object({
29410
- id: z124.string().uuid(),
29411
- content: z124.string(),
29412
- creativeDirection: z124.string(),
29413
- actor: z124.string(),
29414
- actorId: z124.string().nullable().optional()
29749
+ angles: z125.array(z125.object({
29750
+ id: z125.string().uuid(),
29751
+ content: z125.string(),
29752
+ creativeDirection: z125.string(),
29753
+ actor: z125.string(),
29754
+ actorId: z125.string().nullable().optional()
29415
29755
  }).passthrough()).optional(),
29416
- panels: z124.array(z124.object({
29417
- beatId: z124.string(),
29418
- voiceover: z124.string(),
29419
- visualDirection: z124.string()
29756
+ panels: z125.array(z125.object({
29757
+ beatId: z125.string(),
29758
+ voiceover: z125.string(),
29759
+ visualDirection: z125.string()
29420
29760
  }).passthrough()).optional()
29421
29761
  }).optional()
29422
29762
  }).passthrough();
@@ -29769,8 +30109,8 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
29769
30109
  server.registerTool("verify_landing_commerce", {
29770
30110
  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.",
29771
30111
  inputSchema: {
29772
- taskId: z124.string().uuid(),
29773
- editId: z124.string().uuid()
30112
+ taskId: z125.string().uuid(),
30113
+ editId: z125.string().uuid()
29774
30114
  },
29775
30115
  annotations: OVERWRITES_EXTERNAL
29776
30116
  }, async (input) => {
@@ -29791,16 +30131,28 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
29791
30131
  }
29792
30132
  });
29793
30133
  server.registerTool("get_task_status", {
29794
- description: `Devuelve estado y outputs. Sigue llam\xE1ndola hasta done/error o una review; un timeout significa que sigue corriendo. Cuando aparece pendingUserAction, la respuesta a\xF1ade Markdown conversacional con el draft y opciones: mu\xE9stralo, pregunta y espera. Usa resolve_pending_action s\xF3lo tras la respuesta del usuario o delegaci\xF3n expl\xEDcita. Nunca expongas IDs, hashes ni payloads t\xE9cnicos. Despu\xE9s de resolver una review, sigue reviewNextAction cuando exista; s\xF3lo vuelve a get_task_status cuando esa transici\xF3n no exista o cuando get_video_script termine en approved/skipped. En un video animado, ${UNTRUSTED_SITE_TEXT_NOTE}`,
30134
+ description: `Devuelve estado y outputs. Sigue llam\xE1ndola hasta done/error o una review; un timeout significa que sigue corriendo. Cuando aparece pendingUserAction, la respuesta a\xF1ade Markdown conversacional con el draft y opciones: mu\xE9stralo, pregunta y espera. Usa resolve_pending_action s\xF3lo tras la respuesta del usuario o delegaci\xF3n expl\xEDcita. Nunca expongas IDs, hashes ni payloads t\xE9cnicos. Despu\xE9s de resolver una review, sigue reviewNextAction cuando exista; s\xF3lo vuelve a get_task_status cuando esa transici\xF3n no exista o cuando get_video_script termine en approved/skipped. Entrega \xFAnicamente los medios originales de ProductMaker en el visor y los bloques de imagen; nunca los sustituyas ni recrees con otra herramienta. En un video animado, ${UNTRUSTED_SITE_TEXT_NOTE}`,
29795
30135
  inputSchema: GetTaskStatusInput.shape,
29796
- annotations: READS_INTERNAL
29797
- }, async (input, extra) => {
30136
+ annotations: READS_INTERNAL,
30137
+ _meta: taskResultsToolMeta()
30138
+ }, async (input, extra) => observeMcpMediaDelivery(api.fingerprint(), async () => {
29798
30139
  try {
29799
30140
  const signal = extra?.signal;
29800
30141
  const fetcher = /* @__PURE__ */ __name(() => api.getJson(`/v1/status/${encodeURIComponent(input.taskId)}`, {
29801
30142
  signal
29802
30143
  }), "fetcher");
29803
30144
  const snapshot = await pollStatus(fetcher, input.waitSeconds ?? 0, signal);
30145
+ const statusMeta = {
30146
+ taskResults: {
30147
+ state: snapshot.status === "error" ? "error" : [
30148
+ "awaiting_review",
30149
+ "waiting_for_user"
30150
+ ].includes(snapshot.status) ? "awaiting_review" : "pending",
30151
+ images: [],
30152
+ videos: [],
30153
+ links: []
30154
+ }
30155
+ };
29804
30156
  if (snapshot.status !== "done") {
29805
30157
  const review = renderPendingActionMarkdown(snapshot);
29806
30158
  if (review) {
@@ -29819,14 +30171,29 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
29819
30171
  }) ?? review : review
29820
30172
  }
29821
30173
  ],
29822
- structuredContent: snapshot
30174
+ structuredContent: snapshot,
30175
+ _meta: {
30176
+ taskResults: {
30177
+ ...statusMeta.taskResults,
30178
+ state: "awaiting_review"
30179
+ }
30180
+ }
29823
30181
  };
29824
30182
  }
29825
30183
  if (snapshot.kind === "service") {
29826
- const animated = await fetchAnimatedVideoResult(api, input.taskId, signal, "serviceMode" in snapshot ? snapshot.serviceMode : void 0);
29827
- if (animated) {
30184
+ const rawAnimated = await fetchAnimatedVideoResult(api, input.taskId, signal, "serviceMode" in snapshot ? snapshot.serviceMode : void 0);
30185
+ if (rawAnimated) {
30186
+ const animated = proxifyServiceVideoResult(rawAnimated, proxyBaseUrl);
29828
30187
  const continuation2 = buildPollingContinuation(snapshot);
30188
+ const view = buildTaskResultsView(serviceVideoResultMedia(animated), proxyBaseUrl);
29829
30189
  return {
30190
+ structuredContent: {
30191
+ ...snapshot,
30192
+ animatedVideo: toAgentFacingAnimatedVideo(animated)
30193
+ },
30194
+ _meta: view.state === "ready" ? {
30195
+ taskResults: view
30196
+ } : statusMeta,
29830
30197
  content: [
29831
30198
  {
29832
30199
  type: "text",
@@ -29855,6 +30222,7 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
29855
30222
  const continuation = buildPollingContinuation(snapshot);
29856
30223
  if (continuation) {
29857
30224
  return {
30225
+ _meta: statusMeta,
29858
30226
  content: [
29859
30227
  {
29860
30228
  type: "text",
@@ -29870,15 +30238,26 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
29870
30238
  ]
29871
30239
  };
29872
30240
  }
29873
- return asText(snapshot);
30241
+ return {
30242
+ ...asText(snapshot),
30243
+ _meta: statusMeta
30244
+ };
29874
30245
  }
29875
30246
  if (snapshot.kind === "service") {
29876
- const result = await api.getJson(`/v1/tasks/${encodeURIComponent(input.taskId)}/service-result`, {
30247
+ const rawResult = await api.getJson(`/v1/tasks/${encodeURIComponent(input.taskId)}/service-result`, {
29877
30248
  signal
29878
30249
  });
30250
+ const result = proxifyServiceVideoResult(rawResult, proxyBaseUrl);
29879
30251
  const animated = parseAnimatedVideoResult(result);
29880
30252
  if (animated) {
29881
30253
  return {
30254
+ structuredContent: {
30255
+ ...snapshot,
30256
+ result: toAgentFacingAnimatedVideo(animated)
30257
+ },
30258
+ _meta: {
30259
+ taskResults: buildTaskResultsView(serviceVideoResultMedia(animated), proxyBaseUrl)
30260
+ },
29882
30261
  content: [
29883
30262
  {
29884
30263
  type: "text",
@@ -29895,6 +30274,13 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
29895
30274
  };
29896
30275
  }
29897
30276
  return {
30277
+ structuredContent: {
30278
+ ...snapshot,
30279
+ result
30280
+ },
30281
+ _meta: {
30282
+ taskResults: buildTaskResultsView(serviceVideoResultMedia(result), proxyBaseUrl)
30283
+ },
29898
30284
  content: [
29899
30285
  {
29900
30286
  type: "text",
@@ -29916,13 +30302,39 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
29916
30302
  const rawOutputs = await fetchTaskOutputs(api, input.taskId, {
29917
30303
  signal
29918
30304
  });
29919
- const preview2 = rawOutputs.images[0];
29920
- const imageContent = preview2 ? (await buildMcpImagePreviewContent({
29921
- url: preview2.url,
29922
- alt: "Ad creative"
29923
- }, transport)).filter((block) => block.type === "image") : [];
30305
+ const imageContent = await buildMcpGeneratedImageContent(rawOutputs.images.map((image, i) => ({
30306
+ url: image.url,
30307
+ alt: `Imagen ${i + 1}`
30308
+ })), transport);
29924
30309
  const outputs = proxifyOutputs(rawOutputs, proxyBaseUrl);
30310
+ const media = {
30311
+ images: [
30312
+ ...outputs.images.map((image, i) => ({
30313
+ url: image.url,
30314
+ alt: `Imagen ${i + 1}`
30315
+ })),
30316
+ ...outputs.landing.sections.map((section) => ({
30317
+ url: section.url,
30318
+ alt: section.role
30319
+ }))
30320
+ ],
30321
+ videos: outputs.videos.flatMap((video) => video.variants.map((variant) => ({
30322
+ url: variant.url,
30323
+ label: `${video.angleKey} \xB7 ${variant.kind}`,
30324
+ ...video.scriptRewritten ? {
30325
+ scriptRewritten: true
30326
+ } : {}
30327
+ }))),
30328
+ links: []
30329
+ };
29925
30330
  return {
30331
+ structuredContent: {
30332
+ ...snapshot,
30333
+ outputs
30334
+ },
30335
+ _meta: {
30336
+ taskResults: buildTaskResultsView(media, proxyBaseUrl)
30337
+ },
29926
30338
  content: [
29927
30339
  {
29928
30340
  type: "text",
@@ -29943,12 +30355,20 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
29943
30355
  const detail = err instanceof Error ? err.stack ?? err.message : String(err);
29944
30356
  process.stderr.write(`mcp get_task_status: fetchTaskOutputs failed for ${input.taskId}: ${detail}
29945
30357
  `);
29946
- return asText(snapshot);
30358
+ return {
30359
+ ...asText(snapshot),
30360
+ _meta: {
30361
+ taskResults: {
30362
+ ...statusMeta.taskResults,
30363
+ state: "error"
30364
+ }
30365
+ }
30366
+ };
29947
30367
  }
29948
30368
  } catch (e) {
29949
30369
  throw translateError(e);
29950
30370
  }
29951
- });
30371
+ }));
29952
30372
  server.registerTool("list_tasks", {
29953
30373
  description: listTasksGuidance.summary + " \xDAsala para encontrar una tarea previa por nombre o revisar el historial antes de pedir un taskId. Soporta paginaci\xF3n con limit/offset y filtro de texto. No crea, reanuda ni modifica tareas.",
29954
30374
  inputSchema: ListTasksInput.shape,
@@ -29961,16 +30381,16 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
29961
30381
  if (input.search) qs.set("search", input.search);
29962
30382
  const path3 = `/v1/tasks${qs.toString() ? "?" + qs.toString() : ""}`;
29963
30383
  const r = await api.getJson(path3);
29964
- const page = z124.object({
29965
- items: z124.array(z124.unknown())
30384
+ const page = z125.object({
30385
+ items: z125.array(z125.unknown())
29966
30386
  }).passthrough().safeParse(r);
29967
30387
  if (!page.success) return asText(r);
29968
30388
  return asText({
29969
30389
  ...page.data,
29970
30390
  items: page.data.items.map((item) => {
29971
- const servicePage = z124.object({
29972
- taskId: z124.string().uuid(),
29973
- resourceType: z124.literal("service_page")
30391
+ const servicePage = z125.object({
30392
+ taskId: z125.string().uuid(),
30393
+ resourceType: z125.literal("service_page")
29974
30394
  }).passthrough().safeParse(item);
29975
30395
  if (!servicePage.success) return item;
29976
30396
  return {
@@ -30460,28 +30880,28 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
30460
30880
  __name(registerTaskTools, "registerTaskTools");
30461
30881
 
30462
30882
  // src/tools/brands.ts
30463
- import { z as z125 } from "zod";
30883
+ import { z as z126 } from "zod";
30464
30884
  var guidance2 = getProductMakerCapabilityModelGuidance("create_brand");
30465
30885
  var BRAND_START_REPLAY_WINDOW_MS = 15 * 60 * 1e3;
30466
30886
  var BRAND_NOTES_MAX_CHARS = 2e4;
30467
30887
  var BRAND_AMBIGUOUS_REQUEST_RETENTION_MS = 24 * 60 * 60 * 1e3;
30468
30888
  var BRAND_CREATION_REQUEST_LIMIT = 500;
30469
30889
  var brandCreationRequests = /* @__PURE__ */ new Map();
30470
- var CreateBrandInput = z125.object({
30471
- action: z125.enum([
30890
+ var CreateBrandInput = z126.object({
30891
+ action: z126.enum([
30472
30892
  "start",
30473
30893
  "status",
30474
30894
  "list"
30475
30895
  ]).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."),
30476
- sourceUrl: z125.string().trim().min(1).max(BRAND_SOURCE_URL_MAX_LENGTH).optional().describe("Instagram, Facebook, TikTok o web p\xFAblica del negocio, como la dio el usuario (\xAB@sanlucasbarberia\xBB, \xABinstagram.com/sanlucasbarberia\xBB, \xABmibarberia.com\xBB). Obligatorio para start."),
30477
- businessNotes: z125.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."),
30478
- language: z125.enum([
30896
+ sourceUrl: z126.string().trim().min(1).max(BRAND_SOURCE_URL_MAX_LENGTH).optional().describe("Instagram, Facebook, TikTok o web p\xFAblica del negocio, como la dio el usuario (\xAB@sanlucasbarberia\xBB, \xABinstagram.com/sanlucasbarberia\xBB, \xABmibarberia.com\xBB). Obligatorio para start."),
30897
+ businessNotes: z126.string().trim().max(BRAND_NOTES_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cuente de su negocio en el chat (servicios y precios, WhatsApp, ciudad o zona, horarios). Se guarda como documento del negocio y llega tal cual a la marca y a su landing. Copia sus palabras; no inventes datos."),
30898
+ language: z126.enum([
30479
30899
  "es",
30480
30900
  "en",
30481
30901
  "pt"
30482
30902
  ]).optional().describe("Idioma de la conversaci\xF3n. Solo se usa si la p\xE1gina del negocio no deja claro su idioma."),
30483
- confirmed: z125.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, start solo cotiza y no cobra."),
30484
- brandId: z125.string().uuid().optional().describe("ID de la marca. Obligatorio para status; no lo inventes.")
30903
+ confirmed: z126.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, start solo cotiza y no cobra."),
30904
+ brandId: z126.string().uuid().optional().describe("ID de la marca. Obligatorio para status; no lo inventes.")
30485
30905
  }).strict();
30486
30906
  function normalizeBrandSourceUrl(raw) {
30487
30907
  const value = raw.trim();
@@ -30765,24 +31185,24 @@ __name(registerBrandTools, "registerBrandTools");
30765
31185
 
30766
31186
  // src/tools/service-landing.ts
30767
31187
  import { createHash as createHash4, randomUUID } from "crypto";
30768
- import { z as z126 } from "zod";
31188
+ import { z as z127 } from "zod";
30769
31189
  var guidance3 = getProductMakerCapabilityModelGuidance("create_service_landing");
30770
31190
  var SERVICE_LANDING_KEY_NAMESPACE = "6f1d8c2a-3b4e-5f60-8a7b-9c0d1e2f3a4b";
30771
31191
  var SERVICE_LANDING_INFO_MAX_CHARS = 2e4;
30772
- var CreateServiceLandingInput = z126.object({
30773
- action: z126.enum([
31192
+ var CreateServiceLandingInput = z127.object({
31193
+ action: z127.enum([
30774
31194
  "prepare",
30775
31195
  "build",
30776
31196
  "status",
30777
31197
  "publish"
30778
31198
  ]).default("prepare").describe("prepare (gratis) crea o retoma la landing de la marca y da el precio; build (pagado, confirmed=true) genera la p\xE1gina directamente con la marca y los datos guardados; status sigue el avance; publish la publica y devuelve su enlace."),
30779
- brandId: z126.string().uuid().optional().describe("ID de la marca (de create_brand). Obligatorio para prepare. Nunca un taskId de producto."),
30780
- servicePageId: z126.string().uuid().optional().describe("ID de la landing que devolvi\xF3 prepare. Obligatorio para build, status y publish."),
30781
- businessInfo: z126.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."),
30782
- confirmed: z126.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio total y que el usuario acepte. Obligatorio para build."),
30783
- maxCredits: z126.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."),
30784
- operationId: z126.string().uuid().optional().describe("Opcional en status: la operaci\xF3n que devolvi\xF3 build."),
30785
- slug: z126.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.")
31199
+ brandId: z127.string().uuid().optional().describe("ID de la marca (de create_brand). Obligatorio para prepare. Nunca un taskId de producto."),
31200
+ servicePageId: z127.string().uuid().optional().describe("ID de la landing que devolvi\xF3 prepare. Obligatorio para build, status y publish."),
31201
+ businessInfo: z127.string().trim().max(SERVICE_LANDING_INFO_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cont\xF3 del negocio y no estaba en su marca: servicios y precios, WhatsApp o tel\xE9fono, ciudad o zona, horarios. Copia sus palabras; no inventes datos."),
31202
+ confirmed: z127.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio total y que el usuario acepte. Obligatorio para build."),
31203
+ maxCredits: z127.number().int().positive().optional().describe("El total en cr\xE9ditos que el usuario acept\xF3 (el que devolvi\xF3 prepare). Obligatorio para build: ninguna etapa se inicia si su precio supera este total."),
31204
+ operationId: z127.string().uuid().optional().describe("Opcional en status: la operaci\xF3n que devolvi\xF3 build."),
31205
+ slug: z127.string().trim().toLowerCase().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).max(64).optional().describe("Opcional en publish: la direcci\xF3n corta de la p\xE1gina (ej. sanlucas-barberia). Si falta se usa la sugerida desde el nombre del negocio.")
30786
31206
  }).strict();
30787
31207
  function serviceKey(...parts) {
30788
31208
  return deriveUuidV5(parts.join(":"), SERVICE_LANDING_KEY_NAMESPACE);
@@ -31015,7 +31435,7 @@ function registerServiceLandingTools(server, api) {
31015
31435
  const build = quoteRange(generationQuote);
31016
31436
  const totalMin = build.min;
31017
31437
  const totalCredits = build.max;
31018
- const requiredBalanceCredits = generationQuote.credits;
31438
+ const requiredBalanceCredits = totalCredits;
31019
31439
  const askFor = page2.facts.contact.channels.some((channel) => channel.kind === "whatsapp") ? "su ciudad o zona y sus servicios con precio (su WhatsApp ya viene de la marca: no lo pidas)" : "su WhatsApp o tel\xE9fono, su ciudad o zona y sus servicios con precio";
31020
31440
  const priceText = totalMin === totalCredits ? `${totalCredits} cr\xE9ditos` : `entre ${totalMin} y ${totalCredits} cr\xE9ditos`;
31021
31441
  return asText({
@@ -31032,7 +31452,7 @@ function registerServiceLandingTools(server, api) {
31032
31452
  totalCredits,
31033
31453
  requiredBalanceCredits
31034
31454
  },
31035
- nextAction: `En un solo mensaje: dile al usuario que crear su landing cuesta ${priceText} en total (se cobra lo que se use; necesita al menos ${requiredBalanceCredits} cr\xE9ditos de saldo para empezar) y preg\xFAntale, solo si no lo dijo ya en esta conversaci\xF3n, ${askFor} (puede omitirlo). Cuando acepte el precio, llama action=build con servicePageId=${page2.id}, confirmed=true, maxCredits=${totalCredits} y businessInfo con lo que respondi\xF3.`
31455
+ nextAction: `En un solo mensaje: dile al usuario que crear su landing cuesta ${priceText} en total (se cobra lo que se use; necesita al menos ${requiredBalanceCredits} cr\xE9ditos de saldo para empezar) y preg\xFAntale, solo si no lo dijo ya en esta conversaci\xF3n, ${askFor} (puede omitirlo). prepare no consulta el saldo: no interpretes un saldo desconocido como insuficiente ni exijas una comprobaci\xF3n manual. Cuando acepte el precio, llama action=build con servicePageId=${page2.id}, confirmed=true, maxCredits=${totalCredits} y businessInfo con lo que respondi\xF3; comunica cualquier rechazo que devuelva el servidor.`
31036
31456
  });
31037
31457
  }
31038
31458
  if (!input.servicePageId) {
@@ -31157,7 +31577,7 @@ function registerServiceLandingTools(server, api) {
31157
31577
  __name(registerServiceLandingTools, "registerServiceLandingTools");
31158
31578
 
31159
31579
  // src/tools/service-images.ts
31160
- import { z as z127 } from "zod";
31580
+ import { z as z128 } from "zod";
31161
31581
  var guidance4 = getProductMakerCapabilityModelGuidance("create_service_images");
31162
31582
  var SERVICE_IMAGE_FORMATS = [
31163
31583
  "4:5",
@@ -31170,23 +31590,23 @@ var LANGUAGE_TAGS = {
31170
31590
  en: "en-US",
31171
31591
  pt: "pt-BR"
31172
31592
  };
31173
- var CreateServiceImagesInput = z127.object({
31174
- brandId: z127.string().uuid().optional().describe("ID de un servicio propio y listo (de create_brand), obligatorio para cotizar y crear im\xE1genes nuevas. En un retry hist\xF3rico ya confirmado que originalmente no ten\xEDa este campo, conserva la petici\xF3n original. Nunca un taskId de producto."),
31175
- instruction: z127.string().trim().max(4e3).optional().describe("Opcional. Qu\xE9 servicio o promoci\xF3n mostrar, con las palabras del usuario (ej. \xABcorte + barba a $35.000 los martes\xBB). Si se omite, la IA propone la imagen usando la informaci\xF3n del servicio."),
31176
- delegateToAi: z127.boolean().optional().describe("true si el usuario prefiere que la IA elija qu\xE9 mostrar a partir de su servicio. Tambi\xE9n se delega cuando instruction est\xE1 vac\xEDo."),
31177
- format: z127.enum(SERVICE_IMAGE_FORMATS).optional().describe('Formato: "4:5" (feed, por defecto), "9:16" (historias/reels) o "1:1" (cuadrado).'),
31178
- count: z127.number().int().min(1).max(SERVICE_IMAGE_MAX_COUNT).optional().describe("Cu\xE1ntas im\xE1genes, de 1 a 3 (por defecto 1)."),
31179
- quality: z127.enum([
31593
+ var CreateServiceImagesInput = z128.object({
31594
+ brandId: z128.string().uuid().optional().describe("ID de un servicio propio y listo (de create_brand), obligatorio para cotizar y crear im\xE1genes nuevas. En un retry hist\xF3rico ya confirmado que originalmente no ten\xEDa este campo, conserva la petici\xF3n original. Nunca un taskId de producto."),
31595
+ instruction: z128.string().trim().max(4e3).optional().describe("Opcional. Qu\xE9 servicio o promoci\xF3n mostrar, con las palabras del usuario (ej. \xABcorte + barba a $35.000 los martes\xBB). Si se omite, la IA propone la imagen usando la informaci\xF3n del servicio."),
31596
+ delegateToAi: z128.boolean().optional().describe("true si el usuario prefiere que la IA elija qu\xE9 mostrar a partir de su servicio. Tambi\xE9n se delega cuando instruction est\xE1 vac\xEDo."),
31597
+ format: z128.enum(SERVICE_IMAGE_FORMATS).optional().describe('Formato: "4:5" (feed, por defecto), "9:16" (historias/reels) o "1:1" (cuadrado).'),
31598
+ count: z128.number().int().min(1).max(SERVICE_IMAGE_MAX_COUNT).optional().describe("Cu\xE1ntas im\xE1genes, de 1 a 3 (por defecto 1)."),
31599
+ quality: z128.enum([
31180
31600
  "standard",
31181
31601
  "high"
31182
31602
  ]).optional().describe('Calidad: "standard" (por defecto) o "high" (m\xE1s cara; no disponible en 4:5).'),
31183
- language: z127.enum([
31603
+ language: z128.enum([
31184
31604
  "es",
31185
31605
  "en",
31186
31606
  "pt"
31187
31607
  ]).optional().describe("Idioma de los textos de la imagen (por defecto es)."),
31188
- adCopy: z127.boolean().optional().describe("Compatibilidad con clientes anteriores: el copy para publicar siempre est\xE1 incluido en cada imagen de servicios."),
31189
- confirmed: z127.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, solo cotiza y no cobra.")
31608
+ adCopy: z128.boolean().optional().describe("Compatibilidad con clientes anteriores: el copy para publicar siempre est\xE1 incluido en cada imagen de servicios."),
31609
+ confirmed: z128.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, solo cotiza y no cobra.")
31190
31610
  }).strict();
31191
31611
  function serviceImageModel(quality) {
31192
31612
  return quality === "high" ? AD_CREATIVE_MODELS.PREMIUM : AD_CREATIVE_MODELS.STANDARD;
@@ -31300,10 +31720,10 @@ function registerServiceImageTools(server, api, options = {}) {
31300
31720
  ...priceCredits ? {
31301
31721
  priceCredits
31302
31722
  } : {},
31303
- 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."
31723
+ nextAction: "Dile al usuario que est\xE1s creando sus im\xE1genes. Llama get_task_status con este taskId (waitSeconds=45) hasta done (trae las im\xE1genes reales de ProductMaker) o error. Muestra los recursos de imagen devueltos directamente en el chat. Nunca generes ni recrees una imagen sustituta con otra herramienta. Si la vista previa falla, explica el fallo y conserva los enlaces protegidos devueltos."
31304
31724
  });
31305
31725
  } catch (error) {
31306
- if (error instanceof z127.ZodError) throw invalidInputFromZod(error);
31726
+ if (error instanceof z128.ZodError) throw invalidInputFromZod(error);
31307
31727
  throw translateError(error);
31308
31728
  }
31309
31729
  });
@@ -31311,7 +31731,7 @@ function registerServiceImageTools(server, api, options = {}) {
31311
31731
  __name(registerServiceImageTools, "registerServiceImageTools");
31312
31732
 
31313
31733
  // src/tools/creatives.ts
31314
- import { z as z128 } from "zod";
31734
+ import { z as z129 } from "zod";
31315
31735
  var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
31316
31736
  var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
31317
31737
  var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
@@ -31322,72 +31742,72 @@ var CreativeRefs = {
31322
31742
  images: ImagesInput,
31323
31743
  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.'),
31324
31744
  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.'),
31325
- price: z128.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.'),
31326
- offer: z128.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.'),
31327
- compareAtPrice: z128.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
31328
- productContext: z128.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."),
31329
- productLabel: z128.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.'),
31330
- buyerPersona: z128.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.'),
31331
- isCombo: z128.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
31332
- competitorScanEnabled: z128.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."),
31333
- brandId: z128.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.")
31745
+ price: z129.string().min(1).max(120).optional().describe('Precio en formato libre \u2014 ej. "$89.900", "USD 29.99". Opcional pero MUY IMPACTANTE para conversi\xF3n: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar. Si el usuario te dice "t\xFA elige", omite el campo y la IA del backend sugiere uno.'),
31746
+ offer: z129.string().min(1).max(240).optional().describe('Oferta a destacar \u2014 ej. "2x1", "Env\xEDo gratis", "50% OFF". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar (es v\xE1lido que diga "sin oferta"). Si el usuario te dice "t\xFA elige", omite el campo.'),
31747
+ compareAtPrice: z129.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
31748
+ productContext: z129.string().max(3e3).optional().describe("Opcional. Informacion adicional del producto que la IA debe usar como contexto prioritario: uso real, comprador, restricciones, diferenciadores o direccion creativa. No reemplaza la investigacion de competencia; si hay competencia, guia el primer angulo y los outputs no deben contradecirlo."),
31749
+ productLabel: z129.string().trim().max(80).optional().describe('Opcional. Nombre o tipo del producto en pocas palabras (ej. "collar de oro", "quita pelusas para ropa"). Es AUTORITATIVO: la IA usa esta identidad y no la reemplaza por otra categor\xEDa. Si lo omites, la IA lo detecta desde la imagen. NO salta la extracci\xF3n.'),
31750
+ buyerPersona: z129.string().optional().describe('Opcional. Descripci\xF3n del comprador objetivo. Ej. "Mujeres 35-50, profesionales urbanas". Si se omite, la IA infiere desde el \xE1ngulo y producto.'),
31751
+ isCombo: z129.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
31752
+ competitorScanEnabled: z129.boolean().optional().describe("Opcional. Default false: omitirlo significa SIN estudio de mercado. Antes de crear, llama estimate_market_study_cost, muestra al usuario el costo con y sin estudio y preg\xFAntale si lo quiere; env\xEDa true solo si lo acepta (o si solicita la narrativa an\xE1lisis de mercado). En video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico."),
31753
+ brandId: z129.string().uuid().optional().describe("Opcional. ID de una marca del usuario; si se env\xEDa, el sistema usa su voz, colores y persona para enriquecer el creativo.")
31334
31754
  };
31335
- var VideoPresenter = z128.discriminatedUnion("mode", [
31336
- z128.object({
31337
- mode: z128.literal("none")
31755
+ var VideoPresenter = z129.discriminatedUnion("mode", [
31756
+ z129.object({
31757
+ mode: z129.literal("none")
31338
31758
  }).strict(),
31339
- z128.object({
31340
- mode: z128.literal("saved_actor"),
31341
- actorId: z128.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
31759
+ z129.object({
31760
+ mode: z129.literal("saved_actor"),
31761
+ actorId: z129.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
31342
31762
  }).strict(),
31343
- z128.object({
31344
- mode: z128.literal("described"),
31345
- description: z128.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
31763
+ z129.object({
31764
+ mode: z129.literal("described"),
31765
+ description: z129.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
31346
31766
  }).strict()
31347
31767
  ]);
31348
- var VideoCreativeSetup = z128.discriminatedUnion("mode", [
31349
- z128.object({
31350
- mode: z128.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
31768
+ var VideoCreativeSetup = z129.discriminatedUnion("mode", [
31769
+ z129.object({
31770
+ mode: z129.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
31351
31771
  }).strict(),
31352
- z128.object({
31353
- mode: z128.literal("guided"),
31772
+ z129.object({
31773
+ mode: z129.literal("guided"),
31354
31774
  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.'),
31355
- buyerPersona: z128.string().trim().min(1).max(360),
31775
+ buyerPersona: z129.string().trim().min(1).max(360),
31356
31776
  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.'),
31357
31777
  presenter: VideoPresenter,
31358
- creativeDirection: z128.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
31778
+ creativeDirection: z129.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
31359
31779
  }).strict()
31360
31780
  ]);
31361
- var VideoInput = z128.object({
31781
+ var VideoInput = z129.object({
31362
31782
  images: CreativeRefs.images.optional(),
31363
31783
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
31364
- title: z128.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
31365
- primaryAngle: z128.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".'),
31784
+ title: z129.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
31785
+ primaryAngle: z129.string().min(1).describe('\xC1ngulo de venta principal (frase del beneficio). Ej. "Reduce arrugas en 14 d\xEDas" o "Para quienes odian las cremas grasosas".'),
31366
31786
  language: CreativeRefs.language,
31367
31787
  country: CreativeRefs.country,
31368
- aspectRatio: z128.enum([
31788
+ aspectRatio: z129.enum([
31369
31789
  "9:16",
31370
31790
  "16:9",
31371
31791
  "Auto"
31372
31792
  ]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
31373
31793
  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.'),
31374
- durationSeconds: z128.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."),
31375
- videoAngleCount: z128.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."),
31794
+ durationSeconds: z129.number().int().min(4).max(30).default(15).describe("Opcional. Duraci\xF3n objetivo: Un solo clip Econ\xF3mico o Medio usa 15s; Un solo clip Pro usa 15s o 30s; Multiescena usa 15s o 30s totales. La combinaci\xF3n de formato y calidad determina la ruta y el costo."),
31795
+ videoAngleCount: z129.number().int().min(1).max(3).describe("Cantidad de videos a renderizar: 1, 2 o 3. Es una decisi\xF3n de costo obligatoria: preg\xFAntala incluso cuando creativeSetup.mode=automatic."),
31376
31796
  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.'),
31377
31797
  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."),
31378
31798
  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.'),
31379
31799
  videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
31380
31800
  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.'),
31381
- features: z128.array(z128.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
31801
+ features: z129.array(z129.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
31382
31802
  price: CreativeRefs.price,
31383
31803
  offer: CreativeRefs.offer,
31384
31804
  productContext: CreativeRefs.productContext,
31385
31805
  productLabel: CreativeRefs.productLabel,
31386
- cta: z128.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.'),
31387
- scriptNotes: z128.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.'),
31806
+ cta: z129.string().optional().describe('Opcional. Call-to-action final del video. Ej. "Compra ahora", "Pide el tuyo hoy", "Link en bio". Si se omite, la IA escribe uno.'),
31807
+ scriptNotes: z129.string().optional().describe('Opcional. Notas/restricciones para el guion (la IA las usa al redactar). Ej. "No mencionar la marca X", "Tono divertido, no cl\xEDnico", "Mencionar 2x1". NO es el guion literal: creativeSetup.mode=guided activa siempre la revisi\xF3n palabra-por-palabra con get_video_script / approve_video_script.'),
31388
31808
  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.'),
31389
31809
  competitorScanEnabled: CreativeRefs.competitorScanEnabled,
31390
- replicateWinnerWhenFound: z128.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."),
31810
+ replicateWinnerWhenFound: z129.boolean().optional().describe("Conserva la preferencia de copiar un ganador si existe. false permite estudiar el mercado sin reemplazar un \xE1ngulo por el anuncio ganador. No a\xF1adas una pregunta obligatoria para este campo."),
31391
31811
  brandId: CreativeRefs.brandId
31392
31812
  }).strict();
31393
31813
  var FreeVideoQualityEnum = VideoQualityEnum;
@@ -31405,7 +31825,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
31405
31825
  length: 29
31406
31826
  }, (_, index) => index + 2)
31407
31827
  };
31408
- var FreeVideoModelIdEnum = z128.enum([
31828
+ var FreeVideoModelIdEnum = z129.enum([
31409
31829
  "grok-imagine-video-1-5-preview",
31410
31830
  "minimax-h3/reference-to-video",
31411
31831
  "wan/3-0-video",
@@ -31416,66 +31836,66 @@ var FREE_SELECTABLE_MODEL_IDS = [
31416
31836
  "minimax-h3/reference-to-video",
31417
31837
  "wan/3-0-video"
31418
31838
  ];
31419
- var FreeVideoInput = z128.object({
31839
+ var FreeVideoInput = z129.object({
31420
31840
  images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
31421
- rawPrompt: z128.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."),
31841
+ rawPrompt: z129.string().trim().min(1).max(2e3).describe("Prompt o guion exacto del video. Si activas subt\xEDtulos, este mismo texto se usa como guion de subt\xEDtulos."),
31422
31842
  language: CreativeRefs.language,
31423
31843
  quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
31424
31844
  // Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
31425
31845
  // parsed ONLY so the handler can reject it with a message naming its
31426
31846
  // replacement — dropping it silently would turn a caller's explicit
31427
31847
  // Pro++ pick into a quiet fallback to Wan.
31428
- freeProModel: z128.enum([
31848
+ freeProModel: z129.enum([
31429
31849
  "wan",
31430
31850
  "seedance"
31431
31851
  ]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
31432
31852
  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.'),
31433
- durationSeconds: z128.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."),
31853
+ durationSeconds: z129.number().int().min(2).max(30).describe("Duraci\xF3n exacta. Econ\xF3mico: 6, 8, 10 o 15s; Medio: enteros de 4 a 15s; Pro Wan: 2 a 30s; Pro++ Seedance: 4 a 30s."),
31434
31854
  videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
31435
- generateAiMusic: z128.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.'),
31855
+ generateAiMusic: z129.boolean().default(false).describe('Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false. Equivale a generateAiEdit (nivel "pro"): la Edici\xF3n con IA trae su propia m\xFAsica.'),
31436
31856
  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.'),
31437
- addSubtitles: z128.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
31438
- idempotencyKey: z128.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.")
31857
+ addSubtitles: z129.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
31858
+ idempotencyKey: z129.string().uuid().optional().describe("Opcional. Se acepta por compatibilidad pero se ignora: la identidad del reintento se deriva autom\xE1ticamente de los argumentos sem\xE1nticos, as\xED que un retry con los mismos argumentos ya es idempotente sin este campo.")
31439
31859
  }).strict();
31440
31860
  var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
31441
- var ImageCreativeSetup = z128.discriminatedUnion("mode", [
31442
- z128.object({
31443
- mode: z128.literal("automatic")
31861
+ var ImageCreativeSetup = z129.discriminatedUnion("mode", [
31862
+ z129.object({
31863
+ mode: z129.literal("automatic")
31444
31864
  }).strict(),
31445
- z128.object({
31446
- mode: z128.literal("guided"),
31447
- creativeArchetype: z128.union([
31865
+ z129.object({
31866
+ mode: z129.literal("guided"),
31867
+ creativeArchetype: z129.union([
31448
31868
  ImageCreativeArchetypeEnum,
31449
- z128.literal("ai_decides")
31869
+ z129.literal("ai_decides")
31450
31870
  ]),
31451
- visualTreatment: z128.union([
31871
+ visualTreatment: z129.union([
31452
31872
  ImageCreativeVisualTreatmentEnum,
31453
- z128.literal("ai_decides")
31873
+ z129.literal("ai_decides")
31454
31874
  ]),
31455
31875
  aspectRatio: ImageCreativeAspectRatioEnum,
31456
- nVariants: z128.union([
31457
- z128.literal(1),
31458
- z128.literal(2),
31459
- z128.literal(3),
31460
- z128.literal(4),
31461
- z128.literal(6)
31876
+ nVariants: z129.union([
31877
+ z129.literal(1),
31878
+ z129.literal(2),
31879
+ z129.literal(3),
31880
+ z129.literal(4),
31881
+ z129.literal(6)
31462
31882
  ]),
31463
- imageModel: z128.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.'),
31464
- styleMix: z128.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
31465
- generateAdCopy: z128.boolean(),
31466
- competitorScanEnabled: z128.boolean(),
31467
- productContext: z128.string().trim().min(1).max(3e3).nullable(),
31468
- creativeDirection: z128.string().trim().min(1).max(500).nullable(),
31469
- brandColors: z128.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.'),
31470
- headline: z128.string().trim().min(1).max(120).nullable(),
31471
- subheadline: z128.string().trim().min(1).max(160).nullable()
31883
+ imageModel: z129.enum(PUBLIC_IMAGE_QUALITY_INPUTS).describe('Calidad: "image:1k" (Est\xE1ndar) o "image:2k" (Premium). Los tokens gpt-image-2-5:{1k,2k} y gpt-image-2:{1k,2k} se siguen aceptando.'),
31884
+ styleMix: z129.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
31885
+ generateAdCopy: z129.boolean(),
31886
+ competitorScanEnabled: z129.boolean(),
31887
+ productContext: z129.string().trim().min(1).max(3e3).nullable(),
31888
+ creativeDirection: z129.string().trim().min(1).max(500).nullable(),
31889
+ brandColors: z129.string().trim().min(1).max(240).nullable().describe('Colores en lenguaje natural, igual que en el chat web. Ej. "Azul y Dorado". null significa sin colores espec\xEDficos.'),
31890
+ headline: z129.string().trim().min(1).max(120).nullable(),
31891
+ subheadline: z129.string().trim().min(1).max(160).nullable()
31472
31892
  }).strict()
31473
31893
  ]).superRefine((setup, context) => {
31474
31894
  if (setup.mode !== "guided") return;
31475
31895
  const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
31476
31896
  if (needsStyleMix && setup.styleMix === null) {
31477
31897
  context.addIssue({
31478
- code: z128.ZodIssueCode.custom,
31898
+ code: z129.ZodIssueCode.custom,
31479
31899
  path: [
31480
31900
  "styleMix"
31481
31901
  ],
@@ -31484,7 +31904,7 @@ var ImageCreativeSetup = z128.discriminatedUnion("mode", [
31484
31904
  }
31485
31905
  if (!needsStyleMix && setup.styleMix !== null) {
31486
31906
  context.addIssue({
31487
- code: z128.ZodIssueCode.custom,
31907
+ code: z129.ZodIssueCode.custom,
31488
31908
  path: [
31489
31909
  "styleMix"
31490
31910
  ],
@@ -31493,7 +31913,7 @@ var ImageCreativeSetup = z128.discriminatedUnion("mode", [
31493
31913
  }
31494
31914
  if (imageResolutionOf(setup.imageModel) === "2k" && setup.aspectRatio === "4:5") {
31495
31915
  context.addIssue({
31496
- code: z128.ZodIssueCode.custom,
31916
+ code: z129.ZodIssueCode.custom,
31497
31917
  path: [
31498
31918
  "aspectRatio"
31499
31919
  ],
@@ -31501,55 +31921,55 @@ var ImageCreativeSetup = z128.discriminatedUnion("mode", [
31501
31921
  });
31502
31922
  }
31503
31923
  });
31504
- var LandingCreativeSetup = z128.discriminatedUnion("mode", [
31505
- z128.object({
31506
- mode: z128.literal("automatic")
31924
+ var LandingCreativeSetup = z129.discriminatedUnion("mode", [
31925
+ z129.object({
31926
+ mode: z129.literal("automatic")
31507
31927
  }).strict(),
31508
- z128.object({
31509
- mode: z128.literal("guided"),
31928
+ z129.object({
31929
+ mode: z129.literal("guided"),
31510
31930
  landingStrategy: LandingStrategyEnum,
31511
31931
  landingImageFormat: LandingImageFormatEnum,
31512
- competitorScanEnabled: z128.boolean(),
31513
- paymentMethods: z128.string().trim().min(1).max(240).nullable(),
31514
- productContext: z128.string().trim().min(1).max(3e3).nullable(),
31515
- creativeDirection: z128.string().trim().min(1).max(500).nullable(),
31516
- headline: z128.string().trim().min(1).max(120).nullable(),
31517
- subheadline: z128.string().trim().min(1).max(160).nullable()
31932
+ competitorScanEnabled: z129.boolean(),
31933
+ paymentMethods: z129.string().trim().min(1).max(240).nullable(),
31934
+ productContext: z129.string().trim().min(1).max(3e3).nullable(),
31935
+ creativeDirection: z129.string().trim().min(1).max(500).nullable(),
31936
+ headline: z129.string().trim().min(1).max(120).nullable(),
31937
+ subheadline: z129.string().trim().min(1).max(160).nullable()
31518
31938
  }).strict()
31519
31939
  ]);
31520
- var ImageInput = z128.object({
31940
+ var ImageInput = z129.object({
31521
31941
  images: CreativeRefs.images.optional(),
31522
31942
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
31523
- productTitle: z128.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
31524
- primaryAngle: z128.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.'),
31943
+ productTitle: z129.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
31944
+ primaryAngle: z129.string().min(1).optional().describe('Opcional. \xC1ngulo de venta principal. Si se omite, ProductMaker lo genera y creativeSetup.mode="guided" lo muestra para revisi\xF3n antes de crear las im\xE1genes.'),
31525
31945
  buyerPersona: CreativeRefs.buyerPersona,
31526
31946
  language: CreativeRefs.language,
31527
31947
  country: CreativeRefs.country,
31528
31948
  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."),
31529
31949
  imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
31530
- features: z128.array(z128.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
31950
+ features: z129.array(z129.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
31531
31951
  price: CreativeRefs.price,
31532
- omitPrice: z128.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."),
31952
+ omitPrice: z129.boolean().optional().describe("Pon true \xFAnicamente cuando el usuario pida expl\xEDcitamente una imagen sin precio. Evita que el backend reutilice un precio extra\xEDdo del producto. No lo combines con price ni compareAtPrice."),
31533
31953
  compareAtPrice: CreativeRefs.compareAtPrice,
31534
31954
  offer: CreativeRefs.offer,
31535
31955
  productLabel: CreativeRefs.productLabel,
31536
31956
  isCombo: CreativeRefs.isCombo,
31537
31957
  brandId: CreativeRefs.brandId
31538
31958
  });
31539
- var EditImageCreativeInput = z128.object({
31540
- taskId: z128.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
31541
- variantIndex: z128.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
31542
- clientRequestId: z128.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."),
31543
- instruction: z128.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".')
31959
+ var EditImageCreativeInput = z129.object({
31960
+ taskId: z129.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
31961
+ variantIndex: z129.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
31962
+ clientRequestId: z129.string().min(1).max(160).optional().describe("Identidad estable de esta correcci\xF3n; reutil\xEDzala al reconciliar una respuesta perdida, no para otra instrucci\xF3n."),
31963
+ instruction: z129.string().min(1).max(1e3).describe('Qu\xE9 cambiar en esa imagen. Ej. "quita el badge de env\xEDo gratis", "cambia el fondo a blanco".')
31544
31964
  });
31545
- var LandingInput = z128.object({
31546
- includeInitialLandingGif: z128.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."),
31965
+ var LandingInput = z129.object({
31966
+ includeInitialLandingGif: z129.boolean().optional().describe("Opcional. En nuevas landings cl\xE1sicas habilitadas, omitirlo incluye el primer GIF del producto y su coste en el total. Env\xEDa false si el usuario lo excluye: no se genera ni se reserva su coste. Conserva la elecci\xF3n al confirmar y al reintentar."),
31547
31967
  images: CreativeRefs.images.optional(),
31548
31968
  winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
31549
31969
  language: CreativeRefs.language,
31550
31970
  country: CreativeRefs.country,
31551
31971
  creativeSetup: LandingCreativeSetup.describe("Configuraci\xF3n obligatoria de landing cl\xE1sica equivalente al wizard web. No expone landing editable/code mientras siga siendo admin-only."),
31552
- salesAngle: z128.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.'),
31972
+ salesAngle: z129.string().optional().describe('Opcional. \xC1ngulo de venta principal. Ej. "Reduce arrugas en 14 d\xEDas". Si se omite, la IA lo deduce de la imagen.'),
31553
31973
  buyerPersona: CreativeRefs.buyerPersona,
31554
31974
  price: CreativeRefs.price,
31555
31975
  compareAtPrice: CreativeRefs.compareAtPrice,
@@ -31831,8 +32251,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
31831
32251
  server.registerTool("get_image_edit_status", {
31832
32252
  description: imageEditStatusGuidance.summary,
31833
32253
  inputSchema: {
31834
- taskId: z128.string().uuid(),
31835
- operationId: z128.string().uuid()
32254
+ taskId: z129.string().uuid(),
32255
+ operationId: z129.string().uuid()
31836
32256
  },
31837
32257
  annotations: READS_INTERNAL
31838
32258
  }, async (input) => {
@@ -31889,10 +32309,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
31889
32309
  __name(registerCreativeTools, "registerCreativeTools");
31890
32310
 
31891
32311
  // src/tools/creative-variants.ts
31892
- import { z as z129 } from "zod";
32312
+ import { z as z130 } from "zod";
31893
32313
  var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
31894
32314
  var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
31895
- var LandingSectionKeyEnum = z129.enum([
32315
+ var LandingSectionKeyEnum = z130.enum([
31896
32316
  "problem_hook",
31897
32317
  "problem_cost",
31898
32318
  "solution_mechanism",
@@ -31932,24 +32352,24 @@ var LandingSectionKeyEnum = z129.enum([
31932
32352
  "lifestyle_fit",
31933
32353
  "join_lifestyle"
31934
32354
  ]);
31935
- var CreativeVariantKindEnum = z129.enum([
32355
+ var CreativeVariantKindEnum = z130.enum([
31936
32356
  "video",
31937
32357
  "image",
31938
32358
  "landing"
31939
32359
  ]);
31940
- var EstimateCreativeVariantInputBase = z129.object({
31941
- sourceTaskId: z129.string().uuid().describe("ID de la tarea original completada."),
32360
+ var EstimateCreativeVariantInputBase = z130.object({
32361
+ sourceTaskId: z130.string().uuid().describe("ID de la tarea original completada."),
31942
32362
  kind: CreativeVariantKindEnum,
31943
32363
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
31944
32364
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
31945
- nVariants: z129.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
32365
+ nVariants: z130.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
31946
32366
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
31947
- instructions: z129.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.")
32367
+ instructions: z130.string().trim().min(1).max(2e3).optional().describe("Opcional para landing. Si se env\xEDa sin sectionKey, el estimado suma la clasificaci\xF3n pagada con IA.")
31948
32368
  }).strict();
31949
32369
  var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
31950
32370
  if (input.kind === "video" && input.nVariants !== void 0) {
31951
32371
  ctx.addIssue({
31952
- code: z129.ZodIssueCode.custom,
32372
+ code: z130.ZodIssueCode.custom,
31953
32373
  path: [
31954
32374
  "nVariants"
31955
32375
  ],
@@ -31959,7 +32379,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
31959
32379
  if (input.kind !== "video") {
31960
32380
  if (input.videoPreset !== void 0) {
31961
32381
  ctx.addIssue({
31962
- code: z129.ZodIssueCode.custom,
32382
+ code: z130.ZodIssueCode.custom,
31963
32383
  path: [
31964
32384
  "videoPreset"
31965
32385
  ],
@@ -31968,7 +32388,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
31968
32388
  }
31969
32389
  if (input.videoResolution !== void 0) {
31970
32390
  ctx.addIssue({
31971
- code: z129.ZodIssueCode.custom,
32391
+ code: z130.ZodIssueCode.custom,
31972
32392
  path: [
31973
32393
  "videoResolution"
31974
32394
  ],
@@ -31978,7 +32398,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
31978
32398
  }
31979
32399
  if (input.kind !== "image" && input.nVariants !== void 0) {
31980
32400
  ctx.addIssue({
31981
- code: z129.ZodIssueCode.custom,
32401
+ code: z130.ZodIssueCode.custom,
31982
32402
  path: [
31983
32403
  "nVariants"
31984
32404
  ],
@@ -31988,7 +32408,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
31988
32408
  if (input.kind !== "landing") {
31989
32409
  if (input.sectionKey !== void 0) {
31990
32410
  ctx.addIssue({
31991
- code: z129.ZodIssueCode.custom,
32411
+ code: z130.ZodIssueCode.custom,
31992
32412
  path: [
31993
32413
  "sectionKey"
31994
32414
  ],
@@ -31997,7 +32417,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
31997
32417
  }
31998
32418
  if (input.instructions !== void 0) {
31999
32419
  ctx.addIssue({
32000
- code: z129.ZodIssueCode.custom,
32420
+ code: z130.ZodIssueCode.custom,
32001
32421
  path: [
32002
32422
  "instructions"
32003
32423
  ],
@@ -32006,31 +32426,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
32006
32426
  }
32007
32427
  }
32008
32428
  });
32009
- var CreateCreativeVariantInputBase = z129.object({
32010
- sourceTaskId: z129.string().uuid().describe("ID de la tarea original completada."),
32429
+ var CreateCreativeVariantInputBase = z130.object({
32430
+ sourceTaskId: z130.string().uuid().describe("ID de la tarea original completada."),
32011
32431
  kind: CreativeVariantKindEnum,
32012
- confirm: z129.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
32013
- clientRequestId: z129.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."),
32014
- angle: z129.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
32015
- buyerPersona: z129.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
32016
- scriptNotes: z129.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
32017
- creativeDirection: z129.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
32432
+ confirm: z130.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
32433
+ clientRequestId: z130.string().uuid().describe("UUID estable para esta intenci\xF3n (obligatorio por compatibilidad de contrato; el servidor deriva la identidad real del request desde los argumentos sem\xE1nticos, as\xED que un UUID nuevo en un retry NO crea una variante duplicada). Si la API devuelve status=error, una nueva generaci\xF3n exige otra confirmaci\xF3n."),
32434
+ angle: z130.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
32435
+ buyerPersona: z130.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
32436
+ scriptNotes: z130.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
32437
+ creativeDirection: z130.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
32018
32438
  videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
32019
32439
  videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
32020
- generateAiMusic: z129.boolean().optional().describe("Opcional para video."),
32021
- nVariants: z129.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
32440
+ generateAiMusic: z130.boolean().optional().describe("Opcional para video."),
32441
+ nVariants: z130.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
32022
32442
  imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
32023
32443
  creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
32024
32444
  visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
32025
32445
  aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
32026
- styleMix: z129.boolean().optional().describe("Opcional para imagen."),
32446
+ styleMix: z130.boolean().optional().describe("Opcional para imagen."),
32027
32447
  sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
32028
- instructions: z129.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.")
32448
+ instructions: z130.string().trim().min(1).max(2e3).optional().describe("Solicitud libre para una nueva secci\xF3n de landing. La IA la clasifica si no env\xEDas sectionKey.")
32029
32449
  }).strict();
32030
32450
  var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
32031
32451
  if ((input.kind === "video" || input.kind === "image") && !input.angle) {
32032
32452
  ctx.addIssue({
32033
- code: z129.ZodIssueCode.custom,
32453
+ code: z130.ZodIssueCode.custom,
32034
32454
  path: [
32035
32455
  "angle"
32036
32456
  ],
@@ -32039,7 +32459,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
32039
32459
  }
32040
32460
  if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
32041
32461
  ctx.addIssue({
32042
- code: z129.ZodIssueCode.custom,
32462
+ code: z130.ZodIssueCode.custom,
32043
32463
  path: [
32044
32464
  "instructions"
32045
32465
  ],
@@ -32085,7 +32505,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
32085
32505
  for (const field of fieldsByKind[input.kind]) {
32086
32506
  if (input[field] !== void 0) {
32087
32507
  ctx.addIssue({
32088
- code: z129.ZodIssueCode.custom,
32508
+ code: z130.ZodIssueCode.custom,
32089
32509
  path: [
32090
32510
  field
32091
32511
  ],
@@ -32243,13 +32663,13 @@ function registerCreativeVariantTools(server, api) {
32243
32663
  __name(registerCreativeVariantTools, "registerCreativeVariantTools");
32244
32664
 
32245
32665
  // src/tools/script-review.ts
32246
- import { z as z130 } from "zod";
32666
+ import { z as z131 } from "zod";
32247
32667
  var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
32248
32668
  var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
32249
32669
  var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
32250
- var GetVideoScriptInput = z130.object({
32251
- taskId: z130.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
32252
- angleKey: z130.string().min(1).optional().describe('Clave persistida del \xE1ngulo cuyo guion se quiere leer (formato "angle_0", "angle_1", ...). Usa exactamente el angleKey recibido en reviewNextAction.calls al aprobar \xE1ngulos, incluso si s\xF3lo elegiste uno. Si se omite, el backend resuelve a "angle_0" literal; elegir el segundo candidato no crea angle_0. No derives esta clave del n\xFAmero visible del candidato.')
32670
+ var GetVideoScriptInput = z131.object({
32671
+ taskId: z131.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
32672
+ angleKey: z131.string().min(1).optional().describe('Clave persistida del \xE1ngulo cuyo guion se quiere leer (formato "angle_0", "angle_1", ...). Usa exactamente el angleKey recibido en reviewNextAction.calls al aprobar \xE1ngulos, incluso si s\xF3lo elegiste uno. Si se omite, el backend resuelve a "angle_0" literal; elegir el segundo candidato no crea angle_0. No derives esta clave del n\xFAmero visible del candidato.')
32253
32673
  }).strict();
32254
32674
  var ApproveVideoScriptInput = ApproveVideoScriptCapabilityRequest;
32255
32675
  var RegenerateVideoScriptInput = RegenerateVideoScriptCapabilityRequest.extend({
@@ -32354,7 +32774,7 @@ Consulta get_task_status con esta tarea antes de reintentar. Si la tarea termin\
32354
32774
  __name(registerScriptReviewTools, "registerScriptReviewTools");
32355
32775
 
32356
32776
  // src/tools/connections.ts
32357
- import { z as z131 } from "zod";
32777
+ import { z as z132 } from "zod";
32358
32778
  var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
32359
32779
  var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
32360
32780
  var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
@@ -32363,7 +32783,7 @@ var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list
32363
32783
  function registerConnectionTools(server, api) {
32364
32784
  server.registerTool("list_shopify_shops", {
32365
32785
  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.",
32366
- inputSchema: z131.object({}).shape,
32786
+ inputSchema: z132.object({}).shape,
32367
32787
  annotations: READS_INTERNAL
32368
32788
  }, async () => {
32369
32789
  try {
@@ -32375,10 +32795,10 @@ function registerConnectionTools(server, api) {
32375
32795
  });
32376
32796
  server.registerTool("list_shopify_products", {
32377
32797
  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.',
32378
- inputSchema: z131.object({
32379
- shopDomain: z131.string().min(3).max(120),
32380
- query: z131.string().trim().max(120).optional(),
32381
- taskId: z131.string().uuid().optional()
32798
+ inputSchema: z132.object({
32799
+ shopDomain: z132.string().min(3).max(120),
32800
+ query: z132.string().trim().max(120).optional(),
32801
+ taskId: z132.string().uuid().optional()
32382
32802
  }).shape,
32383
32803
  annotations: READS_EXTERNAL
32384
32804
  }, async ({ shopDomain, query, taskId }) => {
@@ -32396,7 +32816,7 @@ function registerConnectionTools(server, api) {
32396
32816
  });
32397
32817
  server.registerTool("list_meta_ad_accounts", {
32398
32818
  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.",
32399
- inputSchema: z131.object({}).shape,
32819
+ inputSchema: z132.object({}).shape,
32400
32820
  annotations: READS_EXTERNAL
32401
32821
  }, async () => {
32402
32822
  try {
@@ -32408,7 +32828,7 @@ function registerConnectionTools(server, api) {
32408
32828
  });
32409
32829
  server.registerTool("list_meta_destinations", {
32410
32830
  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.",
32411
- inputSchema: z131.object({}).shape,
32831
+ inputSchema: z132.object({}).shape,
32412
32832
  annotations: READS_EXTERNAL,
32413
32833
  _meta: {
32414
32834
  "openai/widgetAccessible": true
@@ -32423,7 +32843,7 @@ function registerConnectionTools(server, api) {
32423
32843
  });
32424
32844
  server.registerTool("list_tiktok_advertisers", {
32425
32845
  description: listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.",
32426
- inputSchema: z131.object({}).shape,
32846
+ inputSchema: z132.object({}).shape,
32427
32847
  annotations: READS_EXTERNAL
32428
32848
  }, async () => {
32429
32849
  try {
@@ -32437,7 +32857,7 @@ function registerConnectionTools(server, api) {
32437
32857
  __name(registerConnectionTools, "registerConnectionTools");
32438
32858
 
32439
32859
  // src/tools/actors.ts
32440
- import { z as z132 } from "zod";
32860
+ import { z as z133 } from "zod";
32441
32861
  var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
32442
32862
  var actorVoiceGuidance = {
32443
32863
  capabilities: getProductMakerCapabilityModelGuidance("get_actor_voice_capabilities"),
@@ -32477,7 +32897,7 @@ function sanitizeVoiceResult(value) {
32477
32897
  __name(sanitizeVoiceResult, "sanitizeVoiceResult");
32478
32898
  function registerActorTools(server, api) {
32479
32899
  const actor = {
32480
- actorId: z132.string().min(1).max(64)
32900
+ actorId: z133.string().min(1).max(64)
32481
32901
  };
32482
32902
  const safe = /* @__PURE__ */ __name(async (request) => {
32483
32903
  try {
@@ -32506,8 +32926,8 @@ function registerActorTools(server, api) {
32506
32926
  inputSchema: {
32507
32927
  ...actor,
32508
32928
  draft: ActorVoiceDraftSchema,
32509
- requestKey: z132.string().trim().min(1).max(128),
32510
- acceptedQuoteId: z132.string().trim().min(1).max(128)
32929
+ requestKey: z133.string().trim().min(1).max(128),
32930
+ acceptedQuoteId: z133.string().trim().min(1).max(128)
32511
32931
  },
32512
32932
  annotations: CREATES_PAID
32513
32933
  }, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/previews`, body)));
@@ -32515,7 +32935,7 @@ function registerActorTools(server, api) {
32515
32935
  description: actorVoiceGuidance.get.summary,
32516
32936
  inputSchema: {
32517
32937
  ...actor,
32518
- candidateId: z132.string().min(1).max(64)
32938
+ candidateId: z133.string().min(1).max(64)
32519
32939
  },
32520
32940
  // Polling can resume the first paid submission of an accepted quote.
32521
32941
  // The immutable candidate/operation key keeps recovery idempotent.
@@ -32528,16 +32948,16 @@ function registerActorTools(server, api) {
32528
32948
  description: actorVoiceGuidance.approve.summary,
32529
32949
  inputSchema: {
32530
32950
  ...actor,
32531
- candidateId: z132.string().min(1).max(64),
32532
- expectedRevision: z132.number().int().positive(),
32533
- expectedApprovedRevision: z132.number().int().positive().nullable().optional()
32951
+ candidateId: z133.string().min(1).max(64),
32952
+ expectedRevision: z133.number().int().positive(),
32953
+ expectedApprovedRevision: z133.number().int().positive().nullable().optional()
32534
32954
  },
32535
32955
  // Replaces the selected voice and withdraws the old catalog grants.
32536
32956
  annotations: OVERWRITES_INTERNAL
32537
32957
  }, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/approve`, body)));
32538
32958
  server.registerTool("list_actors", {
32539
32959
  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.",
32540
- inputSchema: z132.object({}).shape,
32960
+ inputSchema: z133.object({}).shape,
32541
32961
  annotations: READS_INTERNAL
32542
32962
  }, async () => {
32543
32963
  try {
@@ -32570,7 +32990,7 @@ function registerActorTools(server, api) {
32570
32990
  __name(registerActorTools, "registerActorTools");
32571
32991
 
32572
32992
  // src/tools/publish.ts
32573
- import { z as z133 } from "zod";
32993
+ import { z as z134 } from "zod";
32574
32994
 
32575
32995
  // src/tools/meta-publish-attempt-id.ts
32576
32996
  var META_PUBLISH_NAMESPACE = "7b19c9ac-b4eb-4db1-970e-c2f24ce30b98";
@@ -32609,40 +33029,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
32609
33029
  var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
32610
33030
  var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
32611
33031
  var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
32612
- var ShopifyInput = z133.object({
32613
- taskId: z133.string().min(1),
32614
- shopDomain: z133.string().min(1),
33032
+ var ShopifyInput = z134.object({
33033
+ taskId: z134.string().min(1),
33034
+ shopDomain: z134.string().min(1),
32615
33035
  /** Override: number of landing images to include. Default = ALL images the
32616
33036
  * task generated (the MCP fetches /v1/results first to count). Bounded
32617
33037
  * generously here; the backend validates each index against
32618
33038
  * landing.images.length and rejects out-of-range. */
32619
- numLandingImages: z133.number().int().min(1).max(20).optional(),
32620
- variantIndex: z133.number().int().min(0).optional(),
33039
+ numLandingImages: z134.number().int().min(1).max(20).optional(),
33040
+ variantIndex: z134.number().int().min(0).optional(),
32621
33041
  /** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
32622
33042
  * When true, the landing renders variant-picker pills; when false, it ships
32623
33043
  * a single-option product page. Defaults to false. */
32624
- showVariantPicker: z133.boolean().optional(),
33044
+ showVariantPicker: z134.boolean().optional(),
32625
33045
  /** Default `auto` updates the product previously published for this task and
32626
33046
  * shop. Use `existing` with targetProductId to choose another product, or
32627
33047
  * `new` only when the user explicitly wants a duplicate/new listing. */
32628
- publicationMode: z133.enum([
33048
+ publicationMode: z134.enum([
32629
33049
  "auto",
32630
33050
  "existing",
32631
33051
  "new"
32632
33052
  ]).optional(),
32633
33053
  /** Shopify product GID, numeric id, or admin product URL. Required when
32634
33054
  * publicationMode is `existing`. */
32635
- targetProductId: z133.string().trim().min(1).max(300).optional(),
33055
+ targetProductId: z134.string().trim().min(1).max(300).optional(),
32636
33056
  /** Add an announcement bar text above add-to-cart (optional). */
32637
- announcementBarEnabled: z133.boolean().optional(),
32638
- announcementBarText: z133.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
33057
+ announcementBarEnabled: z134.boolean().optional(),
33058
+ announcementBarText: z134.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
32639
33059
  commerceCorrection: PublishCommerceCorrectionSchema.optional().describe("Complete seller-confirmed commerce values, with the revision and fingerprint returned in recovery. Never invent missing prices or convert currency."),
32640
- confirmed: z133.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
33060
+ confirmed: z134.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
32641
33061
  });
32642
33062
  var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
32643
33063
  if (value.commerceCorrection && value.confirmed !== true) {
32644
33064
  ctx.addIssue({
32645
- code: z133.ZodIssueCode.custom,
33065
+ code: z134.ZodIssueCode.custom,
32646
33066
  path: [
32647
33067
  "confirmed"
32648
33068
  ],
@@ -32651,7 +33071,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
32651
33071
  }
32652
33072
  if (value.announcementBarEnabled && !value.announcementBarText) {
32653
33073
  ctx.addIssue({
32654
- code: z133.ZodIssueCode.custom,
33074
+ code: z134.ZodIssueCode.custom,
32655
33075
  path: [
32656
33076
  "announcementBarText"
32657
33077
  ],
@@ -32660,7 +33080,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
32660
33080
  }
32661
33081
  if (!value.announcementBarEnabled && value.announcementBarText) {
32662
33082
  ctx.addIssue({
32663
- code: z133.ZodIssueCode.custom,
33083
+ code: z134.ZodIssueCode.custom,
32664
33084
  path: [
32665
33085
  "announcementBarText"
32666
33086
  ],
@@ -32674,90 +33094,90 @@ function parseShopifyInput(rawInput) {
32674
33094
  return parsed.data;
32675
33095
  }
32676
33096
  __name(parseShopifyInput, "parseShopifyInput");
32677
- var McpCampaignConfig = z133.object({
33097
+ var McpCampaignConfig = z134.object({
32678
33098
  /** Legacy USD amount. Meta retains its existing conversion; the TikTok
32679
33099
  * schema below restricts this input to USD advertiser accounts. */
32680
- dailyBudgetUsd: z133.number().positive().optional(),
33100
+ dailyBudgetUsd: z134.number().positive().optional(),
32681
33101
  /** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
32682
33102
  * normalizes at validation). Meta accepts max 1 (single-country ad set).
32683
33103
  * TikTok takes only the first entry. */
32684
- targetCountries: z133.array(CountryIso2Schema).max(1).optional(),
32685
- campaignName: z133.string().trim().min(1).max(100).optional()
33104
+ targetCountries: z134.array(CountryIso2Schema).max(1).optional(),
33105
+ campaignName: z134.string().trim().min(1).max(100).optional()
32686
33106
  });
32687
33107
  var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
32688
- var MetaInput = z133.object({
32689
- taskId: z133.string().min(1),
33108
+ var MetaInput = z134.object({
33109
+ taskId: z134.string().min(1),
32690
33110
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
32691
- portfolioId: z133.string().trim().min(1),
33111
+ portfolioId: z134.string().trim().min(1),
32692
33112
  /** Exact Facebook Page selected from `list_meta_destinations`. */
32693
- pageId: z133.string().trim().min(1),
33113
+ pageId: z134.string().trim().min(1),
32694
33114
  adAccountId: McpAdAccountId,
32695
- pixelId: z133.string().min(1).optional(),
32696
- landingUrl: z133.string().url().optional(),
33115
+ pixelId: z134.string().min(1).optional(),
33116
+ landingUrl: z134.string().url().optional(),
32697
33117
  /** Select which angles to publish by 0-based index. Omit to publish all
32698
33118
  * successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
32699
- angleIndexes: z133.array(z133.number().int().nonnegative()).optional(),
33119
+ angleIndexes: z134.array(z134.number().int().nonnegative()).optional(),
32700
33120
  campaignConfig: McpCampaignConfig.optional(),
32701
33121
  /** Override the ad's primary text (body copy). If omitted, ProductMaker
32702
33122
  * uses the auto-generated copy attached to the task. Capped at 500 chars
32703
33123
  * (Meta's primary-text limit). */
32704
- primaryText: z133.string().trim().min(1).max(500).optional(),
33124
+ primaryText: z134.string().trim().min(1).max(500).optional(),
32705
33125
  /** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
32706
33126
  * (wa.me) instead of a landing page. */
32707
- phoneNumber: z133.string().min(8).max(32).optional()
33127
+ phoneNumber: z134.string().min(8).max(32).optional()
32708
33128
  });
32709
- var GroupedTaskSource = z133.object({
32710
- type: z133.literal("task"),
32711
- taskId: z133.string().min(1),
32712
- angleIndex: z133.number().int().min(0).optional(),
32713
- videoVariant: z133.enum([
33129
+ var GroupedTaskSource = z134.object({
33130
+ type: z134.literal("task"),
33131
+ taskId: z134.string().min(1),
33132
+ angleIndex: z134.number().int().min(0).optional(),
33133
+ videoVariant: z134.enum([
32714
33134
  "with_subtitles",
32715
33135
  "without_subtitles"
32716
33136
  ]).optional(),
32717
- imageVariantIndex: z133.number().int().min(0).optional()
32718
- });
32719
- var GroupedMediaSource = z133.object({
32720
- type: z133.literal("media"),
32721
- url: z133.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
32722
- path: z133.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".'),
32723
- thumbnailUrl: z133.string().url().optional(),
32724
- thumbnailPath: z133.string().min(1).optional()
33137
+ imageVariantIndex: z134.number().int().min(0).optional()
33138
+ });
33139
+ var GroupedMediaSource = z134.object({
33140
+ type: z134.literal("media"),
33141
+ url: z134.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
33142
+ path: z134.string().min(1).optional().describe('Local file path only when this MCP runs over stdio. On the hosted MCP, call request_media_upload and then use source.type="asset".'),
33143
+ thumbnailUrl: z134.string().url().optional(),
33144
+ thumbnailPath: z134.string().min(1).optional()
32725
33145
  }).refine((value) => Boolean(value.url) !== Boolean(value.path), {
32726
33146
  message: "media source needs exactly one of `url` or `path`"
32727
33147
  }).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
32728
33148
  message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
32729
33149
  });
32730
- var GroupedUploadedAssetSource = z133.object({
32731
- type: z133.literal("asset"),
33150
+ var GroupedUploadedAssetSource = z134.object({
33151
+ type: z134.literal("asset"),
32732
33152
  /** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
32733
- assetId: z133.string().uuid(),
32734
- thumbnailAssetId: z133.string().uuid().optional()
33153
+ assetId: z134.string().uuid(),
33154
+ thumbnailAssetId: z134.string().uuid().optional()
32735
33155
  });
32736
- var GroupedCreative = z133.object({
32737
- type: z133.enum([
33156
+ var GroupedCreative = z134.object({
33157
+ type: z134.enum([
32738
33158
  "image",
32739
33159
  "video"
32740
33160
  ]),
32741
- source: z133.union([
33161
+ source: z134.union([
32742
33162
  GroupedTaskSource,
32743
33163
  GroupedMediaSource,
32744
33164
  GroupedUploadedAssetSource
32745
33165
  ]),
32746
- title: z133.string().max(120).optional(),
32747
- description: z133.string().max(500).optional(),
33166
+ title: z134.string().max(120).optional(),
33167
+ description: z134.string().max(500).optional(),
32748
33168
  cta: MetaCtaType.optional(),
32749
- creativeId: z133.string().min(1).optional()
33169
+ creativeId: z134.string().min(1).optional()
32750
33170
  });
32751
- var GroupedCampaignConfigBase = z133.object({
33171
+ var GroupedCampaignConfigBase = z134.object({
32752
33172
  campaignType: MetaCampaignType.default("sales"),
32753
33173
  optimizationMode: MetaOptimizationMode.default("advantage_plus"),
32754
33174
  budgetMode: MetaBudgetMode.optional(),
32755
- campaignDailyBudget: z133.number().int().positive().optional(),
32756
- adSets: z133.array(z133.object({
32757
- tempId: z133.string().min(1).max(80),
32758
- name: z133.string().min(1).max(100),
32759
- dailyBudget: z133.number().int().positive().optional(),
32760
- creativeIds: z133.array(z133.string().min(1)).min(1)
33175
+ campaignDailyBudget: z134.number().int().positive().optional(),
33176
+ adSets: z134.array(z134.object({
33177
+ tempId: z134.string().min(1).max(80),
33178
+ name: z134.string().min(1).max(100),
33179
+ dailyBudget: z134.number().int().positive().optional(),
33180
+ creativeIds: z134.array(z134.string().min(1)).min(1)
32761
33181
  })).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
32762
33182
  /**
32763
33183
  * Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
@@ -32765,17 +33185,17 @@ var GroupedCampaignConfigBase = z133.object({
32765
33185
  * opaque `invalid_literal` and made the WhatsApp destination — supported by
32766
33186
  * the API since #849 — unreachable from this tool.
32767
33187
  */
32768
- destination: z133.discriminatedUnion("type", [
32769
- z133.object({
32770
- type: z133.literal("landing"),
32771
- landingUrl: z133.string().url()
33188
+ destination: z134.discriminatedUnion("type", [
33189
+ z134.object({
33190
+ type: z134.literal("landing"),
33191
+ landingUrl: z134.string().url()
32772
33192
  }),
32773
- z133.object({
32774
- type: z133.literal("whatsapp"),
32775
- phoneNumber: z133.string().min(8).max(32)
33193
+ z134.object({
33194
+ type: z134.literal("whatsapp"),
33195
+ phoneNumber: z134.string().min(8).max(32)
32776
33196
  })
32777
33197
  ]),
32778
- saveAsDefault: z133.boolean().default(false),
33198
+ saveAsDefault: z134.boolean().default(false),
32779
33199
  budgetPolicy: MetaBudgetPolicy.optional()
32780
33200
  });
32781
33201
  function resolveBudgetMode(value) {
@@ -32789,7 +33209,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
32789
33209
  const budgetMode = resolveBudgetMode(value);
32790
33210
  if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
32791
33211
  ctx.addIssue({
32792
- code: z133.ZodIssueCode.custom,
33212
+ code: z134.ZodIssueCode.custom,
32793
33213
  path: [
32794
33214
  "campaignDailyBudget"
32795
33215
  ],
@@ -32800,7 +33220,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
32800
33220
  value.adSets.forEach((adSet, index) => {
32801
33221
  if (adSet.dailyBudget === void 0) {
32802
33222
  ctx.addIssue({
32803
- code: z133.ZodIssueCode.custom,
33223
+ code: z134.ZodIssueCode.custom,
32804
33224
  path: [
32805
33225
  "adSets",
32806
33226
  index,
@@ -32815,25 +33235,25 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
32815
33235
  ...value,
32816
33236
  budgetMode: resolveBudgetMode(value)
32817
33237
  }));
32818
- var PublishCreativesToMetaInputBase = z133.object({
32819
- creatives: z133.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
33238
+ var PublishCreativesToMetaInputBase = z134.object({
33239
+ creatives: z134.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
32820
33240
  /** Exact Meta Business portfolio selected from `list_meta_destinations`. */
32821
- portfolioId: z133.string().trim().min(1),
33241
+ portfolioId: z134.string().trim().min(1),
32822
33242
  /** Exact Facebook Page selected from `list_meta_destinations`. */
32823
- pageId: z133.string().trim().min(1),
33243
+ pageId: z134.string().trim().min(1),
32824
33244
  adAccountId: McpAdAccountId,
32825
- pixelId: z133.string().min(1).optional(),
33245
+ pixelId: z134.string().min(1).optional(),
32826
33246
  /** Required unless `campaignConfig.destination` is whatsapp or a creative
32827
33247
  * comes from a task (the API then lands on the published service landing
32828
33248
  * of its service tasks) — see the superRefine below. Mirrors the API's
32829
33249
  * `FacebookCreateCampaignFromTasksBodySchema`. */
32830
- landingUrl: z133.string().url().optional(),
33250
+ landingUrl: z134.string().url().optional(),
32831
33251
  /** ISO-2 code or resolvable country name — mirrors the API contract
32832
33252
  * (CountryIso2Schema), which normalizes names to alpha-2 at validation.
32833
33253
  * Omitted: the brand country of its service tasks (the API answers
32834
33254
  * META_NO_TARGET_COUNTRY when it has none); "US" for products. */
32835
33255
  targetCountry: CountryIso2Schema.optional(),
32836
- campaignName: z133.string().trim().min(1).max(100),
33256
+ campaignName: z134.string().trim().min(1).max(100),
32837
33257
  campaignConfig: GroupedCampaignConfig.optional()
32838
33258
  });
32839
33259
  var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
@@ -32841,7 +33261,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
32841
33261
  const hasTaskCreative = value.creatives.some((creative) => creative.source.type === "task");
32842
33262
  if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl && !hasTaskCreative) {
32843
33263
  ctx.addIssue({
32844
- code: z133.ZodIssueCode.custom,
33264
+ code: z134.ZodIssueCode.custom,
32845
33265
  path: [
32846
33266
  "landingUrl"
32847
33267
  ],
@@ -32850,7 +33270,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
32850
33270
  }
32851
33271
  if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
32852
33272
  ctx.addIssue({
32853
- code: z133.ZodIssueCode.custom,
33273
+ code: z134.ZodIssueCode.custom,
32854
33274
  path: [
32855
33275
  "campaignConfig",
32856
33276
  "destination",
@@ -32869,16 +33289,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
32869
33289
  }
32870
33290
  return value;
32871
33291
  });
32872
- var PresignUploadResponseSchema = z133.object({
32873
- uploadUrl: z133.string().url().refine((value) => {
33292
+ var PresignUploadResponseSchema = z134.object({
33293
+ uploadUrl: z134.string().url().refine((value) => {
32874
33294
  const url = new URL(value);
32875
33295
  return !url.username && !url.password && url.protocol === "https:";
32876
33296
  }, "presigned upload URL must be HTTPS without embedded credentials"),
32877
- publicUrl: z133.string().url().refine((value) => {
33297
+ publicUrl: z134.string().url().refine((value) => {
32878
33298
  const url = new URL(value);
32879
33299
  return !url.username && !url.password;
32880
33300
  }, "public media URL must not contain embedded credentials"),
32881
- stagingAssetId: z133.string().uuid()
33301
+ stagingAssetId: z134.string().uuid()
32882
33302
  });
32883
33303
  async function uploadResolvedMedia(api, media, assetRole) {
32884
33304
  if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
@@ -32904,14 +33324,14 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
32904
33324
  }
32905
33325
  __name(resolveAndUploadMedia, "resolveAndUploadMedia");
32906
33326
  var TikTokMcpCampaignConfig = McpCampaignConfig.extend({
32907
- dailyBudgetUsd: z133.number().finite().positive().optional().describe("Legacy USD amount, supported only for USD advertiser accounts. No FX conversion."),
32908
- dailyBudget: z133.number().finite().positive().optional().describe("Daily budget in the selected advertiser currency major units; pass budgetCurrency together."),
33327
+ dailyBudgetUsd: z134.number().finite().positive().optional().describe("Legacy USD amount, supported only for USD advertiser accounts. No FX conversion."),
33328
+ dailyBudget: z134.number().finite().positive().optional().describe("Daily budget in the selected advertiser currency major units; pass budgetCurrency together."),
32909
33329
  budgetCurrency: TikTokBudgetCurrencySchema.optional(),
32910
33330
  destination: TikTokCampaignDestinationSchema.optional()
32911
33331
  }).superRefine((value, ctx) => {
32912
33332
  if (value.dailyBudgetUsd !== void 0 && (value.dailyBudget !== void 0 || value.budgetCurrency !== void 0)) {
32913
33333
  ctx.addIssue({
32914
- code: z133.ZodIssueCode.custom,
33334
+ code: z134.ZodIssueCode.custom,
32915
33335
  path: [
32916
33336
  "dailyBudgetUsd"
32917
33337
  ],
@@ -32920,7 +33340,7 @@ var TikTokMcpCampaignConfig = McpCampaignConfig.extend({
32920
33340
  }
32921
33341
  if (value.dailyBudget !== void 0 !== (value.budgetCurrency !== void 0)) {
32922
33342
  ctx.addIssue({
32923
- code: z133.ZodIssueCode.custom,
33343
+ code: z134.ZodIssueCode.custom,
32924
33344
  path: [
32925
33345
  "budgetCurrency"
32926
33346
  ],
@@ -32928,16 +33348,16 @@ var TikTokMcpCampaignConfig = McpCampaignConfig.extend({
32928
33348
  });
32929
33349
  }
32930
33350
  });
32931
- var TikTokInput = z133.object({
32932
- taskId: z133.string().min(1),
32933
- advertiserId: z133.string().min(1),
32934
- pixelId: z133.string().min(1).optional(),
32935
- landingUrl: z133.string().url().optional(),
32936
- angleIndexes: z133.array(z133.number().int().nonnegative()).optional(),
33351
+ var TikTokInput = z134.object({
33352
+ taskId: z134.string().min(1),
33353
+ advertiserId: z134.string().min(1),
33354
+ pixelId: z134.string().min(1).optional(),
33355
+ landingUrl: z134.string().url().optional(),
33356
+ angleIndexes: z134.array(z134.number().int().nonnegative()).optional(),
32937
33357
  campaignConfig: TikTokMcpCampaignConfig.optional(),
32938
33358
  /** Override the ad's description (TikTok's body copy). If omitted,
32939
33359
  * ProductMaker uses the auto-generated copy attached to the task. */
32940
- primaryText: z133.string().trim().min(1).max(500).optional()
33360
+ primaryText: z134.string().trim().min(1).max(500).optional()
32941
33361
  });
32942
33362
  function registerPublishTools(server, api, opts = {}) {
32943
33363
  const transport = opts.transport ?? "http";
@@ -33296,39 +33716,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
33296
33716
 
33297
33717
  // src/tools/meta-upload.ts
33298
33718
  import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
33299
- import { z as z134 } from "zod";
33719
+ import { z as z135 } from "zod";
33300
33720
  var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
33301
- var UploadSessionInputBase = z134.object({
33302
- mediaKind: z134.enum([
33721
+ var UploadSessionInputBase = z135.object({
33722
+ mediaKind: z135.enum([
33303
33723
  "image",
33304
33724
  "video",
33305
33725
  "mixed"
33306
33726
  ]).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."),
33307
- assetRole: z134.enum([
33727
+ assetRole: z135.enum([
33308
33728
  "media",
33309
33729
  "thumbnail"
33310
33730
  ]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
33311
- uploadPurpose: z134.enum([
33731
+ uploadPurpose: z135.enum([
33312
33732
  "product_reference",
33313
33733
  "creative",
33314
33734
  "generic"
33315
33735
  ]).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."),
33316
- maxFiles: z134.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
33736
+ maxFiles: z135.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
33317
33737
  });
33318
- var OpenAiFileReference = z134.object({
33319
- download_url: z134.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."),
33320
- file_id: z134.string().min(1),
33321
- mime_type: z134.string().min(1).optional(),
33322
- file_name: z134.string().min(1).optional()
33738
+ var OpenAiFileReference = z135.object({
33739
+ download_url: z135.string().url().describe("Required by ChatGPT's openai/fileParams schema. The App prefers getFileDownloadUrl(file_id) for a fresh URL, and the server never fetches this value."),
33740
+ file_id: z135.string().min(1),
33741
+ mime_type: z135.string().min(1).optional(),
33742
+ file_name: z135.string().min(1).optional()
33323
33743
  });
33324
33744
  var UploadSessionToolInputShape = {
33325
33745
  ...UploadSessionInputBase.shape,
33326
- files: z134.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.")
33746
+ files: z135.array(OpenAiFileReference).max(10).optional().describe("Optional OpenAI-hosted file references provided by ChatGPT. They are only metadata for the UI bridge and are never forwarded to ProductMaker.")
33327
33747
  };
33328
- var UploadSessionToolInput = z134.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
33748
+ var UploadSessionToolInput = z135.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
33329
33749
  if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
33330
33750
  ctx.addIssue({
33331
- code: z134.ZodIssueCode.custom,
33751
+ code: z135.ZodIssueCode.custom,
33332
33752
  path: [
33333
33753
  "mediaKind"
33334
33754
  ],
@@ -33337,7 +33757,7 @@ var UploadSessionToolInput = z134.object(UploadSessionToolInputShape).superRefin
33337
33757
  }
33338
33758
  if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
33339
33759
  ctx.addIssue({
33340
- code: z134.ZodIssueCode.custom,
33760
+ code: z135.ZodIssueCode.custom,
33341
33761
  path: [
33342
33762
  "maxFiles"
33343
33763
  ],
@@ -33346,7 +33766,7 @@ var UploadSessionToolInput = z134.object(UploadSessionToolInputShape).superRefin
33346
33766
  }
33347
33767
  if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
33348
33768
  ctx.addIssue({
33349
- code: z134.ZodIssueCode.custom,
33769
+ code: z135.ZodIssueCode.custom,
33350
33770
  path: [
33351
33771
  "maxFiles"
33352
33772
  ],
@@ -33354,38 +33774,38 @@ var UploadSessionToolInput = z134.object(UploadSessionToolInputShape).superRefin
33354
33774
  });
33355
33775
  }
33356
33776
  });
33357
- var UploadSessionResponse = z134.object({
33358
- sessionId: z134.string().uuid(),
33359
- uploadPageUrl: z134.string().url(),
33360
- mediaKind: z134.enum([
33777
+ var UploadSessionResponse = z135.object({
33778
+ sessionId: z135.string().uuid(),
33779
+ uploadPageUrl: z135.string().url(),
33780
+ mediaKind: z135.enum([
33361
33781
  "image",
33362
33782
  "video",
33363
33783
  "mixed"
33364
33784
  ]),
33365
- assetRole: z134.enum([
33785
+ assetRole: z135.enum([
33366
33786
  "media",
33367
33787
  "thumbnail"
33368
33788
  ]),
33369
- maxFiles: z134.number().int().positive(),
33370
- expiresAt: z134.string().datetime()
33789
+ maxFiles: z135.number().int().positive(),
33790
+ expiresAt: z135.string().datetime()
33371
33791
  });
33372
- var UploadStatusInput = z134.object({
33373
- sessionId: z134.string().uuid().describe("The sessionId returned by request_media_upload.")
33792
+ var UploadStatusInput = z135.object({
33793
+ sessionId: z135.string().uuid().describe("The sessionId returned by request_media_upload.")
33374
33794
  });
33375
- var UniversalUploadStatusResponse = z134.discriminatedUnion("status", [
33376
- z134.object({
33377
- status: z134.literal("pending"),
33378
- assets: z134.array(z134.never()).length(0)
33795
+ var UniversalUploadStatusResponse = z135.discriminatedUnion("status", [
33796
+ z135.object({
33797
+ status: z135.literal("pending"),
33798
+ assets: z135.array(z135.never()).length(0)
33379
33799
  }),
33380
- z134.object({
33381
- status: z134.literal("uploaded"),
33382
- assets: z134.array(z134.object({
33383
- assetId: z134.string().uuid(),
33384
- mediaKind: z134.enum([
33800
+ z135.object({
33801
+ status: z135.literal("uploaded"),
33802
+ assets: z135.array(z135.object({
33803
+ assetId: z135.string().uuid(),
33804
+ mediaKind: z135.enum([
33385
33805
  "image",
33386
33806
  "video"
33387
33807
  ]),
33388
- assetRole: z134.enum([
33808
+ assetRole: z135.enum([
33389
33809
  "media",
33390
33810
  "thumbnail"
33391
33811
  ])
@@ -33393,13 +33813,13 @@ var UniversalUploadStatusResponse = z134.discriminatedUnion("status", [
33393
33813
  })
33394
33814
  ]);
33395
33815
  var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
33396
- uploadPurpose: z134.enum([
33816
+ uploadPurpose: z135.enum([
33397
33817
  "product_reference",
33398
33818
  "creative",
33399
33819
  "generic"
33400
33820
  ]),
33401
- checkToolName: z134.literal("check_media_upload"),
33402
- resolveEndpoint: z134.string().url()
33821
+ checkToolName: z135.literal("check_media_upload"),
33822
+ resolveEndpoint: z135.string().url()
33403
33823
  });
33404
33824
  function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
33405
33825
  const url = new URL(uploadPageUrl);
@@ -33490,15 +33910,15 @@ function registerMediaUploadTools(server, api) {
33490
33910
  __name(registerMediaUploadTools, "registerMediaUploadTools");
33491
33911
 
33492
33912
  // src/tools/campaigns.ts
33493
- import { z as z135 } from "zod";
33913
+ import { z as z136 } from "zod";
33494
33914
  var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
33495
33915
  var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
33496
- var MetaStatusInput = z135.object({
33497
- campaignId: z135.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
33916
+ var MetaStatusInput = z136.object({
33917
+ campaignId: z136.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
33498
33918
  });
33499
- var TikTokStatusInput = z135.object({
33500
- campaignId: z135.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
33501
- advertiserId: z135.string().min(1).describe("The same advertiserId used to publish the campaign.")
33919
+ var TikTokStatusInput = z136.object({
33920
+ campaignId: z136.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
33921
+ advertiserId: z136.string().min(1).describe("The same advertiserId used to publish the campaign.")
33502
33922
  });
33503
33923
  function registerCampaignTools(server, api) {
33504
33924
  server.registerTool("get_meta_campaign_status", {
@@ -33603,10 +34023,10 @@ function renderTikTokStatusMarkdown(r) {
33603
34023
  __name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
33604
34024
 
33605
34025
  // ../../packages/product-economics/src/product-costing.ts
33606
- import { z as z137 } from "zod";
34026
+ import { z as z138 } from "zod";
33607
34027
 
33608
34028
  // ../../packages/product-economics/src/product-costing-countries.ts
33609
- import { z as z136 } from "zod";
34029
+ import { z as z137 } from "zod";
33610
34030
 
33611
34031
  // ../../packages/product-economics/src/product-costing-shipping-references.json
33612
34032
  var product_costing_shipping_references_default = {
@@ -33670,21 +34090,21 @@ var product_costing_shipping_references_default = {
33670
34090
  };
33671
34091
 
33672
34092
  // ../../packages/product-economics/src/product-costing-countries.ts
33673
- var ShippingReferenceSchema = z136.object({
33674
- reference: z136.number().positive(),
33675
- min: z136.number().nonnegative(),
33676
- max: z136.number().positive(),
33677
- updatedAt: z136.string().date(),
33678
- confidence: z136.enum([
34093
+ var ShippingReferenceSchema = z137.object({
34094
+ reference: z137.number().positive(),
34095
+ min: z137.number().nonnegative(),
34096
+ max: z137.number().positive(),
34097
+ updatedAt: z137.string().date(),
34098
+ confidence: z137.enum([
33679
34099
  "high",
33680
34100
  "medium",
33681
34101
  "medium-low"
33682
34102
  ]),
33683
- sources: z136.array(z136.string().url().startsWith("https://")).min(1).max(3)
34103
+ sources: z137.array(z137.string().url().startsWith("https://")).min(1).max(3)
33684
34104
  }).superRefine(({ reference, min, max }, context) => {
33685
34105
  if (min > reference || reference > max) {
33686
34106
  context.addIssue({
33687
- code: z136.ZodIssueCode.custom,
34107
+ code: z137.ZodIssueCode.custom,
33688
34108
  message: "shipping_reference_outside_range",
33689
34109
  path: [
33690
34110
  "reference"
@@ -33692,7 +34112,7 @@ var ShippingReferenceSchema = z136.object({
33692
34112
  });
33693
34113
  }
33694
34114
  });
33695
- var SHIPPING_REFERENCES = z136.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
34115
+ var SHIPPING_REFERENCES = z137.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
33696
34116
  var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
33697
34117
  var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
33698
34118
  "MX",
@@ -33874,18 +34294,18 @@ function getProductCostingCountryName(country) {
33874
34294
  __name(getProductCostingCountryName, "getProductCostingCountryName");
33875
34295
 
33876
34296
  // ../../packages/product-economics/src/product-costing.ts
33877
- var ProductCostingInputSchema = z137.object({
33878
- country: z137.string().refine(isProductCostingCountryCode, "unsupported_country"),
33879
- supplierCost: z137.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
33880
- shippingCost: z137.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
33881
- returnRate: z137.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
33882
- cancellationRate: z137.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
33883
- adsManagerCpa: z137.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
33884
- desiredMargin: z137.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
34297
+ var ProductCostingInputSchema = z138.object({
34298
+ country: z138.string().refine(isProductCostingCountryCode, "unsupported_country"),
34299
+ supplierCost: z138.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
34300
+ shippingCost: z138.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
34301
+ returnRate: z138.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
34302
+ cancellationRate: z138.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
34303
+ adsManagerCpa: z138.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
34304
+ desiredMargin: z138.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
33885
34305
  }).superRefine(({ returnRate, cancellationRate }, context) => {
33886
34306
  if (returnRate + cancellationRate >= 1) {
33887
34307
  context.addIssue({
33888
- code: z137.ZodIssueCode.custom,
34308
+ code: z138.ZodIssueCode.custom,
33889
34309
  message: "delivery_rate_positive",
33890
34310
  path: [
33891
34311
  "cancellationRate"
@@ -33982,15 +34402,15 @@ function calculateProductCosting(rawInput) {
33982
34402
  __name(calculateProductCosting, "calculateProductCosting");
33983
34403
 
33984
34404
  // src/tools/product-costing.ts
33985
- import { z as z138 } from "zod";
34405
+ import { z as z139 } from "zod";
33986
34406
  var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
33987
- var optionalAmount = /* @__PURE__ */ __name((description) => z138.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
33988
- var optionalPercent = /* @__PURE__ */ __name((description) => z138.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
33989
- var ProductCostingToolInput = z138.object({
33990
- country: z138.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
34407
+ var optionalAmount = /* @__PURE__ */ __name((description) => z139.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
34408
+ var optionalPercent = /* @__PURE__ */ __name((description) => z139.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
34409
+ var ProductCostingToolInput = z139.object({
34410
+ country: z139.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
33991
34411
  message: "Pa\xEDs no soportado por ProductMaker."
33992
34412
  }).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
33993
- supplierCost: z138.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."),
34413
+ supplierCost: z139.number().finite().max(Number.MAX_SAFE_INTEGER).positive().optional().describe("Costo real de una unidad con el proveedor, en la moneda del pa\xEDs. Requerido salvo que uses supplierCostCop para Colombia."),
33994
34414
  supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
33995
34415
  shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
33996
34416
  shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
@@ -34153,7 +34573,7 @@ function formatPercent(value) {
34153
34573
  __name(formatPercent, "formatPercent");
34154
34574
 
34155
34575
  // src/tools/product-research.ts
34156
- import { z as z139 } from "zod";
34576
+ import { z as z140 } from "zod";
34157
34577
 
34158
34578
  // src/tools/product-research-idempotency.ts
34159
34579
  var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
@@ -34524,17 +34944,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
34524
34944
  ]);
34525
34945
  var POLL_INTERVAL_MS = 5e3;
34526
34946
  var MAX_WAIT_SECONDS = 120;
34527
- var FindInput = z139.object({
34947
+ var FindInput = z140.object({
34528
34948
  targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
34529
34949
  categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
34530
- confirmed: z139.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
34531
- waitSeconds: z139.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
34950
+ confirmed: z140.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
34951
+ waitSeconds: z140.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
34532
34952
  });
34533
- var GetInput = z139.object({
34534
- runId: z139.string().uuid().describe("ID del run devuelto por find_winning_products.")
34953
+ var GetInput = z140.object({
34954
+ runId: z140.string().uuid().describe("ID del run devuelto por find_winning_products.")
34535
34955
  });
34536
- var ListInput = z139.object({
34537
- limit: z139.number().int().min(1).max(20).default(10)
34956
+ var ListInput = z140.object({
34957
+ limit: z140.number().int().min(1).max(20).default(10)
34538
34958
  });
34539
34959
  function textResult(text3) {
34540
34960
  return {
@@ -34673,17 +35093,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
34673
35093
  __name(registerProductResearchTools, "registerProductResearchTools");
34674
35094
 
34675
35095
  // src/tools/dropshipping-projects.ts
34676
- import { z as z140 } from "zod";
35096
+ import { z as z141 } from "zod";
34677
35097
  var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
34678
35098
  var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
34679
35099
  var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
34680
- var ProjectId = z140.string().uuid();
34681
- var DropshippingProjectStatus = z140.enum([
35100
+ var ProjectId = z141.string().uuid();
35101
+ var DropshippingProjectStatus = z141.enum([
34682
35102
  "active",
34683
35103
  "completed",
34684
35104
  "archived"
34685
35105
  ]);
34686
- var DropshippingProjectPhase = z140.enum([
35106
+ var DropshippingProjectPhase = z141.enum([
34687
35107
  "research",
34688
35108
  "costing",
34689
35109
  "media",
@@ -34692,21 +35112,21 @@ var DropshippingProjectPhase = z140.enum([
34692
35112
  "advertising",
34693
35113
  "complete"
34694
35114
  ]);
34695
- var DropshippingRewardMilestone = z140.enum([
35115
+ var DropshippingRewardMilestone = z141.enum([
34696
35116
  "product_selected",
34697
35117
  "costing_saved",
34698
35118
  "product_media_ready",
34699
35119
  "creatives_completed",
34700
35120
  "campaign_created"
34701
35121
  ]);
34702
- var TargetCountry = z140.enum([
35122
+ var TargetCountry = z141.enum([
34703
35123
  "CO",
34704
35124
  "MX",
34705
35125
  "PE",
34706
35126
  "EC",
34707
35127
  "CL"
34708
35128
  ]);
34709
- var ResearchCategory = z140.enum([
35129
+ var ResearchCategory = z141.enum([
34710
35130
  "auto",
34711
35131
  "automotive",
34712
35132
  "kitchen",
@@ -34721,7 +35141,7 @@ var ResearchCategory = z140.enum([
34721
35141
  "garden",
34722
35142
  "cleaning"
34723
35143
  ]);
34724
- var HttpUrl3 = z140.string().url().max(2e3).refine((value) => {
35144
+ var HttpUrl3 = z141.string().url().max(2e3).refine((value) => {
34725
35145
  try {
34726
35146
  return [
34727
35147
  "http:",
@@ -34731,45 +35151,45 @@ var HttpUrl3 = z140.string().url().max(2e3).refine((value) => {
34731
35151
  return false;
34732
35152
  }
34733
35153
  }, "URL must use HTTP(S)");
34734
- var ResearchCandidateOrigin = z140.object({
34735
- type: z140.literal("research_candidate"),
35154
+ var ResearchCandidateOrigin = z141.object({
35155
+ type: z141.literal("research_candidate"),
34736
35156
  runId: ProjectId,
34737
- candidateSourceId: z140.string().min(1).max(160)
35157
+ candidateSourceId: z141.string().min(1).max(160)
34738
35158
  });
34739
- var TaskOrigin = z140.object({
34740
- type: z140.literal("task"),
35159
+ var TaskOrigin = z141.object({
35160
+ type: z141.literal("task"),
34741
35161
  taskId: ProjectId
34742
35162
  });
34743
- var ManualOrigin = z140.object({
34744
- type: z140.literal("manual"),
35163
+ var ManualOrigin = z141.object({
35164
+ type: z141.literal("manual"),
34745
35165
  clientRequestId: ProjectId,
34746
- country: z140.string().min(2).max(3).optional()
35166
+ country: z141.string().min(2).max(3).optional()
34747
35167
  });
34748
- var StartProjectInput = z140.object({
34749
- origin: z140.discriminatedUnion("type", [
35168
+ var StartProjectInput = z141.object({
35169
+ origin: z141.discriminatedUnion("type", [
34750
35170
  ResearchCandidateOrigin,
34751
35171
  TaskOrigin,
34752
35172
  ManualOrigin
34753
35173
  ]),
34754
- productName: z140.string().trim().min(1).max(240).optional(),
35174
+ productName: z141.string().trim().min(1).max(240).optional(),
34755
35175
  productUrl: HttpUrl3.optional(),
34756
- country: z140.string().min(2).max(3).optional(),
34757
- languageCode: z140.string().min(2).max(16).optional()
35176
+ country: z141.string().min(2).max(3).optional(),
35177
+ languageCode: z141.string().min(2).max(16).optional()
34758
35178
  }).strict();
34759
- var CostProjectInput = z140.object({
35179
+ var CostProjectInput = z141.object({
34760
35180
  projectId: ProjectId,
34761
- version: z140.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
34762
- country: z140.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
35181
+ version: z141.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
35182
+ country: z141.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
34763
35183
  message: "Pa\xEDs no soportado por ProductMaker."
34764
35184
  }).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
34765
- supplierCost: z140.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."),
34766
- shippingCost: z140.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
34767
- returnRate: z140.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."),
34768
- cancellationRate: z140.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."),
34769
- adsManagerCpa: z140.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
34770
- desiredMargin: z140.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
34771
- });
34772
- var GuideInput = z140.object({
35185
+ supplierCost: z141.number().finite().positive().describe("Costo real de una unidad con el proveedor, en la moneda del pa\xEDs. \xDANICO dato que debes pedirle al usuario: nunca lo inventes."),
35186
+ shippingCost: z141.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
35187
+ returnRate: z141.number().finite().min(0).lt(1).optional().describe("Fracci\xF3n de pedidos devueltos (0.25 = 25%). Omite para usar el valor gu\xEDa del pa\xEDs."),
35188
+ cancellationRate: z141.number().finite().min(0).lt(1).optional().describe("Fracci\xF3n de pedidos cancelados (0.15 = 15%). Omite para usar el valor gu\xEDa del pa\xEDs."),
35189
+ adsManagerCpa: z141.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
35190
+ desiredMargin: z141.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
35191
+ });
35192
+ var GuideInput = z141.object({
34773
35193
  projectId: ProjectId.optional()
34774
35194
  }).strict();
34775
35195
  var NEXT_ACTION_KINDS = [
@@ -34787,29 +35207,29 @@ var NEXT_ACTION_KINDS = [
34787
35207
  "repair_meta_campaign",
34788
35208
  "review_paused_campaign"
34789
35209
  ];
34790
- var DropshippingProjectNextAction = z140.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z140.object({
34791
- kind: z140.literal(kind),
34792
- href: z140.string().min(1)
35210
+ var DropshippingProjectNextAction = z141.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z141.object({
35211
+ kind: z141.literal(kind),
35212
+ href: z141.string().min(1)
34793
35213
  })));
34794
- var CostingInputSchema = z140.object({
34795
- country: z140.string().min(2).max(3),
34796
- supplierCost: z140.number().finite().positive(),
34797
- shippingCost: z140.number().finite().nonnegative(),
34798
- returnRate: z140.number().finite().min(0).lt(1),
34799
- cancellationRate: z140.number().finite().min(0).lt(1),
34800
- adsManagerCpa: z140.number().finite().nonnegative(),
34801
- desiredMargin: z140.number().finite().min(0).lt(1)
35214
+ var CostingInputSchema = z141.object({
35215
+ country: z141.string().min(2).max(3),
35216
+ supplierCost: z141.number().finite().positive(),
35217
+ shippingCost: z141.number().finite().nonnegative(),
35218
+ returnRate: z141.number().finite().min(0).lt(1),
35219
+ cancellationRate: z141.number().finite().min(0).lt(1),
35220
+ adsManagerCpa: z141.number().finite().nonnegative(),
35221
+ desiredMargin: z141.number().finite().min(0).lt(1)
34802
35222
  }).superRefine(({ returnRate, cancellationRate }, context) => {
34803
35223
  if (returnRate + cancellationRate >= 1) context.addIssue({
34804
- code: z140.ZodIssueCode.custom,
35224
+ code: z141.ZodIssueCode.custom,
34805
35225
  path: [
34806
35226
  "cancellationRate"
34807
35227
  ]
34808
35228
  });
34809
35229
  });
34810
- var FiniteCostingNumber = z140.number().finite();
34811
- var CostingResultSchema = z140.object({
34812
- country: z140.string().min(2).max(3),
35230
+ var FiniteCostingNumber = z141.number().finite();
35231
+ var CostingResultSchema = z141.object({
35232
+ country: z141.string().min(2).max(3),
34813
35233
  deliveryRate: FiniteCostingNumber,
34814
35234
  adjustedShippingCost: FiniteCostingNumber,
34815
35235
  adjustedCpa: FiniteCostingNumber,
@@ -34822,45 +35242,45 @@ var CostingResultSchema = z140.object({
34822
35242
  estimatedProfit: FiniteCostingNumber,
34823
35243
  actualMargin: FiniteCostingNumber,
34824
35244
  breakEvenAdsManagerCpa: FiniteCostingNumber,
34825
- wasPriceAutoAdjusted: z140.boolean(),
34826
- profitabilityStatus: z140.literal("healthy")
34827
- });
34828
- var RewardProgressSchema = z140.object({
34829
- campaignKey: z140.literal("dropshipping-launch-v1"),
34830
- totalCredits: z140.number().int().positive(),
34831
- earnedCredits: z140.number().int().nonnegative(),
34832
- milestones: z140.array(z140.object({
35245
+ wasPriceAutoAdjusted: z141.boolean(),
35246
+ profitabilityStatus: z141.literal("healthy")
35247
+ });
35248
+ var RewardProgressSchema = z141.object({
35249
+ campaignKey: z141.literal("dropshipping-launch-v1"),
35250
+ totalCredits: z141.number().int().positive(),
35251
+ earnedCredits: z141.number().int().nonnegative(),
35252
+ milestones: z141.array(z141.object({
34833
35253
  milestone: DropshippingRewardMilestone,
34834
- credits: z140.number().int().positive(),
34835
- available: z140.boolean().optional(),
34836
- earned: z140.boolean(),
35254
+ credits: z141.number().int().positive(),
35255
+ available: z141.boolean().optional(),
35256
+ earned: z141.boolean(),
34837
35257
  grantId: ProjectId.nullable(),
34838
- grantedAt: z140.string().datetime().nullable()
35258
+ grantedAt: z141.string().datetime().nullable()
34839
35259
  })).length(DropshippingRewardMilestone.options.length)
34840
35260
  });
34841
- var ProjectResponseSchema = z140.object({
35261
+ var ProjectResponseSchema = z141.object({
34842
35262
  id: ProjectId,
34843
35263
  taskId: ProjectId.nullable(),
34844
35264
  status: DropshippingProjectStatus,
34845
- originKey: z140.string().min(1),
35265
+ originKey: z141.string().min(1),
34846
35266
  researchRunId: ProjectId.nullable(),
34847
- candidateSourceId: z140.string().nullable(),
34848
- productName: z140.string().nullable(),
35267
+ candidateSourceId: z141.string().nullable(),
35268
+ productName: z141.string().nullable(),
34849
35269
  productUrl: HttpUrl3.nullable(),
34850
35270
  referenceImageUrl: HttpUrl3.nullable(),
34851
- targetCountry: z140.string().nullable(),
34852
- languageCode: z140.string().nullable(),
34853
- hasReferenceImage: z140.boolean(),
34854
- hasWinnerReferenceImage: z140.boolean(),
35271
+ targetCountry: z141.string().nullable(),
35272
+ languageCode: z141.string().nullable(),
35273
+ hasReferenceImage: z141.boolean(),
35274
+ hasWinnerReferenceImage: z141.boolean(),
34855
35275
  costingInput: CostingInputSchema.nullable(),
34856
35276
  costingResult: CostingResultSchema.nullable(),
34857
- costingVersion: z140.number().int().positive().nullable(),
34858
- version: z140.number().int().positive(),
35277
+ costingVersion: z141.number().int().positive().nullable(),
35278
+ version: z141.number().int().positive(),
34859
35279
  phase: DropshippingProjectPhase,
34860
35280
  nextAction: DropshippingProjectNextAction.nullable(),
34861
35281
  rewards: RewardProgressSchema,
34862
- createdAt: z140.string().datetime(),
34863
- updatedAt: z140.string().datetime()
35282
+ createdAt: z141.string().datetime(),
35283
+ updatedAt: z141.string().datetime()
34864
35284
  }).passthrough();
34865
35285
  var NEXT_ACTION_GUIDANCE = {
34866
35286
  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.",
@@ -34980,58 +35400,58 @@ function registerDropshippingProjectTools(server, api) {
34980
35400
  __name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
34981
35401
 
34982
35402
  // src/tools/daily-control.ts
34983
- import { z as z141 } from "zod";
35403
+ import { z as z142 } from "zod";
34984
35404
  var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
34985
35405
  var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
34986
35406
  var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
34987
- var ProviderCampaignIdentifier = z141.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
34988
- var DateOnly = z141.string().regex(/^\d{4}-\d{2}-\d{2}$/);
34989
- var DailyControlInput = z141.object({
35407
+ var ProviderCampaignIdentifier = z142.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
35408
+ var DateOnly = z142.string().regex(/^\d{4}-\d{2}-\d{2}$/);
35409
+ var DailyControlInput = z142.object({
34990
35410
  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."),
34991
- days: z141.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
34992
- projectId: z141.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
35411
+ days: z142.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
35412
+ projectId: z142.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
34993
35413
  }).strict();
34994
- var LinkCampaignInput = z141.object({
34995
- projectId: z141.string().uuid(),
34996
- provider: z141.enum([
35414
+ var LinkCampaignInput = z142.object({
35415
+ projectId: z142.string().uuid(),
35416
+ provider: z142.enum([
34997
35417
  "meta",
34998
35418
  "tiktok"
34999
35419
  ]),
35000
35420
  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."),
35001
35421
  campaignId: ProviderCampaignIdentifier
35002
35422
  }).strict();
35003
- var ReportReturnsInput = z141.object({
35004
- projectId: z141.string().uuid(),
35423
+ var ReportReturnsInput = z142.object({
35424
+ projectId: z142.string().uuid(),
35005
35425
  date: DateOnly,
35006
- returnedOrders: z141.number().int().min(0).max(1e5),
35007
- note: z141.string().trim().max(280).optional()
35008
- }).strict();
35009
- var DailyControlStatusMirror = DailyControlStatusEnum.or(z141.string());
35010
- var DailyControlLightMirror = DailyControlLightEnum.or(z141.string());
35011
- var DailyControlSourceMirror = DailyControlSourceEnum.or(z141.string());
35012
- var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z141.string());
35013
- var DailyControlDayMirror = z141.object({
35014
- date: z141.string(),
35015
- returnedOrders: z141.number(),
35426
+ returnedOrders: z142.number().int().min(0).max(1e5),
35427
+ note: z142.string().trim().max(280).optional()
35428
+ }).strict();
35429
+ var DailyControlStatusMirror = DailyControlStatusEnum.or(z142.string());
35430
+ var DailyControlLightMirror = DailyControlLightEnum.or(z142.string());
35431
+ var DailyControlSourceMirror = DailyControlSourceEnum.or(z142.string());
35432
+ var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z142.string());
35433
+ var DailyControlDayMirror = z142.object({
35434
+ date: z142.string(),
35435
+ returnedOrders: z142.number(),
35016
35436
  returnedSource: DailyControlSourceMirror,
35017
35437
  cancelledSource: DailyControlSourceMirror,
35018
- hasEstimates: z141.boolean(),
35438
+ hasEstimates: z142.boolean(),
35019
35439
  light: DailyControlLightMirror
35020
35440
  }).passthrough();
35021
- var DailyControlProductMirror = z141.object({
35022
- projectId: z141.string().uuid(),
35023
- productName: z141.string().nullable(),
35441
+ var DailyControlProductMirror = z142.object({
35442
+ projectId: z142.string().uuid(),
35443
+ productName: z142.string().nullable(),
35024
35444
  status: DailyControlStatusMirror,
35025
- statusMessage: z141.string().nullable(),
35026
- days: z141.array(DailyControlDayMirror),
35445
+ statusMessage: z142.string().nullable(),
35446
+ days: z142.array(DailyControlDayMirror),
35027
35447
  verdict: DailyControlVerdictMirror.nullable(),
35028
- rationale: z141.string().nullable()
35448
+ rationale: z142.string().nullable()
35029
35449
  }).passthrough();
35030
- var DailyControlResponseMirror = z141.object({
35031
- since: z141.string(),
35032
- until: z141.string(),
35033
- products: z141.array(DailyControlProductMirror),
35034
- archivedProjectSpend: z141.array(z141.unknown())
35450
+ var DailyControlResponseMirror = z142.object({
35451
+ since: z142.string(),
35452
+ until: z142.string(),
35453
+ products: z142.array(DailyControlProductMirror),
35454
+ archivedProjectSpend: z142.array(z142.unknown())
35035
35455
  }).passthrough();
35036
35456
  var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
35037
35457
  function withWarnings(response) {
@@ -35106,7 +35526,7 @@ __name(registerDailyControlTools, "registerDailyControlTools");
35106
35526
  // src/tools/product-control.ts
35107
35527
  import { readFile, stat } from "fs/promises";
35108
35528
  import { basename as basename2, isAbsolute, resolve as resolve3 } from "path";
35109
- import { z as z142 } from "zod";
35529
+ import { z as z143 } from "zod";
35110
35530
  var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
35111
35531
  var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
35112
35532
  var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
@@ -35119,36 +35539,36 @@ var createOperationGuidance = getProductMakerCapabilityModelGuidance("create_ope
35119
35539
  var mergeProductsGuidance = getProductMakerCapabilityModelGuidance("merge_products");
35120
35540
  var syncShopifyOrdersGuidance = getProductMakerCapabilityModelGuidance("sync_shopify_orders");
35121
35541
  var importOrdersFileGuidance = getProductMakerCapabilityModelGuidance("import_orders_file");
35122
- var DateOnly2 = z142.string().regex(/^\d{4}-\d{2}-\d{2}$/);
35542
+ var DateOnly2 = z143.string().regex(/^\d{4}-\d{2}-\d{2}$/);
35123
35543
  var IMPORT_BATCH_MAX2 = 50;
35124
- var ProductControlListInput = z142.object({
35125
- days: z142.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
35544
+ var ProductControlListInput = z143.object({
35545
+ days: z143.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
35126
35546
  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."),
35127
- shopDomain: z142.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
35547
+ shopDomain: z143.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
35128
35548
  }).strict();
35129
- var ImportableProductsInput = z142.object({
35130
- q: z142.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
35131
- after: z142.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
35132
- shopDomain: z142.string().min(1).optional()
35549
+ var ImportableProductsInput = z143.object({
35550
+ q: z143.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
35551
+ after: z143.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
35552
+ shopDomain: z143.string().min(1).optional()
35133
35553
  }).strict();
35134
- var ImportProductControlsInput = z142.object({
35135
- shopifyProductIds: z142.array(z142.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."),
35554
+ var ImportProductControlsInput = z143.object({
35555
+ shopifyProductIds: z143.array(z143.string().min(1).max(64)).min(1).max(IMPORT_BATCH_MAX2).describe("Identificadores tal como vinieron de list_importable_products. NO los inventes ni los deduzcas del t\xEDtulo."),
35136
35556
  // Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
35137
35557
  // sin decir a cuál archivaría el producto bajo la tienda equivocada.
35138
- shopDomain: z142.string().min(1)
35139
- }).strict();
35140
- var SetProductCostingInput = z142.object({
35141
- shopDomain: z142.string().min(1),
35142
- shopifyProductId: z142.string().min(1).max(64),
35143
- targetCountry: z142.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
35144
- supplierCost: z142.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
35145
- shippingCost: z142.number().finite().nonnegative(),
35146
- returnRate: z142.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
35147
- cancellationRate: z142.number().finite().min(0).lt(1)
35148
- }).strict();
35149
- var Count = z142.number().int().min(0).max(1e5).nullable().optional();
35150
- var ReportProductCountsInput = z142.object({
35151
- productControlId: z142.string().uuid().describe("El identificador que devuelve get_product_control."),
35558
+ shopDomain: z143.string().min(1)
35559
+ }).strict();
35560
+ var SetProductCostingInput = z143.object({
35561
+ shopDomain: z143.string().min(1),
35562
+ shopifyProductId: z143.string().min(1).max(64),
35563
+ targetCountry: z143.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
35564
+ supplierCost: z143.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
35565
+ shippingCost: z143.number().finite().nonnegative(),
35566
+ returnRate: z143.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
35567
+ cancellationRate: z143.number().finite().min(0).lt(1)
35568
+ }).strict();
35569
+ var Count = z143.number().int().min(0).max(1e5).nullable().optional();
35570
+ var ReportProductCountsInput = z143.object({
35571
+ productControlId: z143.string().uuid().describe("El identificador que devuelve get_product_control."),
35152
35572
  date: DateOnly2,
35153
35573
  orders: Count.describe("Pedidos que entraron ese d\xEDa."),
35154
35574
  cancelledOrders: Count,
@@ -35158,36 +35578,36 @@ var ReportProductCountsInput = z142.object({
35158
35578
  }).strict();
35159
35579
  var MAX_ORDERS_FILE_BYTES = 8 * 1024 * 1024;
35160
35580
  var SyncShopifyOrdersInput = SyncShopifyOrdersSchema;
35161
- var ImportOrdersFileInput = z142.object({
35581
+ var ImportOrdersFileInput = z143.object({
35162
35582
  /** Ruta ABSOLUTA en la máquina de quien usa el MCP. */
35163
- path: z142.string().min(1),
35164
- operationId: z142.string().uuid().optional(),
35583
+ path: z143.string().min(1),
35584
+ operationId: z143.string().uuid().optional(),
35165
35585
  /** Solo mirar: devuelve el resumen y no escribe nada. */
35166
- dryRun: z142.boolean().optional()
35586
+ dryRun: z143.boolean().optional()
35167
35587
  }).strict();
35168
- var CreateOperationInput = z142.object({
35169
- countryCode: z142.string().length(2),
35170
- label: z142.string().trim().min(1).max(60).optional()
35588
+ var CreateOperationInput = z143.object({
35589
+ countryCode: z143.string().length(2),
35590
+ label: z143.string().trim().min(1).max(60).optional()
35171
35591
  }).strict();
35172
- var MergeProductsInput = z142.object({
35173
- sourceId: z142.string().uuid(),
35174
- targetId: z142.string().uuid()
35592
+ var MergeProductsInput = z143.object({
35593
+ sourceId: z143.string().uuid(),
35594
+ targetId: z143.string().uuid()
35175
35595
  }).strict();
35176
- var SetMonthlyExpenseInput = z142.object({
35177
- month: z142.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
35596
+ var SetMonthlyExpenseInput = z143.object({
35597
+ month: z143.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
35178
35598
  label: SaveMonthlyExpenseSchema.shape.label,
35179
- amount: z142.number().finite().min(0),
35180
- operationId: z142.string().uuid().optional()
35599
+ amount: z143.number().finite().min(0),
35600
+ operationId: z143.string().uuid().optional()
35181
35601
  }).strict();
35182
- var SetAdSpendInput = z142.object({
35183
- month: z142.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
35184
- operationId: z142.string().uuid().optional(),
35602
+ var SetAdSpendInput = z143.object({
35603
+ month: z143.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
35604
+ operationId: z143.string().uuid().optional(),
35185
35605
  /** null RETIRA la corrección; cero afirma que no pautó. */
35186
- amount: z142.number().finite().min(0).nullable()
35606
+ amount: z143.number().finite().min(0).nullable()
35187
35607
  }).strict();
35188
- var GetFinancesInput = z142.object({
35189
- month: z142.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."),
35190
- operationId: z142.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
35608
+ var GetFinancesInput = z143.object({
35609
+ month: z143.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional().describe("Mes en YYYY-MM. Si se omite, el mes en curso. Solo mes calendario."),
35610
+ operationId: z143.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
35191
35611
  }).strict();
35192
35612
  function registerProductControlTools(server, api, { transport = "http" } = {}) {
35193
35613
  server.registerTool("get_product_control", {
@@ -35379,28 +35799,28 @@ function registerProductControlTools(server, api, { transport = "http" } = {}) {
35379
35799
  __name(registerProductControlTools, "registerProductControlTools");
35380
35800
 
35381
35801
  // src/tools/market-study-estimate.ts
35382
- import { z as z143 } from "zod";
35802
+ import { z as z144 } from "zod";
35383
35803
  var estimateMarketStudyGuidance = getProductMakerCapabilityModelGuidance("estimate_market_study_cost");
35384
- var ProductTaskOutputEnum = z143.enum([
35804
+ var ProductTaskOutputEnum = z144.enum([
35385
35805
  "landing",
35386
35806
  "video",
35387
35807
  "image"
35388
35808
  ]);
35389
- var EstimateMarketStudyInput = z143.object({
35390
- kind: z143.enum([
35809
+ var EstimateMarketStudyInput = z144.object({
35810
+ kind: z144.enum([
35391
35811
  "video",
35392
35812
  "product_task"
35393
35813
  ]).describe('"video" para generate_video_creative; "product_task" para create_product_task.'),
35394
- videoAngleCount: z143.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
35395
- durationSeconds: z143.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
35814
+ videoAngleCount: z144.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
35815
+ durationSeconds: z144.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
35396
35816
  videoStructure: VideoStructureEnum.default("single_take"),
35397
35817
  videoQuality: VideoQualityEnum.default("economy"),
35398
35818
  videoResolution: VideoResolutionEnum.default("480p"),
35399
- productImageCount: z143.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
35819
+ productImageCount: z144.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
35400
35820
  outputs: ProductTaskOutputEnum.array().min(1).max(3).optional().describe('Solo para kind="product_task": los mismos outputs de create_product_task. Default: todos.'),
35401
- generateAiMusic: z143.boolean().optional(),
35821
+ generateAiMusic: z144.boolean().optional(),
35402
35822
  generateAiEdit: AiEditRequestSchema.optional(),
35403
- replicateWinnerWhenFound: z143.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.")
35823
+ replicateWinnerWhenFound: z144.boolean().optional().describe("La misma preferencia que enviar\xE1s al crear. false excluye la reserva de r\xE9plica del ganador de la cotizaci\xF3n con estudio.")
35404
35824
  }).strict();
35405
35825
  function buildMarketStudyEstimateRequests(input) {
35406
35826
  const quotesVideo = input.kind === "video" || (input.outputs ?? [
@@ -35539,6 +35959,7 @@ function createServer(opts) {
35539
35959
  });
35540
35960
  registerProductMakerPrompts(server);
35541
35961
  registerMediaUploadAppResource(server, api.publicUrl("/v1/uploaded-assets/sessions/resolve"));
35962
+ registerTaskResultsAppResource(server, proxyBaseUrl);
35542
35963
  registerProductCostingTools(server);
35543
35964
  registerProductResearchTools(server, api);
35544
35965
  registerDropshippingProjectTools(server, api);