@productmaker/mcp 8.0.0 → 8.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/http.js +1632 -802
- package/dist/stdio.js +1616 -786
- package/package.json +1 -1
package/dist/stdio.js
CHANGED
|
@@ -90,6 +90,23 @@ var VideoPreset = z.enum([
|
|
|
90
90
|
]);
|
|
91
91
|
var VoiceId = z.string();
|
|
92
92
|
var _VIDEO_MODEL_SET = new Set(VideoModel.options);
|
|
93
|
+
var BROLL_VIDEO_MODES = new Set(VideoModel.options);
|
|
94
|
+
var PersistedVideoMode = z.enum([
|
|
95
|
+
...VideoModel.options,
|
|
96
|
+
"avatar_talking",
|
|
97
|
+
"hybrid",
|
|
98
|
+
"sora"
|
|
99
|
+
]);
|
|
100
|
+
var PersistedVideoModel = z.enum([
|
|
101
|
+
...VideoModel.options,
|
|
102
|
+
"sora",
|
|
103
|
+
"infinitalk"
|
|
104
|
+
]);
|
|
105
|
+
var PLAN_VIDEO_MODES = [
|
|
106
|
+
...VideoModel.options,
|
|
107
|
+
"avatar_talking",
|
|
108
|
+
"hybrid"
|
|
109
|
+
];
|
|
93
110
|
|
|
94
111
|
// ../../packages/types/src/video-creation.ts
|
|
95
112
|
import { z as z3 } from "zod";
|
|
@@ -1060,40 +1077,206 @@ var VideoTier = z8.preprocess((v) => v === "grok" ? "single_call" : v, z8.enum([
|
|
|
1060
1077
|
"single_call"
|
|
1061
1078
|
]));
|
|
1062
1079
|
var DEFAULT_VIDEO_TIER = "single_call";
|
|
1080
|
+
var WritableVideoTier = VideoTier.refine((tier) => tier !== "legacy", {
|
|
1081
|
+
message: "VIDEO_TIER_RETIRED"
|
|
1082
|
+
});
|
|
1063
1083
|
|
|
1064
|
-
// ../../packages/types/src/image-
|
|
1065
|
-
var
|
|
1066
|
-
"
|
|
1067
|
-
"
|
|
1084
|
+
// ../../packages/types/src/image-models.ts
|
|
1085
|
+
var IMAGE_RESOLUTIONS = [
|
|
1086
|
+
"1k",
|
|
1087
|
+
"2k",
|
|
1088
|
+
"4k"
|
|
1068
1089
|
];
|
|
1069
|
-
var
|
|
1070
|
-
"
|
|
1071
|
-
"5:
|
|
1072
|
-
"
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
"
|
|
1090
|
+
var GPT_IMAGE_2_5_TOKENS = {
|
|
1091
|
+
"1k": "gpt-image-2-5:1k",
|
|
1092
|
+
"2k": "gpt-image-2-5:2k",
|
|
1093
|
+
"4k": "gpt-image-2-5:4k"
|
|
1094
|
+
};
|
|
1095
|
+
var GPT_IMAGE_2_TOKENS = {
|
|
1096
|
+
"1k": "gpt-image-2:1k",
|
|
1097
|
+
"2k": "gpt-image-2:2k",
|
|
1098
|
+
"4k": "gpt-image-2:4k"
|
|
1099
|
+
};
|
|
1100
|
+
var GPT_IMAGE_2_5 = {
|
|
1101
|
+
id: "gpt-image-2.5",
|
|
1102
|
+
status: "active",
|
|
1103
|
+
renderedBy: "gpt-image-2.5",
|
|
1104
|
+
tokens: GPT_IMAGE_2_5_TOKENS,
|
|
1105
|
+
kie: {
|
|
1106
|
+
imageToImage: [
|
|
1107
|
+
"gpt-image-2-5-sunburst-image-to-image",
|
|
1108
|
+
"gpt-image-2-5-flare-image-to-image"
|
|
1109
|
+
],
|
|
1110
|
+
textToImage: [
|
|
1111
|
+
"gpt-image-2-5-sunburst-text-to-image",
|
|
1112
|
+
"gpt-image-2-5-flare-text-to-image"
|
|
1113
|
+
],
|
|
1114
|
+
shorthands: [
|
|
1115
|
+
"gpt-image-2-5"
|
|
1116
|
+
]
|
|
1117
|
+
},
|
|
1118
|
+
fal: {
|
|
1119
|
+
edit: "openai/gpt-image-2.5/sunburst/edit",
|
|
1120
|
+
textToImage: "openai/gpt-image-2.5/sunburst/text-to-image",
|
|
1121
|
+
quality: {
|
|
1122
|
+
"1k": "low",
|
|
1123
|
+
"2k": "medium",
|
|
1124
|
+
"4k": "high"
|
|
1125
|
+
},
|
|
1126
|
+
ourCostCents: {
|
|
1127
|
+
"1k": 1.5,
|
|
1128
|
+
"2k": 6.1,
|
|
1129
|
+
"4k": 17.8
|
|
1130
|
+
}
|
|
1131
|
+
},
|
|
1132
|
+
// Docs KIE de gpt-image-2-5 (sunburst/flare): 27:16, 16:27, 9:8, 8:9 solo 1K;
|
|
1133
|
+
// 4:5 y 5:4 también bloqueados por encima de 1K.
|
|
1134
|
+
ratiosBlockedAbove1k: [
|
|
1135
|
+
"4:5",
|
|
1136
|
+
"5:4",
|
|
1137
|
+
"27:16",
|
|
1138
|
+
"16:27",
|
|
1139
|
+
"9:8",
|
|
1140
|
+
"8:9"
|
|
1141
|
+
],
|
|
1142
|
+
ledgerSuffix: {
|
|
1143
|
+
"1k": "gpt-image-2",
|
|
1144
|
+
"2k": "gpt-image-2:medium",
|
|
1145
|
+
"4k": "gpt-image-2:high"
|
|
1146
|
+
},
|
|
1147
|
+
falLedgerSuffix: {
|
|
1148
|
+
"1k": "gpt-image-2:1k",
|
|
1149
|
+
"2k": "gpt-image-2:2k",
|
|
1150
|
+
"4k": "gpt-image-2:4k"
|
|
1151
|
+
}
|
|
1152
|
+
};
|
|
1153
|
+
var GPT_IMAGE_2 = {
|
|
1154
|
+
...GPT_IMAGE_2_5,
|
|
1155
|
+
id: "gpt-image-2",
|
|
1156
|
+
status: "retired",
|
|
1157
|
+
renderedBy: GPT_IMAGE_2_5.id,
|
|
1158
|
+
tokens: GPT_IMAGE_2_TOKENS,
|
|
1159
|
+
kie: {
|
|
1160
|
+
imageToImage: [
|
|
1161
|
+
"gpt-image-2-image-to-image"
|
|
1162
|
+
],
|
|
1163
|
+
textToImage: [
|
|
1164
|
+
"gpt-image-2-text-to-image"
|
|
1165
|
+
],
|
|
1166
|
+
shorthands: [
|
|
1167
|
+
"gpt-image-2"
|
|
1168
|
+
]
|
|
1169
|
+
},
|
|
1170
|
+
ratiosBlockedAbove1k: [
|
|
1171
|
+
"4:5",
|
|
1172
|
+
"5:4"
|
|
1173
|
+
]
|
|
1174
|
+
};
|
|
1175
|
+
var IMAGE_MODELS = [
|
|
1176
|
+
GPT_IMAGE_2_5,
|
|
1177
|
+
GPT_IMAGE_2
|
|
1076
1178
|
];
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1179
|
+
var ACTIVE_IMAGE_MODEL = GPT_IMAGE_2_5;
|
|
1180
|
+
var IMAGE_WRITE_TOKENS = GPT_IMAGE_2_5_TOKENS;
|
|
1181
|
+
var LEGACY_IMAGE_TOKENS = GPT_IMAGE_2_TOKENS;
|
|
1182
|
+
var PUBLIC_IMAGE_QUALITY_INPUTS = [
|
|
1183
|
+
IMAGE_WRITE_TOKENS["1k"],
|
|
1184
|
+
IMAGE_WRITE_TOKENS["2k"],
|
|
1185
|
+
LEGACY_IMAGE_TOKENS["1k"],
|
|
1186
|
+
LEGACY_IMAGE_TOKENS["2k"],
|
|
1187
|
+
"image:1k",
|
|
1188
|
+
"image:2k"
|
|
1189
|
+
];
|
|
1190
|
+
function entryById(id) {
|
|
1191
|
+
const found = IMAGE_MODELS.find((entry) => entry.id === id);
|
|
1192
|
+
if (!found) throw new Error(`IMAGE_MODEL_UNKNOWN:${id}`);
|
|
1193
|
+
return found;
|
|
1194
|
+
}
|
|
1195
|
+
__name(entryById, "entryById");
|
|
1196
|
+
function resolveImageToken(raw) {
|
|
1197
|
+
if (typeof raw !== "string") return null;
|
|
1198
|
+
let normalized = raw.trim().toLowerCase();
|
|
1199
|
+
let viaFal = false;
|
|
1200
|
+
if (normalized.startsWith("fal:")) {
|
|
1201
|
+
viaFal = true;
|
|
1202
|
+
normalized = normalized.slice("fal:".length);
|
|
1203
|
+
}
|
|
1204
|
+
for (const resolution of IMAGE_RESOLUTIONS) {
|
|
1205
|
+
if (normalized === `image:${resolution}`) {
|
|
1206
|
+
return {
|
|
1207
|
+
resolution,
|
|
1208
|
+
model: ACTIVE_IMAGE_MODEL,
|
|
1209
|
+
declared: ACTIVE_IMAGE_MODEL,
|
|
1210
|
+
spelling: "intent",
|
|
1211
|
+
viaFal
|
|
1212
|
+
};
|
|
1213
|
+
}
|
|
1081
1214
|
}
|
|
1082
|
-
|
|
1215
|
+
for (const entry of IMAGE_MODELS) {
|
|
1216
|
+
for (const resolution of IMAGE_RESOLUTIONS) {
|
|
1217
|
+
if (entry.tokens[resolution] === normalized) {
|
|
1218
|
+
return {
|
|
1219
|
+
resolution,
|
|
1220
|
+
model: entryById(entry.renderedBy),
|
|
1221
|
+
declared: entry,
|
|
1222
|
+
spelling: entry.status === "active" ? "current" : "retired",
|
|
1223
|
+
viaFal
|
|
1224
|
+
};
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
return null;
|
|
1229
|
+
}
|
|
1230
|
+
__name(resolveImageToken, "resolveImageToken");
|
|
1231
|
+
function imageResolutionOf(raw) {
|
|
1232
|
+
const token = resolveImageToken(raw);
|
|
1233
|
+
return token && !token.viaFal ? token.resolution : null;
|
|
1234
|
+
}
|
|
1235
|
+
__name(imageResolutionOf, "imageResolutionOf");
|
|
1236
|
+
function requireKieImageId(ids, index, label) {
|
|
1237
|
+
const id = ids[index];
|
|
1238
|
+
if (!id) throw new Error(`IMAGE_MODEL_NO_KIE_ID:${label}`);
|
|
1239
|
+
return id;
|
|
1240
|
+
}
|
|
1241
|
+
__name(requireKieImageId, "requireKieImageId");
|
|
1242
|
+
var KIE_FLARE_IMAGE_TO_IMAGE_MODEL = requireKieImageId(GPT_IMAGE_2_5.kie.imageToImage, 1, "flare-imageToImage");
|
|
1243
|
+
function canonicalImageModelInput(raw) {
|
|
1244
|
+
if (raw === void 0) return void 0;
|
|
1245
|
+
const token = resolveImageToken(raw);
|
|
1246
|
+
if (!token || token.viaFal || token.spelling !== "intent") return raw;
|
|
1247
|
+
return IMAGE_WRITE_TOKENS[token.resolution];
|
|
1248
|
+
}
|
|
1249
|
+
__name(canonicalImageModelInput, "canonicalImageModelInput");
|
|
1250
|
+
function imageTokenSupportsRatio(aspectRatio, rawToken) {
|
|
1251
|
+
const token = resolveImageToken(rawToken);
|
|
1252
|
+
if (!token) return true;
|
|
1253
|
+
if (token.resolution === "1k") return true;
|
|
1254
|
+
return !token.declared.ratiosBlockedAbove1k.includes(aspectRatio);
|
|
1255
|
+
}
|
|
1256
|
+
__name(imageTokenSupportsRatio, "imageTokenSupportsRatio");
|
|
1257
|
+
|
|
1258
|
+
// ../../packages/types/src/image-provider.ts
|
|
1259
|
+
var GPT_IMAGE_2_RATIOS_BLOCKED_ABOVE_1K = GPT_IMAGE_2.ratiosBlockedAbove1k;
|
|
1260
|
+
var GPT_IMAGE_2_5_RATIOS_BLOCKED_ABOVE_1K = GPT_IMAGE_2_5.ratiosBlockedAbove1k;
|
|
1261
|
+
function gptImage2SupportsTier(aspectRatio, tier) {
|
|
1262
|
+
return imageTokenSupportsRatio(aspectRatio, tier);
|
|
1083
1263
|
}
|
|
1084
1264
|
__name(gptImage2SupportsTier, "gptImage2SupportsTier");
|
|
1085
1265
|
var IMAGE_TIER_UNSUPPORTED_FOR_RATIO_RULE = "image_tier_unsupported_for_ratio";
|
|
1086
1266
|
var IMAGE_TIER_LIST = [
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
"gpt-image-2-5:4k",
|
|
1090
|
-
"gpt-image-2:1k",
|
|
1091
|
-
"gpt-image-2:2k",
|
|
1092
|
-
"gpt-image-2:4k"
|
|
1267
|
+
...Object.values(IMAGE_WRITE_TOKENS),
|
|
1268
|
+
...Object.values(LEGACY_IMAGE_TOKENS)
|
|
1093
1269
|
];
|
|
1270
|
+
function isImageTier(value) {
|
|
1271
|
+
return IMAGE_TIER_LIST.includes(value);
|
|
1272
|
+
}
|
|
1273
|
+
__name(isImageTier, "isImageTier");
|
|
1094
1274
|
function parseImageTier(imageModel) {
|
|
1095
|
-
const
|
|
1096
|
-
|
|
1275
|
+
const token = resolveImageToken(imageModel);
|
|
1276
|
+
if (!token || token.viaFal) return null;
|
|
1277
|
+
if (token.spelling === "intent") return IMAGE_WRITE_TOKENS[token.resolution];
|
|
1278
|
+
const declared = token.declared.tokens[token.resolution];
|
|
1279
|
+
return isImageTier(declared) ? declared : null;
|
|
1097
1280
|
}
|
|
1098
1281
|
__name(parseImageTier, "parseImageTier");
|
|
1099
1282
|
function validateImageTierForRatio(aspectRatio, imageModel) {
|
|
@@ -3830,7 +4013,7 @@ var IngestOptions = z22.object({
|
|
|
3830
4013
|
durationSeconds: FreeVideoOptionsSchema.shape.durationSeconds.optional(),
|
|
3831
4014
|
addSubtitles: FreeVideoOptionsSchema.shape.addSubtitles.optional(),
|
|
3832
4015
|
subtitleText: z22.string().transform((value) => value.trim()).pipe(z22.string().max(FREE_VIDEO_SUBTITLE_MAX_CHARS)).optional(),
|
|
3833
|
-
videoTier:
|
|
4016
|
+
videoTier: WritableVideoTier.default(DEFAULT_VIDEO_TIER),
|
|
3834
4017
|
narrativeStyle: NarrativeStyle.default("review"),
|
|
3835
4018
|
videoPreset: VideoPreset.optional(),
|
|
3836
4019
|
multiAngleVideos: z22.boolean().default(false),
|
|
@@ -3904,7 +4087,9 @@ var IngestOptions = z22.object({
|
|
|
3904
4087
|
aspectRatio: z22.string().optional(),
|
|
3905
4088
|
brandColors: z22.string().optional(),
|
|
3906
4089
|
nVariants: z22.number().int().min(1).max(6).optional(),
|
|
3907
|
-
|
|
4090
|
+
// O7: `image:Nk` is accepted and stored as the spelling written today
|
|
4091
|
+
// (IMAGE_WRITE_TOKENS); see packages/types/src/image-models.ts.
|
|
4092
|
+
imageModel: z22.string().optional().transform((value) => canonicalImageModelInput(value)),
|
|
3908
4093
|
styleMix: z22.string().optional(),
|
|
3909
4094
|
aiDecidesAll: z22.boolean().optional(),
|
|
3910
4095
|
/** Opt out of the competitor-spy analysis. When false the worker skips
|
|
@@ -4023,7 +4208,7 @@ var VideoOptionsOverride = z22.object({
|
|
|
4023
4208
|
videoStructure: VideoStructure.optional(),
|
|
4024
4209
|
videoQuality: VideoQuality.optional(),
|
|
4025
4210
|
videoModel: VideoModel.optional(),
|
|
4026
|
-
videoTier:
|
|
4211
|
+
videoTier: WritableVideoTier.optional(),
|
|
4027
4212
|
ugcFormat: VideoFormat.optional(),
|
|
4028
4213
|
videoStyle: VideoStyle.optional(),
|
|
4029
4214
|
narrativeStyle: NarrativeStyle.optional(),
|
|
@@ -4106,6 +4291,11 @@ var IngestResumePayload = z22.object({
|
|
|
4106
4291
|
// "keep what the task has". See angle-management.service.ts resumeAfterAngles.
|
|
4107
4292
|
videoStyle: VideoStyle.optional(),
|
|
4108
4293
|
videoModel: VideoModel.default("veo"),
|
|
4294
|
+
// READ schema on purpose, unlike IngestOptions/VideoOptionsOverride: resume
|
|
4295
|
+
// does not write the tier — `resumeAfterAngles` projects the route from the
|
|
4296
|
+
// task's OWN persisted tier and ignores this field. MCP and WhatsApp echo
|
|
4297
|
+
// `status.videoTier`, which is still `legacy` for historical rows; refusing
|
|
4298
|
+
// it made those tasks impossible to resume from both channels.
|
|
4109
4299
|
videoTier: VideoTier.optional(),
|
|
4110
4300
|
videoStructure: VideoStructure.optional(),
|
|
4111
4301
|
videoQuality: VideoQuality.optional(),
|
|
@@ -4916,17 +5106,7 @@ var VideoGenerator = z26.object({
|
|
|
4916
5106
|
format: VideoFormat.optional(),
|
|
4917
5107
|
videoStyle: VideoStyle.optional(),
|
|
4918
5108
|
narrativeStyle: NarrativeStyle.optional(),
|
|
4919
|
-
videoMode:
|
|
4920
|
-
"veo",
|
|
4921
|
-
"wan",
|
|
4922
|
-
"bytedance",
|
|
4923
|
-
"seedance",
|
|
4924
|
-
"grok",
|
|
4925
|
-
"kling",
|
|
4926
|
-
"avatar_talking",
|
|
4927
|
-
"hybrid",
|
|
4928
|
-
"sora"
|
|
4929
|
-
]).optional(),
|
|
5109
|
+
videoMode: PersistedVideoMode.optional(),
|
|
4930
5110
|
videoResolution: VideoResolution.optional(),
|
|
4931
5111
|
videoStructure: VideoStructure.optional(),
|
|
4932
5112
|
videoQuality: VideoQuality.optional(),
|
|
@@ -6940,7 +7120,10 @@ var ServiceCreativeEstimationOptions = z34.object({
|
|
|
6940
7120
|
uploadedVideoDurationSeconds: z34.number().min(0).max(240).optional(),
|
|
6941
7121
|
/** Quality the panels render at (its registry model sets the per-second
|
|
6942
7122
|
* price). Absent = economy, the pre-quality service default. */
|
|
6943
|
-
videoQuality: VideoQuality.optional()
|
|
7123
|
+
videoQuality: VideoQuality.optional(),
|
|
7124
|
+
/** Semantic resolution the panels render at (H3 maps 480p/720p to its
|
|
7125
|
+
* native 768P/2K). Absent = 480p, the pre-resolution service default. */
|
|
7126
|
+
videoResolution: VideoResolution.optional()
|
|
6944
7127
|
});
|
|
6945
7128
|
var ActorGridEstimationOptions = z34.object({}).strict();
|
|
6946
7129
|
var CostEstimationRequest = z34.discriminatedUnion("type", [
|
|
@@ -7288,7 +7471,8 @@ var IMAGE_QA_GATES = [
|
|
|
7288
7471
|
"limb",
|
|
7289
7472
|
"device_panel",
|
|
7290
7473
|
"critical_feature",
|
|
7291
|
-
"cross_section"
|
|
7474
|
+
"cross_section",
|
|
7475
|
+
"usage_fidelity"
|
|
7292
7476
|
];
|
|
7293
7477
|
var ImageQaGate = z36.enum(IMAGE_QA_GATES);
|
|
7294
7478
|
var ImageQaGateOutcome = z36.enum([
|
|
@@ -8334,6 +8518,10 @@ var GEMINI_OMNI_FLAT_USER_PRICE_CENTS = 168;
|
|
|
8334
8518
|
// ../../packages/types/src/pricing.ts
|
|
8335
8519
|
var CREDITS_PER_USD_CENT = 10;
|
|
8336
8520
|
var CREDITS_PER_DOLLAR = 100 * CREDITS_PER_USD_CENT;
|
|
8521
|
+
var AD_CREATIVE_MODELS = {
|
|
8522
|
+
STANDARD: IMAGE_WRITE_TOKENS["1k"],
|
|
8523
|
+
PREMIUM: IMAGE_WRITE_TOKENS["2k"]
|
|
8524
|
+
};
|
|
8337
8525
|
var KALODATA_USD_CENTS_PER_PROVIDER_CREDIT = 9;
|
|
8338
8526
|
var KALODATA_PROVIDER_CREDITS_PER_SOURCE_CEILING = 7.5;
|
|
8339
8527
|
var DEFAULT_PRICING = {
|
|
@@ -9292,6 +9480,27 @@ var DEFAULT_PRICING = {
|
|
|
9292
9480
|
ourCostCents: 1.88,
|
|
9293
9481
|
userPriceCents: 3.76
|
|
9294
9482
|
},
|
|
9483
|
+
// Usage decider (role `usage-decider`: Gemini 3.8 Flash effort:'high' since
|
|
9484
|
+
// 05f543eae, ≤6 images + seller text, temperature 0 json_object, once per
|
|
9485
|
+
// classic landing, always on). Was 3¢ measured on Claude
|
|
9486
|
+
// Sonnet 5 (spike 2026-09-24, 17 prod tasks). NOT re-measured on Flash — no
|
|
9487
|
+
// local BillingEntry row carries the Flash decider yet — so it is priced as
|
|
9488
|
+
// the product truth (`openrouter:product-truth`, 2.2¢ measured from
|
|
9489
|
+
// OpenRouter usage.cost): same model, same effort, same ≤6-photo input and a
|
|
9490
|
+
// JSON answer of similar size. Refine from usage.cost after the e2e. Fallback
|
|
9491
|
+
// only (OpenRouter's usage.cost is billed when present).
|
|
9492
|
+
"openrouter:usage-decision": {
|
|
9493
|
+
ourCostCents: 2.2,
|
|
9494
|
+
userPriceCents: 4.4
|
|
9495
|
+
},
|
|
9496
|
+
// Usage-fidelity QA judge (records misuse; regen gated separately behind
|
|
9497
|
+
// always on, bounded by USAGE_FIDELITY_MAX_REGENS). Sized off landing-image-qa beside it: same
|
|
9498
|
+
// shape of call (1-2 images, a verdict), so quoted at the same rate until
|
|
9499
|
+
// it has its own BillingEntry volume to re-derive from.
|
|
9500
|
+
"openrouter:usage-fidelity": {
|
|
9501
|
+
ourCostCents: 1.88,
|
|
9502
|
+
userPriceCents: 3.76
|
|
9503
|
+
},
|
|
9295
9504
|
// Landing commercial-facts extraction (gemini-3.8-flash, ONE text-only call over
|
|
9296
9505
|
// the seller's offer/context/features). Sized off the image-QA key beside it,
|
|
9297
9506
|
// which measured 1.88¢ at ~11.1K prompt tokens: this prompt is capped at ~3K in
|
|
@@ -10030,6 +10239,24 @@ var DEFAULT_PRICING = {
|
|
|
10030
10239
|
ourCostCents: 0.2,
|
|
10031
10240
|
userPriceCents: 0.4
|
|
10032
10241
|
},
|
|
10242
|
+
// Product truth (Gemini 3.8 Flash effort:'high', ≤6 photos + all seller text, once per
|
|
10243
|
+
// extract, always on). Plan C spike 2026-09-24: 6 calls, US$0.132 total ⇒
|
|
10244
|
+
// 2.2¢/call measured from OpenRouter usage.cost. Replaces usage spec + functional demo +
|
|
10245
|
+
// product-use sheet (+ landing visual-context-fusion) on the same task. Fallback only.
|
|
10246
|
+
"openrouter:product-truth": {
|
|
10247
|
+
ourCostCents: 2.2,
|
|
10248
|
+
userPriceCents: 4.4
|
|
10249
|
+
},
|
|
10250
|
+
// Landing creative director, «categorías» arm (Gemini 3.8 Flash effort:'high', ≤6 photos +
|
|
10251
|
+
// all seller text + the section plan, once per classic landing behind
|
|
10252
|
+
// LANDING_DIRECTOR_ENABLED). ESTIMATE, not measured: same call shape as the product truth
|
|
10253
|
+
// (2.2¢) with a ~2-3x longer JSON answer (one content spec per section) ⇒ ~4¢. Replaces
|
|
10254
|
+
// the visual brief (4¢) + visual-context fusion (0.4¢) + usage decision (2.2¢) on that
|
|
10255
|
+
// landing. Refine from OpenRouter usage.cost after the e2e. Fallback only.
|
|
10256
|
+
"openrouter:landing-director": {
|
|
10257
|
+
ourCostCents: 4,
|
|
10258
|
+
userPriceCents: 8
|
|
10259
|
+
},
|
|
10033
10260
|
// Unit = one reference-grouping pass over the user's product images (0.1241¢).
|
|
10034
10261
|
"openrouter:product-reference-grouping": {
|
|
10035
10262
|
ourCostCents: 0.15,
|
|
@@ -13374,7 +13601,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13374
13601
|
"task",
|
|
13375
13602
|
"product"
|
|
13376
13603
|
]),
|
|
13377
|
-
defineCapability("create_service_video", "
|
|
13604
|
+
defineCapability("create_service_video", "c3d81a4f698e01658fa04ebb613a91c8ba43320d21cacda522e72d198036eb21", "credit_consuming", "creative", [
|
|
13378
13605
|
"credit_consuming",
|
|
13379
13606
|
"state_change"
|
|
13380
13607
|
], [
|
|
@@ -13402,6 +13629,9 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13402
13629
|
// MCP-only for now: WhatsApp's service flow keeps the economy default.
|
|
13403
13630
|
slot("video_quality", false, [
|
|
13404
13631
|
"videoQuality"
|
|
13632
|
+
], []),
|
|
13633
|
+
slot("video_resolution", false, [
|
|
13634
|
+
"videoResolution"
|
|
13405
13635
|
], [])
|
|
13406
13636
|
], [
|
|
13407
13637
|
"service_context"
|
|
@@ -13544,7 +13774,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13544
13774
|
"video"
|
|
13545
13775
|
]
|
|
13546
13776
|
),
|
|
13547
|
-
defineCapability("generate_image_creatives", "
|
|
13777
|
+
defineCapability("generate_image_creatives", "2f1698b623d98645b7c618a17988f3aac30f403a9c3f3dc26eb5bdbd9c6ef23e", "credit_consuming", "creative", [
|
|
13548
13778
|
"credit_consuming",
|
|
13549
13779
|
"state_change"
|
|
13550
13780
|
], [
|
|
@@ -14941,79 +15171,696 @@ var WhatsAppPresentationManifestSchema = z67.object({
|
|
|
14941
15171
|
}
|
|
14942
15172
|
});
|
|
14943
15173
|
|
|
14944
|
-
// ../../packages/types/src/
|
|
15174
|
+
// ../../packages/types/src/usage-decision.ts
|
|
14945
15175
|
import { z as z68 } from "zod";
|
|
14946
|
-
|
|
15176
|
+
|
|
15177
|
+
// ../../packages/types/src/text-clamp.ts
|
|
15178
|
+
function clampAtWordBoundary(value, max) {
|
|
15179
|
+
if (typeof value !== "string") return value;
|
|
15180
|
+
if (value.length <= max) return value;
|
|
15181
|
+
const cut = value.slice(0, max);
|
|
15182
|
+
const lastSpace = cut.lastIndexOf(" ");
|
|
15183
|
+
const atWordBoundary = lastSpace > 0 ? cut.slice(0, lastSpace) : cut;
|
|
15184
|
+
return atWordBoundary.replace(/[,;:\s]+$/, "");
|
|
15185
|
+
}
|
|
15186
|
+
__name(clampAtWordBoundary, "clampAtWordBoundary");
|
|
15187
|
+
function clampStringArray(max) {
|
|
15188
|
+
return (value) => {
|
|
15189
|
+
if (!Array.isArray(value)) return value;
|
|
15190
|
+
const nonEmpty = value.filter((item) => typeof item === "string" && item.trim().length > 0);
|
|
15191
|
+
return nonEmpty.slice(0, max);
|
|
15192
|
+
};
|
|
15193
|
+
}
|
|
15194
|
+
__name(clampStringArray, "clampStringArray");
|
|
15195
|
+
|
|
15196
|
+
// ../../packages/types/src/usage-decision.ts
|
|
15197
|
+
var USAGE_SCENE_RULE_MAX_CHARS = 240;
|
|
15198
|
+
var USAGE_DECISION_MAX_REQUIRED_PARTS = 6;
|
|
15199
|
+
var USAGE_DECISION_MAX_ALTERNATE_USES = 4;
|
|
15200
|
+
var USAGE_DECISION_MAX_MISUSE = 5;
|
|
15201
|
+
function clampRule(value) {
|
|
15202
|
+
return clampAtWordBoundary(value, USAGE_SCENE_RULE_MAX_CHARS);
|
|
15203
|
+
}
|
|
15204
|
+
__name(clampRule, "clampRule");
|
|
15205
|
+
var UsageDecisionSchema = z68.object({
|
|
15206
|
+
productIdentity: z68.string().min(1),
|
|
15207
|
+
endUser: z68.object({
|
|
15208
|
+
who: z68.string(),
|
|
15209
|
+
appliedTo: z68.string()
|
|
15210
|
+
}),
|
|
15211
|
+
promise: z68.string().min(1),
|
|
15212
|
+
primaryUse: z68.object({
|
|
15213
|
+
scene: z68.string().min(1),
|
|
15214
|
+
postureAndGrip: z68.string(),
|
|
15215
|
+
contactPoint: z68.string(),
|
|
15216
|
+
requiredParts: z68.preprocess(clampStringArray(USAGE_DECISION_MAX_REQUIRED_PARTS), z68.array(z68.string()).max(USAGE_DECISION_MAX_REQUIRED_PARTS))
|
|
15217
|
+
}),
|
|
15218
|
+
validAlternateUses: z68.preprocess(clampStringArray(USAGE_DECISION_MAX_ALTERNATE_USES), z68.array(z68.string()).max(USAGE_DECISION_MAX_ALTERNATE_USES)),
|
|
15219
|
+
misuse: z68.preprocess(clampStringArray(USAGE_DECISION_MAX_MISUSE), z68.array(z68.string().min(1)).max(USAGE_DECISION_MAX_MISUSE)),
|
|
15220
|
+
useSceneRule: z68.preprocess(clampRule, z68.string().min(1).max(USAGE_SCENE_RULE_MAX_CHARS)),
|
|
15221
|
+
/**
|
|
15222
|
+
* True when the promise can ONLY be shown with the primary use (the pain is bending over and
|
|
15223
|
+
* the product has an extension pole: without the pole there is no promise); false when the
|
|
15224
|
+
* valid alternates sell it equally. Drives whether an alternate use in a use scene is a
|
|
15225
|
+
* failure (`requirePrimary` in the usage judge) and whether the prompts' primary use is
|
|
15226
|
+
* mandatory. Optional and fail-safe: missing (decisions stored before the field) or not a
|
|
15227
|
+
* boolean ⇒ `undefined`, read as false by every caller — never a rejected decision.
|
|
15228
|
+
*/
|
|
15229
|
+
primaryRequired: z68.boolean().optional().catch(void 0),
|
|
15230
|
+
confidence: z68.number().min(0).max(1),
|
|
15231
|
+
modelId: z68.string(),
|
|
15232
|
+
decidedAt: z68.string()
|
|
15233
|
+
});
|
|
15234
|
+
|
|
15235
|
+
// ../../packages/types/src/product-truth.ts
|
|
15236
|
+
import { z as z70 } from "zod";
|
|
15237
|
+
|
|
15238
|
+
// ../../packages/types/src/lenient-zod.ts
|
|
15239
|
+
import { z as z69 } from "zod";
|
|
15240
|
+
function trimAndClamp(value, max) {
|
|
15241
|
+
if (typeof value !== "string") return value;
|
|
15242
|
+
return clampAtWordBoundary(value.replace(/\s+/g, " ").trim(), max);
|
|
15243
|
+
}
|
|
15244
|
+
__name(trimAndClamp, "trimAndClamp");
|
|
15245
|
+
function lenientText(max) {
|
|
15246
|
+
return z69.preprocess((v) => trimAndClamp(v, max), z69.string().min(1).max(max));
|
|
15247
|
+
}
|
|
15248
|
+
__name(lenientText, "lenientText");
|
|
15249
|
+
function lenientOptionalText(max) {
|
|
15250
|
+
return z69.preprocess((v) => {
|
|
15251
|
+
if (typeof v !== "string") return void 0;
|
|
15252
|
+
const clamped = trimAndClamp(v, max);
|
|
15253
|
+
return typeof clamped === "string" && clamped.length > 0 ? clamped : void 0;
|
|
15254
|
+
}, z69.string().max(max).optional());
|
|
15255
|
+
}
|
|
15256
|
+
__name(lenientOptionalText, "lenientOptionalText");
|
|
15257
|
+
function lenientTextList(maxItems, maxChars) {
|
|
15258
|
+
return z69.preprocess((v) => {
|
|
15259
|
+
if (!Array.isArray(v)) return [];
|
|
15260
|
+
return v.map((item) => trimAndClamp(item, maxChars)).filter((item) => typeof item === "string" && item.length > 0).slice(0, maxItems);
|
|
15261
|
+
}, z69.array(z69.string().min(1).max(maxChars)).max(maxItems));
|
|
15262
|
+
}
|
|
15263
|
+
__name(lenientTextList, "lenientTextList");
|
|
15264
|
+
function lenientList(item, maxItems) {
|
|
15265
|
+
return z69.preprocess((v) => {
|
|
15266
|
+
if (!Array.isArray(v)) return [];
|
|
15267
|
+
return v.filter((entry) => item.safeParse(entry).success).slice(0, maxItems);
|
|
15268
|
+
}, z69.array(item).max(maxItems));
|
|
15269
|
+
}
|
|
15270
|
+
__name(lenientList, "lenientList");
|
|
15271
|
+
|
|
15272
|
+
// ../../packages/types/src/product-truth.ts
|
|
15273
|
+
var PRODUCT_TRUTH_SCHEMA_VERSION = 1;
|
|
15274
|
+
var PRODUCT_TRUTH_CAPS = {
|
|
15275
|
+
whatItIs: 160,
|
|
15276
|
+
deliveryForm: 120,
|
|
15277
|
+
distinctiveMarks: 6,
|
|
15278
|
+
distinctiveMarkChars: 160,
|
|
15279
|
+
parts: 12,
|
|
15280
|
+
partNameChars: 80,
|
|
15281
|
+
criticalFeatures: 6,
|
|
15282
|
+
connections: 6,
|
|
15283
|
+
connectionChars: 80,
|
|
15284
|
+
states: 4,
|
|
15285
|
+
stateKeyChars: 60,
|
|
15286
|
+
stateLabelChars: 80,
|
|
15287
|
+
partsPresent: 10,
|
|
15288
|
+
orientationInUseChars: 200,
|
|
15289
|
+
appliedToChars: 120,
|
|
15290
|
+
environmentChars: 120,
|
|
15291
|
+
summaryChars: 200,
|
|
15292
|
+
sceneChars: 300,
|
|
15293
|
+
postureAndGripChars: 160,
|
|
15294
|
+
contactPointChars: 120,
|
|
15295
|
+
steps: 8,
|
|
15296
|
+
stepNameChars: 120,
|
|
15297
|
+
stepInstructionChars: 300,
|
|
15298
|
+
visibleEffectChars: 200,
|
|
15299
|
+
beforeStateChars: 200,
|
|
15300
|
+
requiredProps: 8,
|
|
15301
|
+
requiredPropChars: 120,
|
|
15302
|
+
alternates: 3,
|
|
15303
|
+
misuse: 5,
|
|
15304
|
+
misuseChars: 200,
|
|
15305
|
+
mustShowFeatures: 5,
|
|
15306
|
+
mustShowFeatureChars: 100,
|
|
15307
|
+
safety: 5,
|
|
15308
|
+
safetyChars: 200,
|
|
15309
|
+
forbiddenClaims: 8,
|
|
15310
|
+
unsupportedClaims: 5,
|
|
15311
|
+
claimChars: 200,
|
|
15312
|
+
visualSummaryEnChars: 400
|
|
15313
|
+
};
|
|
15314
|
+
var PRODUCT_TRUTH_END_USER_AGE_BANDS = [
|
|
15315
|
+
"baby",
|
|
15316
|
+
"child",
|
|
15317
|
+
"teen",
|
|
15318
|
+
"adult",
|
|
15319
|
+
"any"
|
|
15320
|
+
];
|
|
15321
|
+
var PRODUCT_TRUTH_END_USER_GENDERS = [
|
|
15322
|
+
"female",
|
|
15323
|
+
"male",
|
|
15324
|
+
"any"
|
|
15325
|
+
];
|
|
15326
|
+
var PRODUCT_TRUTH_UNKNOWN_REASONS = [
|
|
15327
|
+
"model_unsure",
|
|
15328
|
+
"no_signal",
|
|
15329
|
+
"invalid_response",
|
|
15330
|
+
"provider_error"
|
|
15331
|
+
];
|
|
15332
|
+
var text = lenientText;
|
|
15333
|
+
var optionalText = lenientOptionalText;
|
|
15334
|
+
var textList = lenientTextList;
|
|
15335
|
+
function toProductTruthStateKey(value) {
|
|
15336
|
+
if (typeof value !== "string") return void 0;
|
|
15337
|
+
const slug = value.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, PRODUCT_TRUTH_CAPS.stateKeyChars);
|
|
15338
|
+
return slug.length > 0 ? slug : void 0;
|
|
15339
|
+
}
|
|
15340
|
+
__name(toProductTruthStateKey, "toProductTruthStateKey");
|
|
15341
|
+
var stateKey = z70.preprocess(toProductTruthStateKey, z70.string().min(1).max(PRODUCT_TRUTH_CAPS.stateKeyChars));
|
|
15342
|
+
var optionalStateKey = z70.preprocess(toProductTruthStateKey, z70.string().min(1).max(PRODUCT_TRUTH_CAPS.stateKeyChars).optional());
|
|
15343
|
+
var AGE_BAND_ALIASES = {
|
|
15344
|
+
baby: "baby",
|
|
15345
|
+
babies: "baby",
|
|
15346
|
+
infant: "baby",
|
|
15347
|
+
infants: "baby",
|
|
15348
|
+
toddler: "child",
|
|
15349
|
+
child: "child",
|
|
15350
|
+
children: "child",
|
|
15351
|
+
kid: "child",
|
|
15352
|
+
kids: "child",
|
|
15353
|
+
teen: "teen",
|
|
15354
|
+
teens: "teen",
|
|
15355
|
+
teenager: "teen",
|
|
15356
|
+
teenagers: "teen",
|
|
15357
|
+
adult: "adult",
|
|
15358
|
+
adults: "adult",
|
|
15359
|
+
any: "any",
|
|
15360
|
+
all: "any",
|
|
15361
|
+
"all ages": "any"
|
|
15362
|
+
};
|
|
15363
|
+
var GENDER_ALIASES = {
|
|
15364
|
+
female: "female",
|
|
15365
|
+
woman: "female",
|
|
15366
|
+
women: "female",
|
|
15367
|
+
girl: "female",
|
|
15368
|
+
male: "male",
|
|
15369
|
+
man: "male",
|
|
15370
|
+
men: "male",
|
|
15371
|
+
boy: "male",
|
|
15372
|
+
any: "any",
|
|
15373
|
+
unisex: "any",
|
|
15374
|
+
both: "any",
|
|
15375
|
+
all: "any"
|
|
15376
|
+
};
|
|
15377
|
+
function matchAlias(raw, aliases) {
|
|
15378
|
+
if (typeof raw !== "string") return void 0;
|
|
15379
|
+
const text2 = raw.trim().toLowerCase();
|
|
15380
|
+
const exact = aliases[text2];
|
|
15381
|
+
if (exact) return exact;
|
|
15382
|
+
const words = new Set(text2.split(/[^a-z]+/).filter(Boolean));
|
|
15383
|
+
for (const [alias, value] of Object.entries(aliases)) {
|
|
15384
|
+
if (words.has(alias)) return value;
|
|
15385
|
+
}
|
|
15386
|
+
return void 0;
|
|
15387
|
+
}
|
|
15388
|
+
__name(matchAlias, "matchAlias");
|
|
15389
|
+
function normalizeEndUser(value) {
|
|
15390
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
15391
|
+
const v = value;
|
|
15392
|
+
const age = matchAlias(v.ageBand, AGE_BAND_ALIASES);
|
|
15393
|
+
const gender = matchAlias(v.gender, GENDER_ALIASES);
|
|
15394
|
+
if (!age || !gender || typeof v.usedByBuyer !== "boolean") return void 0;
|
|
15395
|
+
return {
|
|
15396
|
+
ageBand: age,
|
|
15397
|
+
gender,
|
|
15398
|
+
usedByBuyer: v.usedByBuyer
|
|
15399
|
+
};
|
|
15400
|
+
}
|
|
15401
|
+
__name(normalizeEndUser, "normalizeEndUser");
|
|
15402
|
+
var ProductTruthEndUserSchema = z70.object({
|
|
15403
|
+
ageBand: z70.enum(PRODUCT_TRUTH_END_USER_AGE_BANDS),
|
|
15404
|
+
gender: z70.enum(PRODUCT_TRUTH_END_USER_GENDERS),
|
|
15405
|
+
usedByBuyer: z70.boolean()
|
|
15406
|
+
});
|
|
15407
|
+
var MATERIAL_HINTS = ProductMorphology.shape.materialHints.unwrap().element.options;
|
|
15408
|
+
var DEMO_TYPES = FunctionalDemonstration.shape.demoType;
|
|
15409
|
+
var PartSchema = z70.object({
|
|
15410
|
+
name: text(PRODUCT_TRUTH_CAPS.partNameChars),
|
|
15411
|
+
kind: z70.enum([
|
|
15412
|
+
"rigid",
|
|
15413
|
+
"flexible",
|
|
15414
|
+
"joint"
|
|
15415
|
+
]).catch("rigid"),
|
|
15416
|
+
count: z70.number().int().min(1).max(20).catch(1)
|
|
15417
|
+
});
|
|
15418
|
+
var CriticalFeatureSchema = z70.object({
|
|
15419
|
+
name: text(60),
|
|
15420
|
+
importance: text(120),
|
|
15421
|
+
antiPattern: optionalText(80),
|
|
15422
|
+
expectedCount: z70.number().int().min(1).max(20).optional().catch(void 0)
|
|
15423
|
+
});
|
|
15424
|
+
var ConnectionSchema = z70.object({
|
|
15425
|
+
part: text(PRODUCT_TRUTH_CAPS.connectionChars),
|
|
15426
|
+
attachesTo: text(PRODUCT_TRUTH_CAPS.connectionChars),
|
|
15427
|
+
where: optionalText(PRODUCT_TRUTH_CAPS.connectionChars)
|
|
15428
|
+
});
|
|
15429
|
+
var StateSchema = z70.object({
|
|
15430
|
+
key: stateKey,
|
|
15431
|
+
label: optionalText(PRODUCT_TRUTH_CAPS.stateLabelChars),
|
|
15432
|
+
partsPresent: textList(PRODUCT_TRUTH_CAPS.partsPresent, PRODUCT_TRUTH_CAPS.partNameChars),
|
|
15433
|
+
orientationInUse: text(PRODUCT_TRUTH_CAPS.orientationInUseChars),
|
|
15434
|
+
naturalOrientation: ProductNaturalOrientation.optional().catch(void 0)
|
|
15435
|
+
});
|
|
15436
|
+
var StepSchema = z70.object({
|
|
15437
|
+
name: text(PRODUCT_TRUTH_CAPS.stepNameChars),
|
|
15438
|
+
instruction: text(PRODUCT_TRUTH_CAPS.stepInstructionChars),
|
|
15439
|
+
kind: z70.enum([
|
|
15440
|
+
"setup",
|
|
15441
|
+
"use",
|
|
15442
|
+
"finish"
|
|
15443
|
+
]).catch("use")
|
|
15444
|
+
});
|
|
15445
|
+
var AlternateSchema = z70.object({
|
|
15446
|
+
summary: text(PRODUCT_TRUTH_CAPS.summaryChars),
|
|
15447
|
+
stateKey: optionalStateKey,
|
|
15448
|
+
advertisedBySeller: z70.boolean().catch(false)
|
|
15449
|
+
});
|
|
15450
|
+
var DemoSchema = z70.object({
|
|
15451
|
+
demoType: DEMO_TYPES.nullable().catch(null),
|
|
15452
|
+
mustShowFeatures: textList(PRODUCT_TRUTH_CAPS.mustShowFeatures, PRODUCT_TRUTH_CAPS.mustShowFeatureChars),
|
|
15453
|
+
importance: z70.enum([
|
|
15454
|
+
"critical",
|
|
15455
|
+
"important",
|
|
15456
|
+
"nice_to_have"
|
|
15457
|
+
]).catch("important")
|
|
15458
|
+
});
|
|
15459
|
+
var objectOrEmpty = /* @__PURE__ */ __name((v) => v && typeof v === "object" && !Array.isArray(v) ? v : {}, "objectOrEmpty");
|
|
15460
|
+
var ProductTruthBody = z70.object({
|
|
15461
|
+
identity: z70.object({
|
|
15462
|
+
whatItIs: text(PRODUCT_TRUTH_CAPS.whatItIs),
|
|
15463
|
+
deliveryForm: optionalText(PRODUCT_TRUTH_CAPS.deliveryForm),
|
|
15464
|
+
distinctiveMarks: textList(PRODUCT_TRUTH_CAPS.distinctiveMarks, PRODUCT_TRUTH_CAPS.distinctiveMarkChars)
|
|
15465
|
+
}),
|
|
15466
|
+
morphology: z70.preprocess(objectOrEmpty, z70.object({
|
|
15467
|
+
shape: ProductGeometryShape.optional().catch(void 0),
|
|
15468
|
+
crossSection: ProductCrossSection.optional().catch(void 0),
|
|
15469
|
+
cornerProfile: ProductCornerProfile.optional().catch(void 0),
|
|
15470
|
+
silhouetteWidthToHeightRatio: z70.number().min(0.05).max(20).optional().catch(void 0),
|
|
15471
|
+
parts: lenientList(PartSchema, PRODUCT_TRUTH_CAPS.parts),
|
|
15472
|
+
criticalFeatures: lenientList(CriticalFeatureSchema, PRODUCT_TRUTH_CAPS.criticalFeatures),
|
|
15473
|
+
shapeLockLevel: z70.enum([
|
|
15474
|
+
"strict",
|
|
15475
|
+
"moderate",
|
|
15476
|
+
"relaxed"
|
|
15477
|
+
]).optional().catch(void 0),
|
|
15478
|
+
materialHints: z70.preprocess((v) => Array.isArray(v) ? [
|
|
15479
|
+
...new Set(v.filter((m) => MATERIAL_HINTS.includes(m)))
|
|
15480
|
+
].slice(0, 3) : [], z70.array(z70.enum(MATERIAL_HINTS)).max(3))
|
|
15481
|
+
})),
|
|
15482
|
+
assembly: z70.object({
|
|
15483
|
+
connections: lenientList(ConnectionSchema, PRODUCT_TRUTH_CAPS.connections),
|
|
15484
|
+
states: z70.preprocess((v) => {
|
|
15485
|
+
if (!Array.isArray(v)) return v;
|
|
15486
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15487
|
+
return v.filter((entry) => {
|
|
15488
|
+
const parsed = StateSchema.safeParse(entry);
|
|
15489
|
+
if (!parsed.success || seen.has(parsed.data.key)) return false;
|
|
15490
|
+
seen.add(parsed.data.key);
|
|
15491
|
+
return true;
|
|
15492
|
+
}).slice(0, PRODUCT_TRUTH_CAPS.states);
|
|
15493
|
+
}, z70.array(StateSchema).min(1).max(PRODUCT_TRUTH_CAPS.states)),
|
|
15494
|
+
defaultStateKey: optionalStateKey
|
|
15495
|
+
}),
|
|
15496
|
+
use: z70.object({
|
|
15497
|
+
endUser: z70.preprocess(normalizeEndUser, ProductTruthEndUserSchema.optional()).catch(void 0),
|
|
15498
|
+
appliedTo: optionalText(PRODUCT_TRUTH_CAPS.appliedToChars),
|
|
15499
|
+
environment: optionalText(PRODUCT_TRUTH_CAPS.environmentChars),
|
|
15500
|
+
primary: z70.object({
|
|
15501
|
+
summary: text(PRODUCT_TRUTH_CAPS.summaryChars),
|
|
15502
|
+
scene: text(PRODUCT_TRUTH_CAPS.sceneChars),
|
|
15503
|
+
postureAndGrip: optionalText(PRODUCT_TRUTH_CAPS.postureAndGripChars),
|
|
15504
|
+
contactPoint: optionalText(PRODUCT_TRUTH_CAPS.contactPointChars),
|
|
15505
|
+
stateKey: optionalStateKey,
|
|
15506
|
+
steps: z70.preprocess((v) => Array.isArray(v) ? v.filter((s) => StepSchema.safeParse(s).success).slice(0, PRODUCT_TRUTH_CAPS.steps) : v, z70.array(StepSchema).min(1).max(PRODUCT_TRUTH_CAPS.steps)),
|
|
15507
|
+
visibleEffect: optionalText(PRODUCT_TRUTH_CAPS.visibleEffectChars),
|
|
15508
|
+
beforeState: optionalText(PRODUCT_TRUTH_CAPS.beforeStateChars),
|
|
15509
|
+
requiredProps: textList(PRODUCT_TRUTH_CAPS.requiredProps, PRODUCT_TRUTH_CAPS.requiredPropChars)
|
|
15510
|
+
}),
|
|
15511
|
+
alternates: lenientList(AlternateSchema, PRODUCT_TRUTH_CAPS.alternates),
|
|
15512
|
+
misuse: textList(PRODUCT_TRUTH_CAPS.misuse, PRODUCT_TRUTH_CAPS.misuseChars),
|
|
15513
|
+
demo: z70.preprocess(objectOrEmpty, DemoSchema),
|
|
15514
|
+
safety: textList(PRODUCT_TRUTH_CAPS.safety, PRODUCT_TRUTH_CAPS.safetyChars)
|
|
15515
|
+
}),
|
|
15516
|
+
claims: z70.preprocess(objectOrEmpty, z70.object({
|
|
15517
|
+
forbidden: textList(PRODUCT_TRUTH_CAPS.forbiddenClaims, PRODUCT_TRUTH_CAPS.claimChars),
|
|
15518
|
+
unsupported: textList(PRODUCT_TRUTH_CAPS.unsupportedClaims, PRODUCT_TRUTH_CAPS.claimChars)
|
|
15519
|
+
})),
|
|
15520
|
+
visualSummaryEn: optionalText(PRODUCT_TRUTH_CAPS.visualSummaryEnChars),
|
|
15521
|
+
evidence: z70.preprocess(objectOrEmpty, z70.object({
|
|
15522
|
+
photoIndexForState: z70.preprocess((v) => {
|
|
15523
|
+
const out = {};
|
|
15524
|
+
if (!v || typeof v !== "object" || Array.isArray(v)) return out;
|
|
15525
|
+
for (const [rawKey, rawIndexes] of Object.entries(v)) {
|
|
15526
|
+
const key = toProductTruthStateKey(rawKey);
|
|
15527
|
+
if (!key || !Array.isArray(rawIndexes)) continue;
|
|
15528
|
+
out[key] = rawIndexes.filter((i) => typeof i === "number" && Number.isInteger(i) && i >= 0 && i < 20);
|
|
15529
|
+
}
|
|
15530
|
+
return out;
|
|
15531
|
+
}, z70.record(z70.array(z70.number().int().min(0).max(19))))
|
|
15532
|
+
})),
|
|
15533
|
+
confidence: z70.preprocess((v) => typeof v === "number" && Number.isFinite(v) ? Math.min(1, Math.max(0, v)) : 0, z70.number().min(0).max(1))
|
|
15534
|
+
});
|
|
15535
|
+
function resolveStateRefs(body) {
|
|
15536
|
+
const keys = new Set(body.assembly.states.map((s) => s.key));
|
|
15537
|
+
const firstKey = body.assembly.states[0]?.key ?? "";
|
|
15538
|
+
const defaultStateKey = body.assembly.defaultStateKey && keys.has(body.assembly.defaultStateKey) ? body.assembly.defaultStateKey : firstKey;
|
|
15539
|
+
const primaryKey = body.use.primary.stateKey && keys.has(body.use.primary.stateKey) ? body.use.primary.stateKey : defaultStateKey;
|
|
15540
|
+
const photoIndexForState = Object.fromEntries(Object.entries(body.evidence.photoIndexForState).filter(([key]) => keys.has(key)));
|
|
15541
|
+
return {
|
|
15542
|
+
...body,
|
|
15543
|
+
assembly: {
|
|
15544
|
+
...body.assembly,
|
|
15545
|
+
defaultStateKey
|
|
15546
|
+
},
|
|
15547
|
+
use: {
|
|
15548
|
+
...body.use,
|
|
15549
|
+
primary: {
|
|
15550
|
+
...body.use.primary,
|
|
15551
|
+
stateKey: primaryKey
|
|
15552
|
+
},
|
|
15553
|
+
alternates: body.use.alternates.map((alt) => ({
|
|
15554
|
+
...alt,
|
|
15555
|
+
stateKey: alt.stateKey && keys.has(alt.stateKey) ? alt.stateKey : defaultStateKey
|
|
15556
|
+
}))
|
|
15557
|
+
},
|
|
15558
|
+
evidence: {
|
|
15559
|
+
...body.evidence,
|
|
15560
|
+
photoIndexForState
|
|
15561
|
+
}
|
|
15562
|
+
};
|
|
15563
|
+
}
|
|
15564
|
+
__name(resolveStateRefs, "resolveStateRefs");
|
|
15565
|
+
var ProductTruthModelResponseSchema = ProductTruthBody.transform(resolveStateRefs);
|
|
15566
|
+
var provenance = {
|
|
15567
|
+
schemaVersion: z70.literal(PRODUCT_TRUTH_SCHEMA_VERSION),
|
|
15568
|
+
modelId: z70.string().min(1),
|
|
15569
|
+
derivedAt: z70.string().min(1),
|
|
15570
|
+
/** Hash of (image keys + seller text + features): a reader that sees a different current
|
|
15571
|
+
* fingerprint treats the truth as absent. See `computeProductTruthFingerprint` in packages/ai. */
|
|
15572
|
+
sourceFingerprint: z70.string().min(1),
|
|
15573
|
+
/** The seller upload KEYS (deduped, sorted) the fingerprint was computed over. Stored so a
|
|
15574
|
+
* reader can recompute the CURRENT fingerprint from today's seller text + features without
|
|
15575
|
+
* knowing the extract job's inputs (plan Global Constraint "Invalidez"). */
|
|
15576
|
+
sourceImageKeys: z70.array(z70.string().min(1)).max(20).optional()
|
|
15577
|
+
};
|
|
15578
|
+
var ProductTruthKnownSchema = ProductTruthBody.extend({
|
|
15579
|
+
...provenance,
|
|
15580
|
+
known: z70.literal(true)
|
|
15581
|
+
}).transform(resolveStateRefs);
|
|
15582
|
+
var ProductTruthUnknownSchema = z70.object({
|
|
15583
|
+
schemaVersion: z70.literal(PRODUCT_TRUTH_SCHEMA_VERSION),
|
|
15584
|
+
known: z70.literal(false),
|
|
15585
|
+
unknownReason: z70.enum(PRODUCT_TRUTH_UNKNOWN_REASONS),
|
|
15586
|
+
modelId: z70.string().optional(),
|
|
15587
|
+
derivedAt: z70.string().min(1),
|
|
15588
|
+
sourceFingerprint: z70.string().min(1),
|
|
15589
|
+
sourceImageKeys: z70.array(z70.string().min(1)).max(20).optional()
|
|
15590
|
+
});
|
|
15591
|
+
var ProductTruthSchema = z70.union([
|
|
15592
|
+
ProductTruthKnownSchema,
|
|
15593
|
+
ProductTruthUnknownSchema
|
|
15594
|
+
]);
|
|
15595
|
+
|
|
15596
|
+
// ../../packages/types/src/landing-director.ts
|
|
15597
|
+
import { z as z71 } from "zod";
|
|
15598
|
+
var LANDING_DIRECTOR_SCHEMA_VERSION = 1;
|
|
15599
|
+
var LANDING_DIRECTOR_ARM = "categories";
|
|
15600
|
+
var LANDING_DIRECTOR_CAPS = {
|
|
15601
|
+
productIdentity: 200,
|
|
15602
|
+
parts: 8,
|
|
15603
|
+
partName: 40,
|
|
15604
|
+
promise: 200,
|
|
15605
|
+
endUserWho: 80,
|
|
15606
|
+
endUserAppliedTo: 80,
|
|
15607
|
+
forbiddenClaims: 10,
|
|
15608
|
+
claimChars: 80,
|
|
15609
|
+
misuse: 5,
|
|
15610
|
+
misuseChars: 120,
|
|
15611
|
+
assembledStates: 3,
|
|
15612
|
+
statePartsMax: 6,
|
|
15613
|
+
orientation: 160,
|
|
15614
|
+
handling: 140,
|
|
15615
|
+
primaryScene: 200,
|
|
15616
|
+
postureAndGrip: 140,
|
|
15617
|
+
contactPoint: 100,
|
|
15618
|
+
alternates: 3,
|
|
15619
|
+
alternateChars: 120,
|
|
15620
|
+
ambiguities: 4,
|
|
15621
|
+
ambiguityChars: 160,
|
|
15622
|
+
sectionKeyChars: 40,
|
|
15623
|
+
personWho: 80,
|
|
15624
|
+
personPosture: 120,
|
|
15625
|
+
personGrip: 120,
|
|
15626
|
+
scene: 450,
|
|
15627
|
+
panels: 4,
|
|
15628
|
+
panelScene: 200,
|
|
15629
|
+
panelCaption: 60,
|
|
15630
|
+
/** Rendered text: an item over its cap is DROPPED, never cut. The headline cap is 80, not
|
|
15631
|
+
* the design's 70: a dropped headline costs the whole director headline, and 7-10 Spanish
|
|
15632
|
+
* words routinely run 70-80 chars. */
|
|
15633
|
+
headline: 80,
|
|
15634
|
+
subheadline: 90,
|
|
15635
|
+
labels: 3,
|
|
15636
|
+
labelChars: 40,
|
|
15637
|
+
captions: 3,
|
|
15638
|
+
captionChars: 60,
|
|
15639
|
+
props: 4,
|
|
15640
|
+
propChars: 40,
|
|
15641
|
+
mustNotShow: 5,
|
|
15642
|
+
mustNotShowChars: 80
|
|
15643
|
+
};
|
|
15644
|
+
var STATE_KEY_PATTERN = /^[a-z][a-z_]{1,23}$/;
|
|
15645
|
+
function toLandingDirectorStateKey(value) {
|
|
15646
|
+
if (typeof value !== "string") return void 0;
|
|
15647
|
+
const slug = value.toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g, "").replace(/[^a-z]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 24).replace(/_+$/g, "");
|
|
15648
|
+
return STATE_KEY_PATTERN.test(slug) ? slug : void 0;
|
|
15649
|
+
}
|
|
15650
|
+
__name(toLandingDirectorStateKey, "toLandingDirectorStateKey");
|
|
15651
|
+
var stateKey2 = z71.preprocess(toLandingDirectorStateKey, z71.string().regex(STATE_KEY_PATTERN));
|
|
15652
|
+
function renderedOptionalText(max) {
|
|
15653
|
+
return z71.preprocess((v) => {
|
|
15654
|
+
if (typeof v !== "string") return void 0;
|
|
15655
|
+
const trimmed = v.replace(/\s+/g, " ").trim();
|
|
15656
|
+
return trimmed.length > 0 && trimmed.length <= max ? trimmed : void 0;
|
|
15657
|
+
}, z71.string().min(1).max(max).optional());
|
|
15658
|
+
}
|
|
15659
|
+
__name(renderedOptionalText, "renderedOptionalText");
|
|
15660
|
+
function renderedTextList(maxItems, maxChars) {
|
|
15661
|
+
return z71.preprocess((v) => {
|
|
15662
|
+
if (!Array.isArray(v)) return [];
|
|
15663
|
+
return v.map((item) => typeof item === "string" ? item.replace(/\s+/g, " ").trim() : "").filter((item) => item.length > 0 && item.length <= maxChars).slice(0, maxItems);
|
|
15664
|
+
}, z71.array(z71.string().min(1).max(maxChars)).max(maxItems));
|
|
15665
|
+
}
|
|
15666
|
+
__name(renderedTextList, "renderedTextList");
|
|
15667
|
+
var C = LANDING_DIRECTOR_CAPS;
|
|
15668
|
+
var PartSchema2 = z71.object({
|
|
15669
|
+
name: lenientText(C.partName),
|
|
15670
|
+
critical: z71.boolean().catch(false)
|
|
15671
|
+
});
|
|
15672
|
+
var AssembledStateSchema = z71.object({
|
|
15673
|
+
key: stateKey2,
|
|
15674
|
+
parts: lenientTextList(C.statePartsMax, C.partName),
|
|
15675
|
+
orientation: lenientText(C.orientation),
|
|
15676
|
+
handling: lenientOptionalText(C.handling)
|
|
15677
|
+
});
|
|
15678
|
+
var END_USER_GENDERS = [
|
|
15679
|
+
"female",
|
|
15680
|
+
"male",
|
|
15681
|
+
"any"
|
|
15682
|
+
];
|
|
15683
|
+
var END_USER_AGE_BANDS = [
|
|
15684
|
+
"child",
|
|
15685
|
+
"teen",
|
|
15686
|
+
"adult",
|
|
15687
|
+
"senior",
|
|
15688
|
+
"any"
|
|
15689
|
+
];
|
|
15690
|
+
var EndUserSchema = z71.object({
|
|
15691
|
+
who: lenientText(C.endUserWho),
|
|
15692
|
+
appliedTo: lenientOptionalText(C.endUserAppliedTo),
|
|
15693
|
+
gender: z71.enum(END_USER_GENDERS).catch("any"),
|
|
15694
|
+
ageBand: z71.enum(END_USER_AGE_BANDS).catch("any")
|
|
15695
|
+
});
|
|
15696
|
+
var LandingDirectorGlobalSchema = z71.object({
|
|
15697
|
+
productIdentity: lenientText(C.productIdentity),
|
|
15698
|
+
parts: lenientList(PartSchema2, C.parts),
|
|
15699
|
+
promise: lenientText(C.promise),
|
|
15700
|
+
endUser: EndUserSchema,
|
|
15701
|
+
forbiddenClaims: lenientTextList(C.forbiddenClaims, C.claimChars),
|
|
15702
|
+
misuse: lenientTextList(C.misuse, C.misuseChars),
|
|
15703
|
+
assembledStates: z71.preprocess((v) => {
|
|
15704
|
+
if (!Array.isArray(v)) return v;
|
|
15705
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15706
|
+
return v.filter((entry) => {
|
|
15707
|
+
const parsed = AssembledStateSchema.safeParse(entry);
|
|
15708
|
+
if (!parsed.success || seen.has(parsed.data.key)) return false;
|
|
15709
|
+
seen.add(parsed.data.key);
|
|
15710
|
+
return true;
|
|
15711
|
+
}).slice(0, C.assembledStates);
|
|
15712
|
+
}, z71.array(AssembledStateSchema).min(1).max(C.assembledStates)),
|
|
15713
|
+
primaryUse: z71.object({
|
|
15714
|
+
assembledState: stateKey2,
|
|
15715
|
+
scene: lenientText(C.primaryScene),
|
|
15716
|
+
postureAndGrip: lenientText(C.postureAndGrip),
|
|
15717
|
+
contactPoint: lenientOptionalText(C.contactPoint)
|
|
15718
|
+
}),
|
|
15719
|
+
primaryRequired: z71.boolean().catch(false),
|
|
15720
|
+
validAlternateUses: lenientTextList(C.alternates, C.alternateChars),
|
|
15721
|
+
ambiguities: lenientTextList(C.ambiguities, C.ambiguityChars)
|
|
15722
|
+
});
|
|
15723
|
+
var LANDING_DIRECTOR_BODY_PARTS = [
|
|
15724
|
+
"hands",
|
|
15725
|
+
"face",
|
|
15726
|
+
"torso",
|
|
15727
|
+
"legs",
|
|
15728
|
+
"feet",
|
|
15729
|
+
"full_body"
|
|
15730
|
+
];
|
|
15731
|
+
var PersonSchema = z71.object({
|
|
15732
|
+
who: lenientText(C.personWho),
|
|
15733
|
+
posture: lenientText(C.personPosture),
|
|
15734
|
+
grip: lenientOptionalText(C.personGrip),
|
|
15735
|
+
bodyPartsVisible: z71.preprocess((v) => Array.isArray(v) ? [
|
|
15736
|
+
...new Set(v.filter((part) => LANDING_DIRECTOR_BODY_PARTS.includes(part)))
|
|
15737
|
+
] : [], z71.array(z71.enum(LANDING_DIRECTOR_BODY_PARTS)))
|
|
15738
|
+
});
|
|
15739
|
+
var LandingDirectorTextSchema = z71.object({
|
|
15740
|
+
headline: renderedOptionalText(C.headline),
|
|
15741
|
+
subheadline: renderedOptionalText(C.subheadline),
|
|
15742
|
+
labels: renderedTextList(C.labels, C.labelChars),
|
|
15743
|
+
captions: renderedTextList(C.captions, C.captionChars)
|
|
15744
|
+
});
|
|
15745
|
+
var PanelSchema = z71.object({
|
|
15746
|
+
scene: lenientText(C.panelScene),
|
|
15747
|
+
caption: renderedOptionalText(C.panelCaption)
|
|
15748
|
+
});
|
|
15749
|
+
var PRODUCT_IN_FRAME_VALUES = [
|
|
15750
|
+
"none",
|
|
15751
|
+
"packshot",
|
|
15752
|
+
"in_use"
|
|
15753
|
+
];
|
|
15754
|
+
var LandingDirectorSectionSchema = z71.object({
|
|
15755
|
+
sectionKey: z71.string().trim().min(1).max(C.sectionKeyChars),
|
|
15756
|
+
/** Present only in the «director» arm. Kept as a flag so the «categorías» validation can
|
|
15757
|
+
* invalidate the section (design §2.3) instead of silently dropping the model's choice. */
|
|
15758
|
+
hasComposition: z71.boolean().default(false),
|
|
15759
|
+
productInFrame: z71.enum(PRODUCT_IN_FRAME_VALUES),
|
|
15760
|
+
assembledState: z71.preprocess((v) => v === null || v === void 0 ? null : toLandingDirectorStateKey(v), z71.string().regex(STATE_KEY_PATTERN).nullable()),
|
|
15761
|
+
usesPrimary: z71.boolean().catch(false),
|
|
15762
|
+
person: z71.preprocess((v) => v === void 0 ? null : v, PersonSchema.nullable()),
|
|
15763
|
+
scene: lenientText(C.scene),
|
|
15764
|
+
panels: lenientList(PanelSchema, C.panels),
|
|
15765
|
+
textToRender: z71.preprocess((v) => v && typeof v === "object" && !Array.isArray(v) ? v : {}, LandingDirectorTextSchema),
|
|
15766
|
+
props: lenientTextList(C.props, C.propChars),
|
|
15767
|
+
mustNotShow: lenientTextList(C.mustNotShow, C.mustNotShowChars)
|
|
15768
|
+
});
|
|
15769
|
+
var LandingDirectorOutputSchema = z71.object({
|
|
15770
|
+
version: z71.literal(LANDING_DIRECTOR_SCHEMA_VERSION),
|
|
15771
|
+
confidence: z71.number().min(0).max(1),
|
|
15772
|
+
global: LandingDirectorGlobalSchema,
|
|
15773
|
+
sections: z71.array(LandingDirectorSectionSchema)
|
|
15774
|
+
});
|
|
15775
|
+
var StoredLandingDirectorSchema = z71.object({
|
|
15776
|
+
version: z71.literal(LANDING_DIRECTOR_SCHEMA_VERSION),
|
|
15777
|
+
arm: z71.literal(LANDING_DIRECTOR_ARM),
|
|
15778
|
+
modelId: z71.string().min(1),
|
|
15779
|
+
generatedAt: z71.string().min(1),
|
|
15780
|
+
confidence: z71.number().min(0).max(1),
|
|
15781
|
+
/** The plan the answer was validated against (sectionKey, or the role on classic). */
|
|
15782
|
+
planSectionKeys: z71.array(z71.string().min(1)),
|
|
15783
|
+
output: LandingDirectorOutputSchema,
|
|
15784
|
+
/** Sections that fell back to the category composition, and why. */
|
|
15785
|
+
fallbackSections: z71.array(z71.object({
|
|
15786
|
+
sectionKey: z71.string().min(1),
|
|
15787
|
+
reason: z71.string().min(1)
|
|
15788
|
+
}))
|
|
15789
|
+
});
|
|
15790
|
+
|
|
15791
|
+
// ../../packages/types/src/flight-recorder.ts
|
|
15792
|
+
import { z as z72 } from "zod";
|
|
15793
|
+
var FlightRecorderGenerationTypeSchema = z72.enum([
|
|
14947
15794
|
"initial",
|
|
14948
15795
|
"regeneration",
|
|
14949
15796
|
"edit",
|
|
14950
15797
|
"retry"
|
|
14951
15798
|
]);
|
|
14952
|
-
var FlightRecorderProviderSchema =
|
|
15799
|
+
var FlightRecorderProviderSchema = z72.enum([
|
|
14953
15800
|
"kie",
|
|
14954
15801
|
"fal"
|
|
14955
15802
|
]);
|
|
14956
|
-
var FlightRecorderElementSchema =
|
|
14957
|
-
name:
|
|
14958
|
-
description:
|
|
14959
|
-
frontalImageUrl:
|
|
14960
|
-
referenceImageUrls:
|
|
14961
|
-
videoUrl:
|
|
14962
|
-
});
|
|
14963
|
-
var FlightRecorderDistillationSchema =
|
|
14964
|
-
actorGender:
|
|
15803
|
+
var FlightRecorderElementSchema = z72.object({
|
|
15804
|
+
name: z72.string().optional(),
|
|
15805
|
+
description: z72.string().optional(),
|
|
15806
|
+
frontalImageUrl: z72.string().optional(),
|
|
15807
|
+
referenceImageUrls: z72.array(z72.string()).optional(),
|
|
15808
|
+
videoUrl: z72.string().optional()
|
|
15809
|
+
});
|
|
15810
|
+
var FlightRecorderDistillationSchema = z72.object({
|
|
15811
|
+
actorGender: z72.enum([
|
|
14965
15812
|
"female",
|
|
14966
15813
|
"male",
|
|
14967
15814
|
"mixed"
|
|
14968
|
-
]).or(
|
|
14969
|
-
voiceId:
|
|
14970
|
-
cameraMotion:
|
|
14971
|
-
}).catchall(
|
|
14972
|
-
var FlightRecorderEntrySchema =
|
|
14973
|
-
schemaVersion:
|
|
14974
|
-
id:
|
|
14975
|
-
taskId:
|
|
14976
|
-
runId:
|
|
14977
|
-
sequence:
|
|
14978
|
-
timestamp:
|
|
14979
|
-
provider: FlightRecorderProviderSchema.or(
|
|
14980
|
-
model:
|
|
14981
|
-
prompt:
|
|
14982
|
-
durationSeconds:
|
|
14983
|
-
aspectRatio:
|
|
14984
|
-
resolution:
|
|
14985
|
-
startImageUrl:
|
|
14986
|
-
endImageUrl:
|
|
14987
|
-
generateAudio:
|
|
15815
|
+
]).or(z72.string()).optional(),
|
|
15816
|
+
voiceId: z72.string().optional(),
|
|
15817
|
+
cameraMotion: z72.string().optional()
|
|
15818
|
+
}).catchall(z72.unknown());
|
|
15819
|
+
var FlightRecorderEntrySchema = z72.object({
|
|
15820
|
+
schemaVersion: z72.literal(1).optional(),
|
|
15821
|
+
id: z72.string().min(1),
|
|
15822
|
+
taskId: z72.string().min(1),
|
|
15823
|
+
runId: z72.string().min(1),
|
|
15824
|
+
sequence: z72.number().int().nonnegative(),
|
|
15825
|
+
timestamp: z72.string().min(1),
|
|
15826
|
+
provider: FlightRecorderProviderSchema.or(z72.string()),
|
|
15827
|
+
model: z72.string().min(1),
|
|
15828
|
+
prompt: z72.string(),
|
|
15829
|
+
durationSeconds: z72.number().nonnegative(),
|
|
15830
|
+
aspectRatio: z72.string().optional(),
|
|
15831
|
+
resolution: z72.string().optional(),
|
|
15832
|
+
startImageUrl: z72.string().optional(),
|
|
15833
|
+
endImageUrl: z72.string().optional(),
|
|
15834
|
+
generateAudio: z72.boolean().optional(),
|
|
14988
15835
|
// Correlation & pipeline metadata
|
|
14989
|
-
angleKey:
|
|
14990
|
-
sceneIndex:
|
|
15836
|
+
angleKey: z72.string().optional(),
|
|
15837
|
+
sceneIndex: z72.number().int().nonnegative().optional(),
|
|
14991
15838
|
generationType: FlightRecorderGenerationTypeSchema,
|
|
14992
|
-
operationId:
|
|
14993
|
-
revisionId:
|
|
14994
|
-
attemptNumber:
|
|
15839
|
+
operationId: z72.string().min(1).optional(),
|
|
15840
|
+
revisionId: z72.string().min(1).optional(),
|
|
15841
|
+
attemptNumber: z72.number().int().nonnegative().default(1),
|
|
14995
15842
|
// Elements & Distillation
|
|
14996
|
-
elements:
|
|
15843
|
+
elements: z72.array(FlightRecorderElementSchema).optional(),
|
|
14997
15844
|
distillation: FlightRecorderDistillationSchema.optional(),
|
|
14998
15845
|
// Raw payload (sanitized of secrets)
|
|
14999
|
-
rawPayload:
|
|
15846
|
+
rawPayload: z72.record(z72.unknown())
|
|
15000
15847
|
});
|
|
15001
|
-
var FlightRecorderQuerySchema =
|
|
15002
|
-
taskId:
|
|
15003
|
-
runId:
|
|
15004
|
-
sceneIndex:
|
|
15005
|
-
angleKey:
|
|
15848
|
+
var FlightRecorderQuerySchema = z72.object({
|
|
15849
|
+
taskId: z72.string().min(1),
|
|
15850
|
+
runId: z72.string().optional(),
|
|
15851
|
+
sceneIndex: z72.number().int().nonnegative().optional(),
|
|
15852
|
+
angleKey: z72.string().optional(),
|
|
15006
15853
|
generationType: FlightRecorderGenerationTypeSchema.optional(),
|
|
15007
|
-
cursor:
|
|
15008
|
-
limit:
|
|
15854
|
+
cursor: z72.number().int().nonnegative().optional(),
|
|
15855
|
+
limit: z72.number().int().positive().optional()
|
|
15009
15856
|
});
|
|
15010
|
-
var FlightRecorderResponseSchema =
|
|
15011
|
-
taskId:
|
|
15012
|
-
runId:
|
|
15013
|
-
entries:
|
|
15857
|
+
var FlightRecorderResponseSchema = z72.object({
|
|
15858
|
+
taskId: z72.string().min(1),
|
|
15859
|
+
runId: z72.string().min(1),
|
|
15860
|
+
entries: z72.array(FlightRecorderEntrySchema),
|
|
15014
15861
|
lastCall: FlightRecorderEntrySchema.nullable(),
|
|
15015
|
-
count:
|
|
15016
|
-
nextCursor:
|
|
15862
|
+
count: z72.number().int().nonnegative(),
|
|
15863
|
+
nextCursor: z72.number().int().nonnegative().nullable()
|
|
15017
15864
|
});
|
|
15018
15865
|
|
|
15019
15866
|
// src/response-body.ts
|
|
@@ -15255,7 +16102,7 @@ var ApiClient = class {
|
|
|
15255
16102
|
};
|
|
15256
16103
|
|
|
15257
16104
|
// src/index.ts
|
|
15258
|
-
var MCP_VERSION = "8.
|
|
16105
|
+
var MCP_VERSION = "8.2.0";
|
|
15259
16106
|
|
|
15260
16107
|
// src/meta-upload-app.ts
|
|
15261
16108
|
import { readFileSync } from "fs";
|
|
@@ -15327,7 +16174,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
|
|
|
15327
16174
|
__name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
|
|
15328
16175
|
|
|
15329
16176
|
// src/tools/tasks.ts
|
|
15330
|
-
import { z as
|
|
16177
|
+
import { z as z76 } from "zod";
|
|
15331
16178
|
|
|
15332
16179
|
// src/resolve-image.ts
|
|
15333
16180
|
import { lookup as dnsLookup } from "dns/promises";
|
|
@@ -15888,10 +16735,10 @@ async function resolveMediaRef(ref, opts) {
|
|
|
15888
16735
|
__name(resolveMediaRef, "resolveMediaRef");
|
|
15889
16736
|
|
|
15890
16737
|
// src/tools/shared.ts
|
|
15891
|
-
import { z as
|
|
15892
|
-
var Lang =
|
|
15893
|
-
var Country =
|
|
15894
|
-
var LandingStrategyEnum =
|
|
16738
|
+
import { z as z73 } from "zod";
|
|
16739
|
+
var Lang = z73.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);
|
|
16740
|
+
var Country = z73.string().min(2).max(3);
|
|
16741
|
+
var LandingStrategyEnum = z73.enum([
|
|
15895
16742
|
"auto",
|
|
15896
16743
|
"classic",
|
|
15897
16744
|
"pain_solution",
|
|
@@ -15900,12 +16747,12 @@ var LandingStrategyEnum = z69.enum([
|
|
|
15900
16747
|
"offer_value",
|
|
15901
16748
|
"lifestyle_identity"
|
|
15902
16749
|
]);
|
|
15903
|
-
var LandingImageFormatEnum =
|
|
16750
|
+
var LandingImageFormatEnum = z73.enum([
|
|
15904
16751
|
"9:16",
|
|
15905
16752
|
"4:5",
|
|
15906
16753
|
"1:1"
|
|
15907
16754
|
]);
|
|
15908
|
-
var VideoPresetEnum =
|
|
16755
|
+
var VideoPresetEnum = z73.enum([
|
|
15909
16756
|
"auto",
|
|
15910
16757
|
"ugc_dynamic",
|
|
15911
16758
|
"ugc_how_to",
|
|
@@ -15918,21 +16765,21 @@ var VideoPresetEnum = z69.enum([
|
|
|
15918
16765
|
"pixar_problem",
|
|
15919
16766
|
"pixar_sassy"
|
|
15920
16767
|
]);
|
|
15921
|
-
var VideoStructureEnum =
|
|
16768
|
+
var VideoStructureEnum = z73.enum([
|
|
15922
16769
|
"single_take",
|
|
15923
16770
|
"multi_scene"
|
|
15924
16771
|
]);
|
|
15925
|
-
var VideoQualityEnum =
|
|
16772
|
+
var VideoQualityEnum = z73.enum([
|
|
15926
16773
|
"economy",
|
|
15927
16774
|
"medium",
|
|
15928
16775
|
"pro"
|
|
15929
16776
|
]);
|
|
15930
|
-
var VideoRouteIdEnum =
|
|
16777
|
+
var VideoRouteIdEnum = z73.enum([
|
|
15931
16778
|
"single_take",
|
|
15932
16779
|
"multi_scene",
|
|
15933
16780
|
"free"
|
|
15934
16781
|
]);
|
|
15935
|
-
var TaskCreativeVariantVideoPresetEnum =
|
|
16782
|
+
var TaskCreativeVariantVideoPresetEnum = z73.enum([
|
|
15936
16783
|
"auto",
|
|
15937
16784
|
"ugc_dynamic",
|
|
15938
16785
|
"ugc_how_to",
|
|
@@ -15949,53 +16796,43 @@ var VIDEO_PRESET_RESOLUTION = {
|
|
|
15949
16796
|
auto: null,
|
|
15950
16797
|
ugc_dynamic: {
|
|
15951
16798
|
videoStyle: "ai_dynamic",
|
|
15952
|
-
narrativeStyle: "review"
|
|
15953
|
-
videoModel: "veo"
|
|
16799
|
+
narrativeStyle: "review"
|
|
15954
16800
|
},
|
|
15955
16801
|
ugc_how_to: {
|
|
15956
16802
|
videoStyle: "ai_dynamic",
|
|
15957
|
-
narrativeStyle: "ugc_how_to"
|
|
15958
|
-
videoModel: "veo"
|
|
16803
|
+
narrativeStyle: "ugc_how_to"
|
|
15959
16804
|
},
|
|
15960
16805
|
ugc_unboxing_chaos: {
|
|
15961
16806
|
videoStyle: "ai_dynamic",
|
|
15962
|
-
narrativeStyle: "ugc_unboxing_chaos"
|
|
15963
|
-
videoModel: "veo"
|
|
16807
|
+
narrativeStyle: "ugc_unboxing_chaos"
|
|
15964
16808
|
},
|
|
15965
16809
|
problem_solution: {
|
|
15966
16810
|
videoStyle: "ai_dynamic",
|
|
15967
|
-
narrativeStyle: "problem_product_cta"
|
|
15968
|
-
videoModel: "kling"
|
|
16811
|
+
narrativeStyle: "problem_product_cta"
|
|
15969
16812
|
},
|
|
15970
16813
|
pixar_problem: {
|
|
15971
16814
|
videoStyle: "ai_dynamic",
|
|
15972
|
-
narrativeStyle: "animated_problem_pixar"
|
|
15973
|
-
videoModel: "kling"
|
|
16815
|
+
narrativeStyle: "animated_problem_pixar"
|
|
15974
16816
|
},
|
|
15975
16817
|
pixar_sassy: {
|
|
15976
16818
|
videoStyle: "ai_dynamic",
|
|
15977
|
-
narrativeStyle: "sassy_product_pixar"
|
|
15978
|
-
videoModel: "seedance"
|
|
16819
|
+
narrativeStyle: "sassy_product_pixar"
|
|
15979
16820
|
},
|
|
15980
16821
|
product_showcase: {
|
|
15981
16822
|
videoStyle: "product_only",
|
|
15982
|
-
narrativeStyle: "product_showcase"
|
|
15983
|
-
videoModel: "veo"
|
|
16823
|
+
narrativeStyle: "product_showcase"
|
|
15984
16824
|
},
|
|
15985
16825
|
wearable_showcase: {
|
|
15986
16826
|
videoStyle: "ugc",
|
|
15987
|
-
narrativeStyle: "wearable_showcase"
|
|
15988
|
-
videoModel: "veo"
|
|
16827
|
+
narrativeStyle: "wearable_showcase"
|
|
15989
16828
|
},
|
|
15990
16829
|
cinematic: {
|
|
15991
16830
|
videoStyle: "product_only",
|
|
15992
|
-
narrativeStyle: "cinematic"
|
|
15993
|
-
videoModel: "grok"
|
|
16831
|
+
narrativeStyle: "cinematic"
|
|
15994
16832
|
},
|
|
15995
16833
|
wild_card: {
|
|
15996
16834
|
videoStyle: "product_only",
|
|
15997
|
-
narrativeStyle: "wild_card"
|
|
15998
|
-
videoModel: "grok"
|
|
16835
|
+
narrativeStyle: "wild_card"
|
|
15999
16836
|
}
|
|
16000
16837
|
};
|
|
16001
16838
|
function resolveVideoPreset(preset) {
|
|
@@ -16003,7 +16840,7 @@ function resolveVideoPreset(preset) {
|
|
|
16003
16840
|
return VIDEO_PRESET_RESOLUTION[preset] ?? null;
|
|
16004
16841
|
}
|
|
16005
16842
|
__name(resolveVideoPreset, "resolveVideoPreset");
|
|
16006
|
-
var VideoTierEnum =
|
|
16843
|
+
var VideoTierEnum = z73.enum([
|
|
16007
16844
|
"basic"
|
|
16008
16845
|
]);
|
|
16009
16846
|
function resolveVideoTier(_tier) {
|
|
@@ -16043,22 +16880,22 @@ function assertSemanticVideoDurationCompatibility(structure, quality, durationSe
|
|
|
16043
16880
|
}
|
|
16044
16881
|
}
|
|
16045
16882
|
__name(assertSemanticVideoDurationCompatibility, "assertSemanticVideoDurationCompatibility");
|
|
16046
|
-
var VideoResolutionEnum =
|
|
16883
|
+
var VideoResolutionEnum = z73.enum([
|
|
16047
16884
|
"480p",
|
|
16048
16885
|
"720p"
|
|
16049
16886
|
]);
|
|
16050
|
-
var CreativeGenderEnum =
|
|
16887
|
+
var CreativeGenderEnum = z73.enum([
|
|
16051
16888
|
"female",
|
|
16052
16889
|
"male",
|
|
16053
16890
|
"mixed"
|
|
16054
16891
|
]);
|
|
16055
|
-
var VideoStyleEnum =
|
|
16892
|
+
var VideoStyleEnum = z73.enum([
|
|
16056
16893
|
"ugc",
|
|
16057
16894
|
"cartoon_3d",
|
|
16058
16895
|
"product_only",
|
|
16059
16896
|
"ai_dynamic"
|
|
16060
16897
|
]);
|
|
16061
|
-
var NarrativeStyleEnum =
|
|
16898
|
+
var NarrativeStyleEnum = z73.enum([
|
|
16062
16899
|
"review",
|
|
16063
16900
|
"ugc_how_to",
|
|
16064
16901
|
"problem_product_cta",
|
|
@@ -16076,7 +16913,7 @@ var NarrativeStyleEnum = z69.enum([
|
|
|
16076
16913
|
"ugc_demo_review",
|
|
16077
16914
|
"market"
|
|
16078
16915
|
]);
|
|
16079
|
-
var PublicNarrativeStyleEnum =
|
|
16916
|
+
var PublicNarrativeStyleEnum = z73.enum([
|
|
16080
16917
|
"review",
|
|
16081
16918
|
"ugc_how_to",
|
|
16082
16919
|
"ugc_unboxing_chaos",
|
|
@@ -16089,7 +16926,7 @@ var PublicNarrativeStyleEnum = z69.enum([
|
|
|
16089
16926
|
"sassy_product_pixar",
|
|
16090
16927
|
"market"
|
|
16091
16928
|
]);
|
|
16092
|
-
var
|
|
16929
|
+
var TaskVideoModelEnum = z73.enum([
|
|
16093
16930
|
"veo",
|
|
16094
16931
|
"wan",
|
|
16095
16932
|
"bytedance",
|
|
@@ -16097,29 +16934,29 @@ var VideoModelEnum = z69.enum([
|
|
|
16097
16934
|
"grok",
|
|
16098
16935
|
"kling"
|
|
16099
16936
|
]);
|
|
16100
|
-
var ProductReferenceUserChoiceEnum =
|
|
16937
|
+
var ProductReferenceUserChoiceEnum = z73.enum([
|
|
16101
16938
|
"same_product",
|
|
16102
16939
|
"variants",
|
|
16103
16940
|
"different_products",
|
|
16104
16941
|
"combo_distinct"
|
|
16105
16942
|
]);
|
|
16106
|
-
var ProductReferenceCandidateGroupingEnum =
|
|
16943
|
+
var ProductReferenceCandidateGroupingEnum = z73.enum([
|
|
16107
16944
|
"same_product_same_variant",
|
|
16108
16945
|
"same_product_different_variants",
|
|
16109
16946
|
"different_products",
|
|
16110
16947
|
"unclear"
|
|
16111
16948
|
]);
|
|
16112
|
-
var ProductReferenceScopeEnum =
|
|
16949
|
+
var ProductReferenceScopeEnum = z73.enum([
|
|
16113
16950
|
"base",
|
|
16114
16951
|
"video_view_pack"
|
|
16115
16952
|
]);
|
|
16116
|
-
var ProductReferenceResolutionDecisionEnum =
|
|
16953
|
+
var ProductReferenceResolutionDecisionEnum = z73.enum([
|
|
16117
16954
|
"approve",
|
|
16118
16955
|
"reject",
|
|
16119
16956
|
"observed_only",
|
|
16120
16957
|
"correct_view"
|
|
16121
16958
|
]);
|
|
16122
|
-
var ProductReferenceRejectionReasonEnum =
|
|
16959
|
+
var ProductReferenceRejectionReasonEnum = z73.enum([
|
|
16123
16960
|
"replacement_requested",
|
|
16124
16961
|
"wrong_product_identity",
|
|
16125
16962
|
"wrong_variant",
|
|
@@ -16130,13 +16967,13 @@ var ProductReferenceRejectionReasonEnum = z69.enum([
|
|
|
16130
16967
|
"not_a_product_photo",
|
|
16131
16968
|
"other"
|
|
16132
16969
|
]);
|
|
16133
|
-
var GapDurationChoiceMirror =
|
|
16134
|
-
angleIndex:
|
|
16135
|
-
recommendedSec:
|
|
16136
|
-
|
|
16137
|
-
|
|
16970
|
+
var GapDurationChoiceMirror = z73.object({
|
|
16971
|
+
angleIndex: z73.number().int().nonnegative(),
|
|
16972
|
+
recommendedSec: z73.union([
|
|
16973
|
+
z73.literal(15),
|
|
16974
|
+
z73.literal(30)
|
|
16138
16975
|
]),
|
|
16139
|
-
estimatedDeltaCredits:
|
|
16976
|
+
estimatedDeltaCredits: z73.number().int().nonnegative().optional()
|
|
16140
16977
|
});
|
|
16141
16978
|
function buildSelectedImageUrlsHash(urls) {
|
|
16142
16979
|
const input = [
|
|
@@ -16146,13 +16983,13 @@ function buildSelectedImageUrlsHash(urls) {
|
|
|
16146
16983
|
return `fnv1a:${hash.toString(16).padStart(8, "0")}:${urls.length}`;
|
|
16147
16984
|
}
|
|
16148
16985
|
__name(buildSelectedImageUrlsHash, "buildSelectedImageUrlsHash");
|
|
16149
|
-
var ImageCreativeStyleEnum =
|
|
16986
|
+
var ImageCreativeStyleEnum = z73.enum([
|
|
16150
16987
|
"studio",
|
|
16151
16988
|
"floating",
|
|
16152
16989
|
"ingredients",
|
|
16153
16990
|
"in_use"
|
|
16154
16991
|
]);
|
|
16155
|
-
var ImageCreativeArchetypeEnum =
|
|
16992
|
+
var ImageCreativeArchetypeEnum = z73.enum([
|
|
16156
16993
|
"direct_response_product_ad",
|
|
16157
16994
|
"hero_outcome",
|
|
16158
16995
|
"offer_value_prop",
|
|
@@ -16161,20 +16998,20 @@ var ImageCreativeArchetypeEnum = z69.enum([
|
|
|
16161
16998
|
"problem_solution",
|
|
16162
16999
|
"lifestyle_identity"
|
|
16163
17000
|
]);
|
|
16164
|
-
var ImageCreativeVisualTreatmentEnum =
|
|
17001
|
+
var ImageCreativeVisualTreatmentEnum = z73.enum([
|
|
16165
17002
|
"performance_product_ad",
|
|
16166
17003
|
"premium_dtc_carousel"
|
|
16167
17004
|
]);
|
|
16168
|
-
var ImageCreativeAspectRatioEnum =
|
|
17005
|
+
var ImageCreativeAspectRatioEnum = z73.enum([
|
|
16169
17006
|
"1:1",
|
|
16170
17007
|
"4:5",
|
|
16171
17008
|
"9:16",
|
|
16172
17009
|
"16:9"
|
|
16173
17010
|
]);
|
|
16174
|
-
var ImageRefSchema =
|
|
16175
|
-
url:
|
|
16176
|
-
path:
|
|
16177
|
-
assetId:
|
|
17011
|
+
var ImageRefSchema = z73.object({
|
|
17012
|
+
url: z73.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.'),
|
|
17013
|
+
path: z73.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`.'),
|
|
17014
|
+
assetId: z73.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.")
|
|
16178
17015
|
}).refine((v) => [
|
|
16179
17016
|
v.url,
|
|
16180
17017
|
v.path,
|
|
@@ -16182,11 +17019,11 @@ var ImageRefSchema = z69.object({
|
|
|
16182
17019
|
].filter(Boolean).length === 1, {
|
|
16183
17020
|
message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
|
|
16184
17021
|
});
|
|
16185
|
-
var ImagesInput =
|
|
17022
|
+
var ImagesInput = z73.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
|
|
16186
17023
|
const assetCount = images.filter((image) => Boolean(image.assetId)).length;
|
|
16187
17024
|
if (assetCount > 0 && assetCount !== images.length) {
|
|
16188
17025
|
ctx.addIssue({
|
|
16189
|
-
code:
|
|
17026
|
+
code: z73.ZodIssueCode.custom,
|
|
16190
17027
|
message: "all image entries must use assetId, or all must use URL/path sources"
|
|
16191
17028
|
});
|
|
16192
17029
|
}
|
|
@@ -16254,14 +17091,14 @@ async function submitCreative(api, opts) {
|
|
|
16254
17091
|
});
|
|
16255
17092
|
}
|
|
16256
17093
|
__name(submitCreative, "submitCreative");
|
|
16257
|
-
var ResearchTargetCountryEnum =
|
|
17094
|
+
var ResearchTargetCountryEnum = z73.enum([
|
|
16258
17095
|
"CO",
|
|
16259
17096
|
"MX",
|
|
16260
17097
|
"PE",
|
|
16261
17098
|
"EC",
|
|
16262
17099
|
"CL"
|
|
16263
17100
|
]);
|
|
16264
|
-
var ResearchCategoryEnum =
|
|
17101
|
+
var ResearchCategoryEnum = z73.enum([
|
|
16265
17102
|
"auto",
|
|
16266
17103
|
"automotive",
|
|
16267
17104
|
"kitchen",
|
|
@@ -16330,7 +17167,7 @@ var OVERWRITES_EXTERNAL = {
|
|
|
16330
17167
|
idempotentHint: false,
|
|
16331
17168
|
openWorldHint: false
|
|
16332
17169
|
};
|
|
16333
|
-
var DailyControlStatusEnum =
|
|
17170
|
+
var DailyControlStatusEnum = z73.enum([
|
|
16334
17171
|
"ok",
|
|
16335
17172
|
"sales_unavailable",
|
|
16336
17173
|
"timezone_unavailable",
|
|
@@ -16343,19 +17180,19 @@ var DailyControlStatusEnum = z69.enum([
|
|
|
16343
17180
|
"product_missing",
|
|
16344
17181
|
"store_unreachable"
|
|
16345
17182
|
]);
|
|
16346
|
-
var DailyControlLightEnum =
|
|
17183
|
+
var DailyControlLightEnum = z73.enum([
|
|
16347
17184
|
"green",
|
|
16348
17185
|
"amber",
|
|
16349
17186
|
"red",
|
|
16350
17187
|
"none"
|
|
16351
17188
|
]);
|
|
16352
|
-
var DailyControlVerdictEnum =
|
|
17189
|
+
var DailyControlVerdictEnum = z73.enum([
|
|
16353
17190
|
"scale",
|
|
16354
17191
|
"hold",
|
|
16355
17192
|
"kill",
|
|
16356
17193
|
"insufficient_sample"
|
|
16357
17194
|
]);
|
|
16358
|
-
var DailyControlSourceEnum =
|
|
17195
|
+
var DailyControlSourceEnum = z73.enum([
|
|
16359
17196
|
"shopify",
|
|
16360
17197
|
"shopify_settling",
|
|
16361
17198
|
"user",
|
|
@@ -17496,29 +18333,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
|
|
|
17496
18333
|
__name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
|
|
17497
18334
|
|
|
17498
18335
|
// src/tools/media-presentation.ts
|
|
17499
|
-
import { z as
|
|
17500
|
-
var HttpsPresentationUrlSchema =
|
|
18336
|
+
import { z as z74 } from "zod";
|
|
18337
|
+
var HttpsPresentationUrlSchema = z74.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
|
|
17501
18338
|
var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
|
|
17502
18339
|
const hostname = new URL(value).hostname.toLowerCase();
|
|
17503
18340
|
return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
|
|
17504
18341
|
}, "preview URL must be owned by ProductMaker");
|
|
17505
|
-
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) =>
|
|
17506
|
-
var PresentationImageSchema =
|
|
17507
|
-
kind:
|
|
18342
|
+
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z74.number().int().positive().max(maximum), "positiveIntAtMost");
|
|
18343
|
+
var PresentationImageSchema = z74.object({
|
|
18344
|
+
kind: z74.literal("image"),
|
|
17508
18345
|
url: HttpsPresentationUrlSchema,
|
|
17509
|
-
mimeType:
|
|
18346
|
+
mimeType: z74.enum([
|
|
17510
18347
|
"image/jpeg",
|
|
17511
18348
|
"image/png"
|
|
17512
18349
|
]),
|
|
17513
18350
|
byteSize: positiveIntAtMost(5 * 1024 * 1024),
|
|
17514
18351
|
width: positiveIntAtMost(16384),
|
|
17515
18352
|
height: positiveIntAtMost(16384),
|
|
17516
|
-
alt:
|
|
18353
|
+
alt: z74.string().trim().min(1).max(240)
|
|
17517
18354
|
}).strict();
|
|
17518
18355
|
var McpMediaPresentationSchema = PresentationImageSchema;
|
|
17519
|
-
var GalleryImageSchema =
|
|
18356
|
+
var GalleryImageSchema = z74.object({
|
|
17520
18357
|
url: ProductMakerPreviewUrlSchema,
|
|
17521
|
-
alt:
|
|
18358
|
+
alt: z74.string().trim().min(1).max(240)
|
|
17522
18359
|
});
|
|
17523
18360
|
var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
|
|
17524
18361
|
async function imageBlocks(image, transport) {
|
|
@@ -17668,10 +18505,10 @@ ${summary}`,
|
|
|
17668
18505
|
__name(requirePaidCreativeConfirmation, "requirePaidCreativeConfirmation");
|
|
17669
18506
|
|
|
17670
18507
|
// src/tools/winning-product-image.ts
|
|
17671
|
-
import { z as
|
|
17672
|
-
var WinnerReferenceInput =
|
|
17673
|
-
runId:
|
|
17674
|
-
candidateSourceId:
|
|
18508
|
+
import { z as z75 } from "zod";
|
|
18509
|
+
var WinnerReferenceInput = z75.object({
|
|
18510
|
+
runId: z75.string().uuid(),
|
|
18511
|
+
candidateSourceId: z75.string().trim().min(1).max(160)
|
|
17675
18512
|
}).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
|
|
17676
18513
|
async function resolveWinnerImages(api, winnerReference, images) {
|
|
17677
18514
|
if (!winnerReference) return images;
|
|
@@ -17708,189 +18545,190 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
|
|
|
17708
18545
|
var createServiceVideoGuidance = getProductMakerCapabilityModelGuidance("create_service_video");
|
|
17709
18546
|
var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
|
|
17710
18547
|
var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
|
|
17711
|
-
var CreateProductTaskInput =
|
|
18548
|
+
var CreateProductTaskInput = z76.object({
|
|
17712
18549
|
images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
|
|
17713
18550
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
17714
|
-
projectId:
|
|
17715
|
-
productUrl:
|
|
18551
|
+
projectId: z76.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
|
|
18552
|
+
productUrl: z76.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."),
|
|
17716
18553
|
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.'),
|
|
17717
18554
|
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.'),
|
|
17718
|
-
price:
|
|
17719
|
-
compareAtPrice:
|
|
17720
|
-
offer:
|
|
17721
|
-
paymentMethods:
|
|
17722
|
-
productContext:
|
|
17723
|
-
productLabel:
|
|
18555
|
+
price: z76.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.'),
|
|
18556
|
+
compareAtPrice: z76.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".'),
|
|
18557
|
+
offer: z76.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.'),
|
|
18558
|
+
paymentMethods: z76.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.'),
|
|
18559
|
+
productContext: z76.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."),
|
|
18560
|
+
productLabel: z76.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.'),
|
|
17724
18561
|
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), excepto "problem_solution", que requiere 30s Multiescena. Opciones: "auto", "ugc_dynamic" (review con experiencia y prueba), "ugc_how_to" (tutorial con pasos y resultado visible), "ugc_unboxing_chaos" (apertura y primera prueba), "problem_solution" (problema concreto, producto como soluci\xF3n y CTA), "product_showcase" (producto ejecutando una funci\xF3n real), "wearable_showcase" (prenda o accesorio modelado), "cinematic" (TV spot con receta cinematogr\xE1fica), "wild_card" (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.'),
|
|
17725
|
-
durationSeconds:
|
|
17726
|
-
|
|
17727
|
-
|
|
18562
|
+
durationSeconds: z76.union([
|
|
18563
|
+
z76.literal(15),
|
|
18564
|
+
z76.literal(30)
|
|
17728
18565
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
17729
|
-
pauseForAngleReview:
|
|
17730
|
-
aiDecidesAll:
|
|
18566
|
+
pauseForAngleReview: z76.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."),
|
|
18567
|
+
aiDecidesAll: z76.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."),
|
|
17731
18568
|
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.'),
|
|
17732
18569
|
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.'),
|
|
17733
18570
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
17734
18571
|
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).'),
|
|
17735
|
-
videoAngleCount:
|
|
18572
|
+
videoAngleCount: z76.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."),
|
|
17736
18573
|
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.'),
|
|
17737
|
-
outputs:
|
|
18574
|
+
outputs: z76.array(z76.enum([
|
|
17738
18575
|
"landing",
|
|
17739
18576
|
"video",
|
|
17740
18577
|
"image"
|
|
17741
18578
|
])).min(2).max(3).optional().describe(`Opcional. Qu\xE9 outputs generar. Default: todos ["landing","video","image"]. Para 2 outputs: ["landing","image"] (sin video), ["video","image"] (sin landing), ["landing","video"] (sin imagen). ${createProductTaskSingleOutputDescription}`),
|
|
17742
|
-
competitorScanEnabled:
|
|
17743
|
-
replicateWinnerWhenFound:
|
|
17744
|
-
brandId:
|
|
17745
|
-
actorId:
|
|
18579
|
+
competitorScanEnabled: z76.boolean().optional().describe("Opcional. Debe enviarse true solo despu\xE9s de que el usuario acepte estudiar la competencia (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. Omitir no autoriza el estudio profundo."),
|
|
18580
|
+
replicateWinnerWhenFound: z76.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."),
|
|
18581
|
+
brandId: z76.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."),
|
|
18582
|
+
actorId: z76.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."),
|
|
17746
18583
|
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.'),
|
|
17747
|
-
creativeDirection:
|
|
17748
|
-
headline:
|
|
17749
|
-
subheadline:
|
|
18584
|
+
creativeDirection: z76.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.'),
|
|
18585
|
+
headline: z76.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."),
|
|
18586
|
+
subheadline: z76.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."),
|
|
17750
18587
|
landingStrategy: LandingStrategyEnum.default("classic").describe('Opcional. Estructura de la landing cl\xE1sica cuando landing est\xE1 entre outputs: "classic" (estructura original probada y recomendada; default del primer rollout), "auto" (la IA decide; experimental), "pain_solution", "social_proof" (Landing Viral: UGC, WhatsApp, Instagram y evidencia social), "benefits_clarity", "offer_value" o "lifestyle_identity". Default "classic".'),
|
|
17751
18588
|
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".')
|
|
17752
18589
|
}).strict();
|
|
17753
|
-
var CreateServiceVideoInput =
|
|
17754
|
-
landingUrl:
|
|
17755
|
-
additionalContext:
|
|
18590
|
+
var CreateServiceVideoInput = z76.object({
|
|
18591
|
+
landingUrl: z76.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
|
|
18592
|
+
additionalContext: z76.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
|
|
17756
18593
|
language: Lang.describe("Idioma del video: es, en o pt."),
|
|
17757
|
-
voiceId:
|
|
17758
|
-
brandId:
|
|
17759
|
-
reviewMode:
|
|
18594
|
+
voiceId: z76.string().trim().min(1).optional().describe('Opcional. Voz de ElevenLabs para toda la narraci\xF3n. Usa "auto" para que la IA la alinee con el presentador o env\xEDa un ID concreto de la lista de voces de la web.'),
|
|
18595
|
+
brandId: z76.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
|
|
18596
|
+
reviewMode: z76.enum([
|
|
17760
18597
|
"automatic",
|
|
17761
18598
|
"guided"
|
|
17762
18599
|
]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
|
|
17763
|
-
videoPreset:
|
|
18600
|
+
videoPreset: z76.enum([
|
|
17764
18601
|
"auto",
|
|
17765
18602
|
"ugc_dynamic",
|
|
17766
18603
|
"ugc_how_to",
|
|
17767
18604
|
"cinematic",
|
|
17768
18605
|
"wild_card"
|
|
17769
18606
|
]).default("auto"),
|
|
17770
|
-
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.')
|
|
18607
|
+
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
18608
|
+
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.')
|
|
17771
18609
|
}).strict();
|
|
17772
|
-
var GetTaskStatusInput =
|
|
17773
|
-
taskId:
|
|
17774
|
-
waitSeconds:
|
|
18610
|
+
var GetTaskStatusInput = z76.object({
|
|
18611
|
+
taskId: z76.string().min(1),
|
|
18612
|
+
waitSeconds: z76.number().int().min(0).max(120).optional()
|
|
17775
18613
|
});
|
|
17776
|
-
var ListTasksInput =
|
|
17777
|
-
limit:
|
|
17778
|
-
offset:
|
|
17779
|
-
search:
|
|
18614
|
+
var ListTasksInput = z76.object({
|
|
18615
|
+
limit: z76.number().int().min(1).max(50).optional(),
|
|
18616
|
+
offset: z76.number().int().min(0).optional(),
|
|
18617
|
+
search: z76.string().optional()
|
|
17780
18618
|
});
|
|
17781
18619
|
var MCP_REVIEW_LIST_FIELD_MAX = 1500;
|
|
17782
18620
|
var MCP_REVIEW_FEATURE_ITEM_MAX = 240;
|
|
17783
|
-
var EditTaskDraftInput =
|
|
17784
|
-
taskId:
|
|
17785
|
-
angleIndex:
|
|
17786
|
-
angle:
|
|
17787
|
-
angle:
|
|
17788
|
-
buyerPersona:
|
|
17789
|
-
actor:
|
|
17790
|
-
actorId:
|
|
17791
|
-
gender:
|
|
18621
|
+
var EditTaskDraftInput = z76.object({
|
|
18622
|
+
taskId: z76.string().min(1),
|
|
18623
|
+
angleIndex: z76.number().int().min(0),
|
|
18624
|
+
angle: z76.object({
|
|
18625
|
+
angle: z76.string().min(1).max(480),
|
|
18626
|
+
buyerPersona: z76.string().min(1).max(360),
|
|
18627
|
+
actor: z76.string().min(1).max(360).optional(),
|
|
18628
|
+
actorId: z76.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."),
|
|
18629
|
+
gender: z76.enum([
|
|
17792
18630
|
"female",
|
|
17793
18631
|
"male"
|
|
17794
18632
|
]).optional(),
|
|
17795
|
-
scriptNotes:
|
|
18633
|
+
scriptNotes: z76.string().max(2e3).optional()
|
|
17796
18634
|
})
|
|
17797
18635
|
});
|
|
17798
|
-
var PendingActionPayload =
|
|
17799
|
-
|
|
17800
|
-
kind:
|
|
18636
|
+
var PendingActionPayload = z76.discriminatedUnion("kind", [
|
|
18637
|
+
z76.object({
|
|
18638
|
+
kind: z76.literal("product_reference_set_approval"),
|
|
17801
18639
|
scope: ProductReferenceScopeEnum.optional(),
|
|
17802
|
-
scopeKey:
|
|
17803
|
-
scopeSnapshotId:
|
|
17804
|
-
expectedScopeHash:
|
|
18640
|
+
scopeKey: z76.string().min(1).max(120).optional(),
|
|
18641
|
+
scopeSnapshotId: z76.string().uuid().optional(),
|
|
18642
|
+
expectedScopeHash: z76.string().min(1).max(128).optional(),
|
|
17805
18643
|
decision: ProductReferenceResolutionDecisionEnum,
|
|
17806
18644
|
reason: ProductReferenceRejectionReasonEnum.optional(),
|
|
17807
|
-
affectedRefKeys:
|
|
17808
|
-
affectedPhotoNumbers:
|
|
17809
|
-
recoveryAction:
|
|
18645
|
+
affectedRefKeys: z76.array(z76.string().min(1).max(200)).min(1).optional(),
|
|
18646
|
+
affectedPhotoNumbers: z76.array(z76.number().int().positive()).min(1).optional(),
|
|
18647
|
+
recoveryAction: z76.enum([
|
|
17810
18648
|
"remove",
|
|
17811
18649
|
"replace",
|
|
17812
18650
|
"upload",
|
|
17813
18651
|
"return_to_selection"
|
|
17814
18652
|
]).optional()
|
|
17815
18653
|
}),
|
|
17816
|
-
|
|
17817
|
-
kind:
|
|
17818
|
-
selectedPhotoNumbers:
|
|
18654
|
+
z76.object({
|
|
18655
|
+
kind: z76.literal("product_reference_confirmation"),
|
|
18656
|
+
selectedPhotoNumbers: z76.array(z76.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."),
|
|
17819
18657
|
userChoice: ProductReferenceUserChoiceEnum.optional(),
|
|
17820
|
-
confirmedProductNames:
|
|
18658
|
+
confirmedProductNames: z76.array(z76.string().min(1).max(120)).min(2).max(8).optional(),
|
|
17821
18659
|
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."),
|
|
17822
18660
|
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."),
|
|
17823
|
-
useMultiSceneShowcase:
|
|
18661
|
+
useMultiSceneShowcase: z76.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
|
|
17824
18662
|
}),
|
|
17825
|
-
|
|
17826
|
-
kind:
|
|
18663
|
+
z76.object({
|
|
18664
|
+
kind: z76.literal("angle_review_approval"),
|
|
17827
18665
|
// All edits are optional — empty action body just approves the
|
|
17828
18666
|
// backend-generated draft as-is. Field shapes mirror the angle-review
|
|
17829
18667
|
// request contracts in @packages/types/wizard.ts; the handler routes to
|
|
17830
18668
|
// the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
|
|
17831
|
-
customAngle:
|
|
18669
|
+
customAngle: z76.string().min(1).max(480).optional(),
|
|
17832
18670
|
// Keep the shared MCP action within the strictest downstream contract:
|
|
17833
18671
|
// autopilot/image resume endpoints cap these fields at 1500 characters.
|
|
17834
|
-
painPoints:
|
|
17835
|
-
benefits:
|
|
18672
|
+
painPoints: z76.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
18673
|
+
benefits: z76.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
17836
18674
|
// Same policy as the two fields above: the strictest downstream contract
|
|
17837
18675
|
// wins. The image endpoint caps each feature at 240 while landing/video
|
|
17838
18676
|
// accept 300, and this single action routes to whichever the task is — so
|
|
17839
18677
|
// accepting 300 here turns a 250-character feature on an image task into
|
|
17840
18678
|
// an opaque HTTP 400 after the model already believed it had been saved.
|
|
17841
|
-
features:
|
|
17842
|
-
buyerPersona:
|
|
18679
|
+
features: z76.array(z76.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
|
|
18680
|
+
buyerPersona: z76.string().min(1).max(360).optional(),
|
|
17843
18681
|
narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n) requiere Multiescena de 30s: en un video de 15s en formato Un solo clip el servidor la rechaza.'),
|
|
17844
|
-
actor:
|
|
17845
|
-
actorId:
|
|
17846
|
-
creativeDirection:
|
|
17847
|
-
selectedAngleNumbers:
|
|
17848
|
-
angleEdits:
|
|
17849
|
-
angleNumber:
|
|
17850
|
-
narrativeSelection:
|
|
18682
|
+
actor: z76.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."),
|
|
18683
|
+
actorId: z76.string().max(120).nullable().optional(),
|
|
18684
|
+
creativeDirection: z76.string().max(2e3).optional(),
|
|
18685
|
+
selectedAngleNumbers: z76.array(z76.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."),
|
|
18686
|
+
angleEdits: z76.array(z76.object({
|
|
18687
|
+
angleNumber: z76.number().int().positive(),
|
|
18688
|
+
narrativeSelection: z76.enum([
|
|
17851
18689
|
"market",
|
|
17852
18690
|
"guided"
|
|
17853
18691
|
]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
|
|
17854
|
-
angle:
|
|
17855
|
-
buyerPersona:
|
|
18692
|
+
angle: z76.string().min(1).max(480).optional(),
|
|
18693
|
+
buyerPersona: z76.string().min(1).max(360).optional(),
|
|
17856
18694
|
narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n) requiere Multiescena de 30s: en un video de 15s en formato Un solo clip el servidor la rechaza.'),
|
|
17857
|
-
actor:
|
|
17858
|
-
actorId:
|
|
17859
|
-
creativeDirection:
|
|
18695
|
+
actor: z76.string().min(1).max(360).optional(),
|
|
18696
|
+
actorId: z76.string().max(120).nullable().optional(),
|
|
18697
|
+
creativeDirection: z76.string().max(2e3).optional()
|
|
17860
18698
|
}).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)."),
|
|
17861
|
-
gapDurationSeconds:
|
|
17862
|
-
|
|
17863
|
-
|
|
18699
|
+
gapDurationSeconds: z76.union([
|
|
18700
|
+
z76.literal(15),
|
|
18701
|
+
z76.literal(30)
|
|
17864
18702
|
]).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.")
|
|
17865
18703
|
}),
|
|
17866
|
-
|
|
17867
|
-
kind:
|
|
17868
|
-
angleId:
|
|
17869
|
-
angleNumber:
|
|
17870
|
-
content:
|
|
17871
|
-
creativeDirection:
|
|
17872
|
-
actor:
|
|
18704
|
+
z76.object({
|
|
18705
|
+
kind: z76.literal("service_angle_approval"),
|
|
18706
|
+
angleId: z76.string().uuid().optional(),
|
|
18707
|
+
angleNumber: z76.number().int().positive().optional(),
|
|
18708
|
+
content: z76.string().min(1).max(480).optional(),
|
|
18709
|
+
creativeDirection: z76.string().min(1).max(1500).optional(),
|
|
18710
|
+
actor: z76.string().min(1).max(360).optional()
|
|
17873
18711
|
}),
|
|
17874
|
-
|
|
17875
|
-
kind:
|
|
17876
|
-
voiceovers:
|
|
17877
|
-
visualDirections:
|
|
17878
|
-
voiceoversByScene:
|
|
17879
|
-
visualDirectionsByScene:
|
|
18712
|
+
z76.object({
|
|
18713
|
+
kind: z76.literal("service_script_approval"),
|
|
18714
|
+
voiceovers: z76.record(z76.string(), z76.string().min(1).max(600)).optional(),
|
|
18715
|
+
visualDirections: z76.record(z76.string(), z76.string().min(1).max(1200)).optional(),
|
|
18716
|
+
voiceoversByScene: z76.record(z76.string(), z76.string().min(1).max(600)).optional(),
|
|
18717
|
+
visualDirectionsByScene: z76.record(z76.string(), z76.string().min(1).max(1200)).optional()
|
|
17880
18718
|
})
|
|
17881
18719
|
]);
|
|
17882
|
-
var ResolvePendingActionInput =
|
|
17883
|
-
taskId:
|
|
18720
|
+
var ResolvePendingActionInput = z76.object({
|
|
18721
|
+
taskId: z76.string().min(1),
|
|
17884
18722
|
action: PendingActionPayload
|
|
17885
18723
|
}).strict();
|
|
17886
18724
|
function resolveVariantConfirmVideoTier(action) {
|
|
17887
18725
|
return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
|
|
17888
18726
|
}
|
|
17889
18727
|
__name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
|
|
17890
|
-
var StatusForResolveSchema =
|
|
18728
|
+
var StatusForResolveSchema = z76.object({
|
|
17891
18729
|
// Metadata used to select the backend resume contract. Older API responses
|
|
17892
18730
|
// may omit these fields, so the resolver keeps the generic fallback.
|
|
17893
|
-
kind:
|
|
18731
|
+
kind: z76.enum([
|
|
17894
18732
|
"autopilot",
|
|
17895
18733
|
"video",
|
|
17896
18734
|
"image",
|
|
@@ -17898,18 +18736,18 @@ var StatusForResolveSchema = z72.object({
|
|
|
17898
18736
|
"mix",
|
|
17899
18737
|
"service"
|
|
17900
18738
|
]).optional(),
|
|
17901
|
-
selectedOutputs:
|
|
18739
|
+
selectedOutputs: z76.array(z76.enum([
|
|
17902
18740
|
"landing",
|
|
17903
18741
|
"video",
|
|
17904
18742
|
"image"
|
|
17905
18743
|
])).optional(),
|
|
17906
|
-
videoAngleCount:
|
|
17907
|
-
ugcFormat:
|
|
18744
|
+
videoAngleCount: z76.number().int().min(1).max(3).optional(),
|
|
18745
|
+
ugcFormat: z76.enum([
|
|
17908
18746
|
"single_8s",
|
|
17909
18747
|
"single_15s",
|
|
17910
18748
|
"double_30s"
|
|
17911
18749
|
]).optional(),
|
|
17912
|
-
videoStyle:
|
|
18750
|
+
videoStyle: z76.enum([
|
|
17913
18751
|
"ugc",
|
|
17914
18752
|
"cartoon_3d",
|
|
17915
18753
|
"product_only",
|
|
@@ -17918,79 +18756,72 @@ var StatusForResolveSchema = z72.object({
|
|
|
17918
18756
|
videoStructure: VideoStructureEnum.optional(),
|
|
17919
18757
|
videoQuality: VideoQualityEnum.optional(),
|
|
17920
18758
|
videoRouteId: VideoRouteIdEnum.optional(),
|
|
17921
|
-
videoModel:
|
|
17922
|
-
|
|
17923
|
-
"wan",
|
|
17924
|
-
"bytedance",
|
|
17925
|
-
"seedance",
|
|
17926
|
-
"grok",
|
|
17927
|
-
"kling"
|
|
17928
|
-
]).optional(),
|
|
17929
|
-
videoTier: z72.enum([
|
|
18759
|
+
videoModel: TaskVideoModelEnum.optional(),
|
|
18760
|
+
videoTier: z76.enum([
|
|
17930
18761
|
"legacy",
|
|
17931
18762
|
"standard",
|
|
17932
18763
|
"pro",
|
|
17933
18764
|
"single_call"
|
|
17934
18765
|
]).optional(),
|
|
17935
|
-
videoResolution:
|
|
18766
|
+
videoResolution: z76.enum([
|
|
17936
18767
|
"480p",
|
|
17937
18768
|
"720p"
|
|
17938
18769
|
]).optional(),
|
|
17939
18770
|
narrativeStyle: NarrativeStyleEnum.optional(),
|
|
17940
|
-
pauseForVideoScriptReview:
|
|
17941
|
-
pendingUserAction:
|
|
17942
|
-
kind:
|
|
17943
|
-
candidateGrouping:
|
|
17944
|
-
selectedImageUrls:
|
|
17945
|
-
proposedProductNames:
|
|
18771
|
+
pauseForVideoScriptReview: z76.boolean().optional(),
|
|
18772
|
+
pendingUserAction: z76.object({
|
|
18773
|
+
kind: z76.string(),
|
|
18774
|
+
candidateGrouping: z76.string().optional(),
|
|
18775
|
+
selectedImageUrls: z76.array(z76.string()).optional(),
|
|
18776
|
+
proposedProductNames: z76.array(z76.string()).optional(),
|
|
17946
18777
|
// Adaptive reference questions are server-owned. Echo only the evidence
|
|
17947
18778
|
// identity and the choices shown by the current snapshot; never accept a
|
|
17948
18779
|
// client-supplied reference set as authorization.
|
|
17949
|
-
options:
|
|
17950
|
-
mode:
|
|
18780
|
+
options: z76.array(ProductReferenceUserChoiceEnum).max(4).optional(),
|
|
18781
|
+
mode: z76.enum([
|
|
17951
18782
|
"question",
|
|
17952
18783
|
"visual_recovery"
|
|
17953
18784
|
]).optional(),
|
|
17954
18785
|
/** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
|
|
17955
|
-
canKeepSelection:
|
|
17956
|
-
decisionKey:
|
|
17957
|
-
questionOrdinal:
|
|
17958
|
-
questionCeiling:
|
|
17959
|
-
|
|
17960
|
-
|
|
18786
|
+
canKeepSelection: z76.boolean().optional(),
|
|
18787
|
+
decisionKey: z76.string().optional(),
|
|
18788
|
+
questionOrdinal: z76.number().int().min(1).max(5).optional(),
|
|
18789
|
+
questionCeiling: z76.union([
|
|
18790
|
+
z76.literal(3),
|
|
18791
|
+
z76.literal(5)
|
|
17961
18792
|
]).optional(),
|
|
17962
|
-
referenceEvidenceVersion:
|
|
17963
|
-
expectedEvidenceHash:
|
|
17964
|
-
question:
|
|
17965
|
-
prompt:
|
|
17966
|
-
helpText:
|
|
17967
|
-
options:
|
|
18793
|
+
referenceEvidenceVersion: z76.number().int().positive().optional(),
|
|
18794
|
+
expectedEvidenceHash: z76.string().optional(),
|
|
18795
|
+
question: z76.object({
|
|
18796
|
+
prompt: z76.string().min(1).max(240),
|
|
18797
|
+
helpText: z76.string().min(1).max(300).optional(),
|
|
18798
|
+
options: z76.array(z76.object({
|
|
17968
18799
|
value: ProductReferenceUserChoiceEnum,
|
|
17969
|
-
label:
|
|
17970
|
-
description:
|
|
18800
|
+
label: z76.string().min(1).max(120),
|
|
18801
|
+
description: z76.string().min(1).max(240).optional()
|
|
17971
18802
|
})).min(2).max(4)
|
|
17972
18803
|
}).optional(),
|
|
17973
18804
|
scope: ProductReferenceScopeEnum.optional(),
|
|
17974
|
-
scopeKey:
|
|
17975
|
-
scopeSnapshotId:
|
|
17976
|
-
scopeHash:
|
|
17977
|
-
baseReferenceSetHash:
|
|
17978
|
-
phase:
|
|
18805
|
+
scopeKey: z76.string().optional(),
|
|
18806
|
+
scopeSnapshotId: z76.string().uuid().optional(),
|
|
18807
|
+
scopeHash: z76.string().optional(),
|
|
18808
|
+
baseReferenceSetHash: z76.string().optional(),
|
|
18809
|
+
phase: z76.enum([
|
|
17979
18810
|
"preparation",
|
|
17980
18811
|
"final"
|
|
17981
18812
|
]).optional(),
|
|
17982
|
-
selectedRefKeys:
|
|
17983
|
-
allowedDecisions:
|
|
17984
|
-
previews:
|
|
17985
|
-
refKey:
|
|
18813
|
+
selectedRefKeys: z76.array(z76.string().min(1).max(200)).optional(),
|
|
18814
|
+
allowedDecisions: z76.array(ProductReferenceResolutionDecisionEnum).optional(),
|
|
18815
|
+
previews: z76.array(z76.object({
|
|
18816
|
+
refKey: z76.string().min(1).max(200)
|
|
17986
18817
|
}).passthrough()).optional(),
|
|
17987
|
-
customAngleDraft:
|
|
17988
|
-
painPointsDraft:
|
|
17989
|
-
benefitsDraft:
|
|
17990
|
-
featuresDraft:
|
|
17991
|
-
angleOptions:
|
|
17992
|
-
index:
|
|
17993
|
-
angle:
|
|
18818
|
+
customAngleDraft: z76.string().optional(),
|
|
18819
|
+
painPointsDraft: z76.string().optional(),
|
|
18820
|
+
benefitsDraft: z76.string().optional(),
|
|
18821
|
+
featuresDraft: z76.array(z76.string()).optional(),
|
|
18822
|
+
angleOptions: z76.array(z76.object({
|
|
18823
|
+
index: z76.number().int().nonnegative(),
|
|
18824
|
+
angle: z76.string().min(1)
|
|
17994
18825
|
}).passthrough()).min(1).max(5).optional(),
|
|
17995
18826
|
// Recommendation consumed only when the caller explicitly sends
|
|
17996
18827
|
// gapDurationSeconds: 30 in the angle approval action.
|
|
@@ -18000,17 +18831,17 @@ var StatusForResolveSchema = z72.object({
|
|
|
18000
18831
|
// keys. `actorId` (the saved custom actor the picker stored) was silently
|
|
18001
18832
|
// dropped here, so the approval handler below could not echo it back on the
|
|
18002
18833
|
// PATCH — the selection looked accepted and reached no render.
|
|
18003
|
-
angles:
|
|
18004
|
-
id:
|
|
18005
|
-
content:
|
|
18006
|
-
creativeDirection:
|
|
18007
|
-
actor:
|
|
18008
|
-
actorId:
|
|
18834
|
+
angles: z76.array(z76.object({
|
|
18835
|
+
id: z76.string().uuid(),
|
|
18836
|
+
content: z76.string(),
|
|
18837
|
+
creativeDirection: z76.string(),
|
|
18838
|
+
actor: z76.string(),
|
|
18839
|
+
actorId: z76.string().nullable().optional()
|
|
18009
18840
|
}).passthrough()).optional(),
|
|
18010
|
-
panels:
|
|
18011
|
-
beatId:
|
|
18012
|
-
voiceover:
|
|
18013
|
-
visualDirection:
|
|
18841
|
+
panels: z76.array(z76.object({
|
|
18842
|
+
beatId: z76.string(),
|
|
18843
|
+
voiceover: z76.string(),
|
|
18844
|
+
visualDirection: z76.string()
|
|
18014
18845
|
}).passthrough()).optional()
|
|
18015
18846
|
}).optional()
|
|
18016
18847
|
}).passthrough();
|
|
@@ -18224,6 +19055,9 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
18224
19055
|
});
|
|
18225
19056
|
server.tool("create_service_video", createServiceVideoGuidance.summary + " Esta acci\xF3n consume cr\xE9ditos: confirma la intenci\xF3n del usuario antes de llamarla. `automatic` genera directamente; `guided` devuelve conceptos para que el usuario apruebe uno mediante `resolve_pending_action`. La web tambi\xE9n acepta demos y anuncios de referencia; el transporte MCP de video adjunto todav\xEDa falla cerrado hasta poder subir bytes de forma segura.", CreateServiceVideoInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
|
|
18226
19057
|
try {
|
|
19058
|
+
if (input.videoQuality === "medium" && input.videoResolution === "720p") {
|
|
19059
|
+
throw mcp(McpErrorCode.INVALID_INPUT, 'videoResolution "720p" no est\xE1 disponible con videoQuality "medium" en videos de servicio (Medio = 768P). Usa "480p" o elige "economy"/"pro".');
|
|
19060
|
+
}
|
|
18227
19061
|
await requirePaidCreativeConfirmation(server, `Video de servicio en ${input.language}. Modo: ${input.reviewMode === "automatic" ? "la IA decide todo" : "reviews conversacionales"}.`);
|
|
18228
19062
|
const created = await api.postJson("/v2/ingest", {
|
|
18229
19063
|
taskType: "service",
|
|
@@ -18237,6 +19071,7 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
18237
19071
|
} : {},
|
|
18238
19072
|
videoPreset: input.videoPreset,
|
|
18239
19073
|
videoQuality: input.videoQuality,
|
|
19074
|
+
videoResolution: input.videoResolution,
|
|
18240
19075
|
reviewMode: input.reviewMode,
|
|
18241
19076
|
...input.brandId ? {
|
|
18242
19077
|
brandId: input.brandId
|
|
@@ -18841,7 +19676,7 @@ __name(registerTaskTools, "registerTaskTools");
|
|
|
18841
19676
|
|
|
18842
19677
|
// src/tools/creatives.ts
|
|
18843
19678
|
import { randomUUID } from "crypto";
|
|
18844
|
-
import { z as
|
|
19679
|
+
import { z as z77 } from "zod";
|
|
18845
19680
|
var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
|
|
18846
19681
|
var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
|
|
18847
19682
|
var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
|
|
@@ -18851,70 +19686,70 @@ var CreativeRefs = {
|
|
|
18851
19686
|
images: ImagesInput,
|
|
18852
19687
|
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.'),
|
|
18853
19688
|
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.'),
|
|
18854
|
-
price:
|
|
18855
|
-
offer:
|
|
18856
|
-
compareAtPrice:
|
|
18857
|
-
productContext:
|
|
18858
|
-
productLabel:
|
|
18859
|
-
buyerPersona:
|
|
18860
|
-
isCombo:
|
|
18861
|
-
competitorScanEnabled:
|
|
18862
|
-
brandId:
|
|
19689
|
+
price: z77.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.'),
|
|
19690
|
+
offer: z77.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.'),
|
|
19691
|
+
compareAtPrice: z77.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
|
|
19692
|
+
productContext: z77.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."),
|
|
19693
|
+
productLabel: z77.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.'),
|
|
19694
|
+
buyerPersona: z77.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.'),
|
|
19695
|
+
isCombo: z77.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
|
|
19696
|
+
competitorScanEnabled: z77.boolean().optional().describe("Opcional. Debe enviarse true solo despu\xE9s de que el usuario acepte estudiar la competencia (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. Omitir no autoriza el estudio profundo."),
|
|
19697
|
+
brandId: z77.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.")
|
|
18863
19698
|
};
|
|
18864
|
-
var VideoPresenter =
|
|
18865
|
-
|
|
18866
|
-
mode:
|
|
19699
|
+
var VideoPresenter = z77.discriminatedUnion("mode", [
|
|
19700
|
+
z77.object({
|
|
19701
|
+
mode: z77.literal("none")
|
|
18867
19702
|
}).strict(),
|
|
18868
|
-
|
|
18869
|
-
mode:
|
|
18870
|
-
actorId:
|
|
19703
|
+
z77.object({
|
|
19704
|
+
mode: z77.literal("saved_actor"),
|
|
19705
|
+
actorId: z77.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
|
|
18871
19706
|
}).strict(),
|
|
18872
|
-
|
|
18873
|
-
mode:
|
|
18874
|
-
description:
|
|
19707
|
+
z77.object({
|
|
19708
|
+
mode: z77.literal("described"),
|
|
19709
|
+
description: z77.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
|
|
18875
19710
|
}).strict()
|
|
18876
19711
|
]);
|
|
18877
|
-
var VideoCreativeSetup =
|
|
18878
|
-
|
|
18879
|
-
mode:
|
|
19712
|
+
var VideoCreativeSetup = z77.discriminatedUnion("mode", [
|
|
19713
|
+
z77.object({
|
|
19714
|
+
mode: z77.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
|
|
18880
19715
|
}).strict(),
|
|
18881
|
-
|
|
18882
|
-
mode:
|
|
19716
|
+
z77.object({
|
|
19717
|
+
mode: z77.literal("guided"),
|
|
18883
19718
|
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. "problem_solution" requiere 30s.'),
|
|
18884
|
-
buyerPersona:
|
|
19719
|
+
buyerPersona: z77.string().trim().min(1).max(360),
|
|
18885
19720
|
presenter: VideoPresenter,
|
|
18886
|
-
creativeDirection:
|
|
19721
|
+
creativeDirection: z77.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
|
|
18887
19722
|
}).strict()
|
|
18888
19723
|
]);
|
|
18889
|
-
var VideoInput =
|
|
19724
|
+
var VideoInput = z77.object({
|
|
18890
19725
|
images: CreativeRefs.images.optional(),
|
|
18891
19726
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
18892
|
-
title:
|
|
18893
|
-
primaryAngle:
|
|
19727
|
+
title: z77.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
|
|
19728
|
+
primaryAngle: z77.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".'),
|
|
18894
19729
|
language: CreativeRefs.language,
|
|
18895
19730
|
country: CreativeRefs.country,
|
|
18896
|
-
aspectRatio:
|
|
19731
|
+
aspectRatio: z77.enum([
|
|
18897
19732
|
"9:16",
|
|
18898
19733
|
"16:9",
|
|
18899
19734
|
"Auto"
|
|
18900
19735
|
]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
|
|
18901
|
-
durationSeconds:
|
|
18902
|
-
videoAngleCount:
|
|
19736
|
+
durationSeconds: z77.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."),
|
|
19737
|
+
videoAngleCount: z77.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."),
|
|
18903
19738
|
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.'),
|
|
18904
19739
|
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."),
|
|
18905
19740
|
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.'),
|
|
18906
19741
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
|
|
18907
19742
|
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.'),
|
|
18908
|
-
features:
|
|
19743
|
+
features: z77.array(z77.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
|
|
18909
19744
|
price: CreativeRefs.price,
|
|
18910
19745
|
offer: CreativeRefs.offer,
|
|
18911
19746
|
productContext: CreativeRefs.productContext,
|
|
18912
19747
|
productLabel: CreativeRefs.productLabel,
|
|
18913
|
-
cta:
|
|
18914
|
-
scriptNotes:
|
|
19748
|
+
cta: z77.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.'),
|
|
19749
|
+
scriptNotes: z77.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.'),
|
|
18915
19750
|
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.'),
|
|
18916
19751
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
18917
|
-
replicateWinnerWhenFound:
|
|
19752
|
+
replicateWinnerWhenFound: z77.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."),
|
|
18918
19753
|
brandId: CreativeRefs.brandId
|
|
18919
19754
|
}).strict();
|
|
18920
19755
|
var FreeVideoQualityEnum = VideoQualityEnum;
|
|
@@ -18932,7 +19767,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
|
|
|
18932
19767
|
length: 29
|
|
18933
19768
|
}, (_, index) => index + 2)
|
|
18934
19769
|
};
|
|
18935
|
-
var FreeVideoModelIdEnum =
|
|
19770
|
+
var FreeVideoModelIdEnum = z77.enum([
|
|
18936
19771
|
"grok-imagine-video-1-5-preview",
|
|
18937
19772
|
"minimax-h3/reference-to-video",
|
|
18938
19773
|
"wan/3-0-video",
|
|
@@ -18943,70 +19778,65 @@ var FREE_SELECTABLE_MODEL_IDS = [
|
|
|
18943
19778
|
"minimax-h3/reference-to-video",
|
|
18944
19779
|
"wan/3-0-video"
|
|
18945
19780
|
];
|
|
18946
|
-
var FreeVideoInput =
|
|
19781
|
+
var FreeVideoInput = z77.object({
|
|
18947
19782
|
images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
|
|
18948
|
-
rawPrompt:
|
|
19783
|
+
rawPrompt: z77.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."),
|
|
18949
19784
|
language: CreativeRefs.language,
|
|
18950
19785
|
quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
|
|
18951
19786
|
// Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
|
|
18952
19787
|
// parsed ONLY so the handler can reject it with a message naming its
|
|
18953
19788
|
// replacement — dropping it silently would turn a caller's explicit
|
|
18954
19789
|
// Pro++ pick into a quiet fallback to Wan.
|
|
18955
|
-
freeProModel:
|
|
19790
|
+
freeProModel: z77.enum([
|
|
18956
19791
|
"wan",
|
|
18957
19792
|
"seedance"
|
|
18958
19793
|
]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
|
|
18959
19794
|
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.'),
|
|
18960
|
-
durationSeconds:
|
|
19795
|
+
durationSeconds: z77.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."),
|
|
18961
19796
|
videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
|
|
18962
|
-
generateAiMusic:
|
|
18963
|
-
addSubtitles:
|
|
18964
|
-
idempotencyKey:
|
|
19797
|
+
generateAiMusic: z77.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
|
|
19798
|
+
addSubtitles: z77.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
|
|
19799
|
+
idempotencyKey: z77.string().uuid().optional().describe("Opcional. UUID para reintentar exactamente esta misma solicitud sin crear ni cobrar otro video. Reutiliza el mismo valor si el cliente no recibi\xF3 la respuesta.")
|
|
18965
19800
|
}).strict();
|
|
18966
19801
|
var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
|
|
18967
|
-
var ImageCreativeSetup =
|
|
18968
|
-
|
|
18969
|
-
mode:
|
|
19802
|
+
var ImageCreativeSetup = z77.discriminatedUnion("mode", [
|
|
19803
|
+
z77.object({
|
|
19804
|
+
mode: z77.literal("automatic")
|
|
18970
19805
|
}).strict(),
|
|
18971
|
-
|
|
18972
|
-
mode:
|
|
18973
|
-
creativeArchetype:
|
|
19806
|
+
z77.object({
|
|
19807
|
+
mode: z77.literal("guided"),
|
|
19808
|
+
creativeArchetype: z77.union([
|
|
18974
19809
|
ImageCreativeArchetypeEnum,
|
|
18975
|
-
|
|
19810
|
+
z77.literal("ai_decides")
|
|
18976
19811
|
]),
|
|
18977
|
-
visualTreatment:
|
|
19812
|
+
visualTreatment: z77.union([
|
|
18978
19813
|
ImageCreativeVisualTreatmentEnum,
|
|
18979
|
-
|
|
19814
|
+
z77.literal("ai_decides")
|
|
18980
19815
|
]),
|
|
18981
19816
|
aspectRatio: ImageCreativeAspectRatioEnum,
|
|
18982
|
-
nVariants:
|
|
18983
|
-
|
|
18984
|
-
|
|
18985
|
-
|
|
18986
|
-
|
|
18987
|
-
|
|
19817
|
+
nVariants: z77.union([
|
|
19818
|
+
z77.literal(1),
|
|
19819
|
+
z77.literal(2),
|
|
19820
|
+
z77.literal(3),
|
|
19821
|
+
z77.literal(4),
|
|
19822
|
+
z77.literal(6)
|
|
18988
19823
|
]),
|
|
18989
|
-
imageModel:
|
|
18990
|
-
|
|
18991
|
-
|
|
18992
|
-
|
|
18993
|
-
|
|
18994
|
-
|
|
18995
|
-
|
|
18996
|
-
|
|
18997
|
-
|
|
18998
|
-
productContext: z73.string().trim().min(1).max(3e3).nullable(),
|
|
18999
|
-
creativeDirection: z73.string().trim().min(1).max(500).nullable(),
|
|
19000
|
-
brandColors: z73.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.'),
|
|
19001
|
-
headline: z73.string().trim().min(1).max(120).nullable(),
|
|
19002
|
-
subheadline: z73.string().trim().min(1).max(160).nullable()
|
|
19824
|
+
imageModel: z77.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.'),
|
|
19825
|
+
styleMix: z77.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
|
|
19826
|
+
generateAdCopy: z77.boolean(),
|
|
19827
|
+
competitorScanEnabled: z77.boolean(),
|
|
19828
|
+
productContext: z77.string().trim().min(1).max(3e3).nullable(),
|
|
19829
|
+
creativeDirection: z77.string().trim().min(1).max(500).nullable(),
|
|
19830
|
+
brandColors: z77.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.'),
|
|
19831
|
+
headline: z77.string().trim().min(1).max(120).nullable(),
|
|
19832
|
+
subheadline: z77.string().trim().min(1).max(160).nullable()
|
|
19003
19833
|
}).strict()
|
|
19004
19834
|
]).superRefine((setup, context) => {
|
|
19005
19835
|
if (setup.mode !== "guided") return;
|
|
19006
19836
|
const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
|
|
19007
19837
|
if (needsStyleMix && setup.styleMix === null) {
|
|
19008
19838
|
context.addIssue({
|
|
19009
|
-
code:
|
|
19839
|
+
code: z77.ZodIssueCode.custom,
|
|
19010
19840
|
path: [
|
|
19011
19841
|
"styleMix"
|
|
19012
19842
|
],
|
|
@@ -19015,16 +19845,16 @@ var ImageCreativeSetup = z73.discriminatedUnion("mode", [
|
|
|
19015
19845
|
}
|
|
19016
19846
|
if (!needsStyleMix && setup.styleMix !== null) {
|
|
19017
19847
|
context.addIssue({
|
|
19018
|
-
code:
|
|
19848
|
+
code: z77.ZodIssueCode.custom,
|
|
19019
19849
|
path: [
|
|
19020
19850
|
"styleMix"
|
|
19021
19851
|
],
|
|
19022
19852
|
message: "styleMix debe ser null cuando nVariants es 1 o 6."
|
|
19023
19853
|
});
|
|
19024
19854
|
}
|
|
19025
|
-
if ((setup.imageModel === "
|
|
19855
|
+
if (imageResolutionOf(setup.imageModel) === "2k" && setup.aspectRatio === "4:5") {
|
|
19026
19856
|
context.addIssue({
|
|
19027
|
-
code:
|
|
19857
|
+
code: z77.ZodIssueCode.custom,
|
|
19028
19858
|
path: [
|
|
19029
19859
|
"aspectRatio"
|
|
19030
19860
|
],
|
|
@@ -19032,53 +19862,53 @@ var ImageCreativeSetup = z73.discriminatedUnion("mode", [
|
|
|
19032
19862
|
});
|
|
19033
19863
|
}
|
|
19034
19864
|
});
|
|
19035
|
-
var LandingCreativeSetup =
|
|
19036
|
-
|
|
19037
|
-
mode:
|
|
19865
|
+
var LandingCreativeSetup = z77.discriminatedUnion("mode", [
|
|
19866
|
+
z77.object({
|
|
19867
|
+
mode: z77.literal("automatic")
|
|
19038
19868
|
}).strict(),
|
|
19039
|
-
|
|
19040
|
-
mode:
|
|
19869
|
+
z77.object({
|
|
19870
|
+
mode: z77.literal("guided"),
|
|
19041
19871
|
landingStrategy: LandingStrategyEnum,
|
|
19042
19872
|
landingImageFormat: LandingImageFormatEnum,
|
|
19043
|
-
competitorScanEnabled:
|
|
19044
|
-
paymentMethods:
|
|
19045
|
-
productContext:
|
|
19046
|
-
creativeDirection:
|
|
19047
|
-
headline:
|
|
19048
|
-
subheadline:
|
|
19873
|
+
competitorScanEnabled: z77.boolean(),
|
|
19874
|
+
paymentMethods: z77.string().trim().min(1).max(240).nullable(),
|
|
19875
|
+
productContext: z77.string().trim().min(1).max(3e3).nullable(),
|
|
19876
|
+
creativeDirection: z77.string().trim().min(1).max(500).nullable(),
|
|
19877
|
+
headline: z77.string().trim().min(1).max(120).nullable(),
|
|
19878
|
+
subheadline: z77.string().trim().min(1).max(160).nullable()
|
|
19049
19879
|
}).strict()
|
|
19050
19880
|
]);
|
|
19051
|
-
var ImageInput =
|
|
19881
|
+
var ImageInput = z77.object({
|
|
19052
19882
|
images: CreativeRefs.images.optional(),
|
|
19053
19883
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
19054
|
-
productTitle:
|
|
19055
|
-
primaryAngle:
|
|
19884
|
+
productTitle: z77.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
|
|
19885
|
+
primaryAngle: z77.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.'),
|
|
19056
19886
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
19057
19887
|
language: CreativeRefs.language,
|
|
19058
19888
|
country: CreativeRefs.country,
|
|
19059
19889
|
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."),
|
|
19060
19890
|
imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
|
|
19061
|
-
features:
|
|
19891
|
+
features: z77.array(z77.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
|
|
19062
19892
|
price: CreativeRefs.price,
|
|
19063
|
-
omitPrice:
|
|
19893
|
+
omitPrice: z77.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."),
|
|
19064
19894
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
19065
19895
|
offer: CreativeRefs.offer,
|
|
19066
19896
|
productLabel: CreativeRefs.productLabel,
|
|
19067
19897
|
isCombo: CreativeRefs.isCombo,
|
|
19068
19898
|
brandId: CreativeRefs.brandId
|
|
19069
19899
|
});
|
|
19070
|
-
var EditImageCreativeInput =
|
|
19071
|
-
taskId:
|
|
19072
|
-
variantIndex:
|
|
19073
|
-
instruction:
|
|
19900
|
+
var EditImageCreativeInput = z77.object({
|
|
19901
|
+
taskId: z77.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
|
|
19902
|
+
variantIndex: z77.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
|
|
19903
|
+
instruction: z77.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".')
|
|
19074
19904
|
});
|
|
19075
|
-
var LandingInput =
|
|
19905
|
+
var LandingInput = z77.object({
|
|
19076
19906
|
images: CreativeRefs.images.optional(),
|
|
19077
19907
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
19078
19908
|
language: CreativeRefs.language,
|
|
19079
19909
|
country: CreativeRefs.country,
|
|
19080
19910
|
creativeSetup: LandingCreativeSetup.describe("Configuraci\xF3n obligatoria de landing cl\xE1sica equivalente al wizard web. No expone landing editable/code mientras siga siendo admin-only."),
|
|
19081
|
-
salesAngle:
|
|
19911
|
+
salesAngle: z77.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.'),
|
|
19082
19912
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
19083
19913
|
price: CreativeRefs.price,
|
|
19084
19914
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
@@ -19097,7 +19927,7 @@ function resolveImageSetup(setup) {
|
|
|
19097
19927
|
},
|
|
19098
19928
|
aspectRatio: setup.aspectRatio,
|
|
19099
19929
|
nVariants: setup.nVariants,
|
|
19100
|
-
imageModel: setup.imageModel,
|
|
19930
|
+
imageModel: canonicalImageModelInput(setup.imageModel),
|
|
19101
19931
|
...setup.nVariants === 6 ? {
|
|
19102
19932
|
styleMix: true
|
|
19103
19933
|
} : setup.styleMix === null ? {} : {
|
|
@@ -19340,10 +20170,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
19340
20170
|
__name(registerCreativeTools, "registerCreativeTools");
|
|
19341
20171
|
|
|
19342
20172
|
// src/tools/creative-variants.ts
|
|
19343
|
-
import { z as
|
|
20173
|
+
import { z as z78 } from "zod";
|
|
19344
20174
|
var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
|
|
19345
20175
|
var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
|
|
19346
|
-
var LandingSectionKeyEnum =
|
|
20176
|
+
var LandingSectionKeyEnum = z78.enum([
|
|
19347
20177
|
"problem_hook",
|
|
19348
20178
|
"problem_cost",
|
|
19349
20179
|
"solution_mechanism",
|
|
@@ -19383,24 +20213,24 @@ var LandingSectionKeyEnum = z74.enum([
|
|
|
19383
20213
|
"lifestyle_fit",
|
|
19384
20214
|
"join_lifestyle"
|
|
19385
20215
|
]);
|
|
19386
|
-
var CreativeVariantKindEnum =
|
|
20216
|
+
var CreativeVariantKindEnum = z78.enum([
|
|
19387
20217
|
"video",
|
|
19388
20218
|
"image",
|
|
19389
20219
|
"landing"
|
|
19390
20220
|
]);
|
|
19391
|
-
var EstimateCreativeVariantInputBase =
|
|
19392
|
-
sourceTaskId:
|
|
20221
|
+
var EstimateCreativeVariantInputBase = z78.object({
|
|
20222
|
+
sourceTaskId: z78.string().uuid().describe("ID de la tarea original completada."),
|
|
19393
20223
|
kind: CreativeVariantKindEnum,
|
|
19394
20224
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
|
|
19395
20225
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
|
|
19396
|
-
nVariants:
|
|
20226
|
+
nVariants: z78.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
19397
20227
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
|
|
19398
|
-
instructions:
|
|
20228
|
+
instructions: z78.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.")
|
|
19399
20229
|
}).strict();
|
|
19400
20230
|
var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
19401
20231
|
if (input.kind === "video" && input.nVariants !== void 0) {
|
|
19402
20232
|
ctx.addIssue({
|
|
19403
|
-
code:
|
|
20233
|
+
code: z78.ZodIssueCode.custom,
|
|
19404
20234
|
path: [
|
|
19405
20235
|
"nVariants"
|
|
19406
20236
|
],
|
|
@@ -19410,7 +20240,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19410
20240
|
if (input.kind !== "video") {
|
|
19411
20241
|
if (input.videoPreset !== void 0) {
|
|
19412
20242
|
ctx.addIssue({
|
|
19413
|
-
code:
|
|
20243
|
+
code: z78.ZodIssueCode.custom,
|
|
19414
20244
|
path: [
|
|
19415
20245
|
"videoPreset"
|
|
19416
20246
|
],
|
|
@@ -19419,7 +20249,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19419
20249
|
}
|
|
19420
20250
|
if (input.videoResolution !== void 0) {
|
|
19421
20251
|
ctx.addIssue({
|
|
19422
|
-
code:
|
|
20252
|
+
code: z78.ZodIssueCode.custom,
|
|
19423
20253
|
path: [
|
|
19424
20254
|
"videoResolution"
|
|
19425
20255
|
],
|
|
@@ -19429,7 +20259,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19429
20259
|
}
|
|
19430
20260
|
if (input.kind !== "image" && input.nVariants !== void 0) {
|
|
19431
20261
|
ctx.addIssue({
|
|
19432
|
-
code:
|
|
20262
|
+
code: z78.ZodIssueCode.custom,
|
|
19433
20263
|
path: [
|
|
19434
20264
|
"nVariants"
|
|
19435
20265
|
],
|
|
@@ -19439,7 +20269,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19439
20269
|
if (input.kind !== "landing") {
|
|
19440
20270
|
if (input.sectionKey !== void 0) {
|
|
19441
20271
|
ctx.addIssue({
|
|
19442
|
-
code:
|
|
20272
|
+
code: z78.ZodIssueCode.custom,
|
|
19443
20273
|
path: [
|
|
19444
20274
|
"sectionKey"
|
|
19445
20275
|
],
|
|
@@ -19448,7 +20278,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19448
20278
|
}
|
|
19449
20279
|
if (input.instructions !== void 0) {
|
|
19450
20280
|
ctx.addIssue({
|
|
19451
|
-
code:
|
|
20281
|
+
code: z78.ZodIssueCode.custom,
|
|
19452
20282
|
path: [
|
|
19453
20283
|
"instructions"
|
|
19454
20284
|
],
|
|
@@ -19457,31 +20287,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19457
20287
|
}
|
|
19458
20288
|
}
|
|
19459
20289
|
});
|
|
19460
|
-
var CreateCreativeVariantInputBase =
|
|
19461
|
-
sourceTaskId:
|
|
20290
|
+
var CreateCreativeVariantInputBase = z78.object({
|
|
20291
|
+
sourceTaskId: z78.string().uuid().describe("ID de la tarea original completada."),
|
|
19462
20292
|
kind: CreativeVariantKindEnum,
|
|
19463
|
-
confirm:
|
|
19464
|
-
clientRequestId:
|
|
19465
|
-
angle:
|
|
19466
|
-
buyerPersona:
|
|
19467
|
-
scriptNotes:
|
|
19468
|
-
creativeDirection:
|
|
20293
|
+
confirm: z78.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
|
|
20294
|
+
clientRequestId: z78.string().uuid().describe("UUID estable y obligatorio para esta intenci\xF3n. Reutil\xEDzalo ante timeouts o transporte ambiguo. Si la API devuelve status=error, una nueva generaci\xF3n exige otra confirmaci\xF3n y un UUID nuevo."),
|
|
20295
|
+
angle: z78.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
|
|
20296
|
+
buyerPersona: z78.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
|
|
20297
|
+
scriptNotes: z78.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
|
|
20298
|
+
creativeDirection: z78.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
|
|
19469
20299
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
|
|
19470
20300
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
|
|
19471
|
-
generateAiMusic:
|
|
19472
|
-
nVariants:
|
|
20301
|
+
generateAiMusic: z78.boolean().optional().describe("Opcional para video."),
|
|
20302
|
+
nVariants: z78.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
19473
20303
|
imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
|
|
19474
20304
|
creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
|
|
19475
20305
|
visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
|
|
19476
20306
|
aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
|
|
19477
|
-
styleMix:
|
|
20307
|
+
styleMix: z78.boolean().optional().describe("Opcional para imagen."),
|
|
19478
20308
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
|
|
19479
|
-
instructions:
|
|
20309
|
+
instructions: z78.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.")
|
|
19480
20310
|
}).strict();
|
|
19481
20311
|
var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
19482
20312
|
if ((input.kind === "video" || input.kind === "image") && !input.angle) {
|
|
19483
20313
|
ctx.addIssue({
|
|
19484
|
-
code:
|
|
20314
|
+
code: z78.ZodIssueCode.custom,
|
|
19485
20315
|
path: [
|
|
19486
20316
|
"angle"
|
|
19487
20317
|
],
|
|
@@ -19490,7 +20320,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
19490
20320
|
}
|
|
19491
20321
|
if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
|
|
19492
20322
|
ctx.addIssue({
|
|
19493
|
-
code:
|
|
20323
|
+
code: z78.ZodIssueCode.custom,
|
|
19494
20324
|
path: [
|
|
19495
20325
|
"instructions"
|
|
19496
20326
|
],
|
|
@@ -19536,7 +20366,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
19536
20366
|
for (const field of fieldsByKind[input.kind]) {
|
|
19537
20367
|
if (input[field] !== void 0) {
|
|
19538
20368
|
ctx.addIssue({
|
|
19539
|
-
code:
|
|
20369
|
+
code: z78.ZodIssueCode.custom,
|
|
19540
20370
|
path: [
|
|
19541
20371
|
field
|
|
19542
20372
|
],
|
|
@@ -19653,32 +20483,32 @@ function registerCreativeVariantTools(server, api) {
|
|
|
19653
20483
|
__name(registerCreativeVariantTools, "registerCreativeVariantTools");
|
|
19654
20484
|
|
|
19655
20485
|
// src/tools/script-review.ts
|
|
19656
|
-
import { z as
|
|
20486
|
+
import { z as z79 } from "zod";
|
|
19657
20487
|
var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
|
|
19658
20488
|
var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
|
|
19659
20489
|
var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
|
|
19660
|
-
var GetVideoScriptInput =
|
|
19661
|
-
taskId:
|
|
19662
|
-
angleKey:
|
|
20490
|
+
var GetVideoScriptInput = z79.object({
|
|
20491
|
+
taskId: z79.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
|
|
20492
|
+
angleKey: z79.string().min(1).optional().describe('Clave del \xE1ngulo cuyo guion se quiere leer (formato "angle_0", "angle_1", ...). REQUERIDO para tareas multi-angle: si se omite, el backend resuelve a "angle_0" LITERAL (no "el primer pendiente"), as\xED que en multi-angle donde angle_0 ya est\xE9 aprobado/saltado obtendr\xEDas status="approved" y nunca alcanzar\xEDas el \xE1ngulo realmente pendiente. Para single-angle puede omitirse.')
|
|
19663
20493
|
}).strict();
|
|
19664
20494
|
var VIDEO_SCRIPT_APPROVAL_MAX_SCENES2 = 50;
|
|
19665
20495
|
var VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2 = 2e3;
|
|
19666
|
-
var ApproveSceneEdit =
|
|
19667
|
-
index:
|
|
19668
|
-
dialogue:
|
|
20496
|
+
var ApproveSceneEdit = z79.object({
|
|
20497
|
+
index: z79.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
|
|
20498
|
+
dialogue: z79.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
|
|
19669
20499
|
message: "dialogue no puede ser s\xF3lo espacios"
|
|
19670
20500
|
}).describe("Di\xE1logo final de la escena. NO puede estar vac\xEDo ni ser s\xF3lo espacios. Puede ser el original sin cambios o la edici\xF3n del usuario.")
|
|
19671
20501
|
}).strict();
|
|
19672
|
-
var ApproveVideoScriptInput =
|
|
19673
|
-
taskId:
|
|
19674
|
-
angleKey:
|
|
19675
|
-
scenes:
|
|
20502
|
+
var ApproveVideoScriptInput = z79.object({
|
|
20503
|
+
taskId: z79.string().min(1).describe("ID de la tarea."),
|
|
20504
|
+
angleKey: z79.string().trim().min(1).max(120).optional().describe('Mismo angleKey usado en get_video_script. REQUERIDO en multi-angle (si se omite el backend resuelve a "angle_0" literal). En single-angle puede omitirse.'),
|
|
20505
|
+
scenes: z79.array(ApproveSceneEdit).min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_SCENES2).describe("Escenas con los di\xE1logos finales. El backend mergea por `index` \u2014 las escenas NO incluidas conservan el di\xE1logo original. Debe haber entre 1 y 50 entradas. Para cada entrada que mandes con un dialogue distinto del original, el backend valida minWords \u2264 words \u2264 maxWords y rechaza con 400 si te sales del rango.")
|
|
19676
20506
|
}).strict();
|
|
19677
|
-
var RegenerateVideoScriptInput =
|
|
19678
|
-
taskId:
|
|
19679
|
-
angleKey:
|
|
20507
|
+
var RegenerateVideoScriptInput = z79.object({
|
|
20508
|
+
taskId: z79.string().min(1).describe("ID de la tarea."),
|
|
20509
|
+
angleKey: z79.string().min(1).describe('Clave del \xE1ngulo a regenerar. Single-angle: pasa "angle_0". Multi-angle: el mismo que devuelve get_video_script. NO se puede omitir \u2014 el backend lo exige siempre.'),
|
|
19680
20510
|
narrativeStyle: NarrativeStyleEnum.describe('Narrativa para el nuevo guion. Incluye valores hist\xF3ricos porque esta herramienta tambi\xE9n regenera tareas antiguas. REQUERIDO \u2014 el backend NO acepta "mantener la actual"; siempre tienes que elegir una. Si el usuario quiere re-rolear con la misma narrativa, pasa la que ya tiene el \xE1ngulo (la ves en get_video_script o en get_task_status).'),
|
|
19681
|
-
narrativeSelection:
|
|
20511
|
+
narrativeSelection: z79.enum([
|
|
19682
20512
|
"market",
|
|
19683
20513
|
"guided"
|
|
19684
20514
|
]).optional().describe("Elecci\xF3n expl\xEDcita del usuario: market usa el estudio de mercado disponible; guided usa la narrativa elegida. Omitir conserva el comportamiento existente.")
|
|
@@ -19759,14 +20589,14 @@ function registerScriptReviewTools(server, api) {
|
|
|
19759
20589
|
__name(registerScriptReviewTools, "registerScriptReviewTools");
|
|
19760
20590
|
|
|
19761
20591
|
// src/tools/connections.ts
|
|
19762
|
-
import { z as
|
|
20592
|
+
import { z as z80 } from "zod";
|
|
19763
20593
|
var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
|
|
19764
20594
|
var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
|
|
19765
20595
|
var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
|
|
19766
20596
|
var listMetaDestinationsGuidance = getProductMakerCapabilityModelGuidance("list_meta_destinations");
|
|
19767
20597
|
var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list_tiktok_advertisers");
|
|
19768
20598
|
function registerConnectionTools(server, api) {
|
|
19769
|
-
server.tool("list_shopify_shops", listShopifyShopsGuidance.summary + " Si la lista est\xE1 vac\xEDa, dile al usuario que conecte una tienda en productmaker.app/integrations antes de intentar publicar.",
|
|
20599
|
+
server.tool("list_shopify_shops", listShopifyShopsGuidance.summary + " Si la lista est\xE1 vac\xEDa, dile al usuario que conecte una tienda en productmaker.app/integrations antes de intentar publicar.", z80.object({}).shape, READS_INTERNAL, async () => {
|
|
19770
20600
|
try {
|
|
19771
20601
|
const r = await api.getJson("/v1/shopify/shops");
|
|
19772
20602
|
return asText(r);
|
|
@@ -19774,10 +20604,10 @@ function registerConnectionTools(server, api) {
|
|
|
19774
20604
|
throw translateError(e);
|
|
19775
20605
|
}
|
|
19776
20606
|
});
|
|
19777
|
-
server.tool("list_shopify_products", 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.',
|
|
19778
|
-
shopDomain:
|
|
19779
|
-
query:
|
|
19780
|
-
taskId:
|
|
20607
|
+
server.tool("list_shopify_products", 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.', z80.object({
|
|
20608
|
+
shopDomain: z80.string().min(3).max(120),
|
|
20609
|
+
query: z80.string().trim().max(120).optional(),
|
|
20610
|
+
taskId: z80.string().uuid().optional()
|
|
19781
20611
|
}).shape, READS_EXTERNAL, async ({ shopDomain, query, taskId }) => {
|
|
19782
20612
|
try {
|
|
19783
20613
|
const params = new URLSearchParams({
|
|
@@ -19791,7 +20621,7 @@ function registerConnectionTools(server, api) {
|
|
|
19791
20621
|
throw translateError(e);
|
|
19792
20622
|
}
|
|
19793
20623
|
});
|
|
19794
|
-
server.tool("list_meta_ad_accounts", 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.",
|
|
20624
|
+
server.tool("list_meta_ad_accounts", 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.", z80.object({}).shape, READS_EXTERNAL, async () => {
|
|
19795
20625
|
try {
|
|
19796
20626
|
const r = await api.getJson("/v1/facebook/ad-accounts");
|
|
19797
20627
|
return asText(r);
|
|
@@ -19801,7 +20631,7 @@ function registerConnectionTools(server, api) {
|
|
|
19801
20631
|
});
|
|
19802
20632
|
server.registerTool("list_meta_destinations", {
|
|
19803
20633
|
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.",
|
|
19804
|
-
inputSchema:
|
|
20634
|
+
inputSchema: z80.object({}).shape,
|
|
19805
20635
|
annotations: READS_EXTERNAL,
|
|
19806
20636
|
_meta: {
|
|
19807
20637
|
"openai/widgetAccessible": true
|
|
@@ -19814,7 +20644,7 @@ function registerConnectionTools(server, api) {
|
|
|
19814
20644
|
throw translateError(e);
|
|
19815
20645
|
}
|
|
19816
20646
|
});
|
|
19817
|
-
server.tool("list_tiktok_advertisers", listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.",
|
|
20647
|
+
server.tool("list_tiktok_advertisers", listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.", z80.object({}).shape, READS_EXTERNAL, async () => {
|
|
19818
20648
|
try {
|
|
19819
20649
|
const r = await api.getJson("/v1/tiktok/advertisers");
|
|
19820
20650
|
return asText(r);
|
|
@@ -19826,10 +20656,10 @@ function registerConnectionTools(server, api) {
|
|
|
19826
20656
|
__name(registerConnectionTools, "registerConnectionTools");
|
|
19827
20657
|
|
|
19828
20658
|
// src/tools/actors.ts
|
|
19829
|
-
import { z as
|
|
20659
|
+
import { z as z81 } from "zod";
|
|
19830
20660
|
var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
|
|
19831
20661
|
function registerActorTools(server, api) {
|
|
19832
|
-
server.tool("list_actors", listActorsGuidance.summary + " Devuelve id, nombre, descripci\xF3n, g\xE9nero y voz. Usa el `id` como `actorId` al crear o editar una tarea. Solo aparecen los personajes listos para usar; si la lista est\xE1 vac\xEDa, dile al usuario que cree uno en productmaker.app antes de intentar asignarlo. No modifica nada.",
|
|
20662
|
+
server.tool("list_actors", listActorsGuidance.summary + " Devuelve id, nombre, descripci\xF3n, g\xE9nero y voz. Usa el `id` como `actorId` al crear o editar una tarea. Solo aparecen los personajes listos para usar; si la lista est\xE1 vac\xEDa, dile al usuario que cree uno en productmaker.app antes de intentar asignarlo. No modifica nada.", z81.object({}).shape, READS_INTERNAL, async () => {
|
|
19833
20663
|
try {
|
|
19834
20664
|
const rows = await api.getJson("/v1/actors");
|
|
19835
20665
|
const actors = (Array.isArray(rows) ? rows : []).filter((actor) => actor.status === "ready").map(({ id, name, description, gender, voiceId }) => ({
|
|
@@ -19850,7 +20680,7 @@ function registerActorTools(server, api) {
|
|
|
19850
20680
|
__name(registerActorTools, "registerActorTools");
|
|
19851
20681
|
|
|
19852
20682
|
// src/tools/publish.ts
|
|
19853
|
-
import { z as
|
|
20683
|
+
import { z as z82 } from "zod";
|
|
19854
20684
|
|
|
19855
20685
|
// src/tools/stable-uuid.ts
|
|
19856
20686
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -19922,40 +20752,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
|
|
|
19922
20752
|
var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
|
|
19923
20753
|
var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
|
|
19924
20754
|
var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
|
|
19925
|
-
var ShopifyInput =
|
|
19926
|
-
taskId:
|
|
19927
|
-
shopDomain:
|
|
20755
|
+
var ShopifyInput = z82.object({
|
|
20756
|
+
taskId: z82.string().min(1),
|
|
20757
|
+
shopDomain: z82.string().min(1),
|
|
19928
20758
|
/** Override: number of landing images to include. Default = ALL images the
|
|
19929
20759
|
* task generated (the MCP fetches /v1/results first to count). Bounded
|
|
19930
20760
|
* generously here; the backend validates each index against
|
|
19931
20761
|
* landing.images.length and rejects out-of-range. */
|
|
19932
|
-
numLandingImages:
|
|
19933
|
-
variantIndex:
|
|
20762
|
+
numLandingImages: z82.number().int().min(1).max(20).optional(),
|
|
20763
|
+
variantIndex: z82.number().int().min(0).optional(),
|
|
19934
20764
|
/** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
|
|
19935
20765
|
* When true, the landing renders variant-picker pills; when false, it ships
|
|
19936
20766
|
* a single-option product page. Defaults to false. */
|
|
19937
|
-
showVariantPicker:
|
|
20767
|
+
showVariantPicker: z82.boolean().optional(),
|
|
19938
20768
|
/** Default `auto` updates the product previously published for this task and
|
|
19939
20769
|
* shop. Use `existing` with targetProductId to choose another product, or
|
|
19940
20770
|
* `new` only when the user explicitly wants a duplicate/new listing. */
|
|
19941
|
-
publicationMode:
|
|
20771
|
+
publicationMode: z82.enum([
|
|
19942
20772
|
"auto",
|
|
19943
20773
|
"existing",
|
|
19944
20774
|
"new"
|
|
19945
20775
|
]).optional(),
|
|
19946
20776
|
/** Shopify product GID, numeric id, or admin product URL. Required when
|
|
19947
20777
|
* publicationMode is `existing`. */
|
|
19948
|
-
targetProductId:
|
|
20778
|
+
targetProductId: z82.string().trim().min(1).max(300).optional(),
|
|
19949
20779
|
/** Add an announcement bar text above add-to-cart (optional). */
|
|
19950
|
-
announcementBarEnabled:
|
|
19951
|
-
announcementBarText:
|
|
20780
|
+
announcementBarEnabled: z82.boolean().optional(),
|
|
20781
|
+
announcementBarText: z82.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
|
|
19952
20782
|
commerceCorrection: PublishCommerceCorrectionSchema.optional().describe("Complete seller-confirmed commerce values, with the revision and fingerprint returned in recovery. Never invent missing prices or convert currency."),
|
|
19953
|
-
confirmed:
|
|
20783
|
+
confirmed: z82.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
|
|
19954
20784
|
});
|
|
19955
20785
|
var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
|
|
19956
20786
|
if (value.commerceCorrection && value.confirmed !== true) {
|
|
19957
20787
|
ctx.addIssue({
|
|
19958
|
-
code:
|
|
20788
|
+
code: z82.ZodIssueCode.custom,
|
|
19959
20789
|
path: [
|
|
19960
20790
|
"confirmed"
|
|
19961
20791
|
],
|
|
@@ -19964,7 +20794,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
19964
20794
|
}
|
|
19965
20795
|
if (value.announcementBarEnabled && !value.announcementBarText) {
|
|
19966
20796
|
ctx.addIssue({
|
|
19967
|
-
code:
|
|
20797
|
+
code: z82.ZodIssueCode.custom,
|
|
19968
20798
|
path: [
|
|
19969
20799
|
"announcementBarText"
|
|
19970
20800
|
],
|
|
@@ -19973,7 +20803,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
19973
20803
|
}
|
|
19974
20804
|
if (!value.announcementBarEnabled && value.announcementBarText) {
|
|
19975
20805
|
ctx.addIssue({
|
|
19976
|
-
code:
|
|
20806
|
+
code: z82.ZodIssueCode.custom,
|
|
19977
20807
|
path: [
|
|
19978
20808
|
"announcementBarText"
|
|
19979
20809
|
],
|
|
@@ -19987,91 +20817,91 @@ function parseShopifyInput(rawInput) {
|
|
|
19987
20817
|
return parsed.data;
|
|
19988
20818
|
}
|
|
19989
20819
|
__name(parseShopifyInput, "parseShopifyInput");
|
|
19990
|
-
var McpCampaignConfig =
|
|
20820
|
+
var McpCampaignConfig = z82.object({
|
|
19991
20821
|
/** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
|
|
19992
20822
|
* converts to the account currency server-side. Do NOT pre-convert: on a COP
|
|
19993
20823
|
* account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
|
|
19994
|
-
dailyBudgetUsd:
|
|
20824
|
+
dailyBudgetUsd: z82.number().positive().optional(),
|
|
19995
20825
|
/** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
|
|
19996
20826
|
* normalizes at validation). Meta accepts max 1 (single-country ad set).
|
|
19997
20827
|
* TikTok takes only the first entry. */
|
|
19998
|
-
targetCountries:
|
|
19999
|
-
campaignName:
|
|
20828
|
+
targetCountries: z82.array(CountryIso2Schema).max(1).optional(),
|
|
20829
|
+
campaignName: z82.string().trim().min(1).max(100).optional()
|
|
20000
20830
|
});
|
|
20001
20831
|
var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
|
|
20002
|
-
var MetaInput =
|
|
20003
|
-
taskId:
|
|
20832
|
+
var MetaInput = z82.object({
|
|
20833
|
+
taskId: z82.string().min(1),
|
|
20004
20834
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
20005
|
-
portfolioId:
|
|
20835
|
+
portfolioId: z82.string().trim().min(1),
|
|
20006
20836
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
20007
|
-
pageId:
|
|
20837
|
+
pageId: z82.string().trim().min(1),
|
|
20008
20838
|
adAccountId: McpAdAccountId,
|
|
20009
|
-
pixelId:
|
|
20010
|
-
landingUrl:
|
|
20839
|
+
pixelId: z82.string().min(1).optional(),
|
|
20840
|
+
landingUrl: z82.string().url().optional(),
|
|
20011
20841
|
/** Select which angles to publish by 0-based index. Omit to publish all
|
|
20012
20842
|
* successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
|
|
20013
|
-
angleIndexes:
|
|
20843
|
+
angleIndexes: z82.array(z82.number().int().nonnegative()).optional(),
|
|
20014
20844
|
campaignConfig: McpCampaignConfig.optional(),
|
|
20015
20845
|
/** Override the ad's primary text (body copy). If omitted, ProductMaker
|
|
20016
20846
|
* uses the auto-generated copy attached to the task. Capped at 500 chars
|
|
20017
20847
|
* (Meta's primary-text limit). */
|
|
20018
|
-
primaryText:
|
|
20848
|
+
primaryText: z82.string().trim().min(1).max(500).optional(),
|
|
20019
20849
|
/** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
|
|
20020
20850
|
* (wa.me) instead of a landing page. */
|
|
20021
|
-
phoneNumber:
|
|
20851
|
+
phoneNumber: z82.string().min(8).max(32).optional()
|
|
20022
20852
|
});
|
|
20023
|
-
var GroupedTaskSource =
|
|
20024
|
-
type:
|
|
20025
|
-
taskId:
|
|
20026
|
-
angleIndex:
|
|
20027
|
-
videoVariant:
|
|
20853
|
+
var GroupedTaskSource = z82.object({
|
|
20854
|
+
type: z82.literal("task"),
|
|
20855
|
+
taskId: z82.string().min(1),
|
|
20856
|
+
angleIndex: z82.number().int().min(0).optional(),
|
|
20857
|
+
videoVariant: z82.enum([
|
|
20028
20858
|
"with_subtitles",
|
|
20029
20859
|
"without_subtitles"
|
|
20030
20860
|
]).optional(),
|
|
20031
|
-
imageVariantIndex:
|
|
20032
|
-
});
|
|
20033
|
-
var GroupedMediaSource =
|
|
20034
|
-
type:
|
|
20035
|
-
url:
|
|
20036
|
-
path:
|
|
20037
|
-
thumbnailUrl:
|
|
20038
|
-
thumbnailPath:
|
|
20861
|
+
imageVariantIndex: z82.number().int().min(0).optional()
|
|
20862
|
+
});
|
|
20863
|
+
var GroupedMediaSource = z82.object({
|
|
20864
|
+
type: z82.literal("media"),
|
|
20865
|
+
url: z82.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
|
|
20866
|
+
path: z82.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".'),
|
|
20867
|
+
thumbnailUrl: z82.string().url().optional(),
|
|
20868
|
+
thumbnailPath: z82.string().min(1).optional()
|
|
20039
20869
|
}).refine((value) => Boolean(value.url) !== Boolean(value.path), {
|
|
20040
20870
|
message: "media source needs exactly one of `url` or `path`"
|
|
20041
20871
|
}).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
|
|
20042
20872
|
message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
|
|
20043
20873
|
});
|
|
20044
|
-
var GroupedUploadedAssetSource =
|
|
20045
|
-
type:
|
|
20874
|
+
var GroupedUploadedAssetSource = z82.object({
|
|
20875
|
+
type: z82.literal("asset"),
|
|
20046
20876
|
/** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
|
|
20047
|
-
assetId:
|
|
20048
|
-
thumbnailAssetId:
|
|
20877
|
+
assetId: z82.string().uuid(),
|
|
20878
|
+
thumbnailAssetId: z82.string().uuid().optional()
|
|
20049
20879
|
});
|
|
20050
|
-
var GroupedCreative =
|
|
20051
|
-
type:
|
|
20880
|
+
var GroupedCreative = z82.object({
|
|
20881
|
+
type: z82.enum([
|
|
20052
20882
|
"image",
|
|
20053
20883
|
"video"
|
|
20054
20884
|
]),
|
|
20055
|
-
source:
|
|
20885
|
+
source: z82.union([
|
|
20056
20886
|
GroupedTaskSource,
|
|
20057
20887
|
GroupedMediaSource,
|
|
20058
20888
|
GroupedUploadedAssetSource
|
|
20059
20889
|
]),
|
|
20060
|
-
title:
|
|
20061
|
-
description:
|
|
20890
|
+
title: z82.string().max(120).optional(),
|
|
20891
|
+
description: z82.string().max(500).optional(),
|
|
20062
20892
|
cta: MetaCtaType.optional(),
|
|
20063
|
-
creativeId:
|
|
20893
|
+
creativeId: z82.string().min(1).optional()
|
|
20064
20894
|
});
|
|
20065
|
-
var GroupedCampaignConfigBase =
|
|
20895
|
+
var GroupedCampaignConfigBase = z82.object({
|
|
20066
20896
|
campaignType: MetaCampaignType.default("sales"),
|
|
20067
20897
|
optimizationMode: MetaOptimizationMode.default("advantage_plus"),
|
|
20068
20898
|
budgetMode: MetaBudgetMode.optional(),
|
|
20069
|
-
campaignDailyBudget:
|
|
20070
|
-
adSets:
|
|
20071
|
-
tempId:
|
|
20072
|
-
name:
|
|
20073
|
-
dailyBudget:
|
|
20074
|
-
creativeIds:
|
|
20899
|
+
campaignDailyBudget: z82.number().int().positive().optional(),
|
|
20900
|
+
adSets: z82.array(z82.object({
|
|
20901
|
+
tempId: z82.string().min(1).max(80),
|
|
20902
|
+
name: z82.string().min(1).max(100),
|
|
20903
|
+
dailyBudget: z82.number().int().positive().optional(),
|
|
20904
|
+
creativeIds: z82.array(z82.string().min(1)).min(1)
|
|
20075
20905
|
})).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
|
|
20076
20906
|
/**
|
|
20077
20907
|
* Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
|
|
@@ -20079,17 +20909,17 @@ var GroupedCampaignConfigBase = z78.object({
|
|
|
20079
20909
|
* opaque `invalid_literal` and made the WhatsApp destination — supported by
|
|
20080
20910
|
* the API since #849 — unreachable from this tool.
|
|
20081
20911
|
*/
|
|
20082
|
-
destination:
|
|
20083
|
-
|
|
20084
|
-
type:
|
|
20085
|
-
landingUrl:
|
|
20912
|
+
destination: z82.discriminatedUnion("type", [
|
|
20913
|
+
z82.object({
|
|
20914
|
+
type: z82.literal("landing"),
|
|
20915
|
+
landingUrl: z82.string().url()
|
|
20086
20916
|
}),
|
|
20087
|
-
|
|
20088
|
-
type:
|
|
20089
|
-
phoneNumber:
|
|
20917
|
+
z82.object({
|
|
20918
|
+
type: z82.literal("whatsapp"),
|
|
20919
|
+
phoneNumber: z82.string().min(8).max(32)
|
|
20090
20920
|
})
|
|
20091
20921
|
]),
|
|
20092
|
-
saveAsDefault:
|
|
20922
|
+
saveAsDefault: z82.boolean().default(false),
|
|
20093
20923
|
budgetPolicy: MetaBudgetPolicy.optional()
|
|
20094
20924
|
});
|
|
20095
20925
|
function resolveBudgetMode(value) {
|
|
@@ -20103,7 +20933,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
20103
20933
|
const budgetMode = resolveBudgetMode(value);
|
|
20104
20934
|
if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
|
|
20105
20935
|
ctx.addIssue({
|
|
20106
|
-
code:
|
|
20936
|
+
code: z82.ZodIssueCode.custom,
|
|
20107
20937
|
path: [
|
|
20108
20938
|
"campaignDailyBudget"
|
|
20109
20939
|
],
|
|
@@ -20114,7 +20944,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
20114
20944
|
value.adSets.forEach((adSet, index) => {
|
|
20115
20945
|
if (adSet.dailyBudget === void 0) {
|
|
20116
20946
|
ctx.addIssue({
|
|
20117
|
-
code:
|
|
20947
|
+
code: z82.ZodIssueCode.custom,
|
|
20118
20948
|
path: [
|
|
20119
20949
|
"adSets",
|
|
20120
20950
|
index,
|
|
@@ -20129,28 +20959,28 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
20129
20959
|
...value,
|
|
20130
20960
|
budgetMode: resolveBudgetMode(value)
|
|
20131
20961
|
}));
|
|
20132
|
-
var PublishCreativesToMetaInputBase =
|
|
20133
|
-
creatives:
|
|
20962
|
+
var PublishCreativesToMetaInputBase = z82.object({
|
|
20963
|
+
creatives: z82.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
|
|
20134
20964
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
20135
|
-
portfolioId:
|
|
20965
|
+
portfolioId: z82.string().trim().min(1),
|
|
20136
20966
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
20137
|
-
pageId:
|
|
20967
|
+
pageId: z82.string().trim().min(1),
|
|
20138
20968
|
adAccountId: McpAdAccountId,
|
|
20139
|
-
pixelId:
|
|
20969
|
+
pixelId: z82.string().min(1).optional(),
|
|
20140
20970
|
/** Required unless `campaignConfig.destination` is whatsapp — see the
|
|
20141
20971
|
* superRefine below. Mirrors the API's `FacebookCreateCampaignFromTasksBodySchema`. */
|
|
20142
|
-
landingUrl:
|
|
20972
|
+
landingUrl: z82.string().url().optional(),
|
|
20143
20973
|
/** ISO-2 code or resolvable country name — mirrors the API contract
|
|
20144
20974
|
* (CountryIso2Schema), which normalizes names to alpha-2 at validation. */
|
|
20145
20975
|
targetCountry: CountryIso2Schema,
|
|
20146
|
-
campaignName:
|
|
20976
|
+
campaignName: z82.string().trim().min(1).max(100),
|
|
20147
20977
|
campaignConfig: GroupedCampaignConfig.optional()
|
|
20148
20978
|
});
|
|
20149
20979
|
var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
|
|
20150
20980
|
const destination = value.campaignConfig?.destination;
|
|
20151
20981
|
if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
|
|
20152
20982
|
ctx.addIssue({
|
|
20153
|
-
code:
|
|
20983
|
+
code: z82.ZodIssueCode.custom,
|
|
20154
20984
|
path: [
|
|
20155
20985
|
"landingUrl"
|
|
20156
20986
|
],
|
|
@@ -20159,7 +20989,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
20159
20989
|
}
|
|
20160
20990
|
if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
|
|
20161
20991
|
ctx.addIssue({
|
|
20162
|
-
code:
|
|
20992
|
+
code: z82.ZodIssueCode.custom,
|
|
20163
20993
|
path: [
|
|
20164
20994
|
"campaignConfig",
|
|
20165
20995
|
"destination",
|
|
@@ -20178,16 +21008,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
20178
21008
|
}
|
|
20179
21009
|
return value;
|
|
20180
21010
|
});
|
|
20181
|
-
var PresignUploadResponseSchema =
|
|
20182
|
-
uploadUrl:
|
|
21011
|
+
var PresignUploadResponseSchema = z82.object({
|
|
21012
|
+
uploadUrl: z82.string().url().refine((value) => {
|
|
20183
21013
|
const url = new URL(value);
|
|
20184
21014
|
return !url.username && !url.password && url.protocol === "https:";
|
|
20185
21015
|
}, "presigned upload URL must be HTTPS without embedded credentials"),
|
|
20186
|
-
publicUrl:
|
|
21016
|
+
publicUrl: z82.string().url().refine((value) => {
|
|
20187
21017
|
const url = new URL(value);
|
|
20188
21018
|
return !url.username && !url.password;
|
|
20189
21019
|
}, "public media URL must not contain embedded credentials"),
|
|
20190
|
-
stagingAssetId:
|
|
21020
|
+
stagingAssetId: z82.string().uuid()
|
|
20191
21021
|
});
|
|
20192
21022
|
async function uploadResolvedMedia(api, media, assetRole) {
|
|
20193
21023
|
if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
|
|
@@ -20212,16 +21042,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
|
|
|
20212
21042
|
return uploadResolvedMedia(api, media, assetRole);
|
|
20213
21043
|
}
|
|
20214
21044
|
__name(resolveAndUploadMedia, "resolveAndUploadMedia");
|
|
20215
|
-
var TikTokInput =
|
|
20216
|
-
taskId:
|
|
20217
|
-
advertiserId:
|
|
20218
|
-
pixelId:
|
|
20219
|
-
landingUrl:
|
|
20220
|
-
angleIndexes:
|
|
21045
|
+
var TikTokInput = z82.object({
|
|
21046
|
+
taskId: z82.string().min(1),
|
|
21047
|
+
advertiserId: z82.string().min(1),
|
|
21048
|
+
pixelId: z82.string().min(1).optional(),
|
|
21049
|
+
landingUrl: z82.string().url().optional(),
|
|
21050
|
+
angleIndexes: z82.array(z82.number().int().nonnegative()).optional(),
|
|
20221
21051
|
campaignConfig: McpCampaignConfig.optional(),
|
|
20222
21052
|
/** Override the ad's description (TikTok's body copy). If omitted,
|
|
20223
21053
|
* ProductMaker uses the auto-generated copy attached to the task. */
|
|
20224
|
-
primaryText:
|
|
21054
|
+
primaryText: z82.string().trim().min(1).max(500).optional()
|
|
20225
21055
|
});
|
|
20226
21056
|
function registerPublishTools(server, api, opts = {}) {
|
|
20227
21057
|
const transport = opts.transport ?? "http";
|
|
@@ -20549,39 +21379,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
|
|
|
20549
21379
|
|
|
20550
21380
|
// src/tools/meta-upload.ts
|
|
20551
21381
|
import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
|
|
20552
|
-
import { z as
|
|
21382
|
+
import { z as z83 } from "zod";
|
|
20553
21383
|
var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
|
|
20554
|
-
var UploadSessionInputBase =
|
|
20555
|
-
mediaKind:
|
|
21384
|
+
var UploadSessionInputBase = z83.object({
|
|
21385
|
+
mediaKind: z83.enum([
|
|
20556
21386
|
"image",
|
|
20557
21387
|
"video",
|
|
20558
21388
|
"mixed"
|
|
20559
21389
|
]).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."),
|
|
20560
|
-
assetRole:
|
|
21390
|
+
assetRole: z83.enum([
|
|
20561
21391
|
"media",
|
|
20562
21392
|
"thumbnail"
|
|
20563
21393
|
]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
|
|
20564
|
-
uploadPurpose:
|
|
21394
|
+
uploadPurpose: z83.enum([
|
|
20565
21395
|
"product_reference",
|
|
20566
21396
|
"creative",
|
|
20567
21397
|
"generic"
|
|
20568
21398
|
]).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."),
|
|
20569
|
-
maxFiles:
|
|
21399
|
+
maxFiles: z83.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
|
|
20570
21400
|
});
|
|
20571
|
-
var OpenAiFileReference =
|
|
20572
|
-
download_url:
|
|
20573
|
-
file_id:
|
|
20574
|
-
mime_type:
|
|
20575
|
-
file_name:
|
|
21401
|
+
var OpenAiFileReference = z83.object({
|
|
21402
|
+
download_url: z83.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."),
|
|
21403
|
+
file_id: z83.string().min(1),
|
|
21404
|
+
mime_type: z83.string().min(1).optional(),
|
|
21405
|
+
file_name: z83.string().min(1).optional()
|
|
20576
21406
|
});
|
|
20577
21407
|
var UploadSessionToolInputShape = {
|
|
20578
21408
|
...UploadSessionInputBase.shape,
|
|
20579
|
-
files:
|
|
21409
|
+
files: z83.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.")
|
|
20580
21410
|
};
|
|
20581
|
-
var UploadSessionToolInput =
|
|
21411
|
+
var UploadSessionToolInput = z83.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
|
|
20582
21412
|
if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
|
|
20583
21413
|
ctx.addIssue({
|
|
20584
|
-
code:
|
|
21414
|
+
code: z83.ZodIssueCode.custom,
|
|
20585
21415
|
path: [
|
|
20586
21416
|
"mediaKind"
|
|
20587
21417
|
],
|
|
@@ -20590,7 +21420,7 @@ var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine
|
|
|
20590
21420
|
}
|
|
20591
21421
|
if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
|
|
20592
21422
|
ctx.addIssue({
|
|
20593
|
-
code:
|
|
21423
|
+
code: z83.ZodIssueCode.custom,
|
|
20594
21424
|
path: [
|
|
20595
21425
|
"maxFiles"
|
|
20596
21426
|
],
|
|
@@ -20599,7 +21429,7 @@ var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine
|
|
|
20599
21429
|
}
|
|
20600
21430
|
if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
|
|
20601
21431
|
ctx.addIssue({
|
|
20602
|
-
code:
|
|
21432
|
+
code: z83.ZodIssueCode.custom,
|
|
20603
21433
|
path: [
|
|
20604
21434
|
"maxFiles"
|
|
20605
21435
|
],
|
|
@@ -20607,38 +21437,38 @@ var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine
|
|
|
20607
21437
|
});
|
|
20608
21438
|
}
|
|
20609
21439
|
});
|
|
20610
|
-
var UploadSessionResponse =
|
|
20611
|
-
sessionId:
|
|
20612
|
-
uploadPageUrl:
|
|
20613
|
-
mediaKind:
|
|
21440
|
+
var UploadSessionResponse = z83.object({
|
|
21441
|
+
sessionId: z83.string().uuid(),
|
|
21442
|
+
uploadPageUrl: z83.string().url(),
|
|
21443
|
+
mediaKind: z83.enum([
|
|
20614
21444
|
"image",
|
|
20615
21445
|
"video",
|
|
20616
21446
|
"mixed"
|
|
20617
21447
|
]),
|
|
20618
|
-
assetRole:
|
|
21448
|
+
assetRole: z83.enum([
|
|
20619
21449
|
"media",
|
|
20620
21450
|
"thumbnail"
|
|
20621
21451
|
]),
|
|
20622
|
-
maxFiles:
|
|
20623
|
-
expiresAt:
|
|
21452
|
+
maxFiles: z83.number().int().positive(),
|
|
21453
|
+
expiresAt: z83.string().datetime()
|
|
20624
21454
|
});
|
|
20625
|
-
var UploadStatusInput =
|
|
20626
|
-
sessionId:
|
|
21455
|
+
var UploadStatusInput = z83.object({
|
|
21456
|
+
sessionId: z83.string().uuid().describe("The sessionId returned by request_media_upload.")
|
|
20627
21457
|
});
|
|
20628
|
-
var UniversalUploadStatusResponse =
|
|
20629
|
-
|
|
20630
|
-
status:
|
|
20631
|
-
assets:
|
|
21458
|
+
var UniversalUploadStatusResponse = z83.discriminatedUnion("status", [
|
|
21459
|
+
z83.object({
|
|
21460
|
+
status: z83.literal("pending"),
|
|
21461
|
+
assets: z83.array(z83.never()).length(0)
|
|
20632
21462
|
}),
|
|
20633
|
-
|
|
20634
|
-
status:
|
|
20635
|
-
assets:
|
|
20636
|
-
assetId:
|
|
20637
|
-
mediaKind:
|
|
21463
|
+
z83.object({
|
|
21464
|
+
status: z83.literal("uploaded"),
|
|
21465
|
+
assets: z83.array(z83.object({
|
|
21466
|
+
assetId: z83.string().uuid(),
|
|
21467
|
+
mediaKind: z83.enum([
|
|
20638
21468
|
"image",
|
|
20639
21469
|
"video"
|
|
20640
21470
|
]),
|
|
20641
|
-
assetRole:
|
|
21471
|
+
assetRole: z83.enum([
|
|
20642
21472
|
"media",
|
|
20643
21473
|
"thumbnail"
|
|
20644
21474
|
])
|
|
@@ -20646,13 +21476,13 @@ var UniversalUploadStatusResponse = z79.discriminatedUnion("status", [
|
|
|
20646
21476
|
})
|
|
20647
21477
|
]);
|
|
20648
21478
|
var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
|
|
20649
|
-
uploadPurpose:
|
|
21479
|
+
uploadPurpose: z83.enum([
|
|
20650
21480
|
"product_reference",
|
|
20651
21481
|
"creative",
|
|
20652
21482
|
"generic"
|
|
20653
21483
|
]),
|
|
20654
|
-
checkToolName:
|
|
20655
|
-
resolveEndpoint:
|
|
21484
|
+
checkToolName: z83.literal("check_media_upload"),
|
|
21485
|
+
resolveEndpoint: z83.string().url()
|
|
20656
21486
|
});
|
|
20657
21487
|
function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
|
|
20658
21488
|
const url = new URL(uploadPageUrl);
|
|
@@ -20743,15 +21573,15 @@ function registerMediaUploadTools(server, api) {
|
|
|
20743
21573
|
__name(registerMediaUploadTools, "registerMediaUploadTools");
|
|
20744
21574
|
|
|
20745
21575
|
// src/tools/campaigns.ts
|
|
20746
|
-
import { z as
|
|
21576
|
+
import { z as z84 } from "zod";
|
|
20747
21577
|
var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
|
|
20748
21578
|
var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
|
|
20749
|
-
var MetaStatusInput =
|
|
20750
|
-
campaignId:
|
|
21579
|
+
var MetaStatusInput = z84.object({
|
|
21580
|
+
campaignId: z84.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
|
|
20751
21581
|
});
|
|
20752
|
-
var TikTokStatusInput =
|
|
20753
|
-
campaignId:
|
|
20754
|
-
advertiserId:
|
|
21582
|
+
var TikTokStatusInput = z84.object({
|
|
21583
|
+
campaignId: z84.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
|
|
21584
|
+
advertiserId: z84.string().min(1).describe("The same advertiserId used to publish the campaign.")
|
|
20755
21585
|
});
|
|
20756
21586
|
function registerCampaignTools(server, api) {
|
|
20757
21587
|
server.tool("get_meta_campaign_status", getMetaCampaignStatusGuidance.summary + " Llama esto DESPU\xC9S de `publish_to_meta` para confirmar que la campa\xF1a se cre\xF3 correctamente y para reportar performance al usuario. Es read-only \u2014 no modifica nada en Meta Ads Manager.", MetaStatusInput.shape, READS_EXTERNAL, async (input) => {
|
|
@@ -20848,10 +21678,10 @@ function renderTikTokStatusMarkdown(r) {
|
|
|
20848
21678
|
__name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
|
|
20849
21679
|
|
|
20850
21680
|
// ../../packages/product-economics/src/product-costing.ts
|
|
20851
|
-
import { z as
|
|
21681
|
+
import { z as z86 } from "zod";
|
|
20852
21682
|
|
|
20853
21683
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
20854
|
-
import { z as
|
|
21684
|
+
import { z as z85 } from "zod";
|
|
20855
21685
|
|
|
20856
21686
|
// ../../packages/product-economics/src/product-costing-shipping-references.json
|
|
20857
21687
|
var product_costing_shipping_references_default = {
|
|
@@ -20915,21 +21745,21 @@ var product_costing_shipping_references_default = {
|
|
|
20915
21745
|
};
|
|
20916
21746
|
|
|
20917
21747
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
20918
|
-
var ShippingReferenceSchema =
|
|
20919
|
-
reference:
|
|
20920
|
-
min:
|
|
20921
|
-
max:
|
|
20922
|
-
updatedAt:
|
|
20923
|
-
confidence:
|
|
21748
|
+
var ShippingReferenceSchema = z85.object({
|
|
21749
|
+
reference: z85.number().positive(),
|
|
21750
|
+
min: z85.number().nonnegative(),
|
|
21751
|
+
max: z85.number().positive(),
|
|
21752
|
+
updatedAt: z85.string().date(),
|
|
21753
|
+
confidence: z85.enum([
|
|
20924
21754
|
"high",
|
|
20925
21755
|
"medium",
|
|
20926
21756
|
"medium-low"
|
|
20927
21757
|
]),
|
|
20928
|
-
sources:
|
|
21758
|
+
sources: z85.array(z85.string().url().startsWith("https://")).min(1).max(3)
|
|
20929
21759
|
}).superRefine(({ reference, min, max }, context) => {
|
|
20930
21760
|
if (min > reference || reference > max) {
|
|
20931
21761
|
context.addIssue({
|
|
20932
|
-
code:
|
|
21762
|
+
code: z85.ZodIssueCode.custom,
|
|
20933
21763
|
message: "shipping_reference_outside_range",
|
|
20934
21764
|
path: [
|
|
20935
21765
|
"reference"
|
|
@@ -20937,7 +21767,7 @@ var ShippingReferenceSchema = z81.object({
|
|
|
20937
21767
|
});
|
|
20938
21768
|
}
|
|
20939
21769
|
});
|
|
20940
|
-
var SHIPPING_REFERENCES =
|
|
21770
|
+
var SHIPPING_REFERENCES = z85.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
|
|
20941
21771
|
var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
|
|
20942
21772
|
var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
|
|
20943
21773
|
"MX",
|
|
@@ -21119,18 +21949,18 @@ function getProductCostingCountryName(country) {
|
|
|
21119
21949
|
__name(getProductCostingCountryName, "getProductCostingCountryName");
|
|
21120
21950
|
|
|
21121
21951
|
// ../../packages/product-economics/src/product-costing.ts
|
|
21122
|
-
var ProductCostingInputSchema =
|
|
21123
|
-
country:
|
|
21124
|
-
supplierCost:
|
|
21125
|
-
shippingCost:
|
|
21126
|
-
returnRate:
|
|
21127
|
-
cancellationRate:
|
|
21128
|
-
adsManagerCpa:
|
|
21129
|
-
desiredMargin:
|
|
21952
|
+
var ProductCostingInputSchema = z86.object({
|
|
21953
|
+
country: z86.string().refine(isProductCostingCountryCode, "unsupported_country"),
|
|
21954
|
+
supplierCost: z86.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
|
|
21955
|
+
shippingCost: z86.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
|
|
21956
|
+
returnRate: z86.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
21957
|
+
cancellationRate: z86.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
21958
|
+
adsManagerCpa: z86.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
|
|
21959
|
+
desiredMargin: z86.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
|
|
21130
21960
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
21131
21961
|
if (returnRate + cancellationRate >= 1) {
|
|
21132
21962
|
context.addIssue({
|
|
21133
|
-
code:
|
|
21963
|
+
code: z86.ZodIssueCode.custom,
|
|
21134
21964
|
message: "delivery_rate_positive",
|
|
21135
21965
|
path: [
|
|
21136
21966
|
"cancellationRate"
|
|
@@ -21227,15 +22057,15 @@ function calculateProductCosting(rawInput) {
|
|
|
21227
22057
|
__name(calculateProductCosting, "calculateProductCosting");
|
|
21228
22058
|
|
|
21229
22059
|
// src/tools/product-costing.ts
|
|
21230
|
-
import { z as
|
|
22060
|
+
import { z as z87 } from "zod";
|
|
21231
22061
|
var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
|
|
21232
|
-
var optionalAmount = /* @__PURE__ */ __name((description) =>
|
|
21233
|
-
var optionalPercent = /* @__PURE__ */ __name((description) =>
|
|
21234
|
-
var ProductCostingToolInput =
|
|
21235
|
-
country:
|
|
22062
|
+
var optionalAmount = /* @__PURE__ */ __name((description) => z87.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
|
|
22063
|
+
var optionalPercent = /* @__PURE__ */ __name((description) => z87.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
|
|
22064
|
+
var ProductCostingToolInput = z87.object({
|
|
22065
|
+
country: z87.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
|
|
21236
22066
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
21237
22067
|
}).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
|
|
21238
|
-
supplierCost:
|
|
22068
|
+
supplierCost: z87.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."),
|
|
21239
22069
|
supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
|
|
21240
22070
|
shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
|
|
21241
22071
|
shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
|
|
@@ -21394,7 +22224,7 @@ function formatPercent(value) {
|
|
|
21394
22224
|
__name(formatPercent, "formatPercent");
|
|
21395
22225
|
|
|
21396
22226
|
// src/tools/product-research.ts
|
|
21397
|
-
import { z as
|
|
22227
|
+
import { z as z88 } from "zod";
|
|
21398
22228
|
|
|
21399
22229
|
// src/tools/product-research-idempotency.ts
|
|
21400
22230
|
var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
|
|
@@ -21765,35 +22595,35 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
|
|
|
21765
22595
|
]);
|
|
21766
22596
|
var POLL_INTERVAL_MS = 5e3;
|
|
21767
22597
|
var MAX_WAIT_SECONDS = 120;
|
|
21768
|
-
var FindInput =
|
|
22598
|
+
var FindInput = z88.object({
|
|
21769
22599
|
targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
|
|
21770
22600
|
categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
|
|
21771
|
-
confirmed:
|
|
21772
|
-
waitSeconds:
|
|
22601
|
+
confirmed: z88.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
|
|
22602
|
+
waitSeconds: z88.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
|
|
21773
22603
|
});
|
|
21774
|
-
var GetInput =
|
|
21775
|
-
runId:
|
|
22604
|
+
var GetInput = z88.object({
|
|
22605
|
+
runId: z88.string().uuid().describe("ID del run devuelto por find_winning_products.")
|
|
21776
22606
|
});
|
|
21777
|
-
var ListInput =
|
|
21778
|
-
limit:
|
|
22607
|
+
var ListInput = z88.object({
|
|
22608
|
+
limit: z88.number().int().min(1).max(20).default(10)
|
|
21779
22609
|
});
|
|
21780
|
-
function textResult(
|
|
22610
|
+
function textResult(text2) {
|
|
21781
22611
|
return {
|
|
21782
22612
|
content: [
|
|
21783
22613
|
{
|
|
21784
22614
|
type: "text",
|
|
21785
|
-
text
|
|
22615
|
+
text: text2
|
|
21786
22616
|
}
|
|
21787
22617
|
]
|
|
21788
22618
|
};
|
|
21789
22619
|
}
|
|
21790
22620
|
__name(textResult, "textResult");
|
|
21791
|
-
function researchResult(run,
|
|
22621
|
+
function researchResult(run, text2) {
|
|
21792
22622
|
return {
|
|
21793
22623
|
content: [
|
|
21794
22624
|
{
|
|
21795
22625
|
type: "text",
|
|
21796
|
-
text
|
|
22626
|
+
text: text2
|
|
21797
22627
|
}
|
|
21798
22628
|
],
|
|
21799
22629
|
structuredContent: run
|
|
@@ -21898,17 +22728,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
|
|
|
21898
22728
|
__name(registerProductResearchTools, "registerProductResearchTools");
|
|
21899
22729
|
|
|
21900
22730
|
// src/tools/dropshipping-projects.ts
|
|
21901
|
-
import { z as
|
|
22731
|
+
import { z as z89 } from "zod";
|
|
21902
22732
|
var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
|
|
21903
22733
|
var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
|
|
21904
22734
|
var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
|
|
21905
|
-
var ProjectId =
|
|
21906
|
-
var DropshippingProjectStatus =
|
|
22735
|
+
var ProjectId = z89.string().uuid();
|
|
22736
|
+
var DropshippingProjectStatus = z89.enum([
|
|
21907
22737
|
"active",
|
|
21908
22738
|
"completed",
|
|
21909
22739
|
"archived"
|
|
21910
22740
|
]);
|
|
21911
|
-
var DropshippingProjectPhase =
|
|
22741
|
+
var DropshippingProjectPhase = z89.enum([
|
|
21912
22742
|
"research",
|
|
21913
22743
|
"costing",
|
|
21914
22744
|
"media",
|
|
@@ -21917,21 +22747,21 @@ var DropshippingProjectPhase = z85.enum([
|
|
|
21917
22747
|
"advertising",
|
|
21918
22748
|
"complete"
|
|
21919
22749
|
]);
|
|
21920
|
-
var DropshippingRewardMilestone =
|
|
22750
|
+
var DropshippingRewardMilestone = z89.enum([
|
|
21921
22751
|
"product_selected",
|
|
21922
22752
|
"costing_saved",
|
|
21923
22753
|
"product_media_ready",
|
|
21924
22754
|
"creatives_completed",
|
|
21925
22755
|
"campaign_created"
|
|
21926
22756
|
]);
|
|
21927
|
-
var TargetCountry =
|
|
22757
|
+
var TargetCountry = z89.enum([
|
|
21928
22758
|
"CO",
|
|
21929
22759
|
"MX",
|
|
21930
22760
|
"PE",
|
|
21931
22761
|
"EC",
|
|
21932
22762
|
"CL"
|
|
21933
22763
|
]);
|
|
21934
|
-
var ResearchCategory =
|
|
22764
|
+
var ResearchCategory = z89.enum([
|
|
21935
22765
|
"auto",
|
|
21936
22766
|
"automotive",
|
|
21937
22767
|
"kitchen",
|
|
@@ -21946,7 +22776,7 @@ var ResearchCategory = z85.enum([
|
|
|
21946
22776
|
"garden",
|
|
21947
22777
|
"cleaning"
|
|
21948
22778
|
]);
|
|
21949
|
-
var HttpUrl3 =
|
|
22779
|
+
var HttpUrl3 = z89.string().url().max(2e3).refine((value) => {
|
|
21950
22780
|
try {
|
|
21951
22781
|
return [
|
|
21952
22782
|
"http:",
|
|
@@ -21956,45 +22786,45 @@ var HttpUrl3 = z85.string().url().max(2e3).refine((value) => {
|
|
|
21956
22786
|
return false;
|
|
21957
22787
|
}
|
|
21958
22788
|
}, "URL must use HTTP(S)");
|
|
21959
|
-
var ResearchCandidateOrigin =
|
|
21960
|
-
type:
|
|
22789
|
+
var ResearchCandidateOrigin = z89.object({
|
|
22790
|
+
type: z89.literal("research_candidate"),
|
|
21961
22791
|
runId: ProjectId,
|
|
21962
|
-
candidateSourceId:
|
|
22792
|
+
candidateSourceId: z89.string().min(1).max(160)
|
|
21963
22793
|
});
|
|
21964
|
-
var TaskOrigin =
|
|
21965
|
-
type:
|
|
22794
|
+
var TaskOrigin = z89.object({
|
|
22795
|
+
type: z89.literal("task"),
|
|
21966
22796
|
taskId: ProjectId
|
|
21967
22797
|
});
|
|
21968
|
-
var ManualOrigin =
|
|
21969
|
-
type:
|
|
22798
|
+
var ManualOrigin = z89.object({
|
|
22799
|
+
type: z89.literal("manual"),
|
|
21970
22800
|
clientRequestId: ProjectId,
|
|
21971
|
-
country:
|
|
22801
|
+
country: z89.string().min(2).max(3).optional()
|
|
21972
22802
|
});
|
|
21973
|
-
var StartProjectInput =
|
|
21974
|
-
origin:
|
|
22803
|
+
var StartProjectInput = z89.object({
|
|
22804
|
+
origin: z89.discriminatedUnion("type", [
|
|
21975
22805
|
ResearchCandidateOrigin,
|
|
21976
22806
|
TaskOrigin,
|
|
21977
22807
|
ManualOrigin
|
|
21978
22808
|
]),
|
|
21979
|
-
productName:
|
|
22809
|
+
productName: z89.string().trim().min(1).max(240).optional(),
|
|
21980
22810
|
productUrl: HttpUrl3.optional(),
|
|
21981
|
-
country:
|
|
21982
|
-
languageCode:
|
|
22811
|
+
country: z89.string().min(2).max(3).optional(),
|
|
22812
|
+
languageCode: z89.string().min(2).max(16).optional()
|
|
21983
22813
|
}).strict();
|
|
21984
|
-
var CostProjectInput =
|
|
22814
|
+
var CostProjectInput = z89.object({
|
|
21985
22815
|
projectId: ProjectId,
|
|
21986
|
-
version:
|
|
21987
|
-
country:
|
|
22816
|
+
version: z89.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
|
|
22817
|
+
country: z89.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
|
|
21988
22818
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
21989
22819
|
}).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
|
|
21990
|
-
supplierCost:
|
|
21991
|
-
shippingCost:
|
|
21992
|
-
returnRate:
|
|
21993
|
-
cancellationRate:
|
|
21994
|
-
adsManagerCpa:
|
|
21995
|
-
desiredMargin:
|
|
21996
|
-
});
|
|
21997
|
-
var GuideInput =
|
|
22820
|
+
supplierCost: z89.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."),
|
|
22821
|
+
shippingCost: z89.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
|
|
22822
|
+
returnRate: z89.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."),
|
|
22823
|
+
cancellationRate: z89.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."),
|
|
22824
|
+
adsManagerCpa: z89.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
|
|
22825
|
+
desiredMargin: z89.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
|
|
22826
|
+
});
|
|
22827
|
+
var GuideInput = z89.object({
|
|
21998
22828
|
projectId: ProjectId.optional()
|
|
21999
22829
|
}).strict();
|
|
22000
22830
|
var NEXT_ACTION_KINDS = [
|
|
@@ -22012,29 +22842,29 @@ var NEXT_ACTION_KINDS = [
|
|
|
22012
22842
|
"repair_meta_campaign",
|
|
22013
22843
|
"review_paused_campaign"
|
|
22014
22844
|
];
|
|
22015
|
-
var DropshippingProjectNextAction =
|
|
22016
|
-
kind:
|
|
22017
|
-
href:
|
|
22845
|
+
var DropshippingProjectNextAction = z89.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z89.object({
|
|
22846
|
+
kind: z89.literal(kind),
|
|
22847
|
+
href: z89.string().min(1)
|
|
22018
22848
|
})));
|
|
22019
|
-
var CostingInputSchema =
|
|
22020
|
-
country:
|
|
22021
|
-
supplierCost:
|
|
22022
|
-
shippingCost:
|
|
22023
|
-
returnRate:
|
|
22024
|
-
cancellationRate:
|
|
22025
|
-
adsManagerCpa:
|
|
22026
|
-
desiredMargin:
|
|
22849
|
+
var CostingInputSchema = z89.object({
|
|
22850
|
+
country: z89.string().min(2).max(3),
|
|
22851
|
+
supplierCost: z89.number().finite().positive(),
|
|
22852
|
+
shippingCost: z89.number().finite().nonnegative(),
|
|
22853
|
+
returnRate: z89.number().finite().min(0).lt(1),
|
|
22854
|
+
cancellationRate: z89.number().finite().min(0).lt(1),
|
|
22855
|
+
adsManagerCpa: z89.number().finite().nonnegative(),
|
|
22856
|
+
desiredMargin: z89.number().finite().min(0).lt(1)
|
|
22027
22857
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
22028
22858
|
if (returnRate + cancellationRate >= 1) context.addIssue({
|
|
22029
|
-
code:
|
|
22859
|
+
code: z89.ZodIssueCode.custom,
|
|
22030
22860
|
path: [
|
|
22031
22861
|
"cancellationRate"
|
|
22032
22862
|
]
|
|
22033
22863
|
});
|
|
22034
22864
|
});
|
|
22035
|
-
var FiniteCostingNumber =
|
|
22036
|
-
var CostingResultSchema =
|
|
22037
|
-
country:
|
|
22865
|
+
var FiniteCostingNumber = z89.number().finite();
|
|
22866
|
+
var CostingResultSchema = z89.object({
|
|
22867
|
+
country: z89.string().min(2).max(3),
|
|
22038
22868
|
deliveryRate: FiniteCostingNumber,
|
|
22039
22869
|
adjustedShippingCost: FiniteCostingNumber,
|
|
22040
22870
|
adjustedCpa: FiniteCostingNumber,
|
|
@@ -22047,45 +22877,45 @@ var CostingResultSchema = z85.object({
|
|
|
22047
22877
|
estimatedProfit: FiniteCostingNumber,
|
|
22048
22878
|
actualMargin: FiniteCostingNumber,
|
|
22049
22879
|
breakEvenAdsManagerCpa: FiniteCostingNumber,
|
|
22050
|
-
wasPriceAutoAdjusted:
|
|
22051
|
-
profitabilityStatus:
|
|
22052
|
-
});
|
|
22053
|
-
var RewardProgressSchema =
|
|
22054
|
-
campaignKey:
|
|
22055
|
-
totalCredits:
|
|
22056
|
-
earnedCredits:
|
|
22057
|
-
milestones:
|
|
22880
|
+
wasPriceAutoAdjusted: z89.boolean(),
|
|
22881
|
+
profitabilityStatus: z89.literal("healthy")
|
|
22882
|
+
});
|
|
22883
|
+
var RewardProgressSchema = z89.object({
|
|
22884
|
+
campaignKey: z89.literal("dropshipping-launch-v1"),
|
|
22885
|
+
totalCredits: z89.number().int().positive(),
|
|
22886
|
+
earnedCredits: z89.number().int().nonnegative(),
|
|
22887
|
+
milestones: z89.array(z89.object({
|
|
22058
22888
|
milestone: DropshippingRewardMilestone,
|
|
22059
|
-
credits:
|
|
22060
|
-
available:
|
|
22061
|
-
earned:
|
|
22889
|
+
credits: z89.number().int().positive(),
|
|
22890
|
+
available: z89.boolean().optional(),
|
|
22891
|
+
earned: z89.boolean(),
|
|
22062
22892
|
grantId: ProjectId.nullable(),
|
|
22063
|
-
grantedAt:
|
|
22893
|
+
grantedAt: z89.string().datetime().nullable()
|
|
22064
22894
|
})).length(DropshippingRewardMilestone.options.length)
|
|
22065
22895
|
});
|
|
22066
|
-
var ProjectResponseSchema =
|
|
22896
|
+
var ProjectResponseSchema = z89.object({
|
|
22067
22897
|
id: ProjectId,
|
|
22068
22898
|
taskId: ProjectId.nullable(),
|
|
22069
22899
|
status: DropshippingProjectStatus,
|
|
22070
|
-
originKey:
|
|
22900
|
+
originKey: z89.string().min(1),
|
|
22071
22901
|
researchRunId: ProjectId.nullable(),
|
|
22072
|
-
candidateSourceId:
|
|
22073
|
-
productName:
|
|
22902
|
+
candidateSourceId: z89.string().nullable(),
|
|
22903
|
+
productName: z89.string().nullable(),
|
|
22074
22904
|
productUrl: HttpUrl3.nullable(),
|
|
22075
22905
|
referenceImageUrl: HttpUrl3.nullable(),
|
|
22076
|
-
targetCountry:
|
|
22077
|
-
languageCode:
|
|
22078
|
-
hasReferenceImage:
|
|
22079
|
-
hasWinnerReferenceImage:
|
|
22906
|
+
targetCountry: z89.string().nullable(),
|
|
22907
|
+
languageCode: z89.string().nullable(),
|
|
22908
|
+
hasReferenceImage: z89.boolean(),
|
|
22909
|
+
hasWinnerReferenceImage: z89.boolean(),
|
|
22080
22910
|
costingInput: CostingInputSchema.nullable(),
|
|
22081
22911
|
costingResult: CostingResultSchema.nullable(),
|
|
22082
|
-
costingVersion:
|
|
22083
|
-
version:
|
|
22912
|
+
costingVersion: z89.number().int().positive().nullable(),
|
|
22913
|
+
version: z89.number().int().positive(),
|
|
22084
22914
|
phase: DropshippingProjectPhase,
|
|
22085
22915
|
nextAction: DropshippingProjectNextAction.nullable(),
|
|
22086
22916
|
rewards: RewardProgressSchema,
|
|
22087
|
-
createdAt:
|
|
22088
|
-
updatedAt:
|
|
22917
|
+
createdAt: z89.string().datetime(),
|
|
22918
|
+
updatedAt: z89.string().datetime()
|
|
22089
22919
|
}).passthrough();
|
|
22090
22920
|
var NEXT_ACTION_GUIDANCE = {
|
|
22091
22921
|
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.",
|
|
@@ -22203,58 +23033,58 @@ function registerDropshippingProjectTools(server, api) {
|
|
|
22203
23033
|
__name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
|
|
22204
23034
|
|
|
22205
23035
|
// src/tools/daily-control.ts
|
|
22206
|
-
import { z as
|
|
23036
|
+
import { z as z90 } from "zod";
|
|
22207
23037
|
var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
|
|
22208
23038
|
var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
|
|
22209
23039
|
var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
|
|
22210
|
-
var ProviderCampaignIdentifier =
|
|
22211
|
-
var DateOnly =
|
|
22212
|
-
var DailyControlInput =
|
|
23040
|
+
var ProviderCampaignIdentifier = z90.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
|
|
23041
|
+
var DateOnly = z90.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
23042
|
+
var DailyControlInput = z90.object({
|
|
22213
23043
|
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."),
|
|
22214
|
-
days:
|
|
22215
|
-
projectId:
|
|
23044
|
+
days: z90.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
|
|
23045
|
+
projectId: z90.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
|
|
22216
23046
|
}).strict();
|
|
22217
|
-
var LinkCampaignInput =
|
|
22218
|
-
projectId:
|
|
22219
|
-
provider:
|
|
23047
|
+
var LinkCampaignInput = z90.object({
|
|
23048
|
+
projectId: z90.string().uuid(),
|
|
23049
|
+
provider: z90.enum([
|
|
22220
23050
|
"meta",
|
|
22221
23051
|
"tiktok"
|
|
22222
23052
|
]),
|
|
22223
23053
|
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."),
|
|
22224
23054
|
campaignId: ProviderCampaignIdentifier
|
|
22225
23055
|
}).strict();
|
|
22226
|
-
var ReportReturnsInput =
|
|
22227
|
-
projectId:
|
|
23056
|
+
var ReportReturnsInput = z90.object({
|
|
23057
|
+
projectId: z90.string().uuid(),
|
|
22228
23058
|
date: DateOnly,
|
|
22229
|
-
returnedOrders:
|
|
22230
|
-
note:
|
|
23059
|
+
returnedOrders: z90.number().int().min(0).max(1e5),
|
|
23060
|
+
note: z90.string().trim().max(280).optional()
|
|
22231
23061
|
}).strict();
|
|
22232
|
-
var DailyControlStatusMirror = DailyControlStatusEnum.or(
|
|
22233
|
-
var DailyControlLightMirror = DailyControlLightEnum.or(
|
|
22234
|
-
var DailyControlSourceMirror = DailyControlSourceEnum.or(
|
|
22235
|
-
var DailyControlVerdictMirror = DailyControlVerdictEnum.or(
|
|
22236
|
-
var DailyControlDayMirror =
|
|
22237
|
-
date:
|
|
22238
|
-
returnedOrders:
|
|
23062
|
+
var DailyControlStatusMirror = DailyControlStatusEnum.or(z90.string());
|
|
23063
|
+
var DailyControlLightMirror = DailyControlLightEnum.or(z90.string());
|
|
23064
|
+
var DailyControlSourceMirror = DailyControlSourceEnum.or(z90.string());
|
|
23065
|
+
var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z90.string());
|
|
23066
|
+
var DailyControlDayMirror = z90.object({
|
|
23067
|
+
date: z90.string(),
|
|
23068
|
+
returnedOrders: z90.number(),
|
|
22239
23069
|
returnedSource: DailyControlSourceMirror,
|
|
22240
23070
|
cancelledSource: DailyControlSourceMirror,
|
|
22241
|
-
hasEstimates:
|
|
23071
|
+
hasEstimates: z90.boolean(),
|
|
22242
23072
|
light: DailyControlLightMirror
|
|
22243
23073
|
}).passthrough();
|
|
22244
|
-
var DailyControlProductMirror =
|
|
22245
|
-
projectId:
|
|
22246
|
-
productName:
|
|
23074
|
+
var DailyControlProductMirror = z90.object({
|
|
23075
|
+
projectId: z90.string().uuid(),
|
|
23076
|
+
productName: z90.string().nullable(),
|
|
22247
23077
|
status: DailyControlStatusMirror,
|
|
22248
|
-
statusMessage:
|
|
22249
|
-
days:
|
|
23078
|
+
statusMessage: z90.string().nullable(),
|
|
23079
|
+
days: z90.array(DailyControlDayMirror),
|
|
22250
23080
|
verdict: DailyControlVerdictMirror.nullable(),
|
|
22251
|
-
rationale:
|
|
23081
|
+
rationale: z90.string().nullable()
|
|
22252
23082
|
}).passthrough();
|
|
22253
|
-
var DailyControlResponseMirror =
|
|
22254
|
-
since:
|
|
22255
|
-
until:
|
|
22256
|
-
products:
|
|
22257
|
-
archivedProjectSpend:
|
|
23083
|
+
var DailyControlResponseMirror = z90.object({
|
|
23084
|
+
since: z90.string(),
|
|
23085
|
+
until: z90.string(),
|
|
23086
|
+
products: z90.array(DailyControlProductMirror),
|
|
23087
|
+
archivedProjectSpend: z90.array(z90.unknown())
|
|
22258
23088
|
}).passthrough();
|
|
22259
23089
|
var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
|
|
22260
23090
|
function withWarnings(response) {
|
|
@@ -22338,42 +23168,42 @@ function registerDailyControlTools(server, api) {
|
|
|
22338
23168
|
__name(registerDailyControlTools, "registerDailyControlTools");
|
|
22339
23169
|
|
|
22340
23170
|
// src/tools/product-control.ts
|
|
22341
|
-
import { z as
|
|
23171
|
+
import { z as z91 } from "zod";
|
|
22342
23172
|
var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
|
|
22343
23173
|
var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
|
|
22344
23174
|
var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
|
|
22345
23175
|
var setProductCostingGuidance = getProductMakerCapabilityModelGuidance("set_product_costing");
|
|
22346
23176
|
var reportProductCountsGuidance = getProductMakerCapabilityModelGuidance("report_product_counts");
|
|
22347
|
-
var DateOnly2 =
|
|
23177
|
+
var DateOnly2 = z91.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
22348
23178
|
var IMPORT_BATCH_MAX2 = 50;
|
|
22349
|
-
var ProductControlListInput =
|
|
22350
|
-
days:
|
|
23179
|
+
var ProductControlListInput = z91.object({
|
|
23180
|
+
days: z91.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
|
|
22351
23181
|
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."),
|
|
22352
|
-
shopDomain:
|
|
23182
|
+
shopDomain: z91.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
|
|
22353
23183
|
}).strict();
|
|
22354
|
-
var ImportableProductsInput =
|
|
22355
|
-
q:
|
|
22356
|
-
after:
|
|
22357
|
-
shopDomain:
|
|
23184
|
+
var ImportableProductsInput = z91.object({
|
|
23185
|
+
q: z91.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
|
|
23186
|
+
after: z91.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
|
|
23187
|
+
shopDomain: z91.string().min(1).optional()
|
|
22358
23188
|
}).strict();
|
|
22359
|
-
var ImportProductControlsInput =
|
|
22360
|
-
shopifyProductIds:
|
|
23189
|
+
var ImportProductControlsInput = z91.object({
|
|
23190
|
+
shopifyProductIds: z91.array(z91.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."),
|
|
22361
23191
|
// Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
|
|
22362
23192
|
// sin decir a cuál archivaría el producto bajo la tienda equivocada.
|
|
22363
|
-
shopDomain:
|
|
23193
|
+
shopDomain: z91.string().min(1)
|
|
22364
23194
|
}).strict();
|
|
22365
|
-
var SetProductCostingInput =
|
|
22366
|
-
shopDomain:
|
|
22367
|
-
shopifyProductId:
|
|
22368
|
-
targetCountry:
|
|
22369
|
-
supplierCost:
|
|
22370
|
-
shippingCost:
|
|
22371
|
-
returnRate:
|
|
22372
|
-
cancellationRate:
|
|
23195
|
+
var SetProductCostingInput = z91.object({
|
|
23196
|
+
shopDomain: z91.string().min(1),
|
|
23197
|
+
shopifyProductId: z91.string().min(1).max(64),
|
|
23198
|
+
targetCountry: z91.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
|
|
23199
|
+
supplierCost: z91.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
|
|
23200
|
+
shippingCost: z91.number().finite().nonnegative(),
|
|
23201
|
+
returnRate: z91.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
|
|
23202
|
+
cancellationRate: z91.number().finite().min(0).lt(1)
|
|
22373
23203
|
}).strict();
|
|
22374
|
-
var Count =
|
|
22375
|
-
var ReportProductCountsInput =
|
|
22376
|
-
productControlId:
|
|
23204
|
+
var Count = z91.number().int().min(0).max(1e5).nullable().optional();
|
|
23205
|
+
var ReportProductCountsInput = z91.object({
|
|
23206
|
+
productControlId: z91.string().uuid().describe("El identificador que devuelve get_product_control."),
|
|
22377
23207
|
date: DateOnly2,
|
|
22378
23208
|
orders: Count.describe("Pedidos que entraron ese d\xEDa."),
|
|
22379
23209
|
cancelledOrders: Count,
|