@productmaker/mcp 8.1.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 +1618 -799
- package/dist/stdio.js +1602 -783
- 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(),
|
|
@@ -7291,7 +7471,8 @@ var IMAGE_QA_GATES = [
|
|
|
7291
7471
|
"limb",
|
|
7292
7472
|
"device_panel",
|
|
7293
7473
|
"critical_feature",
|
|
7294
|
-
"cross_section"
|
|
7474
|
+
"cross_section",
|
|
7475
|
+
"usage_fidelity"
|
|
7295
7476
|
];
|
|
7296
7477
|
var ImageQaGate = z36.enum(IMAGE_QA_GATES);
|
|
7297
7478
|
var ImageQaGateOutcome = z36.enum([
|
|
@@ -8337,6 +8518,10 @@ var GEMINI_OMNI_FLAT_USER_PRICE_CENTS = 168;
|
|
|
8337
8518
|
// ../../packages/types/src/pricing.ts
|
|
8338
8519
|
var CREDITS_PER_USD_CENT = 10;
|
|
8339
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
|
+
};
|
|
8340
8525
|
var KALODATA_USD_CENTS_PER_PROVIDER_CREDIT = 9;
|
|
8341
8526
|
var KALODATA_PROVIDER_CREDITS_PER_SOURCE_CEILING = 7.5;
|
|
8342
8527
|
var DEFAULT_PRICING = {
|
|
@@ -9295,6 +9480,27 @@ var DEFAULT_PRICING = {
|
|
|
9295
9480
|
ourCostCents: 1.88,
|
|
9296
9481
|
userPriceCents: 3.76
|
|
9297
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
|
+
},
|
|
9298
9504
|
// Landing commercial-facts extraction (gemini-3.8-flash, ONE text-only call over
|
|
9299
9505
|
// the seller's offer/context/features). Sized off the image-QA key beside it,
|
|
9300
9506
|
// which measured 1.88¢ at ~11.1K prompt tokens: this prompt is capped at ~3K in
|
|
@@ -10033,6 +10239,24 @@ var DEFAULT_PRICING = {
|
|
|
10033
10239
|
ourCostCents: 0.2,
|
|
10034
10240
|
userPriceCents: 0.4
|
|
10035
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
|
+
},
|
|
10036
10260
|
// Unit = one reference-grouping pass over the user's product images (0.1241¢).
|
|
10037
10261
|
"openrouter:product-reference-grouping": {
|
|
10038
10262
|
ourCostCents: 0.15,
|
|
@@ -13550,7 +13774,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13550
13774
|
"video"
|
|
13551
13775
|
]
|
|
13552
13776
|
),
|
|
13553
|
-
defineCapability("generate_image_creatives", "
|
|
13777
|
+
defineCapability("generate_image_creatives", "2f1698b623d98645b7c618a17988f3aac30f403a9c3f3dc26eb5bdbd9c6ef23e", "credit_consuming", "creative", [
|
|
13554
13778
|
"credit_consuming",
|
|
13555
13779
|
"state_change"
|
|
13556
13780
|
], [
|
|
@@ -14947,79 +15171,696 @@ var WhatsAppPresentationManifestSchema = z67.object({
|
|
|
14947
15171
|
}
|
|
14948
15172
|
});
|
|
14949
15173
|
|
|
14950
|
-
// ../../packages/types/src/
|
|
15174
|
+
// ../../packages/types/src/usage-decision.ts
|
|
14951
15175
|
import { z as z68 } from "zod";
|
|
14952
|
-
|
|
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([
|
|
14953
15794
|
"initial",
|
|
14954
15795
|
"regeneration",
|
|
14955
15796
|
"edit",
|
|
14956
15797
|
"retry"
|
|
14957
15798
|
]);
|
|
14958
|
-
var FlightRecorderProviderSchema =
|
|
15799
|
+
var FlightRecorderProviderSchema = z72.enum([
|
|
14959
15800
|
"kie",
|
|
14960
15801
|
"fal"
|
|
14961
15802
|
]);
|
|
14962
|
-
var FlightRecorderElementSchema =
|
|
14963
|
-
name:
|
|
14964
|
-
description:
|
|
14965
|
-
frontalImageUrl:
|
|
14966
|
-
referenceImageUrls:
|
|
14967
|
-
videoUrl:
|
|
14968
|
-
});
|
|
14969
|
-
var FlightRecorderDistillationSchema =
|
|
14970
|
-
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([
|
|
14971
15812
|
"female",
|
|
14972
15813
|
"male",
|
|
14973
15814
|
"mixed"
|
|
14974
|
-
]).or(
|
|
14975
|
-
voiceId:
|
|
14976
|
-
cameraMotion:
|
|
14977
|
-
}).catchall(
|
|
14978
|
-
var FlightRecorderEntrySchema =
|
|
14979
|
-
schemaVersion:
|
|
14980
|
-
id:
|
|
14981
|
-
taskId:
|
|
14982
|
-
runId:
|
|
14983
|
-
sequence:
|
|
14984
|
-
timestamp:
|
|
14985
|
-
provider: FlightRecorderProviderSchema.or(
|
|
14986
|
-
model:
|
|
14987
|
-
prompt:
|
|
14988
|
-
durationSeconds:
|
|
14989
|
-
aspectRatio:
|
|
14990
|
-
resolution:
|
|
14991
|
-
startImageUrl:
|
|
14992
|
-
endImageUrl:
|
|
14993
|
-
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(),
|
|
14994
15835
|
// Correlation & pipeline metadata
|
|
14995
|
-
angleKey:
|
|
14996
|
-
sceneIndex:
|
|
15836
|
+
angleKey: z72.string().optional(),
|
|
15837
|
+
sceneIndex: z72.number().int().nonnegative().optional(),
|
|
14997
15838
|
generationType: FlightRecorderGenerationTypeSchema,
|
|
14998
|
-
operationId:
|
|
14999
|
-
revisionId:
|
|
15000
|
-
attemptNumber:
|
|
15839
|
+
operationId: z72.string().min(1).optional(),
|
|
15840
|
+
revisionId: z72.string().min(1).optional(),
|
|
15841
|
+
attemptNumber: z72.number().int().nonnegative().default(1),
|
|
15001
15842
|
// Elements & Distillation
|
|
15002
|
-
elements:
|
|
15843
|
+
elements: z72.array(FlightRecorderElementSchema).optional(),
|
|
15003
15844
|
distillation: FlightRecorderDistillationSchema.optional(),
|
|
15004
15845
|
// Raw payload (sanitized of secrets)
|
|
15005
|
-
rawPayload:
|
|
15846
|
+
rawPayload: z72.record(z72.unknown())
|
|
15006
15847
|
});
|
|
15007
|
-
var FlightRecorderQuerySchema =
|
|
15008
|
-
taskId:
|
|
15009
|
-
runId:
|
|
15010
|
-
sceneIndex:
|
|
15011
|
-
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(),
|
|
15012
15853
|
generationType: FlightRecorderGenerationTypeSchema.optional(),
|
|
15013
|
-
cursor:
|
|
15014
|
-
limit:
|
|
15854
|
+
cursor: z72.number().int().nonnegative().optional(),
|
|
15855
|
+
limit: z72.number().int().positive().optional()
|
|
15015
15856
|
});
|
|
15016
|
-
var FlightRecorderResponseSchema =
|
|
15017
|
-
taskId:
|
|
15018
|
-
runId:
|
|
15019
|
-
entries:
|
|
15857
|
+
var FlightRecorderResponseSchema = z72.object({
|
|
15858
|
+
taskId: z72.string().min(1),
|
|
15859
|
+
runId: z72.string().min(1),
|
|
15860
|
+
entries: z72.array(FlightRecorderEntrySchema),
|
|
15020
15861
|
lastCall: FlightRecorderEntrySchema.nullable(),
|
|
15021
|
-
count:
|
|
15022
|
-
nextCursor:
|
|
15862
|
+
count: z72.number().int().nonnegative(),
|
|
15863
|
+
nextCursor: z72.number().int().nonnegative().nullable()
|
|
15023
15864
|
});
|
|
15024
15865
|
|
|
15025
15866
|
// src/response-body.ts
|
|
@@ -15261,7 +16102,7 @@ var ApiClient = class {
|
|
|
15261
16102
|
};
|
|
15262
16103
|
|
|
15263
16104
|
// src/index.ts
|
|
15264
|
-
var MCP_VERSION = "8.
|
|
16105
|
+
var MCP_VERSION = "8.2.0";
|
|
15265
16106
|
|
|
15266
16107
|
// src/meta-upload-app.ts
|
|
15267
16108
|
import { readFileSync } from "fs";
|
|
@@ -15333,7 +16174,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
|
|
|
15333
16174
|
__name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
|
|
15334
16175
|
|
|
15335
16176
|
// src/tools/tasks.ts
|
|
15336
|
-
import { z as
|
|
16177
|
+
import { z as z76 } from "zod";
|
|
15337
16178
|
|
|
15338
16179
|
// src/resolve-image.ts
|
|
15339
16180
|
import { lookup as dnsLookup } from "dns/promises";
|
|
@@ -15894,10 +16735,10 @@ async function resolveMediaRef(ref, opts) {
|
|
|
15894
16735
|
__name(resolveMediaRef, "resolveMediaRef");
|
|
15895
16736
|
|
|
15896
16737
|
// src/tools/shared.ts
|
|
15897
|
-
import { z as
|
|
15898
|
-
var Lang =
|
|
15899
|
-
var Country =
|
|
15900
|
-
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([
|
|
15901
16742
|
"auto",
|
|
15902
16743
|
"classic",
|
|
15903
16744
|
"pain_solution",
|
|
@@ -15906,12 +16747,12 @@ var LandingStrategyEnum = z69.enum([
|
|
|
15906
16747
|
"offer_value",
|
|
15907
16748
|
"lifestyle_identity"
|
|
15908
16749
|
]);
|
|
15909
|
-
var LandingImageFormatEnum =
|
|
16750
|
+
var LandingImageFormatEnum = z73.enum([
|
|
15910
16751
|
"9:16",
|
|
15911
16752
|
"4:5",
|
|
15912
16753
|
"1:1"
|
|
15913
16754
|
]);
|
|
15914
|
-
var VideoPresetEnum =
|
|
16755
|
+
var VideoPresetEnum = z73.enum([
|
|
15915
16756
|
"auto",
|
|
15916
16757
|
"ugc_dynamic",
|
|
15917
16758
|
"ugc_how_to",
|
|
@@ -15924,21 +16765,21 @@ var VideoPresetEnum = z69.enum([
|
|
|
15924
16765
|
"pixar_problem",
|
|
15925
16766
|
"pixar_sassy"
|
|
15926
16767
|
]);
|
|
15927
|
-
var VideoStructureEnum =
|
|
16768
|
+
var VideoStructureEnum = z73.enum([
|
|
15928
16769
|
"single_take",
|
|
15929
16770
|
"multi_scene"
|
|
15930
16771
|
]);
|
|
15931
|
-
var VideoQualityEnum =
|
|
16772
|
+
var VideoQualityEnum = z73.enum([
|
|
15932
16773
|
"economy",
|
|
15933
16774
|
"medium",
|
|
15934
16775
|
"pro"
|
|
15935
16776
|
]);
|
|
15936
|
-
var VideoRouteIdEnum =
|
|
16777
|
+
var VideoRouteIdEnum = z73.enum([
|
|
15937
16778
|
"single_take",
|
|
15938
16779
|
"multi_scene",
|
|
15939
16780
|
"free"
|
|
15940
16781
|
]);
|
|
15941
|
-
var TaskCreativeVariantVideoPresetEnum =
|
|
16782
|
+
var TaskCreativeVariantVideoPresetEnum = z73.enum([
|
|
15942
16783
|
"auto",
|
|
15943
16784
|
"ugc_dynamic",
|
|
15944
16785
|
"ugc_how_to",
|
|
@@ -15955,53 +16796,43 @@ var VIDEO_PRESET_RESOLUTION = {
|
|
|
15955
16796
|
auto: null,
|
|
15956
16797
|
ugc_dynamic: {
|
|
15957
16798
|
videoStyle: "ai_dynamic",
|
|
15958
|
-
narrativeStyle: "review"
|
|
15959
|
-
videoModel: "veo"
|
|
16799
|
+
narrativeStyle: "review"
|
|
15960
16800
|
},
|
|
15961
16801
|
ugc_how_to: {
|
|
15962
16802
|
videoStyle: "ai_dynamic",
|
|
15963
|
-
narrativeStyle: "ugc_how_to"
|
|
15964
|
-
videoModel: "veo"
|
|
16803
|
+
narrativeStyle: "ugc_how_to"
|
|
15965
16804
|
},
|
|
15966
16805
|
ugc_unboxing_chaos: {
|
|
15967
16806
|
videoStyle: "ai_dynamic",
|
|
15968
|
-
narrativeStyle: "ugc_unboxing_chaos"
|
|
15969
|
-
videoModel: "veo"
|
|
16807
|
+
narrativeStyle: "ugc_unboxing_chaos"
|
|
15970
16808
|
},
|
|
15971
16809
|
problem_solution: {
|
|
15972
16810
|
videoStyle: "ai_dynamic",
|
|
15973
|
-
narrativeStyle: "problem_product_cta"
|
|
15974
|
-
videoModel: "kling"
|
|
16811
|
+
narrativeStyle: "problem_product_cta"
|
|
15975
16812
|
},
|
|
15976
16813
|
pixar_problem: {
|
|
15977
16814
|
videoStyle: "ai_dynamic",
|
|
15978
|
-
narrativeStyle: "animated_problem_pixar"
|
|
15979
|
-
videoModel: "kling"
|
|
16815
|
+
narrativeStyle: "animated_problem_pixar"
|
|
15980
16816
|
},
|
|
15981
16817
|
pixar_sassy: {
|
|
15982
16818
|
videoStyle: "ai_dynamic",
|
|
15983
|
-
narrativeStyle: "sassy_product_pixar"
|
|
15984
|
-
videoModel: "seedance"
|
|
16819
|
+
narrativeStyle: "sassy_product_pixar"
|
|
15985
16820
|
},
|
|
15986
16821
|
product_showcase: {
|
|
15987
16822
|
videoStyle: "product_only",
|
|
15988
|
-
narrativeStyle: "product_showcase"
|
|
15989
|
-
videoModel: "veo"
|
|
16823
|
+
narrativeStyle: "product_showcase"
|
|
15990
16824
|
},
|
|
15991
16825
|
wearable_showcase: {
|
|
15992
16826
|
videoStyle: "ugc",
|
|
15993
|
-
narrativeStyle: "wearable_showcase"
|
|
15994
|
-
videoModel: "veo"
|
|
16827
|
+
narrativeStyle: "wearable_showcase"
|
|
15995
16828
|
},
|
|
15996
16829
|
cinematic: {
|
|
15997
16830
|
videoStyle: "product_only",
|
|
15998
|
-
narrativeStyle: "cinematic"
|
|
15999
|
-
videoModel: "grok"
|
|
16831
|
+
narrativeStyle: "cinematic"
|
|
16000
16832
|
},
|
|
16001
16833
|
wild_card: {
|
|
16002
16834
|
videoStyle: "product_only",
|
|
16003
|
-
narrativeStyle: "wild_card"
|
|
16004
|
-
videoModel: "grok"
|
|
16835
|
+
narrativeStyle: "wild_card"
|
|
16005
16836
|
}
|
|
16006
16837
|
};
|
|
16007
16838
|
function resolveVideoPreset(preset) {
|
|
@@ -16009,7 +16840,7 @@ function resolveVideoPreset(preset) {
|
|
|
16009
16840
|
return VIDEO_PRESET_RESOLUTION[preset] ?? null;
|
|
16010
16841
|
}
|
|
16011
16842
|
__name(resolveVideoPreset, "resolveVideoPreset");
|
|
16012
|
-
var VideoTierEnum =
|
|
16843
|
+
var VideoTierEnum = z73.enum([
|
|
16013
16844
|
"basic"
|
|
16014
16845
|
]);
|
|
16015
16846
|
function resolveVideoTier(_tier) {
|
|
@@ -16049,22 +16880,22 @@ function assertSemanticVideoDurationCompatibility(structure, quality, durationSe
|
|
|
16049
16880
|
}
|
|
16050
16881
|
}
|
|
16051
16882
|
__name(assertSemanticVideoDurationCompatibility, "assertSemanticVideoDurationCompatibility");
|
|
16052
|
-
var VideoResolutionEnum =
|
|
16883
|
+
var VideoResolutionEnum = z73.enum([
|
|
16053
16884
|
"480p",
|
|
16054
16885
|
"720p"
|
|
16055
16886
|
]);
|
|
16056
|
-
var CreativeGenderEnum =
|
|
16887
|
+
var CreativeGenderEnum = z73.enum([
|
|
16057
16888
|
"female",
|
|
16058
16889
|
"male",
|
|
16059
16890
|
"mixed"
|
|
16060
16891
|
]);
|
|
16061
|
-
var VideoStyleEnum =
|
|
16892
|
+
var VideoStyleEnum = z73.enum([
|
|
16062
16893
|
"ugc",
|
|
16063
16894
|
"cartoon_3d",
|
|
16064
16895
|
"product_only",
|
|
16065
16896
|
"ai_dynamic"
|
|
16066
16897
|
]);
|
|
16067
|
-
var NarrativeStyleEnum =
|
|
16898
|
+
var NarrativeStyleEnum = z73.enum([
|
|
16068
16899
|
"review",
|
|
16069
16900
|
"ugc_how_to",
|
|
16070
16901
|
"problem_product_cta",
|
|
@@ -16082,7 +16913,7 @@ var NarrativeStyleEnum = z69.enum([
|
|
|
16082
16913
|
"ugc_demo_review",
|
|
16083
16914
|
"market"
|
|
16084
16915
|
]);
|
|
16085
|
-
var PublicNarrativeStyleEnum =
|
|
16916
|
+
var PublicNarrativeStyleEnum = z73.enum([
|
|
16086
16917
|
"review",
|
|
16087
16918
|
"ugc_how_to",
|
|
16088
16919
|
"ugc_unboxing_chaos",
|
|
@@ -16095,7 +16926,7 @@ var PublicNarrativeStyleEnum = z69.enum([
|
|
|
16095
16926
|
"sassy_product_pixar",
|
|
16096
16927
|
"market"
|
|
16097
16928
|
]);
|
|
16098
|
-
var
|
|
16929
|
+
var TaskVideoModelEnum = z73.enum([
|
|
16099
16930
|
"veo",
|
|
16100
16931
|
"wan",
|
|
16101
16932
|
"bytedance",
|
|
@@ -16103,29 +16934,29 @@ var VideoModelEnum = z69.enum([
|
|
|
16103
16934
|
"grok",
|
|
16104
16935
|
"kling"
|
|
16105
16936
|
]);
|
|
16106
|
-
var ProductReferenceUserChoiceEnum =
|
|
16937
|
+
var ProductReferenceUserChoiceEnum = z73.enum([
|
|
16107
16938
|
"same_product",
|
|
16108
16939
|
"variants",
|
|
16109
16940
|
"different_products",
|
|
16110
16941
|
"combo_distinct"
|
|
16111
16942
|
]);
|
|
16112
|
-
var ProductReferenceCandidateGroupingEnum =
|
|
16943
|
+
var ProductReferenceCandidateGroupingEnum = z73.enum([
|
|
16113
16944
|
"same_product_same_variant",
|
|
16114
16945
|
"same_product_different_variants",
|
|
16115
16946
|
"different_products",
|
|
16116
16947
|
"unclear"
|
|
16117
16948
|
]);
|
|
16118
|
-
var ProductReferenceScopeEnum =
|
|
16949
|
+
var ProductReferenceScopeEnum = z73.enum([
|
|
16119
16950
|
"base",
|
|
16120
16951
|
"video_view_pack"
|
|
16121
16952
|
]);
|
|
16122
|
-
var ProductReferenceResolutionDecisionEnum =
|
|
16953
|
+
var ProductReferenceResolutionDecisionEnum = z73.enum([
|
|
16123
16954
|
"approve",
|
|
16124
16955
|
"reject",
|
|
16125
16956
|
"observed_only",
|
|
16126
16957
|
"correct_view"
|
|
16127
16958
|
]);
|
|
16128
|
-
var ProductReferenceRejectionReasonEnum =
|
|
16959
|
+
var ProductReferenceRejectionReasonEnum = z73.enum([
|
|
16129
16960
|
"replacement_requested",
|
|
16130
16961
|
"wrong_product_identity",
|
|
16131
16962
|
"wrong_variant",
|
|
@@ -16136,13 +16967,13 @@ var ProductReferenceRejectionReasonEnum = z69.enum([
|
|
|
16136
16967
|
"not_a_product_photo",
|
|
16137
16968
|
"other"
|
|
16138
16969
|
]);
|
|
16139
|
-
var GapDurationChoiceMirror =
|
|
16140
|
-
angleIndex:
|
|
16141
|
-
recommendedSec:
|
|
16142
|
-
|
|
16143
|
-
|
|
16970
|
+
var GapDurationChoiceMirror = z73.object({
|
|
16971
|
+
angleIndex: z73.number().int().nonnegative(),
|
|
16972
|
+
recommendedSec: z73.union([
|
|
16973
|
+
z73.literal(15),
|
|
16974
|
+
z73.literal(30)
|
|
16144
16975
|
]),
|
|
16145
|
-
estimatedDeltaCredits:
|
|
16976
|
+
estimatedDeltaCredits: z73.number().int().nonnegative().optional()
|
|
16146
16977
|
});
|
|
16147
16978
|
function buildSelectedImageUrlsHash(urls) {
|
|
16148
16979
|
const input = [
|
|
@@ -16152,13 +16983,13 @@ function buildSelectedImageUrlsHash(urls) {
|
|
|
16152
16983
|
return `fnv1a:${hash.toString(16).padStart(8, "0")}:${urls.length}`;
|
|
16153
16984
|
}
|
|
16154
16985
|
__name(buildSelectedImageUrlsHash, "buildSelectedImageUrlsHash");
|
|
16155
|
-
var ImageCreativeStyleEnum =
|
|
16986
|
+
var ImageCreativeStyleEnum = z73.enum([
|
|
16156
16987
|
"studio",
|
|
16157
16988
|
"floating",
|
|
16158
16989
|
"ingredients",
|
|
16159
16990
|
"in_use"
|
|
16160
16991
|
]);
|
|
16161
|
-
var ImageCreativeArchetypeEnum =
|
|
16992
|
+
var ImageCreativeArchetypeEnum = z73.enum([
|
|
16162
16993
|
"direct_response_product_ad",
|
|
16163
16994
|
"hero_outcome",
|
|
16164
16995
|
"offer_value_prop",
|
|
@@ -16167,20 +16998,20 @@ var ImageCreativeArchetypeEnum = z69.enum([
|
|
|
16167
16998
|
"problem_solution",
|
|
16168
16999
|
"lifestyle_identity"
|
|
16169
17000
|
]);
|
|
16170
|
-
var ImageCreativeVisualTreatmentEnum =
|
|
17001
|
+
var ImageCreativeVisualTreatmentEnum = z73.enum([
|
|
16171
17002
|
"performance_product_ad",
|
|
16172
17003
|
"premium_dtc_carousel"
|
|
16173
17004
|
]);
|
|
16174
|
-
var ImageCreativeAspectRatioEnum =
|
|
17005
|
+
var ImageCreativeAspectRatioEnum = z73.enum([
|
|
16175
17006
|
"1:1",
|
|
16176
17007
|
"4:5",
|
|
16177
17008
|
"9:16",
|
|
16178
17009
|
"16:9"
|
|
16179
17010
|
]);
|
|
16180
|
-
var ImageRefSchema =
|
|
16181
|
-
url:
|
|
16182
|
-
path:
|
|
16183
|
-
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.")
|
|
16184
17015
|
}).refine((v) => [
|
|
16185
17016
|
v.url,
|
|
16186
17017
|
v.path,
|
|
@@ -16188,11 +17019,11 @@ var ImageRefSchema = z69.object({
|
|
|
16188
17019
|
].filter(Boolean).length === 1, {
|
|
16189
17020
|
message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
|
|
16190
17021
|
});
|
|
16191
|
-
var ImagesInput =
|
|
17022
|
+
var ImagesInput = z73.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
|
|
16192
17023
|
const assetCount = images.filter((image) => Boolean(image.assetId)).length;
|
|
16193
17024
|
if (assetCount > 0 && assetCount !== images.length) {
|
|
16194
17025
|
ctx.addIssue({
|
|
16195
|
-
code:
|
|
17026
|
+
code: z73.ZodIssueCode.custom,
|
|
16196
17027
|
message: "all image entries must use assetId, or all must use URL/path sources"
|
|
16197
17028
|
});
|
|
16198
17029
|
}
|
|
@@ -16260,14 +17091,14 @@ async function submitCreative(api, opts) {
|
|
|
16260
17091
|
});
|
|
16261
17092
|
}
|
|
16262
17093
|
__name(submitCreative, "submitCreative");
|
|
16263
|
-
var ResearchTargetCountryEnum =
|
|
17094
|
+
var ResearchTargetCountryEnum = z73.enum([
|
|
16264
17095
|
"CO",
|
|
16265
17096
|
"MX",
|
|
16266
17097
|
"PE",
|
|
16267
17098
|
"EC",
|
|
16268
17099
|
"CL"
|
|
16269
17100
|
]);
|
|
16270
|
-
var ResearchCategoryEnum =
|
|
17101
|
+
var ResearchCategoryEnum = z73.enum([
|
|
16271
17102
|
"auto",
|
|
16272
17103
|
"automotive",
|
|
16273
17104
|
"kitchen",
|
|
@@ -16336,7 +17167,7 @@ var OVERWRITES_EXTERNAL = {
|
|
|
16336
17167
|
idempotentHint: false,
|
|
16337
17168
|
openWorldHint: false
|
|
16338
17169
|
};
|
|
16339
|
-
var DailyControlStatusEnum =
|
|
17170
|
+
var DailyControlStatusEnum = z73.enum([
|
|
16340
17171
|
"ok",
|
|
16341
17172
|
"sales_unavailable",
|
|
16342
17173
|
"timezone_unavailable",
|
|
@@ -16349,19 +17180,19 @@ var DailyControlStatusEnum = z69.enum([
|
|
|
16349
17180
|
"product_missing",
|
|
16350
17181
|
"store_unreachable"
|
|
16351
17182
|
]);
|
|
16352
|
-
var DailyControlLightEnum =
|
|
17183
|
+
var DailyControlLightEnum = z73.enum([
|
|
16353
17184
|
"green",
|
|
16354
17185
|
"amber",
|
|
16355
17186
|
"red",
|
|
16356
17187
|
"none"
|
|
16357
17188
|
]);
|
|
16358
|
-
var DailyControlVerdictEnum =
|
|
17189
|
+
var DailyControlVerdictEnum = z73.enum([
|
|
16359
17190
|
"scale",
|
|
16360
17191
|
"hold",
|
|
16361
17192
|
"kill",
|
|
16362
17193
|
"insufficient_sample"
|
|
16363
17194
|
]);
|
|
16364
|
-
var DailyControlSourceEnum =
|
|
17195
|
+
var DailyControlSourceEnum = z73.enum([
|
|
16365
17196
|
"shopify",
|
|
16366
17197
|
"shopify_settling",
|
|
16367
17198
|
"user",
|
|
@@ -17502,29 +18333,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
|
|
|
17502
18333
|
__name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
|
|
17503
18334
|
|
|
17504
18335
|
// src/tools/media-presentation.ts
|
|
17505
|
-
import { z as
|
|
17506
|
-
var HttpsPresentationUrlSchema =
|
|
18336
|
+
import { z as z74 } from "zod";
|
|
18337
|
+
var HttpsPresentationUrlSchema = z74.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
|
|
17507
18338
|
var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
|
|
17508
18339
|
const hostname = new URL(value).hostname.toLowerCase();
|
|
17509
18340
|
return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
|
|
17510
18341
|
}, "preview URL must be owned by ProductMaker");
|
|
17511
|
-
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) =>
|
|
17512
|
-
var PresentationImageSchema =
|
|
17513
|
-
kind:
|
|
18342
|
+
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z74.number().int().positive().max(maximum), "positiveIntAtMost");
|
|
18343
|
+
var PresentationImageSchema = z74.object({
|
|
18344
|
+
kind: z74.literal("image"),
|
|
17514
18345
|
url: HttpsPresentationUrlSchema,
|
|
17515
|
-
mimeType:
|
|
18346
|
+
mimeType: z74.enum([
|
|
17516
18347
|
"image/jpeg",
|
|
17517
18348
|
"image/png"
|
|
17518
18349
|
]),
|
|
17519
18350
|
byteSize: positiveIntAtMost(5 * 1024 * 1024),
|
|
17520
18351
|
width: positiveIntAtMost(16384),
|
|
17521
18352
|
height: positiveIntAtMost(16384),
|
|
17522
|
-
alt:
|
|
18353
|
+
alt: z74.string().trim().min(1).max(240)
|
|
17523
18354
|
}).strict();
|
|
17524
18355
|
var McpMediaPresentationSchema = PresentationImageSchema;
|
|
17525
|
-
var GalleryImageSchema =
|
|
18356
|
+
var GalleryImageSchema = z74.object({
|
|
17526
18357
|
url: ProductMakerPreviewUrlSchema,
|
|
17527
|
-
alt:
|
|
18358
|
+
alt: z74.string().trim().min(1).max(240)
|
|
17528
18359
|
});
|
|
17529
18360
|
var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
|
|
17530
18361
|
async function imageBlocks(image, transport) {
|
|
@@ -17674,10 +18505,10 @@ ${summary}`,
|
|
|
17674
18505
|
__name(requirePaidCreativeConfirmation, "requirePaidCreativeConfirmation");
|
|
17675
18506
|
|
|
17676
18507
|
// src/tools/winning-product-image.ts
|
|
17677
|
-
import { z as
|
|
17678
|
-
var WinnerReferenceInput =
|
|
17679
|
-
runId:
|
|
17680
|
-
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)
|
|
17681
18512
|
}).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
|
|
17682
18513
|
async function resolveWinnerImages(api, winnerReference, images) {
|
|
17683
18514
|
if (!winnerReference) return images;
|
|
@@ -17714,59 +18545,59 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
|
|
|
17714
18545
|
var createServiceVideoGuidance = getProductMakerCapabilityModelGuidance("create_service_video");
|
|
17715
18546
|
var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
|
|
17716
18547
|
var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
|
|
17717
|
-
var CreateProductTaskInput =
|
|
18548
|
+
var CreateProductTaskInput = z76.object({
|
|
17718
18549
|
images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
|
|
17719
18550
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
17720
|
-
projectId:
|
|
17721
|
-
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."),
|
|
17722
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.'),
|
|
17723
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.'),
|
|
17724
|
-
price:
|
|
17725
|
-
compareAtPrice:
|
|
17726
|
-
offer:
|
|
17727
|
-
paymentMethods:
|
|
17728
|
-
productContext:
|
|
17729
|
-
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.'),
|
|
17730
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.'),
|
|
17731
|
-
durationSeconds:
|
|
17732
|
-
|
|
17733
|
-
|
|
18562
|
+
durationSeconds: z76.union([
|
|
18563
|
+
z76.literal(15),
|
|
18564
|
+
z76.literal(30)
|
|
17734
18565
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
17735
|
-
pauseForAngleReview:
|
|
17736
|
-
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."),
|
|
17737
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.'),
|
|
17738
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.'),
|
|
17739
18570
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
17740
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).'),
|
|
17741
|
-
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."),
|
|
17742
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.'),
|
|
17743
|
-
outputs:
|
|
18574
|
+
outputs: z76.array(z76.enum([
|
|
17744
18575
|
"landing",
|
|
17745
18576
|
"video",
|
|
17746
18577
|
"image"
|
|
17747
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}`),
|
|
17748
|
-
competitorScanEnabled:
|
|
17749
|
-
replicateWinnerWhenFound:
|
|
17750
|
-
brandId:
|
|
17751
|
-
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."),
|
|
17752
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.'),
|
|
17753
|
-
creativeDirection:
|
|
17754
|
-
headline:
|
|
17755
|
-
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."),
|
|
17756
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".'),
|
|
17757
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".')
|
|
17758
18589
|
}).strict();
|
|
17759
|
-
var CreateServiceVideoInput =
|
|
17760
|
-
landingUrl:
|
|
17761
|
-
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.'),
|
|
17762
18593
|
language: Lang.describe("Idioma del video: es, en o pt."),
|
|
17763
|
-
voiceId:
|
|
17764
|
-
brandId:
|
|
17765
|
-
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([
|
|
17766
18597
|
"automatic",
|
|
17767
18598
|
"guided"
|
|
17768
18599
|
]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
|
|
17769
|
-
videoPreset:
|
|
18600
|
+
videoPreset: z76.enum([
|
|
17770
18601
|
"auto",
|
|
17771
18602
|
"ugc_dynamic",
|
|
17772
18603
|
"ugc_how_to",
|
|
@@ -17776,128 +18607,128 @@ var CreateServiceVideoInput = z72.object({
|
|
|
17776
18607
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
17777
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.')
|
|
17778
18609
|
}).strict();
|
|
17779
|
-
var GetTaskStatusInput =
|
|
17780
|
-
taskId:
|
|
17781
|
-
waitSeconds:
|
|
18610
|
+
var GetTaskStatusInput = z76.object({
|
|
18611
|
+
taskId: z76.string().min(1),
|
|
18612
|
+
waitSeconds: z76.number().int().min(0).max(120).optional()
|
|
17782
18613
|
});
|
|
17783
|
-
var ListTasksInput =
|
|
17784
|
-
limit:
|
|
17785
|
-
offset:
|
|
17786
|
-
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()
|
|
17787
18618
|
});
|
|
17788
18619
|
var MCP_REVIEW_LIST_FIELD_MAX = 1500;
|
|
17789
18620
|
var MCP_REVIEW_FEATURE_ITEM_MAX = 240;
|
|
17790
|
-
var EditTaskDraftInput =
|
|
17791
|
-
taskId:
|
|
17792
|
-
angleIndex:
|
|
17793
|
-
angle:
|
|
17794
|
-
angle:
|
|
17795
|
-
buyerPersona:
|
|
17796
|
-
actor:
|
|
17797
|
-
actorId:
|
|
17798
|
-
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([
|
|
17799
18630
|
"female",
|
|
17800
18631
|
"male"
|
|
17801
18632
|
]).optional(),
|
|
17802
|
-
scriptNotes:
|
|
18633
|
+
scriptNotes: z76.string().max(2e3).optional()
|
|
17803
18634
|
})
|
|
17804
18635
|
});
|
|
17805
|
-
var PendingActionPayload =
|
|
17806
|
-
|
|
17807
|
-
kind:
|
|
18636
|
+
var PendingActionPayload = z76.discriminatedUnion("kind", [
|
|
18637
|
+
z76.object({
|
|
18638
|
+
kind: z76.literal("product_reference_set_approval"),
|
|
17808
18639
|
scope: ProductReferenceScopeEnum.optional(),
|
|
17809
|
-
scopeKey:
|
|
17810
|
-
scopeSnapshotId:
|
|
17811
|
-
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(),
|
|
17812
18643
|
decision: ProductReferenceResolutionDecisionEnum,
|
|
17813
18644
|
reason: ProductReferenceRejectionReasonEnum.optional(),
|
|
17814
|
-
affectedRefKeys:
|
|
17815
|
-
affectedPhotoNumbers:
|
|
17816
|
-
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([
|
|
17817
18648
|
"remove",
|
|
17818
18649
|
"replace",
|
|
17819
18650
|
"upload",
|
|
17820
18651
|
"return_to_selection"
|
|
17821
18652
|
]).optional()
|
|
17822
18653
|
}),
|
|
17823
|
-
|
|
17824
|
-
kind:
|
|
17825
|
-
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."),
|
|
17826
18657
|
userChoice: ProductReferenceUserChoiceEnum.optional(),
|
|
17827
|
-
confirmedProductNames:
|
|
18658
|
+
confirmedProductNames: z76.array(z76.string().min(1).max(120)).min(2).max(8).optional(),
|
|
17828
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."),
|
|
17829
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."),
|
|
17830
|
-
useMultiSceneShowcase:
|
|
18661
|
+
useMultiSceneShowcase: z76.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
|
|
17831
18662
|
}),
|
|
17832
|
-
|
|
17833
|
-
kind:
|
|
18663
|
+
z76.object({
|
|
18664
|
+
kind: z76.literal("angle_review_approval"),
|
|
17834
18665
|
// All edits are optional — empty action body just approves the
|
|
17835
18666
|
// backend-generated draft as-is. Field shapes mirror the angle-review
|
|
17836
18667
|
// request contracts in @packages/types/wizard.ts; the handler routes to
|
|
17837
18668
|
// the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
|
|
17838
|
-
customAngle:
|
|
18669
|
+
customAngle: z76.string().min(1).max(480).optional(),
|
|
17839
18670
|
// Keep the shared MCP action within the strictest downstream contract:
|
|
17840
18671
|
// autopilot/image resume endpoints cap these fields at 1500 characters.
|
|
17841
|
-
painPoints:
|
|
17842
|
-
benefits:
|
|
18672
|
+
painPoints: z76.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
18673
|
+
benefits: z76.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
17843
18674
|
// Same policy as the two fields above: the strictest downstream contract
|
|
17844
18675
|
// wins. The image endpoint caps each feature at 240 while landing/video
|
|
17845
18676
|
// accept 300, and this single action routes to whichever the task is — so
|
|
17846
18677
|
// accepting 300 here turns a 250-character feature on an image task into
|
|
17847
18678
|
// an opaque HTTP 400 after the model already believed it had been saved.
|
|
17848
|
-
features:
|
|
17849
|
-
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(),
|
|
17850
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.'),
|
|
17851
|
-
actor:
|
|
17852
|
-
actorId:
|
|
17853
|
-
creativeDirection:
|
|
17854
|
-
selectedAngleNumbers:
|
|
17855
|
-
angleEdits:
|
|
17856
|
-
angleNumber:
|
|
17857
|
-
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([
|
|
17858
18689
|
"market",
|
|
17859
18690
|
"guided"
|
|
17860
18691
|
]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
|
|
17861
|
-
angle:
|
|
17862
|
-
buyerPersona:
|
|
18692
|
+
angle: z76.string().min(1).max(480).optional(),
|
|
18693
|
+
buyerPersona: z76.string().min(1).max(360).optional(),
|
|
17863
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.'),
|
|
17864
|
-
actor:
|
|
17865
|
-
actorId:
|
|
17866
|
-
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()
|
|
17867
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)."),
|
|
17868
|
-
gapDurationSeconds:
|
|
17869
|
-
|
|
17870
|
-
|
|
18699
|
+
gapDurationSeconds: z76.union([
|
|
18700
|
+
z76.literal(15),
|
|
18701
|
+
z76.literal(30)
|
|
17871
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.")
|
|
17872
18703
|
}),
|
|
17873
|
-
|
|
17874
|
-
kind:
|
|
17875
|
-
angleId:
|
|
17876
|
-
angleNumber:
|
|
17877
|
-
content:
|
|
17878
|
-
creativeDirection:
|
|
17879
|
-
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()
|
|
17880
18711
|
}),
|
|
17881
|
-
|
|
17882
|
-
kind:
|
|
17883
|
-
voiceovers:
|
|
17884
|
-
visualDirections:
|
|
17885
|
-
voiceoversByScene:
|
|
17886
|
-
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()
|
|
17887
18718
|
})
|
|
17888
18719
|
]);
|
|
17889
|
-
var ResolvePendingActionInput =
|
|
17890
|
-
taskId:
|
|
18720
|
+
var ResolvePendingActionInput = z76.object({
|
|
18721
|
+
taskId: z76.string().min(1),
|
|
17891
18722
|
action: PendingActionPayload
|
|
17892
18723
|
}).strict();
|
|
17893
18724
|
function resolveVariantConfirmVideoTier(action) {
|
|
17894
18725
|
return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
|
|
17895
18726
|
}
|
|
17896
18727
|
__name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
|
|
17897
|
-
var StatusForResolveSchema =
|
|
18728
|
+
var StatusForResolveSchema = z76.object({
|
|
17898
18729
|
// Metadata used to select the backend resume contract. Older API responses
|
|
17899
18730
|
// may omit these fields, so the resolver keeps the generic fallback.
|
|
17900
|
-
kind:
|
|
18731
|
+
kind: z76.enum([
|
|
17901
18732
|
"autopilot",
|
|
17902
18733
|
"video",
|
|
17903
18734
|
"image",
|
|
@@ -17905,18 +18736,18 @@ var StatusForResolveSchema = z72.object({
|
|
|
17905
18736
|
"mix",
|
|
17906
18737
|
"service"
|
|
17907
18738
|
]).optional(),
|
|
17908
|
-
selectedOutputs:
|
|
18739
|
+
selectedOutputs: z76.array(z76.enum([
|
|
17909
18740
|
"landing",
|
|
17910
18741
|
"video",
|
|
17911
18742
|
"image"
|
|
17912
18743
|
])).optional(),
|
|
17913
|
-
videoAngleCount:
|
|
17914
|
-
ugcFormat:
|
|
18744
|
+
videoAngleCount: z76.number().int().min(1).max(3).optional(),
|
|
18745
|
+
ugcFormat: z76.enum([
|
|
17915
18746
|
"single_8s",
|
|
17916
18747
|
"single_15s",
|
|
17917
18748
|
"double_30s"
|
|
17918
18749
|
]).optional(),
|
|
17919
|
-
videoStyle:
|
|
18750
|
+
videoStyle: z76.enum([
|
|
17920
18751
|
"ugc",
|
|
17921
18752
|
"cartoon_3d",
|
|
17922
18753
|
"product_only",
|
|
@@ -17925,79 +18756,72 @@ var StatusForResolveSchema = z72.object({
|
|
|
17925
18756
|
videoStructure: VideoStructureEnum.optional(),
|
|
17926
18757
|
videoQuality: VideoQualityEnum.optional(),
|
|
17927
18758
|
videoRouteId: VideoRouteIdEnum.optional(),
|
|
17928
|
-
videoModel:
|
|
17929
|
-
|
|
17930
|
-
"wan",
|
|
17931
|
-
"bytedance",
|
|
17932
|
-
"seedance",
|
|
17933
|
-
"grok",
|
|
17934
|
-
"kling"
|
|
17935
|
-
]).optional(),
|
|
17936
|
-
videoTier: z72.enum([
|
|
18759
|
+
videoModel: TaskVideoModelEnum.optional(),
|
|
18760
|
+
videoTier: z76.enum([
|
|
17937
18761
|
"legacy",
|
|
17938
18762
|
"standard",
|
|
17939
18763
|
"pro",
|
|
17940
18764
|
"single_call"
|
|
17941
18765
|
]).optional(),
|
|
17942
|
-
videoResolution:
|
|
18766
|
+
videoResolution: z76.enum([
|
|
17943
18767
|
"480p",
|
|
17944
18768
|
"720p"
|
|
17945
18769
|
]).optional(),
|
|
17946
18770
|
narrativeStyle: NarrativeStyleEnum.optional(),
|
|
17947
|
-
pauseForVideoScriptReview:
|
|
17948
|
-
pendingUserAction:
|
|
17949
|
-
kind:
|
|
17950
|
-
candidateGrouping:
|
|
17951
|
-
selectedImageUrls:
|
|
17952
|
-
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(),
|
|
17953
18777
|
// Adaptive reference questions are server-owned. Echo only the evidence
|
|
17954
18778
|
// identity and the choices shown by the current snapshot; never accept a
|
|
17955
18779
|
// client-supplied reference set as authorization.
|
|
17956
|
-
options:
|
|
17957
|
-
mode:
|
|
18780
|
+
options: z76.array(ProductReferenceUserChoiceEnum).max(4).optional(),
|
|
18781
|
+
mode: z76.enum([
|
|
17958
18782
|
"question",
|
|
17959
18783
|
"visual_recovery"
|
|
17960
18784
|
]).optional(),
|
|
17961
18785
|
/** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
|
|
17962
|
-
canKeepSelection:
|
|
17963
|
-
decisionKey:
|
|
17964
|
-
questionOrdinal:
|
|
17965
|
-
questionCeiling:
|
|
17966
|
-
|
|
17967
|
-
|
|
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)
|
|
17968
18792
|
]).optional(),
|
|
17969
|
-
referenceEvidenceVersion:
|
|
17970
|
-
expectedEvidenceHash:
|
|
17971
|
-
question:
|
|
17972
|
-
prompt:
|
|
17973
|
-
helpText:
|
|
17974
|
-
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({
|
|
17975
18799
|
value: ProductReferenceUserChoiceEnum,
|
|
17976
|
-
label:
|
|
17977
|
-
description:
|
|
18800
|
+
label: z76.string().min(1).max(120),
|
|
18801
|
+
description: z76.string().min(1).max(240).optional()
|
|
17978
18802
|
})).min(2).max(4)
|
|
17979
18803
|
}).optional(),
|
|
17980
18804
|
scope: ProductReferenceScopeEnum.optional(),
|
|
17981
|
-
scopeKey:
|
|
17982
|
-
scopeSnapshotId:
|
|
17983
|
-
scopeHash:
|
|
17984
|
-
baseReferenceSetHash:
|
|
17985
|
-
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([
|
|
17986
18810
|
"preparation",
|
|
17987
18811
|
"final"
|
|
17988
18812
|
]).optional(),
|
|
17989
|
-
selectedRefKeys:
|
|
17990
|
-
allowedDecisions:
|
|
17991
|
-
previews:
|
|
17992
|
-
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)
|
|
17993
18817
|
}).passthrough()).optional(),
|
|
17994
|
-
customAngleDraft:
|
|
17995
|
-
painPointsDraft:
|
|
17996
|
-
benefitsDraft:
|
|
17997
|
-
featuresDraft:
|
|
17998
|
-
angleOptions:
|
|
17999
|
-
index:
|
|
18000
|
-
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)
|
|
18001
18825
|
}).passthrough()).min(1).max(5).optional(),
|
|
18002
18826
|
// Recommendation consumed only when the caller explicitly sends
|
|
18003
18827
|
// gapDurationSeconds: 30 in the angle approval action.
|
|
@@ -18007,17 +18831,17 @@ var StatusForResolveSchema = z72.object({
|
|
|
18007
18831
|
// keys. `actorId` (the saved custom actor the picker stored) was silently
|
|
18008
18832
|
// dropped here, so the approval handler below could not echo it back on the
|
|
18009
18833
|
// PATCH — the selection looked accepted and reached no render.
|
|
18010
|
-
angles:
|
|
18011
|
-
id:
|
|
18012
|
-
content:
|
|
18013
|
-
creativeDirection:
|
|
18014
|
-
actor:
|
|
18015
|
-
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()
|
|
18016
18840
|
}).passthrough()).optional(),
|
|
18017
|
-
panels:
|
|
18018
|
-
beatId:
|
|
18019
|
-
voiceover:
|
|
18020
|
-
visualDirection:
|
|
18841
|
+
panels: z76.array(z76.object({
|
|
18842
|
+
beatId: z76.string(),
|
|
18843
|
+
voiceover: z76.string(),
|
|
18844
|
+
visualDirection: z76.string()
|
|
18021
18845
|
}).passthrough()).optional()
|
|
18022
18846
|
}).optional()
|
|
18023
18847
|
}).passthrough();
|
|
@@ -18852,7 +19676,7 @@ __name(registerTaskTools, "registerTaskTools");
|
|
|
18852
19676
|
|
|
18853
19677
|
// src/tools/creatives.ts
|
|
18854
19678
|
import { randomUUID } from "crypto";
|
|
18855
|
-
import { z as
|
|
19679
|
+
import { z as z77 } from "zod";
|
|
18856
19680
|
var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
|
|
18857
19681
|
var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
|
|
18858
19682
|
var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
|
|
@@ -18862,70 +19686,70 @@ var CreativeRefs = {
|
|
|
18862
19686
|
images: ImagesInput,
|
|
18863
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.'),
|
|
18864
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.'),
|
|
18865
|
-
price:
|
|
18866
|
-
offer:
|
|
18867
|
-
compareAtPrice:
|
|
18868
|
-
productContext:
|
|
18869
|
-
productLabel:
|
|
18870
|
-
buyerPersona:
|
|
18871
|
-
isCombo:
|
|
18872
|
-
competitorScanEnabled:
|
|
18873
|
-
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.")
|
|
18874
19698
|
};
|
|
18875
|
-
var VideoPresenter =
|
|
18876
|
-
|
|
18877
|
-
mode:
|
|
19699
|
+
var VideoPresenter = z77.discriminatedUnion("mode", [
|
|
19700
|
+
z77.object({
|
|
19701
|
+
mode: z77.literal("none")
|
|
18878
19702
|
}).strict(),
|
|
18879
|
-
|
|
18880
|
-
mode:
|
|
18881
|
-
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.")
|
|
18882
19706
|
}).strict(),
|
|
18883
|
-
|
|
18884
|
-
mode:
|
|
18885
|
-
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.")
|
|
18886
19710
|
}).strict()
|
|
18887
19711
|
]);
|
|
18888
|
-
var VideoCreativeSetup =
|
|
18889
|
-
|
|
18890
|
-
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".')
|
|
18891
19715
|
}).strict(),
|
|
18892
|
-
|
|
18893
|
-
mode:
|
|
19716
|
+
z77.object({
|
|
19717
|
+
mode: z77.literal("guided"),
|
|
18894
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.'),
|
|
18895
|
-
buyerPersona:
|
|
19719
|
+
buyerPersona: z77.string().trim().min(1).max(360),
|
|
18896
19720
|
presenter: VideoPresenter,
|
|
18897
|
-
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.")
|
|
18898
19722
|
}).strict()
|
|
18899
19723
|
]);
|
|
18900
|
-
var VideoInput =
|
|
19724
|
+
var VideoInput = z77.object({
|
|
18901
19725
|
images: CreativeRefs.images.optional(),
|
|
18902
19726
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
18903
|
-
title:
|
|
18904
|
-
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".'),
|
|
18905
19729
|
language: CreativeRefs.language,
|
|
18906
19730
|
country: CreativeRefs.country,
|
|
18907
|
-
aspectRatio:
|
|
19731
|
+
aspectRatio: z77.enum([
|
|
18908
19732
|
"9:16",
|
|
18909
19733
|
"16:9",
|
|
18910
19734
|
"Auto"
|
|
18911
19735
|
]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
|
|
18912
|
-
durationSeconds:
|
|
18913
|
-
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."),
|
|
18914
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.'),
|
|
18915
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."),
|
|
18916
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.'),
|
|
18917
19741
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
|
|
18918
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.'),
|
|
18919
|
-
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"].'),
|
|
18920
19744
|
price: CreativeRefs.price,
|
|
18921
19745
|
offer: CreativeRefs.offer,
|
|
18922
19746
|
productContext: CreativeRefs.productContext,
|
|
18923
19747
|
productLabel: CreativeRefs.productLabel,
|
|
18924
|
-
cta:
|
|
18925
|
-
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.'),
|
|
18926
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.'),
|
|
18927
19751
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
18928
|
-
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."),
|
|
18929
19753
|
brandId: CreativeRefs.brandId
|
|
18930
19754
|
}).strict();
|
|
18931
19755
|
var FreeVideoQualityEnum = VideoQualityEnum;
|
|
@@ -18943,7 +19767,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
|
|
|
18943
19767
|
length: 29
|
|
18944
19768
|
}, (_, index) => index + 2)
|
|
18945
19769
|
};
|
|
18946
|
-
var FreeVideoModelIdEnum =
|
|
19770
|
+
var FreeVideoModelIdEnum = z77.enum([
|
|
18947
19771
|
"grok-imagine-video-1-5-preview",
|
|
18948
19772
|
"minimax-h3/reference-to-video",
|
|
18949
19773
|
"wan/3-0-video",
|
|
@@ -18954,70 +19778,65 @@ var FREE_SELECTABLE_MODEL_IDS = [
|
|
|
18954
19778
|
"minimax-h3/reference-to-video",
|
|
18955
19779
|
"wan/3-0-video"
|
|
18956
19780
|
];
|
|
18957
|
-
var FreeVideoInput =
|
|
19781
|
+
var FreeVideoInput = z77.object({
|
|
18958
19782
|
images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
|
|
18959
|
-
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."),
|
|
18960
19784
|
language: CreativeRefs.language,
|
|
18961
19785
|
quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
|
|
18962
19786
|
// Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
|
|
18963
19787
|
// parsed ONLY so the handler can reject it with a message naming its
|
|
18964
19788
|
// replacement — dropping it silently would turn a caller's explicit
|
|
18965
19789
|
// Pro++ pick into a quiet fallback to Wan.
|
|
18966
|
-
freeProModel:
|
|
19790
|
+
freeProModel: z77.enum([
|
|
18967
19791
|
"wan",
|
|
18968
19792
|
"seedance"
|
|
18969
19793
|
]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
|
|
18970
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.'),
|
|
18971
|
-
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."),
|
|
18972
19796
|
videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
|
|
18973
|
-
generateAiMusic:
|
|
18974
|
-
addSubtitles:
|
|
18975
|
-
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.")
|
|
18976
19800
|
}).strict();
|
|
18977
19801
|
var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
|
|
18978
|
-
var ImageCreativeSetup =
|
|
18979
|
-
|
|
18980
|
-
mode:
|
|
19802
|
+
var ImageCreativeSetup = z77.discriminatedUnion("mode", [
|
|
19803
|
+
z77.object({
|
|
19804
|
+
mode: z77.literal("automatic")
|
|
18981
19805
|
}).strict(),
|
|
18982
|
-
|
|
18983
|
-
mode:
|
|
18984
|
-
creativeArchetype:
|
|
19806
|
+
z77.object({
|
|
19807
|
+
mode: z77.literal("guided"),
|
|
19808
|
+
creativeArchetype: z77.union([
|
|
18985
19809
|
ImageCreativeArchetypeEnum,
|
|
18986
|
-
|
|
19810
|
+
z77.literal("ai_decides")
|
|
18987
19811
|
]),
|
|
18988
|
-
visualTreatment:
|
|
19812
|
+
visualTreatment: z77.union([
|
|
18989
19813
|
ImageCreativeVisualTreatmentEnum,
|
|
18990
|
-
|
|
19814
|
+
z77.literal("ai_decides")
|
|
18991
19815
|
]),
|
|
18992
19816
|
aspectRatio: ImageCreativeAspectRatioEnum,
|
|
18993
|
-
nVariants:
|
|
18994
|
-
|
|
18995
|
-
|
|
18996
|
-
|
|
18997
|
-
|
|
18998
|
-
|
|
18999
|
-
]),
|
|
19000
|
-
imageModel: z73.enum([
|
|
19001
|
-
"gpt-image-2-5:1k",
|
|
19002
|
-
"gpt-image-2-5:2k",
|
|
19003
|
-
"gpt-image-2:1k",
|
|
19004
|
-
"gpt-image-2:2k"
|
|
19817
|
+
nVariants: z77.union([
|
|
19818
|
+
z77.literal(1),
|
|
19819
|
+
z77.literal(2),
|
|
19820
|
+
z77.literal(3),
|
|
19821
|
+
z77.literal(4),
|
|
19822
|
+
z77.literal(6)
|
|
19005
19823
|
]),
|
|
19006
|
-
|
|
19007
|
-
|
|
19008
|
-
|
|
19009
|
-
|
|
19010
|
-
|
|
19011
|
-
|
|
19012
|
-
|
|
19013
|
-
|
|
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()
|
|
19014
19833
|
}).strict()
|
|
19015
19834
|
]).superRefine((setup, context) => {
|
|
19016
19835
|
if (setup.mode !== "guided") return;
|
|
19017
19836
|
const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
|
|
19018
19837
|
if (needsStyleMix && setup.styleMix === null) {
|
|
19019
19838
|
context.addIssue({
|
|
19020
|
-
code:
|
|
19839
|
+
code: z77.ZodIssueCode.custom,
|
|
19021
19840
|
path: [
|
|
19022
19841
|
"styleMix"
|
|
19023
19842
|
],
|
|
@@ -19026,16 +19845,16 @@ var ImageCreativeSetup = z73.discriminatedUnion("mode", [
|
|
|
19026
19845
|
}
|
|
19027
19846
|
if (!needsStyleMix && setup.styleMix !== null) {
|
|
19028
19847
|
context.addIssue({
|
|
19029
|
-
code:
|
|
19848
|
+
code: z77.ZodIssueCode.custom,
|
|
19030
19849
|
path: [
|
|
19031
19850
|
"styleMix"
|
|
19032
19851
|
],
|
|
19033
19852
|
message: "styleMix debe ser null cuando nVariants es 1 o 6."
|
|
19034
19853
|
});
|
|
19035
19854
|
}
|
|
19036
|
-
if ((setup.imageModel === "
|
|
19855
|
+
if (imageResolutionOf(setup.imageModel) === "2k" && setup.aspectRatio === "4:5") {
|
|
19037
19856
|
context.addIssue({
|
|
19038
|
-
code:
|
|
19857
|
+
code: z77.ZodIssueCode.custom,
|
|
19039
19858
|
path: [
|
|
19040
19859
|
"aspectRatio"
|
|
19041
19860
|
],
|
|
@@ -19043,53 +19862,53 @@ var ImageCreativeSetup = z73.discriminatedUnion("mode", [
|
|
|
19043
19862
|
});
|
|
19044
19863
|
}
|
|
19045
19864
|
});
|
|
19046
|
-
var LandingCreativeSetup =
|
|
19047
|
-
|
|
19048
|
-
mode:
|
|
19865
|
+
var LandingCreativeSetup = z77.discriminatedUnion("mode", [
|
|
19866
|
+
z77.object({
|
|
19867
|
+
mode: z77.literal("automatic")
|
|
19049
19868
|
}).strict(),
|
|
19050
|
-
|
|
19051
|
-
mode:
|
|
19869
|
+
z77.object({
|
|
19870
|
+
mode: z77.literal("guided"),
|
|
19052
19871
|
landingStrategy: LandingStrategyEnum,
|
|
19053
19872
|
landingImageFormat: LandingImageFormatEnum,
|
|
19054
|
-
competitorScanEnabled:
|
|
19055
|
-
paymentMethods:
|
|
19056
|
-
productContext:
|
|
19057
|
-
creativeDirection:
|
|
19058
|
-
headline:
|
|
19059
|
-
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()
|
|
19060
19879
|
}).strict()
|
|
19061
19880
|
]);
|
|
19062
|
-
var ImageInput =
|
|
19881
|
+
var ImageInput = z77.object({
|
|
19063
19882
|
images: CreativeRefs.images.optional(),
|
|
19064
19883
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
19065
|
-
productTitle:
|
|
19066
|
-
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.'),
|
|
19067
19886
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
19068
19887
|
language: CreativeRefs.language,
|
|
19069
19888
|
country: CreativeRefs.country,
|
|
19070
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."),
|
|
19071
19890
|
imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
|
|
19072
|
-
features:
|
|
19891
|
+
features: z77.array(z77.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
|
|
19073
19892
|
price: CreativeRefs.price,
|
|
19074
|
-
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."),
|
|
19075
19894
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
19076
19895
|
offer: CreativeRefs.offer,
|
|
19077
19896
|
productLabel: CreativeRefs.productLabel,
|
|
19078
19897
|
isCombo: CreativeRefs.isCombo,
|
|
19079
19898
|
brandId: CreativeRefs.brandId
|
|
19080
19899
|
});
|
|
19081
|
-
var EditImageCreativeInput =
|
|
19082
|
-
taskId:
|
|
19083
|
-
variantIndex:
|
|
19084
|
-
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".')
|
|
19085
19904
|
});
|
|
19086
|
-
var LandingInput =
|
|
19905
|
+
var LandingInput = z77.object({
|
|
19087
19906
|
images: CreativeRefs.images.optional(),
|
|
19088
19907
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
19089
19908
|
language: CreativeRefs.language,
|
|
19090
19909
|
country: CreativeRefs.country,
|
|
19091
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."),
|
|
19092
|
-
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.'),
|
|
19093
19912
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
19094
19913
|
price: CreativeRefs.price,
|
|
19095
19914
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
@@ -19108,7 +19927,7 @@ function resolveImageSetup(setup) {
|
|
|
19108
19927
|
},
|
|
19109
19928
|
aspectRatio: setup.aspectRatio,
|
|
19110
19929
|
nVariants: setup.nVariants,
|
|
19111
|
-
imageModel: setup.imageModel,
|
|
19930
|
+
imageModel: canonicalImageModelInput(setup.imageModel),
|
|
19112
19931
|
...setup.nVariants === 6 ? {
|
|
19113
19932
|
styleMix: true
|
|
19114
19933
|
} : setup.styleMix === null ? {} : {
|
|
@@ -19351,10 +20170,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
19351
20170
|
__name(registerCreativeTools, "registerCreativeTools");
|
|
19352
20171
|
|
|
19353
20172
|
// src/tools/creative-variants.ts
|
|
19354
|
-
import { z as
|
|
20173
|
+
import { z as z78 } from "zod";
|
|
19355
20174
|
var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
|
|
19356
20175
|
var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
|
|
19357
|
-
var LandingSectionKeyEnum =
|
|
20176
|
+
var LandingSectionKeyEnum = z78.enum([
|
|
19358
20177
|
"problem_hook",
|
|
19359
20178
|
"problem_cost",
|
|
19360
20179
|
"solution_mechanism",
|
|
@@ -19394,24 +20213,24 @@ var LandingSectionKeyEnum = z74.enum([
|
|
|
19394
20213
|
"lifestyle_fit",
|
|
19395
20214
|
"join_lifestyle"
|
|
19396
20215
|
]);
|
|
19397
|
-
var CreativeVariantKindEnum =
|
|
20216
|
+
var CreativeVariantKindEnum = z78.enum([
|
|
19398
20217
|
"video",
|
|
19399
20218
|
"image",
|
|
19400
20219
|
"landing"
|
|
19401
20220
|
]);
|
|
19402
|
-
var EstimateCreativeVariantInputBase =
|
|
19403
|
-
sourceTaskId:
|
|
20221
|
+
var EstimateCreativeVariantInputBase = z78.object({
|
|
20222
|
+
sourceTaskId: z78.string().uuid().describe("ID de la tarea original completada."),
|
|
19404
20223
|
kind: CreativeVariantKindEnum,
|
|
19405
20224
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
|
|
19406
20225
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
|
|
19407
|
-
nVariants:
|
|
20226
|
+
nVariants: z78.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
19408
20227
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
|
|
19409
|
-
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.")
|
|
19410
20229
|
}).strict();
|
|
19411
20230
|
var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
19412
20231
|
if (input.kind === "video" && input.nVariants !== void 0) {
|
|
19413
20232
|
ctx.addIssue({
|
|
19414
|
-
code:
|
|
20233
|
+
code: z78.ZodIssueCode.custom,
|
|
19415
20234
|
path: [
|
|
19416
20235
|
"nVariants"
|
|
19417
20236
|
],
|
|
@@ -19421,7 +20240,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19421
20240
|
if (input.kind !== "video") {
|
|
19422
20241
|
if (input.videoPreset !== void 0) {
|
|
19423
20242
|
ctx.addIssue({
|
|
19424
|
-
code:
|
|
20243
|
+
code: z78.ZodIssueCode.custom,
|
|
19425
20244
|
path: [
|
|
19426
20245
|
"videoPreset"
|
|
19427
20246
|
],
|
|
@@ -19430,7 +20249,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19430
20249
|
}
|
|
19431
20250
|
if (input.videoResolution !== void 0) {
|
|
19432
20251
|
ctx.addIssue({
|
|
19433
|
-
code:
|
|
20252
|
+
code: z78.ZodIssueCode.custom,
|
|
19434
20253
|
path: [
|
|
19435
20254
|
"videoResolution"
|
|
19436
20255
|
],
|
|
@@ -19440,7 +20259,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19440
20259
|
}
|
|
19441
20260
|
if (input.kind !== "image" && input.nVariants !== void 0) {
|
|
19442
20261
|
ctx.addIssue({
|
|
19443
|
-
code:
|
|
20262
|
+
code: z78.ZodIssueCode.custom,
|
|
19444
20263
|
path: [
|
|
19445
20264
|
"nVariants"
|
|
19446
20265
|
],
|
|
@@ -19450,7 +20269,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19450
20269
|
if (input.kind !== "landing") {
|
|
19451
20270
|
if (input.sectionKey !== void 0) {
|
|
19452
20271
|
ctx.addIssue({
|
|
19453
|
-
code:
|
|
20272
|
+
code: z78.ZodIssueCode.custom,
|
|
19454
20273
|
path: [
|
|
19455
20274
|
"sectionKey"
|
|
19456
20275
|
],
|
|
@@ -19459,7 +20278,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19459
20278
|
}
|
|
19460
20279
|
if (input.instructions !== void 0) {
|
|
19461
20280
|
ctx.addIssue({
|
|
19462
|
-
code:
|
|
20281
|
+
code: z78.ZodIssueCode.custom,
|
|
19463
20282
|
path: [
|
|
19464
20283
|
"instructions"
|
|
19465
20284
|
],
|
|
@@ -19468,31 +20287,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19468
20287
|
}
|
|
19469
20288
|
}
|
|
19470
20289
|
});
|
|
19471
|
-
var CreateCreativeVariantInputBase =
|
|
19472
|
-
sourceTaskId:
|
|
20290
|
+
var CreateCreativeVariantInputBase = z78.object({
|
|
20291
|
+
sourceTaskId: z78.string().uuid().describe("ID de la tarea original completada."),
|
|
19473
20292
|
kind: CreativeVariantKindEnum,
|
|
19474
|
-
confirm:
|
|
19475
|
-
clientRequestId:
|
|
19476
|
-
angle:
|
|
19477
|
-
buyerPersona:
|
|
19478
|
-
scriptNotes:
|
|
19479
|
-
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."),
|
|
19480
20299
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
|
|
19481
20300
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
|
|
19482
|
-
generateAiMusic:
|
|
19483
|
-
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)."),
|
|
19484
20303
|
imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
|
|
19485
20304
|
creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
|
|
19486
20305
|
visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
|
|
19487
20306
|
aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
|
|
19488
|
-
styleMix:
|
|
20307
|
+
styleMix: z78.boolean().optional().describe("Opcional para imagen."),
|
|
19489
20308
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
|
|
19490
|
-
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.")
|
|
19491
20310
|
}).strict();
|
|
19492
20311
|
var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
19493
20312
|
if ((input.kind === "video" || input.kind === "image") && !input.angle) {
|
|
19494
20313
|
ctx.addIssue({
|
|
19495
|
-
code:
|
|
20314
|
+
code: z78.ZodIssueCode.custom,
|
|
19496
20315
|
path: [
|
|
19497
20316
|
"angle"
|
|
19498
20317
|
],
|
|
@@ -19501,7 +20320,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
19501
20320
|
}
|
|
19502
20321
|
if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
|
|
19503
20322
|
ctx.addIssue({
|
|
19504
|
-
code:
|
|
20323
|
+
code: z78.ZodIssueCode.custom,
|
|
19505
20324
|
path: [
|
|
19506
20325
|
"instructions"
|
|
19507
20326
|
],
|
|
@@ -19547,7 +20366,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
19547
20366
|
for (const field of fieldsByKind[input.kind]) {
|
|
19548
20367
|
if (input[field] !== void 0) {
|
|
19549
20368
|
ctx.addIssue({
|
|
19550
|
-
code:
|
|
20369
|
+
code: z78.ZodIssueCode.custom,
|
|
19551
20370
|
path: [
|
|
19552
20371
|
field
|
|
19553
20372
|
],
|
|
@@ -19664,32 +20483,32 @@ function registerCreativeVariantTools(server, api) {
|
|
|
19664
20483
|
__name(registerCreativeVariantTools, "registerCreativeVariantTools");
|
|
19665
20484
|
|
|
19666
20485
|
// src/tools/script-review.ts
|
|
19667
|
-
import { z as
|
|
20486
|
+
import { z as z79 } from "zod";
|
|
19668
20487
|
var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
|
|
19669
20488
|
var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
|
|
19670
20489
|
var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
|
|
19671
|
-
var GetVideoScriptInput =
|
|
19672
|
-
taskId:
|
|
19673
|
-
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.')
|
|
19674
20493
|
}).strict();
|
|
19675
20494
|
var VIDEO_SCRIPT_APPROVAL_MAX_SCENES2 = 50;
|
|
19676
20495
|
var VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2 = 2e3;
|
|
19677
|
-
var ApproveSceneEdit =
|
|
19678
|
-
index:
|
|
19679
|
-
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, {
|
|
19680
20499
|
message: "dialogue no puede ser s\xF3lo espacios"
|
|
19681
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.")
|
|
19682
20501
|
}).strict();
|
|
19683
|
-
var ApproveVideoScriptInput =
|
|
19684
|
-
taskId:
|
|
19685
|
-
angleKey:
|
|
19686
|
-
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.")
|
|
19687
20506
|
}).strict();
|
|
19688
|
-
var RegenerateVideoScriptInput =
|
|
19689
|
-
taskId:
|
|
19690
|
-
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.'),
|
|
19691
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).'),
|
|
19692
|
-
narrativeSelection:
|
|
20511
|
+
narrativeSelection: z79.enum([
|
|
19693
20512
|
"market",
|
|
19694
20513
|
"guided"
|
|
19695
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.")
|
|
@@ -19770,14 +20589,14 @@ function registerScriptReviewTools(server, api) {
|
|
|
19770
20589
|
__name(registerScriptReviewTools, "registerScriptReviewTools");
|
|
19771
20590
|
|
|
19772
20591
|
// src/tools/connections.ts
|
|
19773
|
-
import { z as
|
|
20592
|
+
import { z as z80 } from "zod";
|
|
19774
20593
|
var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
|
|
19775
20594
|
var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
|
|
19776
20595
|
var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
|
|
19777
20596
|
var listMetaDestinationsGuidance = getProductMakerCapabilityModelGuidance("list_meta_destinations");
|
|
19778
20597
|
var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list_tiktok_advertisers");
|
|
19779
20598
|
function registerConnectionTools(server, api) {
|
|
19780
|
-
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 () => {
|
|
19781
20600
|
try {
|
|
19782
20601
|
const r = await api.getJson("/v1/shopify/shops");
|
|
19783
20602
|
return asText(r);
|
|
@@ -19785,10 +20604,10 @@ function registerConnectionTools(server, api) {
|
|
|
19785
20604
|
throw translateError(e);
|
|
19786
20605
|
}
|
|
19787
20606
|
});
|
|
19788
|
-
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.',
|
|
19789
|
-
shopDomain:
|
|
19790
|
-
query:
|
|
19791
|
-
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()
|
|
19792
20611
|
}).shape, READS_EXTERNAL, async ({ shopDomain, query, taskId }) => {
|
|
19793
20612
|
try {
|
|
19794
20613
|
const params = new URLSearchParams({
|
|
@@ -19802,7 +20621,7 @@ function registerConnectionTools(server, api) {
|
|
|
19802
20621
|
throw translateError(e);
|
|
19803
20622
|
}
|
|
19804
20623
|
});
|
|
19805
|
-
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 () => {
|
|
19806
20625
|
try {
|
|
19807
20626
|
const r = await api.getJson("/v1/facebook/ad-accounts");
|
|
19808
20627
|
return asText(r);
|
|
@@ -19812,7 +20631,7 @@ function registerConnectionTools(server, api) {
|
|
|
19812
20631
|
});
|
|
19813
20632
|
server.registerTool("list_meta_destinations", {
|
|
19814
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.",
|
|
19815
|
-
inputSchema:
|
|
20634
|
+
inputSchema: z80.object({}).shape,
|
|
19816
20635
|
annotations: READS_EXTERNAL,
|
|
19817
20636
|
_meta: {
|
|
19818
20637
|
"openai/widgetAccessible": true
|
|
@@ -19825,7 +20644,7 @@ function registerConnectionTools(server, api) {
|
|
|
19825
20644
|
throw translateError(e);
|
|
19826
20645
|
}
|
|
19827
20646
|
});
|
|
19828
|
-
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 () => {
|
|
19829
20648
|
try {
|
|
19830
20649
|
const r = await api.getJson("/v1/tiktok/advertisers");
|
|
19831
20650
|
return asText(r);
|
|
@@ -19837,10 +20656,10 @@ function registerConnectionTools(server, api) {
|
|
|
19837
20656
|
__name(registerConnectionTools, "registerConnectionTools");
|
|
19838
20657
|
|
|
19839
20658
|
// src/tools/actors.ts
|
|
19840
|
-
import { z as
|
|
20659
|
+
import { z as z81 } from "zod";
|
|
19841
20660
|
var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
|
|
19842
20661
|
function registerActorTools(server, api) {
|
|
19843
|
-
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 () => {
|
|
19844
20663
|
try {
|
|
19845
20664
|
const rows = await api.getJson("/v1/actors");
|
|
19846
20665
|
const actors = (Array.isArray(rows) ? rows : []).filter((actor) => actor.status === "ready").map(({ id, name, description, gender, voiceId }) => ({
|
|
@@ -19861,7 +20680,7 @@ function registerActorTools(server, api) {
|
|
|
19861
20680
|
__name(registerActorTools, "registerActorTools");
|
|
19862
20681
|
|
|
19863
20682
|
// src/tools/publish.ts
|
|
19864
|
-
import { z as
|
|
20683
|
+
import { z as z82 } from "zod";
|
|
19865
20684
|
|
|
19866
20685
|
// src/tools/stable-uuid.ts
|
|
19867
20686
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -19933,40 +20752,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
|
|
|
19933
20752
|
var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
|
|
19934
20753
|
var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
|
|
19935
20754
|
var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
|
|
19936
|
-
var ShopifyInput =
|
|
19937
|
-
taskId:
|
|
19938
|
-
shopDomain:
|
|
20755
|
+
var ShopifyInput = z82.object({
|
|
20756
|
+
taskId: z82.string().min(1),
|
|
20757
|
+
shopDomain: z82.string().min(1),
|
|
19939
20758
|
/** Override: number of landing images to include. Default = ALL images the
|
|
19940
20759
|
* task generated (the MCP fetches /v1/results first to count). Bounded
|
|
19941
20760
|
* generously here; the backend validates each index against
|
|
19942
20761
|
* landing.images.length and rejects out-of-range. */
|
|
19943
|
-
numLandingImages:
|
|
19944
|
-
variantIndex:
|
|
20762
|
+
numLandingImages: z82.number().int().min(1).max(20).optional(),
|
|
20763
|
+
variantIndex: z82.number().int().min(0).optional(),
|
|
19945
20764
|
/** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
|
|
19946
20765
|
* When true, the landing renders variant-picker pills; when false, it ships
|
|
19947
20766
|
* a single-option product page. Defaults to false. */
|
|
19948
|
-
showVariantPicker:
|
|
20767
|
+
showVariantPicker: z82.boolean().optional(),
|
|
19949
20768
|
/** Default `auto` updates the product previously published for this task and
|
|
19950
20769
|
* shop. Use `existing` with targetProductId to choose another product, or
|
|
19951
20770
|
* `new` only when the user explicitly wants a duplicate/new listing. */
|
|
19952
|
-
publicationMode:
|
|
20771
|
+
publicationMode: z82.enum([
|
|
19953
20772
|
"auto",
|
|
19954
20773
|
"existing",
|
|
19955
20774
|
"new"
|
|
19956
20775
|
]).optional(),
|
|
19957
20776
|
/** Shopify product GID, numeric id, or admin product URL. Required when
|
|
19958
20777
|
* publicationMode is `existing`. */
|
|
19959
|
-
targetProductId:
|
|
20778
|
+
targetProductId: z82.string().trim().min(1).max(300).optional(),
|
|
19960
20779
|
/** Add an announcement bar text above add-to-cart (optional). */
|
|
19961
|
-
announcementBarEnabled:
|
|
19962
|
-
announcementBarText:
|
|
20780
|
+
announcementBarEnabled: z82.boolean().optional(),
|
|
20781
|
+
announcementBarText: z82.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
|
|
19963
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."),
|
|
19964
|
-
confirmed:
|
|
20783
|
+
confirmed: z82.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
|
|
19965
20784
|
});
|
|
19966
20785
|
var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
|
|
19967
20786
|
if (value.commerceCorrection && value.confirmed !== true) {
|
|
19968
20787
|
ctx.addIssue({
|
|
19969
|
-
code:
|
|
20788
|
+
code: z82.ZodIssueCode.custom,
|
|
19970
20789
|
path: [
|
|
19971
20790
|
"confirmed"
|
|
19972
20791
|
],
|
|
@@ -19975,7 +20794,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
19975
20794
|
}
|
|
19976
20795
|
if (value.announcementBarEnabled && !value.announcementBarText) {
|
|
19977
20796
|
ctx.addIssue({
|
|
19978
|
-
code:
|
|
20797
|
+
code: z82.ZodIssueCode.custom,
|
|
19979
20798
|
path: [
|
|
19980
20799
|
"announcementBarText"
|
|
19981
20800
|
],
|
|
@@ -19984,7 +20803,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
19984
20803
|
}
|
|
19985
20804
|
if (!value.announcementBarEnabled && value.announcementBarText) {
|
|
19986
20805
|
ctx.addIssue({
|
|
19987
|
-
code:
|
|
20806
|
+
code: z82.ZodIssueCode.custom,
|
|
19988
20807
|
path: [
|
|
19989
20808
|
"announcementBarText"
|
|
19990
20809
|
],
|
|
@@ -19998,91 +20817,91 @@ function parseShopifyInput(rawInput) {
|
|
|
19998
20817
|
return parsed.data;
|
|
19999
20818
|
}
|
|
20000
20819
|
__name(parseShopifyInput, "parseShopifyInput");
|
|
20001
|
-
var McpCampaignConfig =
|
|
20820
|
+
var McpCampaignConfig = z82.object({
|
|
20002
20821
|
/** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
|
|
20003
20822
|
* converts to the account currency server-side. Do NOT pre-convert: on a COP
|
|
20004
20823
|
* account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
|
|
20005
|
-
dailyBudgetUsd:
|
|
20824
|
+
dailyBudgetUsd: z82.number().positive().optional(),
|
|
20006
20825
|
/** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
|
|
20007
20826
|
* normalizes at validation). Meta accepts max 1 (single-country ad set).
|
|
20008
20827
|
* TikTok takes only the first entry. */
|
|
20009
|
-
targetCountries:
|
|
20010
|
-
campaignName:
|
|
20828
|
+
targetCountries: z82.array(CountryIso2Schema).max(1).optional(),
|
|
20829
|
+
campaignName: z82.string().trim().min(1).max(100).optional()
|
|
20011
20830
|
});
|
|
20012
20831
|
var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
|
|
20013
|
-
var MetaInput =
|
|
20014
|
-
taskId:
|
|
20832
|
+
var MetaInput = z82.object({
|
|
20833
|
+
taskId: z82.string().min(1),
|
|
20015
20834
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
20016
|
-
portfolioId:
|
|
20835
|
+
portfolioId: z82.string().trim().min(1),
|
|
20017
20836
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
20018
|
-
pageId:
|
|
20837
|
+
pageId: z82.string().trim().min(1),
|
|
20019
20838
|
adAccountId: McpAdAccountId,
|
|
20020
|
-
pixelId:
|
|
20021
|
-
landingUrl:
|
|
20839
|
+
pixelId: z82.string().min(1).optional(),
|
|
20840
|
+
landingUrl: z82.string().url().optional(),
|
|
20022
20841
|
/** Select which angles to publish by 0-based index. Omit to publish all
|
|
20023
20842
|
* successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
|
|
20024
|
-
angleIndexes:
|
|
20843
|
+
angleIndexes: z82.array(z82.number().int().nonnegative()).optional(),
|
|
20025
20844
|
campaignConfig: McpCampaignConfig.optional(),
|
|
20026
20845
|
/** Override the ad's primary text (body copy). If omitted, ProductMaker
|
|
20027
20846
|
* uses the auto-generated copy attached to the task. Capped at 500 chars
|
|
20028
20847
|
* (Meta's primary-text limit). */
|
|
20029
|
-
primaryText:
|
|
20848
|
+
primaryText: z82.string().trim().min(1).max(500).optional(),
|
|
20030
20849
|
/** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
|
|
20031
20850
|
* (wa.me) instead of a landing page. */
|
|
20032
|
-
phoneNumber:
|
|
20851
|
+
phoneNumber: z82.string().min(8).max(32).optional()
|
|
20033
20852
|
});
|
|
20034
|
-
var GroupedTaskSource =
|
|
20035
|
-
type:
|
|
20036
|
-
taskId:
|
|
20037
|
-
angleIndex:
|
|
20038
|
-
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([
|
|
20039
20858
|
"with_subtitles",
|
|
20040
20859
|
"without_subtitles"
|
|
20041
20860
|
]).optional(),
|
|
20042
|
-
imageVariantIndex:
|
|
20043
|
-
});
|
|
20044
|
-
var GroupedMediaSource =
|
|
20045
|
-
type:
|
|
20046
|
-
url:
|
|
20047
|
-
path:
|
|
20048
|
-
thumbnailUrl:
|
|
20049
|
-
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()
|
|
20050
20869
|
}).refine((value) => Boolean(value.url) !== Boolean(value.path), {
|
|
20051
20870
|
message: "media source needs exactly one of `url` or `path`"
|
|
20052
20871
|
}).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
|
|
20053
20872
|
message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
|
|
20054
20873
|
});
|
|
20055
|
-
var GroupedUploadedAssetSource =
|
|
20056
|
-
type:
|
|
20874
|
+
var GroupedUploadedAssetSource = z82.object({
|
|
20875
|
+
type: z82.literal("asset"),
|
|
20057
20876
|
/** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
|
|
20058
|
-
assetId:
|
|
20059
|
-
thumbnailAssetId:
|
|
20877
|
+
assetId: z82.string().uuid(),
|
|
20878
|
+
thumbnailAssetId: z82.string().uuid().optional()
|
|
20060
20879
|
});
|
|
20061
|
-
var GroupedCreative =
|
|
20062
|
-
type:
|
|
20880
|
+
var GroupedCreative = z82.object({
|
|
20881
|
+
type: z82.enum([
|
|
20063
20882
|
"image",
|
|
20064
20883
|
"video"
|
|
20065
20884
|
]),
|
|
20066
|
-
source:
|
|
20885
|
+
source: z82.union([
|
|
20067
20886
|
GroupedTaskSource,
|
|
20068
20887
|
GroupedMediaSource,
|
|
20069
20888
|
GroupedUploadedAssetSource
|
|
20070
20889
|
]),
|
|
20071
|
-
title:
|
|
20072
|
-
description:
|
|
20890
|
+
title: z82.string().max(120).optional(),
|
|
20891
|
+
description: z82.string().max(500).optional(),
|
|
20073
20892
|
cta: MetaCtaType.optional(),
|
|
20074
|
-
creativeId:
|
|
20893
|
+
creativeId: z82.string().min(1).optional()
|
|
20075
20894
|
});
|
|
20076
|
-
var GroupedCampaignConfigBase =
|
|
20895
|
+
var GroupedCampaignConfigBase = z82.object({
|
|
20077
20896
|
campaignType: MetaCampaignType.default("sales"),
|
|
20078
20897
|
optimizationMode: MetaOptimizationMode.default("advantage_plus"),
|
|
20079
20898
|
budgetMode: MetaBudgetMode.optional(),
|
|
20080
|
-
campaignDailyBudget:
|
|
20081
|
-
adSets:
|
|
20082
|
-
tempId:
|
|
20083
|
-
name:
|
|
20084
|
-
dailyBudget:
|
|
20085
|
-
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)
|
|
20086
20905
|
})).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
|
|
20087
20906
|
/**
|
|
20088
20907
|
* Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
|
|
@@ -20090,17 +20909,17 @@ var GroupedCampaignConfigBase = z78.object({
|
|
|
20090
20909
|
* opaque `invalid_literal` and made the WhatsApp destination — supported by
|
|
20091
20910
|
* the API since #849 — unreachable from this tool.
|
|
20092
20911
|
*/
|
|
20093
|
-
destination:
|
|
20094
|
-
|
|
20095
|
-
type:
|
|
20096
|
-
landingUrl:
|
|
20912
|
+
destination: z82.discriminatedUnion("type", [
|
|
20913
|
+
z82.object({
|
|
20914
|
+
type: z82.literal("landing"),
|
|
20915
|
+
landingUrl: z82.string().url()
|
|
20097
20916
|
}),
|
|
20098
|
-
|
|
20099
|
-
type:
|
|
20100
|
-
phoneNumber:
|
|
20917
|
+
z82.object({
|
|
20918
|
+
type: z82.literal("whatsapp"),
|
|
20919
|
+
phoneNumber: z82.string().min(8).max(32)
|
|
20101
20920
|
})
|
|
20102
20921
|
]),
|
|
20103
|
-
saveAsDefault:
|
|
20922
|
+
saveAsDefault: z82.boolean().default(false),
|
|
20104
20923
|
budgetPolicy: MetaBudgetPolicy.optional()
|
|
20105
20924
|
});
|
|
20106
20925
|
function resolveBudgetMode(value) {
|
|
@@ -20114,7 +20933,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
20114
20933
|
const budgetMode = resolveBudgetMode(value);
|
|
20115
20934
|
if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
|
|
20116
20935
|
ctx.addIssue({
|
|
20117
|
-
code:
|
|
20936
|
+
code: z82.ZodIssueCode.custom,
|
|
20118
20937
|
path: [
|
|
20119
20938
|
"campaignDailyBudget"
|
|
20120
20939
|
],
|
|
@@ -20125,7 +20944,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
20125
20944
|
value.adSets.forEach((adSet, index) => {
|
|
20126
20945
|
if (adSet.dailyBudget === void 0) {
|
|
20127
20946
|
ctx.addIssue({
|
|
20128
|
-
code:
|
|
20947
|
+
code: z82.ZodIssueCode.custom,
|
|
20129
20948
|
path: [
|
|
20130
20949
|
"adSets",
|
|
20131
20950
|
index,
|
|
@@ -20140,28 +20959,28 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
20140
20959
|
...value,
|
|
20141
20960
|
budgetMode: resolveBudgetMode(value)
|
|
20142
20961
|
}));
|
|
20143
|
-
var PublishCreativesToMetaInputBase =
|
|
20144
|
-
creatives:
|
|
20962
|
+
var PublishCreativesToMetaInputBase = z82.object({
|
|
20963
|
+
creatives: z82.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
|
|
20145
20964
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
20146
|
-
portfolioId:
|
|
20965
|
+
portfolioId: z82.string().trim().min(1),
|
|
20147
20966
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
20148
|
-
pageId:
|
|
20967
|
+
pageId: z82.string().trim().min(1),
|
|
20149
20968
|
adAccountId: McpAdAccountId,
|
|
20150
|
-
pixelId:
|
|
20969
|
+
pixelId: z82.string().min(1).optional(),
|
|
20151
20970
|
/** Required unless `campaignConfig.destination` is whatsapp — see the
|
|
20152
20971
|
* superRefine below. Mirrors the API's `FacebookCreateCampaignFromTasksBodySchema`. */
|
|
20153
|
-
landingUrl:
|
|
20972
|
+
landingUrl: z82.string().url().optional(),
|
|
20154
20973
|
/** ISO-2 code or resolvable country name — mirrors the API contract
|
|
20155
20974
|
* (CountryIso2Schema), which normalizes names to alpha-2 at validation. */
|
|
20156
20975
|
targetCountry: CountryIso2Schema,
|
|
20157
|
-
campaignName:
|
|
20976
|
+
campaignName: z82.string().trim().min(1).max(100),
|
|
20158
20977
|
campaignConfig: GroupedCampaignConfig.optional()
|
|
20159
20978
|
});
|
|
20160
20979
|
var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
|
|
20161
20980
|
const destination = value.campaignConfig?.destination;
|
|
20162
20981
|
if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
|
|
20163
20982
|
ctx.addIssue({
|
|
20164
|
-
code:
|
|
20983
|
+
code: z82.ZodIssueCode.custom,
|
|
20165
20984
|
path: [
|
|
20166
20985
|
"landingUrl"
|
|
20167
20986
|
],
|
|
@@ -20170,7 +20989,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
20170
20989
|
}
|
|
20171
20990
|
if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
|
|
20172
20991
|
ctx.addIssue({
|
|
20173
|
-
code:
|
|
20992
|
+
code: z82.ZodIssueCode.custom,
|
|
20174
20993
|
path: [
|
|
20175
20994
|
"campaignConfig",
|
|
20176
20995
|
"destination",
|
|
@@ -20189,16 +21008,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
20189
21008
|
}
|
|
20190
21009
|
return value;
|
|
20191
21010
|
});
|
|
20192
|
-
var PresignUploadResponseSchema =
|
|
20193
|
-
uploadUrl:
|
|
21011
|
+
var PresignUploadResponseSchema = z82.object({
|
|
21012
|
+
uploadUrl: z82.string().url().refine((value) => {
|
|
20194
21013
|
const url = new URL(value);
|
|
20195
21014
|
return !url.username && !url.password && url.protocol === "https:";
|
|
20196
21015
|
}, "presigned upload URL must be HTTPS without embedded credentials"),
|
|
20197
|
-
publicUrl:
|
|
21016
|
+
publicUrl: z82.string().url().refine((value) => {
|
|
20198
21017
|
const url = new URL(value);
|
|
20199
21018
|
return !url.username && !url.password;
|
|
20200
21019
|
}, "public media URL must not contain embedded credentials"),
|
|
20201
|
-
stagingAssetId:
|
|
21020
|
+
stagingAssetId: z82.string().uuid()
|
|
20202
21021
|
});
|
|
20203
21022
|
async function uploadResolvedMedia(api, media, assetRole) {
|
|
20204
21023
|
if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
|
|
@@ -20223,16 +21042,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
|
|
|
20223
21042
|
return uploadResolvedMedia(api, media, assetRole);
|
|
20224
21043
|
}
|
|
20225
21044
|
__name(resolveAndUploadMedia, "resolveAndUploadMedia");
|
|
20226
|
-
var TikTokInput =
|
|
20227
|
-
taskId:
|
|
20228
|
-
advertiserId:
|
|
20229
|
-
pixelId:
|
|
20230
|
-
landingUrl:
|
|
20231
|
-
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(),
|
|
20232
21051
|
campaignConfig: McpCampaignConfig.optional(),
|
|
20233
21052
|
/** Override the ad's description (TikTok's body copy). If omitted,
|
|
20234
21053
|
* ProductMaker uses the auto-generated copy attached to the task. */
|
|
20235
|
-
primaryText:
|
|
21054
|
+
primaryText: z82.string().trim().min(1).max(500).optional()
|
|
20236
21055
|
});
|
|
20237
21056
|
function registerPublishTools(server, api, opts = {}) {
|
|
20238
21057
|
const transport = opts.transport ?? "http";
|
|
@@ -20560,39 +21379,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
|
|
|
20560
21379
|
|
|
20561
21380
|
// src/tools/meta-upload.ts
|
|
20562
21381
|
import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
|
|
20563
|
-
import { z as
|
|
21382
|
+
import { z as z83 } from "zod";
|
|
20564
21383
|
var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
|
|
20565
|
-
var UploadSessionInputBase =
|
|
20566
|
-
mediaKind:
|
|
21384
|
+
var UploadSessionInputBase = z83.object({
|
|
21385
|
+
mediaKind: z83.enum([
|
|
20567
21386
|
"image",
|
|
20568
21387
|
"video",
|
|
20569
21388
|
"mixed"
|
|
20570
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."),
|
|
20571
|
-
assetRole:
|
|
21390
|
+
assetRole: z83.enum([
|
|
20572
21391
|
"media",
|
|
20573
21392
|
"thumbnail"
|
|
20574
21393
|
]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
|
|
20575
|
-
uploadPurpose:
|
|
21394
|
+
uploadPurpose: z83.enum([
|
|
20576
21395
|
"product_reference",
|
|
20577
21396
|
"creative",
|
|
20578
21397
|
"generic"
|
|
20579
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."),
|
|
20580
|
-
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.")
|
|
20581
21400
|
});
|
|
20582
|
-
var OpenAiFileReference =
|
|
20583
|
-
download_url:
|
|
20584
|
-
file_id:
|
|
20585
|
-
mime_type:
|
|
20586
|
-
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()
|
|
20587
21406
|
});
|
|
20588
21407
|
var UploadSessionToolInputShape = {
|
|
20589
21408
|
...UploadSessionInputBase.shape,
|
|
20590
|
-
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.")
|
|
20591
21410
|
};
|
|
20592
|
-
var UploadSessionToolInput =
|
|
21411
|
+
var UploadSessionToolInput = z83.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
|
|
20593
21412
|
if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
|
|
20594
21413
|
ctx.addIssue({
|
|
20595
|
-
code:
|
|
21414
|
+
code: z83.ZodIssueCode.custom,
|
|
20596
21415
|
path: [
|
|
20597
21416
|
"mediaKind"
|
|
20598
21417
|
],
|
|
@@ -20601,7 +21420,7 @@ var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine
|
|
|
20601
21420
|
}
|
|
20602
21421
|
if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
|
|
20603
21422
|
ctx.addIssue({
|
|
20604
|
-
code:
|
|
21423
|
+
code: z83.ZodIssueCode.custom,
|
|
20605
21424
|
path: [
|
|
20606
21425
|
"maxFiles"
|
|
20607
21426
|
],
|
|
@@ -20610,7 +21429,7 @@ var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine
|
|
|
20610
21429
|
}
|
|
20611
21430
|
if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
|
|
20612
21431
|
ctx.addIssue({
|
|
20613
|
-
code:
|
|
21432
|
+
code: z83.ZodIssueCode.custom,
|
|
20614
21433
|
path: [
|
|
20615
21434
|
"maxFiles"
|
|
20616
21435
|
],
|
|
@@ -20618,38 +21437,38 @@ var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine
|
|
|
20618
21437
|
});
|
|
20619
21438
|
}
|
|
20620
21439
|
});
|
|
20621
|
-
var UploadSessionResponse =
|
|
20622
|
-
sessionId:
|
|
20623
|
-
uploadPageUrl:
|
|
20624
|
-
mediaKind:
|
|
21440
|
+
var UploadSessionResponse = z83.object({
|
|
21441
|
+
sessionId: z83.string().uuid(),
|
|
21442
|
+
uploadPageUrl: z83.string().url(),
|
|
21443
|
+
mediaKind: z83.enum([
|
|
20625
21444
|
"image",
|
|
20626
21445
|
"video",
|
|
20627
21446
|
"mixed"
|
|
20628
21447
|
]),
|
|
20629
|
-
assetRole:
|
|
21448
|
+
assetRole: z83.enum([
|
|
20630
21449
|
"media",
|
|
20631
21450
|
"thumbnail"
|
|
20632
21451
|
]),
|
|
20633
|
-
maxFiles:
|
|
20634
|
-
expiresAt:
|
|
21452
|
+
maxFiles: z83.number().int().positive(),
|
|
21453
|
+
expiresAt: z83.string().datetime()
|
|
20635
21454
|
});
|
|
20636
|
-
var UploadStatusInput =
|
|
20637
|
-
sessionId:
|
|
21455
|
+
var UploadStatusInput = z83.object({
|
|
21456
|
+
sessionId: z83.string().uuid().describe("The sessionId returned by request_media_upload.")
|
|
20638
21457
|
});
|
|
20639
|
-
var UniversalUploadStatusResponse =
|
|
20640
|
-
|
|
20641
|
-
status:
|
|
20642
|
-
assets:
|
|
21458
|
+
var UniversalUploadStatusResponse = z83.discriminatedUnion("status", [
|
|
21459
|
+
z83.object({
|
|
21460
|
+
status: z83.literal("pending"),
|
|
21461
|
+
assets: z83.array(z83.never()).length(0)
|
|
20643
21462
|
}),
|
|
20644
|
-
|
|
20645
|
-
status:
|
|
20646
|
-
assets:
|
|
20647
|
-
assetId:
|
|
20648
|
-
mediaKind:
|
|
21463
|
+
z83.object({
|
|
21464
|
+
status: z83.literal("uploaded"),
|
|
21465
|
+
assets: z83.array(z83.object({
|
|
21466
|
+
assetId: z83.string().uuid(),
|
|
21467
|
+
mediaKind: z83.enum([
|
|
20649
21468
|
"image",
|
|
20650
21469
|
"video"
|
|
20651
21470
|
]),
|
|
20652
|
-
assetRole:
|
|
21471
|
+
assetRole: z83.enum([
|
|
20653
21472
|
"media",
|
|
20654
21473
|
"thumbnail"
|
|
20655
21474
|
])
|
|
@@ -20657,13 +21476,13 @@ var UniversalUploadStatusResponse = z79.discriminatedUnion("status", [
|
|
|
20657
21476
|
})
|
|
20658
21477
|
]);
|
|
20659
21478
|
var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
|
|
20660
|
-
uploadPurpose:
|
|
21479
|
+
uploadPurpose: z83.enum([
|
|
20661
21480
|
"product_reference",
|
|
20662
21481
|
"creative",
|
|
20663
21482
|
"generic"
|
|
20664
21483
|
]),
|
|
20665
|
-
checkToolName:
|
|
20666
|
-
resolveEndpoint:
|
|
21484
|
+
checkToolName: z83.literal("check_media_upload"),
|
|
21485
|
+
resolveEndpoint: z83.string().url()
|
|
20667
21486
|
});
|
|
20668
21487
|
function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
|
|
20669
21488
|
const url = new URL(uploadPageUrl);
|
|
@@ -20754,15 +21573,15 @@ function registerMediaUploadTools(server, api) {
|
|
|
20754
21573
|
__name(registerMediaUploadTools, "registerMediaUploadTools");
|
|
20755
21574
|
|
|
20756
21575
|
// src/tools/campaigns.ts
|
|
20757
|
-
import { z as
|
|
21576
|
+
import { z as z84 } from "zod";
|
|
20758
21577
|
var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
|
|
20759
21578
|
var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
|
|
20760
|
-
var MetaStatusInput =
|
|
20761
|
-
campaignId:
|
|
21579
|
+
var MetaStatusInput = z84.object({
|
|
21580
|
+
campaignId: z84.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
|
|
20762
21581
|
});
|
|
20763
|
-
var TikTokStatusInput =
|
|
20764
|
-
campaignId:
|
|
20765
|
-
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.")
|
|
20766
21585
|
});
|
|
20767
21586
|
function registerCampaignTools(server, api) {
|
|
20768
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) => {
|
|
@@ -20859,10 +21678,10 @@ function renderTikTokStatusMarkdown(r) {
|
|
|
20859
21678
|
__name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
|
|
20860
21679
|
|
|
20861
21680
|
// ../../packages/product-economics/src/product-costing.ts
|
|
20862
|
-
import { z as
|
|
21681
|
+
import { z as z86 } from "zod";
|
|
20863
21682
|
|
|
20864
21683
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
20865
|
-
import { z as
|
|
21684
|
+
import { z as z85 } from "zod";
|
|
20866
21685
|
|
|
20867
21686
|
// ../../packages/product-economics/src/product-costing-shipping-references.json
|
|
20868
21687
|
var product_costing_shipping_references_default = {
|
|
@@ -20926,21 +21745,21 @@ var product_costing_shipping_references_default = {
|
|
|
20926
21745
|
};
|
|
20927
21746
|
|
|
20928
21747
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
20929
|
-
var ShippingReferenceSchema =
|
|
20930
|
-
reference:
|
|
20931
|
-
min:
|
|
20932
|
-
max:
|
|
20933
|
-
updatedAt:
|
|
20934
|
-
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([
|
|
20935
21754
|
"high",
|
|
20936
21755
|
"medium",
|
|
20937
21756
|
"medium-low"
|
|
20938
21757
|
]),
|
|
20939
|
-
sources:
|
|
21758
|
+
sources: z85.array(z85.string().url().startsWith("https://")).min(1).max(3)
|
|
20940
21759
|
}).superRefine(({ reference, min, max }, context) => {
|
|
20941
21760
|
if (min > reference || reference > max) {
|
|
20942
21761
|
context.addIssue({
|
|
20943
|
-
code:
|
|
21762
|
+
code: z85.ZodIssueCode.custom,
|
|
20944
21763
|
message: "shipping_reference_outside_range",
|
|
20945
21764
|
path: [
|
|
20946
21765
|
"reference"
|
|
@@ -20948,7 +21767,7 @@ var ShippingReferenceSchema = z81.object({
|
|
|
20948
21767
|
});
|
|
20949
21768
|
}
|
|
20950
21769
|
});
|
|
20951
|
-
var SHIPPING_REFERENCES =
|
|
21770
|
+
var SHIPPING_REFERENCES = z85.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
|
|
20952
21771
|
var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
|
|
20953
21772
|
var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
|
|
20954
21773
|
"MX",
|
|
@@ -21130,18 +21949,18 @@ function getProductCostingCountryName(country) {
|
|
|
21130
21949
|
__name(getProductCostingCountryName, "getProductCostingCountryName");
|
|
21131
21950
|
|
|
21132
21951
|
// ../../packages/product-economics/src/product-costing.ts
|
|
21133
|
-
var ProductCostingInputSchema =
|
|
21134
|
-
country:
|
|
21135
|
-
supplierCost:
|
|
21136
|
-
shippingCost:
|
|
21137
|
-
returnRate:
|
|
21138
|
-
cancellationRate:
|
|
21139
|
-
adsManagerCpa:
|
|
21140
|
-
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")
|
|
21141
21960
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
21142
21961
|
if (returnRate + cancellationRate >= 1) {
|
|
21143
21962
|
context.addIssue({
|
|
21144
|
-
code:
|
|
21963
|
+
code: z86.ZodIssueCode.custom,
|
|
21145
21964
|
message: "delivery_rate_positive",
|
|
21146
21965
|
path: [
|
|
21147
21966
|
"cancellationRate"
|
|
@@ -21238,15 +22057,15 @@ function calculateProductCosting(rawInput) {
|
|
|
21238
22057
|
__name(calculateProductCosting, "calculateProductCosting");
|
|
21239
22058
|
|
|
21240
22059
|
// src/tools/product-costing.ts
|
|
21241
|
-
import { z as
|
|
22060
|
+
import { z as z87 } from "zod";
|
|
21242
22061
|
var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
|
|
21243
|
-
var optionalAmount = /* @__PURE__ */ __name((description) =>
|
|
21244
|
-
var optionalPercent = /* @__PURE__ */ __name((description) =>
|
|
21245
|
-
var ProductCostingToolInput =
|
|
21246
|
-
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, {
|
|
21247
22066
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
21248
22067
|
}).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
|
|
21249
|
-
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."),
|
|
21250
22069
|
supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
|
|
21251
22070
|
shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
|
|
21252
22071
|
shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
|
|
@@ -21405,7 +22224,7 @@ function formatPercent(value) {
|
|
|
21405
22224
|
__name(formatPercent, "formatPercent");
|
|
21406
22225
|
|
|
21407
22226
|
// src/tools/product-research.ts
|
|
21408
|
-
import { z as
|
|
22227
|
+
import { z as z88 } from "zod";
|
|
21409
22228
|
|
|
21410
22229
|
// src/tools/product-research-idempotency.ts
|
|
21411
22230
|
var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
|
|
@@ -21776,35 +22595,35 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
|
|
|
21776
22595
|
]);
|
|
21777
22596
|
var POLL_INTERVAL_MS = 5e3;
|
|
21778
22597
|
var MAX_WAIT_SECONDS = 120;
|
|
21779
|
-
var FindInput =
|
|
22598
|
+
var FindInput = z88.object({
|
|
21780
22599
|
targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
|
|
21781
22600
|
categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
|
|
21782
|
-
confirmed:
|
|
21783
|
-
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.")
|
|
21784
22603
|
});
|
|
21785
|
-
var GetInput =
|
|
21786
|
-
runId:
|
|
22604
|
+
var GetInput = z88.object({
|
|
22605
|
+
runId: z88.string().uuid().describe("ID del run devuelto por find_winning_products.")
|
|
21787
22606
|
});
|
|
21788
|
-
var ListInput =
|
|
21789
|
-
limit:
|
|
22607
|
+
var ListInput = z88.object({
|
|
22608
|
+
limit: z88.number().int().min(1).max(20).default(10)
|
|
21790
22609
|
});
|
|
21791
|
-
function textResult(
|
|
22610
|
+
function textResult(text2) {
|
|
21792
22611
|
return {
|
|
21793
22612
|
content: [
|
|
21794
22613
|
{
|
|
21795
22614
|
type: "text",
|
|
21796
|
-
text
|
|
22615
|
+
text: text2
|
|
21797
22616
|
}
|
|
21798
22617
|
]
|
|
21799
22618
|
};
|
|
21800
22619
|
}
|
|
21801
22620
|
__name(textResult, "textResult");
|
|
21802
|
-
function researchResult(run,
|
|
22621
|
+
function researchResult(run, text2) {
|
|
21803
22622
|
return {
|
|
21804
22623
|
content: [
|
|
21805
22624
|
{
|
|
21806
22625
|
type: "text",
|
|
21807
|
-
text
|
|
22626
|
+
text: text2
|
|
21808
22627
|
}
|
|
21809
22628
|
],
|
|
21810
22629
|
structuredContent: run
|
|
@@ -21909,17 +22728,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
|
|
|
21909
22728
|
__name(registerProductResearchTools, "registerProductResearchTools");
|
|
21910
22729
|
|
|
21911
22730
|
// src/tools/dropshipping-projects.ts
|
|
21912
|
-
import { z as
|
|
22731
|
+
import { z as z89 } from "zod";
|
|
21913
22732
|
var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
|
|
21914
22733
|
var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
|
|
21915
22734
|
var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
|
|
21916
|
-
var ProjectId =
|
|
21917
|
-
var DropshippingProjectStatus =
|
|
22735
|
+
var ProjectId = z89.string().uuid();
|
|
22736
|
+
var DropshippingProjectStatus = z89.enum([
|
|
21918
22737
|
"active",
|
|
21919
22738
|
"completed",
|
|
21920
22739
|
"archived"
|
|
21921
22740
|
]);
|
|
21922
|
-
var DropshippingProjectPhase =
|
|
22741
|
+
var DropshippingProjectPhase = z89.enum([
|
|
21923
22742
|
"research",
|
|
21924
22743
|
"costing",
|
|
21925
22744
|
"media",
|
|
@@ -21928,21 +22747,21 @@ var DropshippingProjectPhase = z85.enum([
|
|
|
21928
22747
|
"advertising",
|
|
21929
22748
|
"complete"
|
|
21930
22749
|
]);
|
|
21931
|
-
var DropshippingRewardMilestone =
|
|
22750
|
+
var DropshippingRewardMilestone = z89.enum([
|
|
21932
22751
|
"product_selected",
|
|
21933
22752
|
"costing_saved",
|
|
21934
22753
|
"product_media_ready",
|
|
21935
22754
|
"creatives_completed",
|
|
21936
22755
|
"campaign_created"
|
|
21937
22756
|
]);
|
|
21938
|
-
var TargetCountry =
|
|
22757
|
+
var TargetCountry = z89.enum([
|
|
21939
22758
|
"CO",
|
|
21940
22759
|
"MX",
|
|
21941
22760
|
"PE",
|
|
21942
22761
|
"EC",
|
|
21943
22762
|
"CL"
|
|
21944
22763
|
]);
|
|
21945
|
-
var ResearchCategory =
|
|
22764
|
+
var ResearchCategory = z89.enum([
|
|
21946
22765
|
"auto",
|
|
21947
22766
|
"automotive",
|
|
21948
22767
|
"kitchen",
|
|
@@ -21957,7 +22776,7 @@ var ResearchCategory = z85.enum([
|
|
|
21957
22776
|
"garden",
|
|
21958
22777
|
"cleaning"
|
|
21959
22778
|
]);
|
|
21960
|
-
var HttpUrl3 =
|
|
22779
|
+
var HttpUrl3 = z89.string().url().max(2e3).refine((value) => {
|
|
21961
22780
|
try {
|
|
21962
22781
|
return [
|
|
21963
22782
|
"http:",
|
|
@@ -21967,45 +22786,45 @@ var HttpUrl3 = z85.string().url().max(2e3).refine((value) => {
|
|
|
21967
22786
|
return false;
|
|
21968
22787
|
}
|
|
21969
22788
|
}, "URL must use HTTP(S)");
|
|
21970
|
-
var ResearchCandidateOrigin =
|
|
21971
|
-
type:
|
|
22789
|
+
var ResearchCandidateOrigin = z89.object({
|
|
22790
|
+
type: z89.literal("research_candidate"),
|
|
21972
22791
|
runId: ProjectId,
|
|
21973
|
-
candidateSourceId:
|
|
22792
|
+
candidateSourceId: z89.string().min(1).max(160)
|
|
21974
22793
|
});
|
|
21975
|
-
var TaskOrigin =
|
|
21976
|
-
type:
|
|
22794
|
+
var TaskOrigin = z89.object({
|
|
22795
|
+
type: z89.literal("task"),
|
|
21977
22796
|
taskId: ProjectId
|
|
21978
22797
|
});
|
|
21979
|
-
var ManualOrigin =
|
|
21980
|
-
type:
|
|
22798
|
+
var ManualOrigin = z89.object({
|
|
22799
|
+
type: z89.literal("manual"),
|
|
21981
22800
|
clientRequestId: ProjectId,
|
|
21982
|
-
country:
|
|
22801
|
+
country: z89.string().min(2).max(3).optional()
|
|
21983
22802
|
});
|
|
21984
|
-
var StartProjectInput =
|
|
21985
|
-
origin:
|
|
22803
|
+
var StartProjectInput = z89.object({
|
|
22804
|
+
origin: z89.discriminatedUnion("type", [
|
|
21986
22805
|
ResearchCandidateOrigin,
|
|
21987
22806
|
TaskOrigin,
|
|
21988
22807
|
ManualOrigin
|
|
21989
22808
|
]),
|
|
21990
|
-
productName:
|
|
22809
|
+
productName: z89.string().trim().min(1).max(240).optional(),
|
|
21991
22810
|
productUrl: HttpUrl3.optional(),
|
|
21992
|
-
country:
|
|
21993
|
-
languageCode:
|
|
22811
|
+
country: z89.string().min(2).max(3).optional(),
|
|
22812
|
+
languageCode: z89.string().min(2).max(16).optional()
|
|
21994
22813
|
}).strict();
|
|
21995
|
-
var CostProjectInput =
|
|
22814
|
+
var CostProjectInput = z89.object({
|
|
21996
22815
|
projectId: ProjectId,
|
|
21997
|
-
version:
|
|
21998
|
-
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, {
|
|
21999
22818
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
22000
22819
|
}).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
|
|
22001
|
-
supplierCost:
|
|
22002
|
-
shippingCost:
|
|
22003
|
-
returnRate:
|
|
22004
|
-
cancellationRate:
|
|
22005
|
-
adsManagerCpa:
|
|
22006
|
-
desiredMargin:
|
|
22007
|
-
});
|
|
22008
|
-
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({
|
|
22009
22828
|
projectId: ProjectId.optional()
|
|
22010
22829
|
}).strict();
|
|
22011
22830
|
var NEXT_ACTION_KINDS = [
|
|
@@ -22023,29 +22842,29 @@ var NEXT_ACTION_KINDS = [
|
|
|
22023
22842
|
"repair_meta_campaign",
|
|
22024
22843
|
"review_paused_campaign"
|
|
22025
22844
|
];
|
|
22026
|
-
var DropshippingProjectNextAction =
|
|
22027
|
-
kind:
|
|
22028
|
-
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)
|
|
22029
22848
|
})));
|
|
22030
|
-
var CostingInputSchema =
|
|
22031
|
-
country:
|
|
22032
|
-
supplierCost:
|
|
22033
|
-
shippingCost:
|
|
22034
|
-
returnRate:
|
|
22035
|
-
cancellationRate:
|
|
22036
|
-
adsManagerCpa:
|
|
22037
|
-
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)
|
|
22038
22857
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
22039
22858
|
if (returnRate + cancellationRate >= 1) context.addIssue({
|
|
22040
|
-
code:
|
|
22859
|
+
code: z89.ZodIssueCode.custom,
|
|
22041
22860
|
path: [
|
|
22042
22861
|
"cancellationRate"
|
|
22043
22862
|
]
|
|
22044
22863
|
});
|
|
22045
22864
|
});
|
|
22046
|
-
var FiniteCostingNumber =
|
|
22047
|
-
var CostingResultSchema =
|
|
22048
|
-
country:
|
|
22865
|
+
var FiniteCostingNumber = z89.number().finite();
|
|
22866
|
+
var CostingResultSchema = z89.object({
|
|
22867
|
+
country: z89.string().min(2).max(3),
|
|
22049
22868
|
deliveryRate: FiniteCostingNumber,
|
|
22050
22869
|
adjustedShippingCost: FiniteCostingNumber,
|
|
22051
22870
|
adjustedCpa: FiniteCostingNumber,
|
|
@@ -22058,45 +22877,45 @@ var CostingResultSchema = z85.object({
|
|
|
22058
22877
|
estimatedProfit: FiniteCostingNumber,
|
|
22059
22878
|
actualMargin: FiniteCostingNumber,
|
|
22060
22879
|
breakEvenAdsManagerCpa: FiniteCostingNumber,
|
|
22061
|
-
wasPriceAutoAdjusted:
|
|
22062
|
-
profitabilityStatus:
|
|
22063
|
-
});
|
|
22064
|
-
var RewardProgressSchema =
|
|
22065
|
-
campaignKey:
|
|
22066
|
-
totalCredits:
|
|
22067
|
-
earnedCredits:
|
|
22068
|
-
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({
|
|
22069
22888
|
milestone: DropshippingRewardMilestone,
|
|
22070
|
-
credits:
|
|
22071
|
-
available:
|
|
22072
|
-
earned:
|
|
22889
|
+
credits: z89.number().int().positive(),
|
|
22890
|
+
available: z89.boolean().optional(),
|
|
22891
|
+
earned: z89.boolean(),
|
|
22073
22892
|
grantId: ProjectId.nullable(),
|
|
22074
|
-
grantedAt:
|
|
22893
|
+
grantedAt: z89.string().datetime().nullable()
|
|
22075
22894
|
})).length(DropshippingRewardMilestone.options.length)
|
|
22076
22895
|
});
|
|
22077
|
-
var ProjectResponseSchema =
|
|
22896
|
+
var ProjectResponseSchema = z89.object({
|
|
22078
22897
|
id: ProjectId,
|
|
22079
22898
|
taskId: ProjectId.nullable(),
|
|
22080
22899
|
status: DropshippingProjectStatus,
|
|
22081
|
-
originKey:
|
|
22900
|
+
originKey: z89.string().min(1),
|
|
22082
22901
|
researchRunId: ProjectId.nullable(),
|
|
22083
|
-
candidateSourceId:
|
|
22084
|
-
productName:
|
|
22902
|
+
candidateSourceId: z89.string().nullable(),
|
|
22903
|
+
productName: z89.string().nullable(),
|
|
22085
22904
|
productUrl: HttpUrl3.nullable(),
|
|
22086
22905
|
referenceImageUrl: HttpUrl3.nullable(),
|
|
22087
|
-
targetCountry:
|
|
22088
|
-
languageCode:
|
|
22089
|
-
hasReferenceImage:
|
|
22090
|
-
hasWinnerReferenceImage:
|
|
22906
|
+
targetCountry: z89.string().nullable(),
|
|
22907
|
+
languageCode: z89.string().nullable(),
|
|
22908
|
+
hasReferenceImage: z89.boolean(),
|
|
22909
|
+
hasWinnerReferenceImage: z89.boolean(),
|
|
22091
22910
|
costingInput: CostingInputSchema.nullable(),
|
|
22092
22911
|
costingResult: CostingResultSchema.nullable(),
|
|
22093
|
-
costingVersion:
|
|
22094
|
-
version:
|
|
22912
|
+
costingVersion: z89.number().int().positive().nullable(),
|
|
22913
|
+
version: z89.number().int().positive(),
|
|
22095
22914
|
phase: DropshippingProjectPhase,
|
|
22096
22915
|
nextAction: DropshippingProjectNextAction.nullable(),
|
|
22097
22916
|
rewards: RewardProgressSchema,
|
|
22098
|
-
createdAt:
|
|
22099
|
-
updatedAt:
|
|
22917
|
+
createdAt: z89.string().datetime(),
|
|
22918
|
+
updatedAt: z89.string().datetime()
|
|
22100
22919
|
}).passthrough();
|
|
22101
22920
|
var NEXT_ACTION_GUIDANCE = {
|
|
22102
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.",
|
|
@@ -22214,58 +23033,58 @@ function registerDropshippingProjectTools(server, api) {
|
|
|
22214
23033
|
__name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
|
|
22215
23034
|
|
|
22216
23035
|
// src/tools/daily-control.ts
|
|
22217
|
-
import { z as
|
|
23036
|
+
import { z as z90 } from "zod";
|
|
22218
23037
|
var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
|
|
22219
23038
|
var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
|
|
22220
23039
|
var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
|
|
22221
|
-
var ProviderCampaignIdentifier =
|
|
22222
|
-
var DateOnly =
|
|
22223
|
-
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({
|
|
22224
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."),
|
|
22225
|
-
days:
|
|
22226
|
-
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.")
|
|
22227
23046
|
}).strict();
|
|
22228
|
-
var LinkCampaignInput =
|
|
22229
|
-
projectId:
|
|
22230
|
-
provider:
|
|
23047
|
+
var LinkCampaignInput = z90.object({
|
|
23048
|
+
projectId: z90.string().uuid(),
|
|
23049
|
+
provider: z90.enum([
|
|
22231
23050
|
"meta",
|
|
22232
23051
|
"tiktok"
|
|
22233
23052
|
]),
|
|
22234
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."),
|
|
22235
23054
|
campaignId: ProviderCampaignIdentifier
|
|
22236
23055
|
}).strict();
|
|
22237
|
-
var ReportReturnsInput =
|
|
22238
|
-
projectId:
|
|
23056
|
+
var ReportReturnsInput = z90.object({
|
|
23057
|
+
projectId: z90.string().uuid(),
|
|
22239
23058
|
date: DateOnly,
|
|
22240
|
-
returnedOrders:
|
|
22241
|
-
note:
|
|
23059
|
+
returnedOrders: z90.number().int().min(0).max(1e5),
|
|
23060
|
+
note: z90.string().trim().max(280).optional()
|
|
22242
23061
|
}).strict();
|
|
22243
|
-
var DailyControlStatusMirror = DailyControlStatusEnum.or(
|
|
22244
|
-
var DailyControlLightMirror = DailyControlLightEnum.or(
|
|
22245
|
-
var DailyControlSourceMirror = DailyControlSourceEnum.or(
|
|
22246
|
-
var DailyControlVerdictMirror = DailyControlVerdictEnum.or(
|
|
22247
|
-
var DailyControlDayMirror =
|
|
22248
|
-
date:
|
|
22249
|
-
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(),
|
|
22250
23069
|
returnedSource: DailyControlSourceMirror,
|
|
22251
23070
|
cancelledSource: DailyControlSourceMirror,
|
|
22252
|
-
hasEstimates:
|
|
23071
|
+
hasEstimates: z90.boolean(),
|
|
22253
23072
|
light: DailyControlLightMirror
|
|
22254
23073
|
}).passthrough();
|
|
22255
|
-
var DailyControlProductMirror =
|
|
22256
|
-
projectId:
|
|
22257
|
-
productName:
|
|
23074
|
+
var DailyControlProductMirror = z90.object({
|
|
23075
|
+
projectId: z90.string().uuid(),
|
|
23076
|
+
productName: z90.string().nullable(),
|
|
22258
23077
|
status: DailyControlStatusMirror,
|
|
22259
|
-
statusMessage:
|
|
22260
|
-
days:
|
|
23078
|
+
statusMessage: z90.string().nullable(),
|
|
23079
|
+
days: z90.array(DailyControlDayMirror),
|
|
22261
23080
|
verdict: DailyControlVerdictMirror.nullable(),
|
|
22262
|
-
rationale:
|
|
23081
|
+
rationale: z90.string().nullable()
|
|
22263
23082
|
}).passthrough();
|
|
22264
|
-
var DailyControlResponseMirror =
|
|
22265
|
-
since:
|
|
22266
|
-
until:
|
|
22267
|
-
products:
|
|
22268
|
-
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())
|
|
22269
23088
|
}).passthrough();
|
|
22270
23089
|
var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
|
|
22271
23090
|
function withWarnings(response) {
|
|
@@ -22349,42 +23168,42 @@ function registerDailyControlTools(server, api) {
|
|
|
22349
23168
|
__name(registerDailyControlTools, "registerDailyControlTools");
|
|
22350
23169
|
|
|
22351
23170
|
// src/tools/product-control.ts
|
|
22352
|
-
import { z as
|
|
23171
|
+
import { z as z91 } from "zod";
|
|
22353
23172
|
var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
|
|
22354
23173
|
var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
|
|
22355
23174
|
var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
|
|
22356
23175
|
var setProductCostingGuidance = getProductMakerCapabilityModelGuidance("set_product_costing");
|
|
22357
23176
|
var reportProductCountsGuidance = getProductMakerCapabilityModelGuidance("report_product_counts");
|
|
22358
|
-
var DateOnly2 =
|
|
23177
|
+
var DateOnly2 = z91.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
22359
23178
|
var IMPORT_BATCH_MAX2 = 50;
|
|
22360
|
-
var ProductControlListInput =
|
|
22361
|
-
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."),
|
|
22362
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."),
|
|
22363
|
-
shopDomain:
|
|
23182
|
+
shopDomain: z91.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
|
|
22364
23183
|
}).strict();
|
|
22365
|
-
var ImportableProductsInput =
|
|
22366
|
-
q:
|
|
22367
|
-
after:
|
|
22368
|
-
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()
|
|
22369
23188
|
}).strict();
|
|
22370
|
-
var ImportProductControlsInput =
|
|
22371
|
-
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."),
|
|
22372
23191
|
// Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
|
|
22373
23192
|
// sin decir a cuál archivaría el producto bajo la tienda equivocada.
|
|
22374
|
-
shopDomain:
|
|
23193
|
+
shopDomain: z91.string().min(1)
|
|
22375
23194
|
}).strict();
|
|
22376
|
-
var SetProductCostingInput =
|
|
22377
|
-
shopDomain:
|
|
22378
|
-
shopifyProductId:
|
|
22379
|
-
targetCountry:
|
|
22380
|
-
supplierCost:
|
|
22381
|
-
shippingCost:
|
|
22382
|
-
returnRate:
|
|
22383
|
-
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)
|
|
22384
23203
|
}).strict();
|
|
22385
|
-
var Count =
|
|
22386
|
-
var ReportProductCountsInput =
|
|
22387
|
-
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."),
|
|
22388
23207
|
date: DateOnly2,
|
|
22389
23208
|
orders: Count.describe("Pedidos que entraron ese d\xEDa."),
|
|
22390
23209
|
cancelledOrders: Count,
|