@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/http.js
CHANGED
|
@@ -68,6 +68,23 @@ var VideoPreset = z.enum([
|
|
|
68
68
|
]);
|
|
69
69
|
var VoiceId = z.string();
|
|
70
70
|
var _VIDEO_MODEL_SET = new Set(VideoModel.options);
|
|
71
|
+
var BROLL_VIDEO_MODES = new Set(VideoModel.options);
|
|
72
|
+
var PersistedVideoMode = z.enum([
|
|
73
|
+
...VideoModel.options,
|
|
74
|
+
"avatar_talking",
|
|
75
|
+
"hybrid",
|
|
76
|
+
"sora"
|
|
77
|
+
]);
|
|
78
|
+
var PersistedVideoModel = z.enum([
|
|
79
|
+
...VideoModel.options,
|
|
80
|
+
"sora",
|
|
81
|
+
"infinitalk"
|
|
82
|
+
]);
|
|
83
|
+
var PLAN_VIDEO_MODES = [
|
|
84
|
+
...VideoModel.options,
|
|
85
|
+
"avatar_talking",
|
|
86
|
+
"hybrid"
|
|
87
|
+
];
|
|
71
88
|
|
|
72
89
|
// ../../packages/types/src/video-creation.ts
|
|
73
90
|
import { z as z3 } from "zod";
|
|
@@ -1038,40 +1055,206 @@ var VideoTier = z8.preprocess((v) => v === "grok" ? "single_call" : v, z8.enum([
|
|
|
1038
1055
|
"single_call"
|
|
1039
1056
|
]));
|
|
1040
1057
|
var DEFAULT_VIDEO_TIER = "single_call";
|
|
1058
|
+
var WritableVideoTier = VideoTier.refine((tier) => tier !== "legacy", {
|
|
1059
|
+
message: "VIDEO_TIER_RETIRED"
|
|
1060
|
+
});
|
|
1041
1061
|
|
|
1042
|
-
// ../../packages/types/src/image-
|
|
1043
|
-
var
|
|
1044
|
-
"
|
|
1045
|
-
"
|
|
1062
|
+
// ../../packages/types/src/image-models.ts
|
|
1063
|
+
var IMAGE_RESOLUTIONS = [
|
|
1064
|
+
"1k",
|
|
1065
|
+
"2k",
|
|
1066
|
+
"4k"
|
|
1046
1067
|
];
|
|
1047
|
-
var
|
|
1048
|
-
"
|
|
1049
|
-
"5:
|
|
1050
|
-
"
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
"
|
|
1068
|
+
var GPT_IMAGE_2_5_TOKENS = {
|
|
1069
|
+
"1k": "gpt-image-2-5:1k",
|
|
1070
|
+
"2k": "gpt-image-2-5:2k",
|
|
1071
|
+
"4k": "gpt-image-2-5:4k"
|
|
1072
|
+
};
|
|
1073
|
+
var GPT_IMAGE_2_TOKENS = {
|
|
1074
|
+
"1k": "gpt-image-2:1k",
|
|
1075
|
+
"2k": "gpt-image-2:2k",
|
|
1076
|
+
"4k": "gpt-image-2:4k"
|
|
1077
|
+
};
|
|
1078
|
+
var GPT_IMAGE_2_5 = {
|
|
1079
|
+
id: "gpt-image-2.5",
|
|
1080
|
+
status: "active",
|
|
1081
|
+
renderedBy: "gpt-image-2.5",
|
|
1082
|
+
tokens: GPT_IMAGE_2_5_TOKENS,
|
|
1083
|
+
kie: {
|
|
1084
|
+
imageToImage: [
|
|
1085
|
+
"gpt-image-2-5-sunburst-image-to-image",
|
|
1086
|
+
"gpt-image-2-5-flare-image-to-image"
|
|
1087
|
+
],
|
|
1088
|
+
textToImage: [
|
|
1089
|
+
"gpt-image-2-5-sunburst-text-to-image",
|
|
1090
|
+
"gpt-image-2-5-flare-text-to-image"
|
|
1091
|
+
],
|
|
1092
|
+
shorthands: [
|
|
1093
|
+
"gpt-image-2-5"
|
|
1094
|
+
]
|
|
1095
|
+
},
|
|
1096
|
+
fal: {
|
|
1097
|
+
edit: "openai/gpt-image-2.5/sunburst/edit",
|
|
1098
|
+
textToImage: "openai/gpt-image-2.5/sunburst/text-to-image",
|
|
1099
|
+
quality: {
|
|
1100
|
+
"1k": "low",
|
|
1101
|
+
"2k": "medium",
|
|
1102
|
+
"4k": "high"
|
|
1103
|
+
},
|
|
1104
|
+
ourCostCents: {
|
|
1105
|
+
"1k": 1.5,
|
|
1106
|
+
"2k": 6.1,
|
|
1107
|
+
"4k": 17.8
|
|
1108
|
+
}
|
|
1109
|
+
},
|
|
1110
|
+
// Docs KIE de gpt-image-2-5 (sunburst/flare): 27:16, 16:27, 9:8, 8:9 solo 1K;
|
|
1111
|
+
// 4:5 y 5:4 también bloqueados por encima de 1K.
|
|
1112
|
+
ratiosBlockedAbove1k: [
|
|
1113
|
+
"4:5",
|
|
1114
|
+
"5:4",
|
|
1115
|
+
"27:16",
|
|
1116
|
+
"16:27",
|
|
1117
|
+
"9:8",
|
|
1118
|
+
"8:9"
|
|
1119
|
+
],
|
|
1120
|
+
ledgerSuffix: {
|
|
1121
|
+
"1k": "gpt-image-2",
|
|
1122
|
+
"2k": "gpt-image-2:medium",
|
|
1123
|
+
"4k": "gpt-image-2:high"
|
|
1124
|
+
},
|
|
1125
|
+
falLedgerSuffix: {
|
|
1126
|
+
"1k": "gpt-image-2:1k",
|
|
1127
|
+
"2k": "gpt-image-2:2k",
|
|
1128
|
+
"4k": "gpt-image-2:4k"
|
|
1129
|
+
}
|
|
1130
|
+
};
|
|
1131
|
+
var GPT_IMAGE_2 = {
|
|
1132
|
+
...GPT_IMAGE_2_5,
|
|
1133
|
+
id: "gpt-image-2",
|
|
1134
|
+
status: "retired",
|
|
1135
|
+
renderedBy: GPT_IMAGE_2_5.id,
|
|
1136
|
+
tokens: GPT_IMAGE_2_TOKENS,
|
|
1137
|
+
kie: {
|
|
1138
|
+
imageToImage: [
|
|
1139
|
+
"gpt-image-2-image-to-image"
|
|
1140
|
+
],
|
|
1141
|
+
textToImage: [
|
|
1142
|
+
"gpt-image-2-text-to-image"
|
|
1143
|
+
],
|
|
1144
|
+
shorthands: [
|
|
1145
|
+
"gpt-image-2"
|
|
1146
|
+
]
|
|
1147
|
+
},
|
|
1148
|
+
ratiosBlockedAbove1k: [
|
|
1149
|
+
"4:5",
|
|
1150
|
+
"5:4"
|
|
1151
|
+
]
|
|
1152
|
+
};
|
|
1153
|
+
var IMAGE_MODELS = [
|
|
1154
|
+
GPT_IMAGE_2_5,
|
|
1155
|
+
GPT_IMAGE_2
|
|
1054
1156
|
];
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1157
|
+
var ACTIVE_IMAGE_MODEL = GPT_IMAGE_2_5;
|
|
1158
|
+
var IMAGE_WRITE_TOKENS = GPT_IMAGE_2_5_TOKENS;
|
|
1159
|
+
var LEGACY_IMAGE_TOKENS = GPT_IMAGE_2_TOKENS;
|
|
1160
|
+
var PUBLIC_IMAGE_QUALITY_INPUTS = [
|
|
1161
|
+
IMAGE_WRITE_TOKENS["1k"],
|
|
1162
|
+
IMAGE_WRITE_TOKENS["2k"],
|
|
1163
|
+
LEGACY_IMAGE_TOKENS["1k"],
|
|
1164
|
+
LEGACY_IMAGE_TOKENS["2k"],
|
|
1165
|
+
"image:1k",
|
|
1166
|
+
"image:2k"
|
|
1167
|
+
];
|
|
1168
|
+
function entryById(id) {
|
|
1169
|
+
const found = IMAGE_MODELS.find((entry) => entry.id === id);
|
|
1170
|
+
if (!found) throw new Error(`IMAGE_MODEL_UNKNOWN:${id}`);
|
|
1171
|
+
return found;
|
|
1172
|
+
}
|
|
1173
|
+
__name(entryById, "entryById");
|
|
1174
|
+
function resolveImageToken(raw) {
|
|
1175
|
+
if (typeof raw !== "string") return null;
|
|
1176
|
+
let normalized = raw.trim().toLowerCase();
|
|
1177
|
+
let viaFal = false;
|
|
1178
|
+
if (normalized.startsWith("fal:")) {
|
|
1179
|
+
viaFal = true;
|
|
1180
|
+
normalized = normalized.slice("fal:".length);
|
|
1181
|
+
}
|
|
1182
|
+
for (const resolution of IMAGE_RESOLUTIONS) {
|
|
1183
|
+
if (normalized === `image:${resolution}`) {
|
|
1184
|
+
return {
|
|
1185
|
+
resolution,
|
|
1186
|
+
model: ACTIVE_IMAGE_MODEL,
|
|
1187
|
+
declared: ACTIVE_IMAGE_MODEL,
|
|
1188
|
+
spelling: "intent",
|
|
1189
|
+
viaFal
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
for (const entry of IMAGE_MODELS) {
|
|
1194
|
+
for (const resolution of IMAGE_RESOLUTIONS) {
|
|
1195
|
+
if (entry.tokens[resolution] === normalized) {
|
|
1196
|
+
return {
|
|
1197
|
+
resolution,
|
|
1198
|
+
model: entryById(entry.renderedBy),
|
|
1199
|
+
declared: entry,
|
|
1200
|
+
spelling: entry.status === "active" ? "current" : "retired",
|
|
1201
|
+
viaFal
|
|
1202
|
+
};
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1059
1205
|
}
|
|
1060
|
-
return
|
|
1206
|
+
return null;
|
|
1207
|
+
}
|
|
1208
|
+
__name(resolveImageToken, "resolveImageToken");
|
|
1209
|
+
function imageResolutionOf(raw) {
|
|
1210
|
+
const token = resolveImageToken(raw);
|
|
1211
|
+
return token && !token.viaFal ? token.resolution : null;
|
|
1212
|
+
}
|
|
1213
|
+
__name(imageResolutionOf, "imageResolutionOf");
|
|
1214
|
+
function requireKieImageId(ids, index, label) {
|
|
1215
|
+
const id = ids[index];
|
|
1216
|
+
if (!id) throw new Error(`IMAGE_MODEL_NO_KIE_ID:${label}`);
|
|
1217
|
+
return id;
|
|
1218
|
+
}
|
|
1219
|
+
__name(requireKieImageId, "requireKieImageId");
|
|
1220
|
+
var KIE_FLARE_IMAGE_TO_IMAGE_MODEL = requireKieImageId(GPT_IMAGE_2_5.kie.imageToImage, 1, "flare-imageToImage");
|
|
1221
|
+
function canonicalImageModelInput(raw) {
|
|
1222
|
+
if (raw === void 0) return void 0;
|
|
1223
|
+
const token = resolveImageToken(raw);
|
|
1224
|
+
if (!token || token.viaFal || token.spelling !== "intent") return raw;
|
|
1225
|
+
return IMAGE_WRITE_TOKENS[token.resolution];
|
|
1226
|
+
}
|
|
1227
|
+
__name(canonicalImageModelInput, "canonicalImageModelInput");
|
|
1228
|
+
function imageTokenSupportsRatio(aspectRatio, rawToken) {
|
|
1229
|
+
const token = resolveImageToken(rawToken);
|
|
1230
|
+
if (!token) return true;
|
|
1231
|
+
if (token.resolution === "1k") return true;
|
|
1232
|
+
return !token.declared.ratiosBlockedAbove1k.includes(aspectRatio);
|
|
1233
|
+
}
|
|
1234
|
+
__name(imageTokenSupportsRatio, "imageTokenSupportsRatio");
|
|
1235
|
+
|
|
1236
|
+
// ../../packages/types/src/image-provider.ts
|
|
1237
|
+
var GPT_IMAGE_2_RATIOS_BLOCKED_ABOVE_1K = GPT_IMAGE_2.ratiosBlockedAbove1k;
|
|
1238
|
+
var GPT_IMAGE_2_5_RATIOS_BLOCKED_ABOVE_1K = GPT_IMAGE_2_5.ratiosBlockedAbove1k;
|
|
1239
|
+
function gptImage2SupportsTier(aspectRatio, tier) {
|
|
1240
|
+
return imageTokenSupportsRatio(aspectRatio, tier);
|
|
1061
1241
|
}
|
|
1062
1242
|
__name(gptImage2SupportsTier, "gptImage2SupportsTier");
|
|
1063
1243
|
var IMAGE_TIER_UNSUPPORTED_FOR_RATIO_RULE = "image_tier_unsupported_for_ratio";
|
|
1064
1244
|
var IMAGE_TIER_LIST = [
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
"gpt-image-2-5:4k",
|
|
1068
|
-
"gpt-image-2:1k",
|
|
1069
|
-
"gpt-image-2:2k",
|
|
1070
|
-
"gpt-image-2:4k"
|
|
1245
|
+
...Object.values(IMAGE_WRITE_TOKENS),
|
|
1246
|
+
...Object.values(LEGACY_IMAGE_TOKENS)
|
|
1071
1247
|
];
|
|
1248
|
+
function isImageTier(value) {
|
|
1249
|
+
return IMAGE_TIER_LIST.includes(value);
|
|
1250
|
+
}
|
|
1251
|
+
__name(isImageTier, "isImageTier");
|
|
1072
1252
|
function parseImageTier(imageModel) {
|
|
1073
|
-
const
|
|
1074
|
-
|
|
1253
|
+
const token = resolveImageToken(imageModel);
|
|
1254
|
+
if (!token || token.viaFal) return null;
|
|
1255
|
+
if (token.spelling === "intent") return IMAGE_WRITE_TOKENS[token.resolution];
|
|
1256
|
+
const declared = token.declared.tokens[token.resolution];
|
|
1257
|
+
return isImageTier(declared) ? declared : null;
|
|
1075
1258
|
}
|
|
1076
1259
|
__name(parseImageTier, "parseImageTier");
|
|
1077
1260
|
function validateImageTierForRatio(aspectRatio, imageModel) {
|
|
@@ -3808,7 +3991,7 @@ var IngestOptions = z22.object({
|
|
|
3808
3991
|
durationSeconds: FreeVideoOptionsSchema.shape.durationSeconds.optional(),
|
|
3809
3992
|
addSubtitles: FreeVideoOptionsSchema.shape.addSubtitles.optional(),
|
|
3810
3993
|
subtitleText: z22.string().transform((value) => value.trim()).pipe(z22.string().max(FREE_VIDEO_SUBTITLE_MAX_CHARS)).optional(),
|
|
3811
|
-
videoTier:
|
|
3994
|
+
videoTier: WritableVideoTier.default(DEFAULT_VIDEO_TIER),
|
|
3812
3995
|
narrativeStyle: NarrativeStyle.default("review"),
|
|
3813
3996
|
videoPreset: VideoPreset.optional(),
|
|
3814
3997
|
multiAngleVideos: z22.boolean().default(false),
|
|
@@ -3882,7 +4065,9 @@ var IngestOptions = z22.object({
|
|
|
3882
4065
|
aspectRatio: z22.string().optional(),
|
|
3883
4066
|
brandColors: z22.string().optional(),
|
|
3884
4067
|
nVariants: z22.number().int().min(1).max(6).optional(),
|
|
3885
|
-
|
|
4068
|
+
// O7: `image:Nk` is accepted and stored as the spelling written today
|
|
4069
|
+
// (IMAGE_WRITE_TOKENS); see packages/types/src/image-models.ts.
|
|
4070
|
+
imageModel: z22.string().optional().transform((value) => canonicalImageModelInput(value)),
|
|
3886
4071
|
styleMix: z22.string().optional(),
|
|
3887
4072
|
aiDecidesAll: z22.boolean().optional(),
|
|
3888
4073
|
/** Opt out of the competitor-spy analysis. When false the worker skips
|
|
@@ -4001,7 +4186,7 @@ var VideoOptionsOverride = z22.object({
|
|
|
4001
4186
|
videoStructure: VideoStructure.optional(),
|
|
4002
4187
|
videoQuality: VideoQuality.optional(),
|
|
4003
4188
|
videoModel: VideoModel.optional(),
|
|
4004
|
-
videoTier:
|
|
4189
|
+
videoTier: WritableVideoTier.optional(),
|
|
4005
4190
|
ugcFormat: VideoFormat.optional(),
|
|
4006
4191
|
videoStyle: VideoStyle.optional(),
|
|
4007
4192
|
narrativeStyle: NarrativeStyle.optional(),
|
|
@@ -4084,6 +4269,11 @@ var IngestResumePayload = z22.object({
|
|
|
4084
4269
|
// "keep what the task has". See angle-management.service.ts resumeAfterAngles.
|
|
4085
4270
|
videoStyle: VideoStyle.optional(),
|
|
4086
4271
|
videoModel: VideoModel.default("veo"),
|
|
4272
|
+
// READ schema on purpose, unlike IngestOptions/VideoOptionsOverride: resume
|
|
4273
|
+
// does not write the tier — `resumeAfterAngles` projects the route from the
|
|
4274
|
+
// task's OWN persisted tier and ignores this field. MCP and WhatsApp echo
|
|
4275
|
+
// `status.videoTier`, which is still `legacy` for historical rows; refusing
|
|
4276
|
+
// it made those tasks impossible to resume from both channels.
|
|
4087
4277
|
videoTier: VideoTier.optional(),
|
|
4088
4278
|
videoStructure: VideoStructure.optional(),
|
|
4089
4279
|
videoQuality: VideoQuality.optional(),
|
|
@@ -4894,17 +5084,7 @@ var VideoGenerator = z26.object({
|
|
|
4894
5084
|
format: VideoFormat.optional(),
|
|
4895
5085
|
videoStyle: VideoStyle.optional(),
|
|
4896
5086
|
narrativeStyle: NarrativeStyle.optional(),
|
|
4897
|
-
videoMode:
|
|
4898
|
-
"veo",
|
|
4899
|
-
"wan",
|
|
4900
|
-
"bytedance",
|
|
4901
|
-
"seedance",
|
|
4902
|
-
"grok",
|
|
4903
|
-
"kling",
|
|
4904
|
-
"avatar_talking",
|
|
4905
|
-
"hybrid",
|
|
4906
|
-
"sora"
|
|
4907
|
-
]).optional(),
|
|
5087
|
+
videoMode: PersistedVideoMode.optional(),
|
|
4908
5088
|
videoResolution: VideoResolution.optional(),
|
|
4909
5089
|
videoStructure: VideoStructure.optional(),
|
|
4910
5090
|
videoQuality: VideoQuality.optional(),
|
|
@@ -7269,7 +7449,8 @@ var IMAGE_QA_GATES = [
|
|
|
7269
7449
|
"limb",
|
|
7270
7450
|
"device_panel",
|
|
7271
7451
|
"critical_feature",
|
|
7272
|
-
"cross_section"
|
|
7452
|
+
"cross_section",
|
|
7453
|
+
"usage_fidelity"
|
|
7273
7454
|
];
|
|
7274
7455
|
var ImageQaGate = z36.enum(IMAGE_QA_GATES);
|
|
7275
7456
|
var ImageQaGateOutcome = z36.enum([
|
|
@@ -8315,6 +8496,10 @@ var GEMINI_OMNI_FLAT_USER_PRICE_CENTS = 168;
|
|
|
8315
8496
|
// ../../packages/types/src/pricing.ts
|
|
8316
8497
|
var CREDITS_PER_USD_CENT = 10;
|
|
8317
8498
|
var CREDITS_PER_DOLLAR = 100 * CREDITS_PER_USD_CENT;
|
|
8499
|
+
var AD_CREATIVE_MODELS = {
|
|
8500
|
+
STANDARD: IMAGE_WRITE_TOKENS["1k"],
|
|
8501
|
+
PREMIUM: IMAGE_WRITE_TOKENS["2k"]
|
|
8502
|
+
};
|
|
8318
8503
|
var KALODATA_USD_CENTS_PER_PROVIDER_CREDIT = 9;
|
|
8319
8504
|
var KALODATA_PROVIDER_CREDITS_PER_SOURCE_CEILING = 7.5;
|
|
8320
8505
|
var DEFAULT_PRICING = {
|
|
@@ -9273,6 +9458,27 @@ var DEFAULT_PRICING = {
|
|
|
9273
9458
|
ourCostCents: 1.88,
|
|
9274
9459
|
userPriceCents: 3.76
|
|
9275
9460
|
},
|
|
9461
|
+
// Usage decider (role `usage-decider`: Gemini 3.8 Flash effort:'high' since
|
|
9462
|
+
// 05f543eae, ≤6 images + seller text, temperature 0 json_object, once per
|
|
9463
|
+
// classic landing, always on). Was 3¢ measured on Claude
|
|
9464
|
+
// Sonnet 5 (spike 2026-09-24, 17 prod tasks). NOT re-measured on Flash — no
|
|
9465
|
+
// local BillingEntry row carries the Flash decider yet — so it is priced as
|
|
9466
|
+
// the product truth (`openrouter:product-truth`, 2.2¢ measured from
|
|
9467
|
+
// OpenRouter usage.cost): same model, same effort, same ≤6-photo input and a
|
|
9468
|
+
// JSON answer of similar size. Refine from usage.cost after the e2e. Fallback
|
|
9469
|
+
// only (OpenRouter's usage.cost is billed when present).
|
|
9470
|
+
"openrouter:usage-decision": {
|
|
9471
|
+
ourCostCents: 2.2,
|
|
9472
|
+
userPriceCents: 4.4
|
|
9473
|
+
},
|
|
9474
|
+
// Usage-fidelity QA judge (records misuse; regen gated separately behind
|
|
9475
|
+
// always on, bounded by USAGE_FIDELITY_MAX_REGENS). Sized off landing-image-qa beside it: same
|
|
9476
|
+
// shape of call (1-2 images, a verdict), so quoted at the same rate until
|
|
9477
|
+
// it has its own BillingEntry volume to re-derive from.
|
|
9478
|
+
"openrouter:usage-fidelity": {
|
|
9479
|
+
ourCostCents: 1.88,
|
|
9480
|
+
userPriceCents: 3.76
|
|
9481
|
+
},
|
|
9276
9482
|
// Landing commercial-facts extraction (gemini-3.8-flash, ONE text-only call over
|
|
9277
9483
|
// the seller's offer/context/features). Sized off the image-QA key beside it,
|
|
9278
9484
|
// which measured 1.88¢ at ~11.1K prompt tokens: this prompt is capped at ~3K in
|
|
@@ -10011,6 +10217,24 @@ var DEFAULT_PRICING = {
|
|
|
10011
10217
|
ourCostCents: 0.2,
|
|
10012
10218
|
userPriceCents: 0.4
|
|
10013
10219
|
},
|
|
10220
|
+
// Product truth (Gemini 3.8 Flash effort:'high', ≤6 photos + all seller text, once per
|
|
10221
|
+
// extract, always on). Plan C spike 2026-09-24: 6 calls, US$0.132 total ⇒
|
|
10222
|
+
// 2.2¢/call measured from OpenRouter usage.cost. Replaces usage spec + functional demo +
|
|
10223
|
+
// product-use sheet (+ landing visual-context-fusion) on the same task. Fallback only.
|
|
10224
|
+
"openrouter:product-truth": {
|
|
10225
|
+
ourCostCents: 2.2,
|
|
10226
|
+
userPriceCents: 4.4
|
|
10227
|
+
},
|
|
10228
|
+
// Landing creative director, «categorías» arm (Gemini 3.8 Flash effort:'high', ≤6 photos +
|
|
10229
|
+
// all seller text + the section plan, once per classic landing behind
|
|
10230
|
+
// LANDING_DIRECTOR_ENABLED). ESTIMATE, not measured: same call shape as the product truth
|
|
10231
|
+
// (2.2¢) with a ~2-3x longer JSON answer (one content spec per section) ⇒ ~4¢. Replaces
|
|
10232
|
+
// the visual brief (4¢) + visual-context fusion (0.4¢) + usage decision (2.2¢) on that
|
|
10233
|
+
// landing. Refine from OpenRouter usage.cost after the e2e. Fallback only.
|
|
10234
|
+
"openrouter:landing-director": {
|
|
10235
|
+
ourCostCents: 4,
|
|
10236
|
+
userPriceCents: 8
|
|
10237
|
+
},
|
|
10014
10238
|
// Unit = one reference-grouping pass over the user's product images (0.1241¢).
|
|
10015
10239
|
"openrouter:product-reference-grouping": {
|
|
10016
10240
|
ourCostCents: 0.15,
|
|
@@ -13528,7 +13752,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13528
13752
|
"video"
|
|
13529
13753
|
]
|
|
13530
13754
|
),
|
|
13531
|
-
defineCapability("generate_image_creatives", "
|
|
13755
|
+
defineCapability("generate_image_creatives", "2f1698b623d98645b7c618a17988f3aac30f403a9c3f3dc26eb5bdbd9c6ef23e", "credit_consuming", "creative", [
|
|
13532
13756
|
"credit_consuming",
|
|
13533
13757
|
"state_change"
|
|
13534
13758
|
], [
|
|
@@ -15179,79 +15403,696 @@ var WhatsAppPresentationManifestSchema = z67.object({
|
|
|
15179
15403
|
}
|
|
15180
15404
|
});
|
|
15181
15405
|
|
|
15182
|
-
// ../../packages/types/src/
|
|
15406
|
+
// ../../packages/types/src/usage-decision.ts
|
|
15183
15407
|
import { z as z68 } from "zod";
|
|
15184
|
-
|
|
15408
|
+
|
|
15409
|
+
// ../../packages/types/src/text-clamp.ts
|
|
15410
|
+
function clampAtWordBoundary(value, max) {
|
|
15411
|
+
if (typeof value !== "string") return value;
|
|
15412
|
+
if (value.length <= max) return value;
|
|
15413
|
+
const cut = value.slice(0, max);
|
|
15414
|
+
const lastSpace = cut.lastIndexOf(" ");
|
|
15415
|
+
const atWordBoundary = lastSpace > 0 ? cut.slice(0, lastSpace) : cut;
|
|
15416
|
+
return atWordBoundary.replace(/[,;:\s]+$/, "");
|
|
15417
|
+
}
|
|
15418
|
+
__name(clampAtWordBoundary, "clampAtWordBoundary");
|
|
15419
|
+
function clampStringArray(max) {
|
|
15420
|
+
return (value) => {
|
|
15421
|
+
if (!Array.isArray(value)) return value;
|
|
15422
|
+
const nonEmpty = value.filter((item) => typeof item === "string" && item.trim().length > 0);
|
|
15423
|
+
return nonEmpty.slice(0, max);
|
|
15424
|
+
};
|
|
15425
|
+
}
|
|
15426
|
+
__name(clampStringArray, "clampStringArray");
|
|
15427
|
+
|
|
15428
|
+
// ../../packages/types/src/usage-decision.ts
|
|
15429
|
+
var USAGE_SCENE_RULE_MAX_CHARS = 240;
|
|
15430
|
+
var USAGE_DECISION_MAX_REQUIRED_PARTS = 6;
|
|
15431
|
+
var USAGE_DECISION_MAX_ALTERNATE_USES = 4;
|
|
15432
|
+
var USAGE_DECISION_MAX_MISUSE = 5;
|
|
15433
|
+
function clampRule(value) {
|
|
15434
|
+
return clampAtWordBoundary(value, USAGE_SCENE_RULE_MAX_CHARS);
|
|
15435
|
+
}
|
|
15436
|
+
__name(clampRule, "clampRule");
|
|
15437
|
+
var UsageDecisionSchema = z68.object({
|
|
15438
|
+
productIdentity: z68.string().min(1),
|
|
15439
|
+
endUser: z68.object({
|
|
15440
|
+
who: z68.string(),
|
|
15441
|
+
appliedTo: z68.string()
|
|
15442
|
+
}),
|
|
15443
|
+
promise: z68.string().min(1),
|
|
15444
|
+
primaryUse: z68.object({
|
|
15445
|
+
scene: z68.string().min(1),
|
|
15446
|
+
postureAndGrip: z68.string(),
|
|
15447
|
+
contactPoint: z68.string(),
|
|
15448
|
+
requiredParts: z68.preprocess(clampStringArray(USAGE_DECISION_MAX_REQUIRED_PARTS), z68.array(z68.string()).max(USAGE_DECISION_MAX_REQUIRED_PARTS))
|
|
15449
|
+
}),
|
|
15450
|
+
validAlternateUses: z68.preprocess(clampStringArray(USAGE_DECISION_MAX_ALTERNATE_USES), z68.array(z68.string()).max(USAGE_DECISION_MAX_ALTERNATE_USES)),
|
|
15451
|
+
misuse: z68.preprocess(clampStringArray(USAGE_DECISION_MAX_MISUSE), z68.array(z68.string().min(1)).max(USAGE_DECISION_MAX_MISUSE)),
|
|
15452
|
+
useSceneRule: z68.preprocess(clampRule, z68.string().min(1).max(USAGE_SCENE_RULE_MAX_CHARS)),
|
|
15453
|
+
/**
|
|
15454
|
+
* True when the promise can ONLY be shown with the primary use (the pain is bending over and
|
|
15455
|
+
* the product has an extension pole: without the pole there is no promise); false when the
|
|
15456
|
+
* valid alternates sell it equally. Drives whether an alternate use in a use scene is a
|
|
15457
|
+
* failure (`requirePrimary` in the usage judge) and whether the prompts' primary use is
|
|
15458
|
+
* mandatory. Optional and fail-safe: missing (decisions stored before the field) or not a
|
|
15459
|
+
* boolean ⇒ `undefined`, read as false by every caller — never a rejected decision.
|
|
15460
|
+
*/
|
|
15461
|
+
primaryRequired: z68.boolean().optional().catch(void 0),
|
|
15462
|
+
confidence: z68.number().min(0).max(1),
|
|
15463
|
+
modelId: z68.string(),
|
|
15464
|
+
decidedAt: z68.string()
|
|
15465
|
+
});
|
|
15466
|
+
|
|
15467
|
+
// ../../packages/types/src/product-truth.ts
|
|
15468
|
+
import { z as z70 } from "zod";
|
|
15469
|
+
|
|
15470
|
+
// ../../packages/types/src/lenient-zod.ts
|
|
15471
|
+
import { z as z69 } from "zod";
|
|
15472
|
+
function trimAndClamp(value, max) {
|
|
15473
|
+
if (typeof value !== "string") return value;
|
|
15474
|
+
return clampAtWordBoundary(value.replace(/\s+/g, " ").trim(), max);
|
|
15475
|
+
}
|
|
15476
|
+
__name(trimAndClamp, "trimAndClamp");
|
|
15477
|
+
function lenientText(max) {
|
|
15478
|
+
return z69.preprocess((v) => trimAndClamp(v, max), z69.string().min(1).max(max));
|
|
15479
|
+
}
|
|
15480
|
+
__name(lenientText, "lenientText");
|
|
15481
|
+
function lenientOptionalText(max) {
|
|
15482
|
+
return z69.preprocess((v) => {
|
|
15483
|
+
if (typeof v !== "string") return void 0;
|
|
15484
|
+
const clamped = trimAndClamp(v, max);
|
|
15485
|
+
return typeof clamped === "string" && clamped.length > 0 ? clamped : void 0;
|
|
15486
|
+
}, z69.string().max(max).optional());
|
|
15487
|
+
}
|
|
15488
|
+
__name(lenientOptionalText, "lenientOptionalText");
|
|
15489
|
+
function lenientTextList(maxItems, maxChars) {
|
|
15490
|
+
return z69.preprocess((v) => {
|
|
15491
|
+
if (!Array.isArray(v)) return [];
|
|
15492
|
+
return v.map((item) => trimAndClamp(item, maxChars)).filter((item) => typeof item === "string" && item.length > 0).slice(0, maxItems);
|
|
15493
|
+
}, z69.array(z69.string().min(1).max(maxChars)).max(maxItems));
|
|
15494
|
+
}
|
|
15495
|
+
__name(lenientTextList, "lenientTextList");
|
|
15496
|
+
function lenientList(item, maxItems) {
|
|
15497
|
+
return z69.preprocess((v) => {
|
|
15498
|
+
if (!Array.isArray(v)) return [];
|
|
15499
|
+
return v.filter((entry) => item.safeParse(entry).success).slice(0, maxItems);
|
|
15500
|
+
}, z69.array(item).max(maxItems));
|
|
15501
|
+
}
|
|
15502
|
+
__name(lenientList, "lenientList");
|
|
15503
|
+
|
|
15504
|
+
// ../../packages/types/src/product-truth.ts
|
|
15505
|
+
var PRODUCT_TRUTH_SCHEMA_VERSION = 1;
|
|
15506
|
+
var PRODUCT_TRUTH_CAPS = {
|
|
15507
|
+
whatItIs: 160,
|
|
15508
|
+
deliveryForm: 120,
|
|
15509
|
+
distinctiveMarks: 6,
|
|
15510
|
+
distinctiveMarkChars: 160,
|
|
15511
|
+
parts: 12,
|
|
15512
|
+
partNameChars: 80,
|
|
15513
|
+
criticalFeatures: 6,
|
|
15514
|
+
connections: 6,
|
|
15515
|
+
connectionChars: 80,
|
|
15516
|
+
states: 4,
|
|
15517
|
+
stateKeyChars: 60,
|
|
15518
|
+
stateLabelChars: 80,
|
|
15519
|
+
partsPresent: 10,
|
|
15520
|
+
orientationInUseChars: 200,
|
|
15521
|
+
appliedToChars: 120,
|
|
15522
|
+
environmentChars: 120,
|
|
15523
|
+
summaryChars: 200,
|
|
15524
|
+
sceneChars: 300,
|
|
15525
|
+
postureAndGripChars: 160,
|
|
15526
|
+
contactPointChars: 120,
|
|
15527
|
+
steps: 8,
|
|
15528
|
+
stepNameChars: 120,
|
|
15529
|
+
stepInstructionChars: 300,
|
|
15530
|
+
visibleEffectChars: 200,
|
|
15531
|
+
beforeStateChars: 200,
|
|
15532
|
+
requiredProps: 8,
|
|
15533
|
+
requiredPropChars: 120,
|
|
15534
|
+
alternates: 3,
|
|
15535
|
+
misuse: 5,
|
|
15536
|
+
misuseChars: 200,
|
|
15537
|
+
mustShowFeatures: 5,
|
|
15538
|
+
mustShowFeatureChars: 100,
|
|
15539
|
+
safety: 5,
|
|
15540
|
+
safetyChars: 200,
|
|
15541
|
+
forbiddenClaims: 8,
|
|
15542
|
+
unsupportedClaims: 5,
|
|
15543
|
+
claimChars: 200,
|
|
15544
|
+
visualSummaryEnChars: 400
|
|
15545
|
+
};
|
|
15546
|
+
var PRODUCT_TRUTH_END_USER_AGE_BANDS = [
|
|
15547
|
+
"baby",
|
|
15548
|
+
"child",
|
|
15549
|
+
"teen",
|
|
15550
|
+
"adult",
|
|
15551
|
+
"any"
|
|
15552
|
+
];
|
|
15553
|
+
var PRODUCT_TRUTH_END_USER_GENDERS = [
|
|
15554
|
+
"female",
|
|
15555
|
+
"male",
|
|
15556
|
+
"any"
|
|
15557
|
+
];
|
|
15558
|
+
var PRODUCT_TRUTH_UNKNOWN_REASONS = [
|
|
15559
|
+
"model_unsure",
|
|
15560
|
+
"no_signal",
|
|
15561
|
+
"invalid_response",
|
|
15562
|
+
"provider_error"
|
|
15563
|
+
];
|
|
15564
|
+
var text = lenientText;
|
|
15565
|
+
var optionalText = lenientOptionalText;
|
|
15566
|
+
var textList = lenientTextList;
|
|
15567
|
+
function toProductTruthStateKey(value) {
|
|
15568
|
+
if (typeof value !== "string") return void 0;
|
|
15569
|
+
const slug = value.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, PRODUCT_TRUTH_CAPS.stateKeyChars);
|
|
15570
|
+
return slug.length > 0 ? slug : void 0;
|
|
15571
|
+
}
|
|
15572
|
+
__name(toProductTruthStateKey, "toProductTruthStateKey");
|
|
15573
|
+
var stateKey = z70.preprocess(toProductTruthStateKey, z70.string().min(1).max(PRODUCT_TRUTH_CAPS.stateKeyChars));
|
|
15574
|
+
var optionalStateKey = z70.preprocess(toProductTruthStateKey, z70.string().min(1).max(PRODUCT_TRUTH_CAPS.stateKeyChars).optional());
|
|
15575
|
+
var AGE_BAND_ALIASES = {
|
|
15576
|
+
baby: "baby",
|
|
15577
|
+
babies: "baby",
|
|
15578
|
+
infant: "baby",
|
|
15579
|
+
infants: "baby",
|
|
15580
|
+
toddler: "child",
|
|
15581
|
+
child: "child",
|
|
15582
|
+
children: "child",
|
|
15583
|
+
kid: "child",
|
|
15584
|
+
kids: "child",
|
|
15585
|
+
teen: "teen",
|
|
15586
|
+
teens: "teen",
|
|
15587
|
+
teenager: "teen",
|
|
15588
|
+
teenagers: "teen",
|
|
15589
|
+
adult: "adult",
|
|
15590
|
+
adults: "adult",
|
|
15591
|
+
any: "any",
|
|
15592
|
+
all: "any",
|
|
15593
|
+
"all ages": "any"
|
|
15594
|
+
};
|
|
15595
|
+
var GENDER_ALIASES = {
|
|
15596
|
+
female: "female",
|
|
15597
|
+
woman: "female",
|
|
15598
|
+
women: "female",
|
|
15599
|
+
girl: "female",
|
|
15600
|
+
male: "male",
|
|
15601
|
+
man: "male",
|
|
15602
|
+
men: "male",
|
|
15603
|
+
boy: "male",
|
|
15604
|
+
any: "any",
|
|
15605
|
+
unisex: "any",
|
|
15606
|
+
both: "any",
|
|
15607
|
+
all: "any"
|
|
15608
|
+
};
|
|
15609
|
+
function matchAlias(raw, aliases) {
|
|
15610
|
+
if (typeof raw !== "string") return void 0;
|
|
15611
|
+
const text2 = raw.trim().toLowerCase();
|
|
15612
|
+
const exact = aliases[text2];
|
|
15613
|
+
if (exact) return exact;
|
|
15614
|
+
const words = new Set(text2.split(/[^a-z]+/).filter(Boolean));
|
|
15615
|
+
for (const [alias, value] of Object.entries(aliases)) {
|
|
15616
|
+
if (words.has(alias)) return value;
|
|
15617
|
+
}
|
|
15618
|
+
return void 0;
|
|
15619
|
+
}
|
|
15620
|
+
__name(matchAlias, "matchAlias");
|
|
15621
|
+
function normalizeEndUser(value) {
|
|
15622
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
15623
|
+
const v = value;
|
|
15624
|
+
const age = matchAlias(v.ageBand, AGE_BAND_ALIASES);
|
|
15625
|
+
const gender = matchAlias(v.gender, GENDER_ALIASES);
|
|
15626
|
+
if (!age || !gender || typeof v.usedByBuyer !== "boolean") return void 0;
|
|
15627
|
+
return {
|
|
15628
|
+
ageBand: age,
|
|
15629
|
+
gender,
|
|
15630
|
+
usedByBuyer: v.usedByBuyer
|
|
15631
|
+
};
|
|
15632
|
+
}
|
|
15633
|
+
__name(normalizeEndUser, "normalizeEndUser");
|
|
15634
|
+
var ProductTruthEndUserSchema = z70.object({
|
|
15635
|
+
ageBand: z70.enum(PRODUCT_TRUTH_END_USER_AGE_BANDS),
|
|
15636
|
+
gender: z70.enum(PRODUCT_TRUTH_END_USER_GENDERS),
|
|
15637
|
+
usedByBuyer: z70.boolean()
|
|
15638
|
+
});
|
|
15639
|
+
var MATERIAL_HINTS = ProductMorphology.shape.materialHints.unwrap().element.options;
|
|
15640
|
+
var DEMO_TYPES = FunctionalDemonstration.shape.demoType;
|
|
15641
|
+
var PartSchema = z70.object({
|
|
15642
|
+
name: text(PRODUCT_TRUTH_CAPS.partNameChars),
|
|
15643
|
+
kind: z70.enum([
|
|
15644
|
+
"rigid",
|
|
15645
|
+
"flexible",
|
|
15646
|
+
"joint"
|
|
15647
|
+
]).catch("rigid"),
|
|
15648
|
+
count: z70.number().int().min(1).max(20).catch(1)
|
|
15649
|
+
});
|
|
15650
|
+
var CriticalFeatureSchema = z70.object({
|
|
15651
|
+
name: text(60),
|
|
15652
|
+
importance: text(120),
|
|
15653
|
+
antiPattern: optionalText(80),
|
|
15654
|
+
expectedCount: z70.number().int().min(1).max(20).optional().catch(void 0)
|
|
15655
|
+
});
|
|
15656
|
+
var ConnectionSchema = z70.object({
|
|
15657
|
+
part: text(PRODUCT_TRUTH_CAPS.connectionChars),
|
|
15658
|
+
attachesTo: text(PRODUCT_TRUTH_CAPS.connectionChars),
|
|
15659
|
+
where: optionalText(PRODUCT_TRUTH_CAPS.connectionChars)
|
|
15660
|
+
});
|
|
15661
|
+
var StateSchema = z70.object({
|
|
15662
|
+
key: stateKey,
|
|
15663
|
+
label: optionalText(PRODUCT_TRUTH_CAPS.stateLabelChars),
|
|
15664
|
+
partsPresent: textList(PRODUCT_TRUTH_CAPS.partsPresent, PRODUCT_TRUTH_CAPS.partNameChars),
|
|
15665
|
+
orientationInUse: text(PRODUCT_TRUTH_CAPS.orientationInUseChars),
|
|
15666
|
+
naturalOrientation: ProductNaturalOrientation.optional().catch(void 0)
|
|
15667
|
+
});
|
|
15668
|
+
var StepSchema = z70.object({
|
|
15669
|
+
name: text(PRODUCT_TRUTH_CAPS.stepNameChars),
|
|
15670
|
+
instruction: text(PRODUCT_TRUTH_CAPS.stepInstructionChars),
|
|
15671
|
+
kind: z70.enum([
|
|
15672
|
+
"setup",
|
|
15673
|
+
"use",
|
|
15674
|
+
"finish"
|
|
15675
|
+
]).catch("use")
|
|
15676
|
+
});
|
|
15677
|
+
var AlternateSchema = z70.object({
|
|
15678
|
+
summary: text(PRODUCT_TRUTH_CAPS.summaryChars),
|
|
15679
|
+
stateKey: optionalStateKey,
|
|
15680
|
+
advertisedBySeller: z70.boolean().catch(false)
|
|
15681
|
+
});
|
|
15682
|
+
var DemoSchema = z70.object({
|
|
15683
|
+
demoType: DEMO_TYPES.nullable().catch(null),
|
|
15684
|
+
mustShowFeatures: textList(PRODUCT_TRUTH_CAPS.mustShowFeatures, PRODUCT_TRUTH_CAPS.mustShowFeatureChars),
|
|
15685
|
+
importance: z70.enum([
|
|
15686
|
+
"critical",
|
|
15687
|
+
"important",
|
|
15688
|
+
"nice_to_have"
|
|
15689
|
+
]).catch("important")
|
|
15690
|
+
});
|
|
15691
|
+
var objectOrEmpty = /* @__PURE__ */ __name((v) => v && typeof v === "object" && !Array.isArray(v) ? v : {}, "objectOrEmpty");
|
|
15692
|
+
var ProductTruthBody = z70.object({
|
|
15693
|
+
identity: z70.object({
|
|
15694
|
+
whatItIs: text(PRODUCT_TRUTH_CAPS.whatItIs),
|
|
15695
|
+
deliveryForm: optionalText(PRODUCT_TRUTH_CAPS.deliveryForm),
|
|
15696
|
+
distinctiveMarks: textList(PRODUCT_TRUTH_CAPS.distinctiveMarks, PRODUCT_TRUTH_CAPS.distinctiveMarkChars)
|
|
15697
|
+
}),
|
|
15698
|
+
morphology: z70.preprocess(objectOrEmpty, z70.object({
|
|
15699
|
+
shape: ProductGeometryShape.optional().catch(void 0),
|
|
15700
|
+
crossSection: ProductCrossSection.optional().catch(void 0),
|
|
15701
|
+
cornerProfile: ProductCornerProfile.optional().catch(void 0),
|
|
15702
|
+
silhouetteWidthToHeightRatio: z70.number().min(0.05).max(20).optional().catch(void 0),
|
|
15703
|
+
parts: lenientList(PartSchema, PRODUCT_TRUTH_CAPS.parts),
|
|
15704
|
+
criticalFeatures: lenientList(CriticalFeatureSchema, PRODUCT_TRUTH_CAPS.criticalFeatures),
|
|
15705
|
+
shapeLockLevel: z70.enum([
|
|
15706
|
+
"strict",
|
|
15707
|
+
"moderate",
|
|
15708
|
+
"relaxed"
|
|
15709
|
+
]).optional().catch(void 0),
|
|
15710
|
+
materialHints: z70.preprocess((v) => Array.isArray(v) ? [
|
|
15711
|
+
...new Set(v.filter((m) => MATERIAL_HINTS.includes(m)))
|
|
15712
|
+
].slice(0, 3) : [], z70.array(z70.enum(MATERIAL_HINTS)).max(3))
|
|
15713
|
+
})),
|
|
15714
|
+
assembly: z70.object({
|
|
15715
|
+
connections: lenientList(ConnectionSchema, PRODUCT_TRUTH_CAPS.connections),
|
|
15716
|
+
states: z70.preprocess((v) => {
|
|
15717
|
+
if (!Array.isArray(v)) return v;
|
|
15718
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15719
|
+
return v.filter((entry) => {
|
|
15720
|
+
const parsed = StateSchema.safeParse(entry);
|
|
15721
|
+
if (!parsed.success || seen.has(parsed.data.key)) return false;
|
|
15722
|
+
seen.add(parsed.data.key);
|
|
15723
|
+
return true;
|
|
15724
|
+
}).slice(0, PRODUCT_TRUTH_CAPS.states);
|
|
15725
|
+
}, z70.array(StateSchema).min(1).max(PRODUCT_TRUTH_CAPS.states)),
|
|
15726
|
+
defaultStateKey: optionalStateKey
|
|
15727
|
+
}),
|
|
15728
|
+
use: z70.object({
|
|
15729
|
+
endUser: z70.preprocess(normalizeEndUser, ProductTruthEndUserSchema.optional()).catch(void 0),
|
|
15730
|
+
appliedTo: optionalText(PRODUCT_TRUTH_CAPS.appliedToChars),
|
|
15731
|
+
environment: optionalText(PRODUCT_TRUTH_CAPS.environmentChars),
|
|
15732
|
+
primary: z70.object({
|
|
15733
|
+
summary: text(PRODUCT_TRUTH_CAPS.summaryChars),
|
|
15734
|
+
scene: text(PRODUCT_TRUTH_CAPS.sceneChars),
|
|
15735
|
+
postureAndGrip: optionalText(PRODUCT_TRUTH_CAPS.postureAndGripChars),
|
|
15736
|
+
contactPoint: optionalText(PRODUCT_TRUTH_CAPS.contactPointChars),
|
|
15737
|
+
stateKey: optionalStateKey,
|
|
15738
|
+
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)),
|
|
15739
|
+
visibleEffect: optionalText(PRODUCT_TRUTH_CAPS.visibleEffectChars),
|
|
15740
|
+
beforeState: optionalText(PRODUCT_TRUTH_CAPS.beforeStateChars),
|
|
15741
|
+
requiredProps: textList(PRODUCT_TRUTH_CAPS.requiredProps, PRODUCT_TRUTH_CAPS.requiredPropChars)
|
|
15742
|
+
}),
|
|
15743
|
+
alternates: lenientList(AlternateSchema, PRODUCT_TRUTH_CAPS.alternates),
|
|
15744
|
+
misuse: textList(PRODUCT_TRUTH_CAPS.misuse, PRODUCT_TRUTH_CAPS.misuseChars),
|
|
15745
|
+
demo: z70.preprocess(objectOrEmpty, DemoSchema),
|
|
15746
|
+
safety: textList(PRODUCT_TRUTH_CAPS.safety, PRODUCT_TRUTH_CAPS.safetyChars)
|
|
15747
|
+
}),
|
|
15748
|
+
claims: z70.preprocess(objectOrEmpty, z70.object({
|
|
15749
|
+
forbidden: textList(PRODUCT_TRUTH_CAPS.forbiddenClaims, PRODUCT_TRUTH_CAPS.claimChars),
|
|
15750
|
+
unsupported: textList(PRODUCT_TRUTH_CAPS.unsupportedClaims, PRODUCT_TRUTH_CAPS.claimChars)
|
|
15751
|
+
})),
|
|
15752
|
+
visualSummaryEn: optionalText(PRODUCT_TRUTH_CAPS.visualSummaryEnChars),
|
|
15753
|
+
evidence: z70.preprocess(objectOrEmpty, z70.object({
|
|
15754
|
+
photoIndexForState: z70.preprocess((v) => {
|
|
15755
|
+
const out = {};
|
|
15756
|
+
if (!v || typeof v !== "object" || Array.isArray(v)) return out;
|
|
15757
|
+
for (const [rawKey, rawIndexes] of Object.entries(v)) {
|
|
15758
|
+
const key = toProductTruthStateKey(rawKey);
|
|
15759
|
+
if (!key || !Array.isArray(rawIndexes)) continue;
|
|
15760
|
+
out[key] = rawIndexes.filter((i) => typeof i === "number" && Number.isInteger(i) && i >= 0 && i < 20);
|
|
15761
|
+
}
|
|
15762
|
+
return out;
|
|
15763
|
+
}, z70.record(z70.array(z70.number().int().min(0).max(19))))
|
|
15764
|
+
})),
|
|
15765
|
+
confidence: z70.preprocess((v) => typeof v === "number" && Number.isFinite(v) ? Math.min(1, Math.max(0, v)) : 0, z70.number().min(0).max(1))
|
|
15766
|
+
});
|
|
15767
|
+
function resolveStateRefs(body) {
|
|
15768
|
+
const keys = new Set(body.assembly.states.map((s) => s.key));
|
|
15769
|
+
const firstKey = body.assembly.states[0]?.key ?? "";
|
|
15770
|
+
const defaultStateKey = body.assembly.defaultStateKey && keys.has(body.assembly.defaultStateKey) ? body.assembly.defaultStateKey : firstKey;
|
|
15771
|
+
const primaryKey = body.use.primary.stateKey && keys.has(body.use.primary.stateKey) ? body.use.primary.stateKey : defaultStateKey;
|
|
15772
|
+
const photoIndexForState = Object.fromEntries(Object.entries(body.evidence.photoIndexForState).filter(([key]) => keys.has(key)));
|
|
15773
|
+
return {
|
|
15774
|
+
...body,
|
|
15775
|
+
assembly: {
|
|
15776
|
+
...body.assembly,
|
|
15777
|
+
defaultStateKey
|
|
15778
|
+
},
|
|
15779
|
+
use: {
|
|
15780
|
+
...body.use,
|
|
15781
|
+
primary: {
|
|
15782
|
+
...body.use.primary,
|
|
15783
|
+
stateKey: primaryKey
|
|
15784
|
+
},
|
|
15785
|
+
alternates: body.use.alternates.map((alt) => ({
|
|
15786
|
+
...alt,
|
|
15787
|
+
stateKey: alt.stateKey && keys.has(alt.stateKey) ? alt.stateKey : defaultStateKey
|
|
15788
|
+
}))
|
|
15789
|
+
},
|
|
15790
|
+
evidence: {
|
|
15791
|
+
...body.evidence,
|
|
15792
|
+
photoIndexForState
|
|
15793
|
+
}
|
|
15794
|
+
};
|
|
15795
|
+
}
|
|
15796
|
+
__name(resolveStateRefs, "resolveStateRefs");
|
|
15797
|
+
var ProductTruthModelResponseSchema = ProductTruthBody.transform(resolveStateRefs);
|
|
15798
|
+
var provenance = {
|
|
15799
|
+
schemaVersion: z70.literal(PRODUCT_TRUTH_SCHEMA_VERSION),
|
|
15800
|
+
modelId: z70.string().min(1),
|
|
15801
|
+
derivedAt: z70.string().min(1),
|
|
15802
|
+
/** Hash of (image keys + seller text + features): a reader that sees a different current
|
|
15803
|
+
* fingerprint treats the truth as absent. See `computeProductTruthFingerprint` in packages/ai. */
|
|
15804
|
+
sourceFingerprint: z70.string().min(1),
|
|
15805
|
+
/** The seller upload KEYS (deduped, sorted) the fingerprint was computed over. Stored so a
|
|
15806
|
+
* reader can recompute the CURRENT fingerprint from today's seller text + features without
|
|
15807
|
+
* knowing the extract job's inputs (plan Global Constraint "Invalidez"). */
|
|
15808
|
+
sourceImageKeys: z70.array(z70.string().min(1)).max(20).optional()
|
|
15809
|
+
};
|
|
15810
|
+
var ProductTruthKnownSchema = ProductTruthBody.extend({
|
|
15811
|
+
...provenance,
|
|
15812
|
+
known: z70.literal(true)
|
|
15813
|
+
}).transform(resolveStateRefs);
|
|
15814
|
+
var ProductTruthUnknownSchema = z70.object({
|
|
15815
|
+
schemaVersion: z70.literal(PRODUCT_TRUTH_SCHEMA_VERSION),
|
|
15816
|
+
known: z70.literal(false),
|
|
15817
|
+
unknownReason: z70.enum(PRODUCT_TRUTH_UNKNOWN_REASONS),
|
|
15818
|
+
modelId: z70.string().optional(),
|
|
15819
|
+
derivedAt: z70.string().min(1),
|
|
15820
|
+
sourceFingerprint: z70.string().min(1),
|
|
15821
|
+
sourceImageKeys: z70.array(z70.string().min(1)).max(20).optional()
|
|
15822
|
+
});
|
|
15823
|
+
var ProductTruthSchema = z70.union([
|
|
15824
|
+
ProductTruthKnownSchema,
|
|
15825
|
+
ProductTruthUnknownSchema
|
|
15826
|
+
]);
|
|
15827
|
+
|
|
15828
|
+
// ../../packages/types/src/landing-director.ts
|
|
15829
|
+
import { z as z71 } from "zod";
|
|
15830
|
+
var LANDING_DIRECTOR_SCHEMA_VERSION = 1;
|
|
15831
|
+
var LANDING_DIRECTOR_ARM = "categories";
|
|
15832
|
+
var LANDING_DIRECTOR_CAPS = {
|
|
15833
|
+
productIdentity: 200,
|
|
15834
|
+
parts: 8,
|
|
15835
|
+
partName: 40,
|
|
15836
|
+
promise: 200,
|
|
15837
|
+
endUserWho: 80,
|
|
15838
|
+
endUserAppliedTo: 80,
|
|
15839
|
+
forbiddenClaims: 10,
|
|
15840
|
+
claimChars: 80,
|
|
15841
|
+
misuse: 5,
|
|
15842
|
+
misuseChars: 120,
|
|
15843
|
+
assembledStates: 3,
|
|
15844
|
+
statePartsMax: 6,
|
|
15845
|
+
orientation: 160,
|
|
15846
|
+
handling: 140,
|
|
15847
|
+
primaryScene: 200,
|
|
15848
|
+
postureAndGrip: 140,
|
|
15849
|
+
contactPoint: 100,
|
|
15850
|
+
alternates: 3,
|
|
15851
|
+
alternateChars: 120,
|
|
15852
|
+
ambiguities: 4,
|
|
15853
|
+
ambiguityChars: 160,
|
|
15854
|
+
sectionKeyChars: 40,
|
|
15855
|
+
personWho: 80,
|
|
15856
|
+
personPosture: 120,
|
|
15857
|
+
personGrip: 120,
|
|
15858
|
+
scene: 450,
|
|
15859
|
+
panels: 4,
|
|
15860
|
+
panelScene: 200,
|
|
15861
|
+
panelCaption: 60,
|
|
15862
|
+
/** Rendered text: an item over its cap is DROPPED, never cut. The headline cap is 80, not
|
|
15863
|
+
* the design's 70: a dropped headline costs the whole director headline, and 7-10 Spanish
|
|
15864
|
+
* words routinely run 70-80 chars. */
|
|
15865
|
+
headline: 80,
|
|
15866
|
+
subheadline: 90,
|
|
15867
|
+
labels: 3,
|
|
15868
|
+
labelChars: 40,
|
|
15869
|
+
captions: 3,
|
|
15870
|
+
captionChars: 60,
|
|
15871
|
+
props: 4,
|
|
15872
|
+
propChars: 40,
|
|
15873
|
+
mustNotShow: 5,
|
|
15874
|
+
mustNotShowChars: 80
|
|
15875
|
+
};
|
|
15876
|
+
var STATE_KEY_PATTERN = /^[a-z][a-z_]{1,23}$/;
|
|
15877
|
+
function toLandingDirectorStateKey(value) {
|
|
15878
|
+
if (typeof value !== "string") return void 0;
|
|
15879
|
+
const slug = value.toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g, "").replace(/[^a-z]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 24).replace(/_+$/g, "");
|
|
15880
|
+
return STATE_KEY_PATTERN.test(slug) ? slug : void 0;
|
|
15881
|
+
}
|
|
15882
|
+
__name(toLandingDirectorStateKey, "toLandingDirectorStateKey");
|
|
15883
|
+
var stateKey2 = z71.preprocess(toLandingDirectorStateKey, z71.string().regex(STATE_KEY_PATTERN));
|
|
15884
|
+
function renderedOptionalText(max) {
|
|
15885
|
+
return z71.preprocess((v) => {
|
|
15886
|
+
if (typeof v !== "string") return void 0;
|
|
15887
|
+
const trimmed = v.replace(/\s+/g, " ").trim();
|
|
15888
|
+
return trimmed.length > 0 && trimmed.length <= max ? trimmed : void 0;
|
|
15889
|
+
}, z71.string().min(1).max(max).optional());
|
|
15890
|
+
}
|
|
15891
|
+
__name(renderedOptionalText, "renderedOptionalText");
|
|
15892
|
+
function renderedTextList(maxItems, maxChars) {
|
|
15893
|
+
return z71.preprocess((v) => {
|
|
15894
|
+
if (!Array.isArray(v)) return [];
|
|
15895
|
+
return v.map((item) => typeof item === "string" ? item.replace(/\s+/g, " ").trim() : "").filter((item) => item.length > 0 && item.length <= maxChars).slice(0, maxItems);
|
|
15896
|
+
}, z71.array(z71.string().min(1).max(maxChars)).max(maxItems));
|
|
15897
|
+
}
|
|
15898
|
+
__name(renderedTextList, "renderedTextList");
|
|
15899
|
+
var C = LANDING_DIRECTOR_CAPS;
|
|
15900
|
+
var PartSchema2 = z71.object({
|
|
15901
|
+
name: lenientText(C.partName),
|
|
15902
|
+
critical: z71.boolean().catch(false)
|
|
15903
|
+
});
|
|
15904
|
+
var AssembledStateSchema = z71.object({
|
|
15905
|
+
key: stateKey2,
|
|
15906
|
+
parts: lenientTextList(C.statePartsMax, C.partName),
|
|
15907
|
+
orientation: lenientText(C.orientation),
|
|
15908
|
+
handling: lenientOptionalText(C.handling)
|
|
15909
|
+
});
|
|
15910
|
+
var END_USER_GENDERS = [
|
|
15911
|
+
"female",
|
|
15912
|
+
"male",
|
|
15913
|
+
"any"
|
|
15914
|
+
];
|
|
15915
|
+
var END_USER_AGE_BANDS = [
|
|
15916
|
+
"child",
|
|
15917
|
+
"teen",
|
|
15918
|
+
"adult",
|
|
15919
|
+
"senior",
|
|
15920
|
+
"any"
|
|
15921
|
+
];
|
|
15922
|
+
var EndUserSchema = z71.object({
|
|
15923
|
+
who: lenientText(C.endUserWho),
|
|
15924
|
+
appliedTo: lenientOptionalText(C.endUserAppliedTo),
|
|
15925
|
+
gender: z71.enum(END_USER_GENDERS).catch("any"),
|
|
15926
|
+
ageBand: z71.enum(END_USER_AGE_BANDS).catch("any")
|
|
15927
|
+
});
|
|
15928
|
+
var LandingDirectorGlobalSchema = z71.object({
|
|
15929
|
+
productIdentity: lenientText(C.productIdentity),
|
|
15930
|
+
parts: lenientList(PartSchema2, C.parts),
|
|
15931
|
+
promise: lenientText(C.promise),
|
|
15932
|
+
endUser: EndUserSchema,
|
|
15933
|
+
forbiddenClaims: lenientTextList(C.forbiddenClaims, C.claimChars),
|
|
15934
|
+
misuse: lenientTextList(C.misuse, C.misuseChars),
|
|
15935
|
+
assembledStates: z71.preprocess((v) => {
|
|
15936
|
+
if (!Array.isArray(v)) return v;
|
|
15937
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15938
|
+
return v.filter((entry) => {
|
|
15939
|
+
const parsed = AssembledStateSchema.safeParse(entry);
|
|
15940
|
+
if (!parsed.success || seen.has(parsed.data.key)) return false;
|
|
15941
|
+
seen.add(parsed.data.key);
|
|
15942
|
+
return true;
|
|
15943
|
+
}).slice(0, C.assembledStates);
|
|
15944
|
+
}, z71.array(AssembledStateSchema).min(1).max(C.assembledStates)),
|
|
15945
|
+
primaryUse: z71.object({
|
|
15946
|
+
assembledState: stateKey2,
|
|
15947
|
+
scene: lenientText(C.primaryScene),
|
|
15948
|
+
postureAndGrip: lenientText(C.postureAndGrip),
|
|
15949
|
+
contactPoint: lenientOptionalText(C.contactPoint)
|
|
15950
|
+
}),
|
|
15951
|
+
primaryRequired: z71.boolean().catch(false),
|
|
15952
|
+
validAlternateUses: lenientTextList(C.alternates, C.alternateChars),
|
|
15953
|
+
ambiguities: lenientTextList(C.ambiguities, C.ambiguityChars)
|
|
15954
|
+
});
|
|
15955
|
+
var LANDING_DIRECTOR_BODY_PARTS = [
|
|
15956
|
+
"hands",
|
|
15957
|
+
"face",
|
|
15958
|
+
"torso",
|
|
15959
|
+
"legs",
|
|
15960
|
+
"feet",
|
|
15961
|
+
"full_body"
|
|
15962
|
+
];
|
|
15963
|
+
var PersonSchema = z71.object({
|
|
15964
|
+
who: lenientText(C.personWho),
|
|
15965
|
+
posture: lenientText(C.personPosture),
|
|
15966
|
+
grip: lenientOptionalText(C.personGrip),
|
|
15967
|
+
bodyPartsVisible: z71.preprocess((v) => Array.isArray(v) ? [
|
|
15968
|
+
...new Set(v.filter((part) => LANDING_DIRECTOR_BODY_PARTS.includes(part)))
|
|
15969
|
+
] : [], z71.array(z71.enum(LANDING_DIRECTOR_BODY_PARTS)))
|
|
15970
|
+
});
|
|
15971
|
+
var LandingDirectorTextSchema = z71.object({
|
|
15972
|
+
headline: renderedOptionalText(C.headline),
|
|
15973
|
+
subheadline: renderedOptionalText(C.subheadline),
|
|
15974
|
+
labels: renderedTextList(C.labels, C.labelChars),
|
|
15975
|
+
captions: renderedTextList(C.captions, C.captionChars)
|
|
15976
|
+
});
|
|
15977
|
+
var PanelSchema = z71.object({
|
|
15978
|
+
scene: lenientText(C.panelScene),
|
|
15979
|
+
caption: renderedOptionalText(C.panelCaption)
|
|
15980
|
+
});
|
|
15981
|
+
var PRODUCT_IN_FRAME_VALUES = [
|
|
15982
|
+
"none",
|
|
15983
|
+
"packshot",
|
|
15984
|
+
"in_use"
|
|
15985
|
+
];
|
|
15986
|
+
var LandingDirectorSectionSchema = z71.object({
|
|
15987
|
+
sectionKey: z71.string().trim().min(1).max(C.sectionKeyChars),
|
|
15988
|
+
/** Present only in the «director» arm. Kept as a flag so the «categorías» validation can
|
|
15989
|
+
* invalidate the section (design §2.3) instead of silently dropping the model's choice. */
|
|
15990
|
+
hasComposition: z71.boolean().default(false),
|
|
15991
|
+
productInFrame: z71.enum(PRODUCT_IN_FRAME_VALUES),
|
|
15992
|
+
assembledState: z71.preprocess((v) => v === null || v === void 0 ? null : toLandingDirectorStateKey(v), z71.string().regex(STATE_KEY_PATTERN).nullable()),
|
|
15993
|
+
usesPrimary: z71.boolean().catch(false),
|
|
15994
|
+
person: z71.preprocess((v) => v === void 0 ? null : v, PersonSchema.nullable()),
|
|
15995
|
+
scene: lenientText(C.scene),
|
|
15996
|
+
panels: lenientList(PanelSchema, C.panels),
|
|
15997
|
+
textToRender: z71.preprocess((v) => v && typeof v === "object" && !Array.isArray(v) ? v : {}, LandingDirectorTextSchema),
|
|
15998
|
+
props: lenientTextList(C.props, C.propChars),
|
|
15999
|
+
mustNotShow: lenientTextList(C.mustNotShow, C.mustNotShowChars)
|
|
16000
|
+
});
|
|
16001
|
+
var LandingDirectorOutputSchema = z71.object({
|
|
16002
|
+
version: z71.literal(LANDING_DIRECTOR_SCHEMA_VERSION),
|
|
16003
|
+
confidence: z71.number().min(0).max(1),
|
|
16004
|
+
global: LandingDirectorGlobalSchema,
|
|
16005
|
+
sections: z71.array(LandingDirectorSectionSchema)
|
|
16006
|
+
});
|
|
16007
|
+
var StoredLandingDirectorSchema = z71.object({
|
|
16008
|
+
version: z71.literal(LANDING_DIRECTOR_SCHEMA_VERSION),
|
|
16009
|
+
arm: z71.literal(LANDING_DIRECTOR_ARM),
|
|
16010
|
+
modelId: z71.string().min(1),
|
|
16011
|
+
generatedAt: z71.string().min(1),
|
|
16012
|
+
confidence: z71.number().min(0).max(1),
|
|
16013
|
+
/** The plan the answer was validated against (sectionKey, or the role on classic). */
|
|
16014
|
+
planSectionKeys: z71.array(z71.string().min(1)),
|
|
16015
|
+
output: LandingDirectorOutputSchema,
|
|
16016
|
+
/** Sections that fell back to the category composition, and why. */
|
|
16017
|
+
fallbackSections: z71.array(z71.object({
|
|
16018
|
+
sectionKey: z71.string().min(1),
|
|
16019
|
+
reason: z71.string().min(1)
|
|
16020
|
+
}))
|
|
16021
|
+
});
|
|
16022
|
+
|
|
16023
|
+
// ../../packages/types/src/flight-recorder.ts
|
|
16024
|
+
import { z as z72 } from "zod";
|
|
16025
|
+
var FlightRecorderGenerationTypeSchema = z72.enum([
|
|
15185
16026
|
"initial",
|
|
15186
16027
|
"regeneration",
|
|
15187
16028
|
"edit",
|
|
15188
16029
|
"retry"
|
|
15189
16030
|
]);
|
|
15190
|
-
var FlightRecorderProviderSchema =
|
|
16031
|
+
var FlightRecorderProviderSchema = z72.enum([
|
|
15191
16032
|
"kie",
|
|
15192
16033
|
"fal"
|
|
15193
16034
|
]);
|
|
15194
|
-
var FlightRecorderElementSchema =
|
|
15195
|
-
name:
|
|
15196
|
-
description:
|
|
15197
|
-
frontalImageUrl:
|
|
15198
|
-
referenceImageUrls:
|
|
15199
|
-
videoUrl:
|
|
15200
|
-
});
|
|
15201
|
-
var FlightRecorderDistillationSchema =
|
|
15202
|
-
actorGender:
|
|
16035
|
+
var FlightRecorderElementSchema = z72.object({
|
|
16036
|
+
name: z72.string().optional(),
|
|
16037
|
+
description: z72.string().optional(),
|
|
16038
|
+
frontalImageUrl: z72.string().optional(),
|
|
16039
|
+
referenceImageUrls: z72.array(z72.string()).optional(),
|
|
16040
|
+
videoUrl: z72.string().optional()
|
|
16041
|
+
});
|
|
16042
|
+
var FlightRecorderDistillationSchema = z72.object({
|
|
16043
|
+
actorGender: z72.enum([
|
|
15203
16044
|
"female",
|
|
15204
16045
|
"male",
|
|
15205
16046
|
"mixed"
|
|
15206
|
-
]).or(
|
|
15207
|
-
voiceId:
|
|
15208
|
-
cameraMotion:
|
|
15209
|
-
}).catchall(
|
|
15210
|
-
var FlightRecorderEntrySchema =
|
|
15211
|
-
schemaVersion:
|
|
15212
|
-
id:
|
|
15213
|
-
taskId:
|
|
15214
|
-
runId:
|
|
15215
|
-
sequence:
|
|
15216
|
-
timestamp:
|
|
15217
|
-
provider: FlightRecorderProviderSchema.or(
|
|
15218
|
-
model:
|
|
15219
|
-
prompt:
|
|
15220
|
-
durationSeconds:
|
|
15221
|
-
aspectRatio:
|
|
15222
|
-
resolution:
|
|
15223
|
-
startImageUrl:
|
|
15224
|
-
endImageUrl:
|
|
15225
|
-
generateAudio:
|
|
16047
|
+
]).or(z72.string()).optional(),
|
|
16048
|
+
voiceId: z72.string().optional(),
|
|
16049
|
+
cameraMotion: z72.string().optional()
|
|
16050
|
+
}).catchall(z72.unknown());
|
|
16051
|
+
var FlightRecorderEntrySchema = z72.object({
|
|
16052
|
+
schemaVersion: z72.literal(1).optional(),
|
|
16053
|
+
id: z72.string().min(1),
|
|
16054
|
+
taskId: z72.string().min(1),
|
|
16055
|
+
runId: z72.string().min(1),
|
|
16056
|
+
sequence: z72.number().int().nonnegative(),
|
|
16057
|
+
timestamp: z72.string().min(1),
|
|
16058
|
+
provider: FlightRecorderProviderSchema.or(z72.string()),
|
|
16059
|
+
model: z72.string().min(1),
|
|
16060
|
+
prompt: z72.string(),
|
|
16061
|
+
durationSeconds: z72.number().nonnegative(),
|
|
16062
|
+
aspectRatio: z72.string().optional(),
|
|
16063
|
+
resolution: z72.string().optional(),
|
|
16064
|
+
startImageUrl: z72.string().optional(),
|
|
16065
|
+
endImageUrl: z72.string().optional(),
|
|
16066
|
+
generateAudio: z72.boolean().optional(),
|
|
15226
16067
|
// Correlation & pipeline metadata
|
|
15227
|
-
angleKey:
|
|
15228
|
-
sceneIndex:
|
|
16068
|
+
angleKey: z72.string().optional(),
|
|
16069
|
+
sceneIndex: z72.number().int().nonnegative().optional(),
|
|
15229
16070
|
generationType: FlightRecorderGenerationTypeSchema,
|
|
15230
|
-
operationId:
|
|
15231
|
-
revisionId:
|
|
15232
|
-
attemptNumber:
|
|
16071
|
+
operationId: z72.string().min(1).optional(),
|
|
16072
|
+
revisionId: z72.string().min(1).optional(),
|
|
16073
|
+
attemptNumber: z72.number().int().nonnegative().default(1),
|
|
15233
16074
|
// Elements & Distillation
|
|
15234
|
-
elements:
|
|
16075
|
+
elements: z72.array(FlightRecorderElementSchema).optional(),
|
|
15235
16076
|
distillation: FlightRecorderDistillationSchema.optional(),
|
|
15236
16077
|
// Raw payload (sanitized of secrets)
|
|
15237
|
-
rawPayload:
|
|
16078
|
+
rawPayload: z72.record(z72.unknown())
|
|
15238
16079
|
});
|
|
15239
|
-
var FlightRecorderQuerySchema =
|
|
15240
|
-
taskId:
|
|
15241
|
-
runId:
|
|
15242
|
-
sceneIndex:
|
|
15243
|
-
angleKey:
|
|
16080
|
+
var FlightRecorderQuerySchema = z72.object({
|
|
16081
|
+
taskId: z72.string().min(1),
|
|
16082
|
+
runId: z72.string().optional(),
|
|
16083
|
+
sceneIndex: z72.number().int().nonnegative().optional(),
|
|
16084
|
+
angleKey: z72.string().optional(),
|
|
15244
16085
|
generationType: FlightRecorderGenerationTypeSchema.optional(),
|
|
15245
|
-
cursor:
|
|
15246
|
-
limit:
|
|
16086
|
+
cursor: z72.number().int().nonnegative().optional(),
|
|
16087
|
+
limit: z72.number().int().positive().optional()
|
|
15247
16088
|
});
|
|
15248
|
-
var FlightRecorderResponseSchema =
|
|
15249
|
-
taskId:
|
|
15250
|
-
runId:
|
|
15251
|
-
entries:
|
|
16089
|
+
var FlightRecorderResponseSchema = z72.object({
|
|
16090
|
+
taskId: z72.string().min(1),
|
|
16091
|
+
runId: z72.string().min(1),
|
|
16092
|
+
entries: z72.array(FlightRecorderEntrySchema),
|
|
15252
16093
|
lastCall: FlightRecorderEntrySchema.nullable(),
|
|
15253
|
-
count:
|
|
15254
|
-
nextCursor:
|
|
16094
|
+
count: z72.number().int().nonnegative(),
|
|
16095
|
+
nextCursor: z72.number().int().nonnegative().nullable()
|
|
15255
16096
|
});
|
|
15256
16097
|
|
|
15257
16098
|
// src/http.ts
|
|
@@ -15426,8 +16267,8 @@ async function readResponseText(response, maxBytes) {
|
|
|
15426
16267
|
}
|
|
15427
16268
|
__name(readResponseText, "readResponseText");
|
|
15428
16269
|
async function readResponseJson(response, maxBytes) {
|
|
15429
|
-
const
|
|
15430
|
-
return JSON.parse(
|
|
16270
|
+
const text2 = await readResponseText(response, maxBytes);
|
|
16271
|
+
return JSON.parse(text2);
|
|
15431
16272
|
}
|
|
15432
16273
|
__name(readResponseJson, "readResponseJson");
|
|
15433
16274
|
|
|
@@ -15760,22 +16601,22 @@ import { InsufficientScopeError, InvalidTokenError } from "@modelcontextprotocol
|
|
|
15760
16601
|
import { createRemoteJWKSet as createRemoteJWKSet2, jwtVerify as jwtVerify2 } from "jose";
|
|
15761
16602
|
|
|
15762
16603
|
// src/auth/oauth-config.ts
|
|
15763
|
-
import { z as
|
|
16604
|
+
import { z as z73 } from "zod";
|
|
15764
16605
|
var MCP_RESOURCE = new URL("https://mcp.productmaker.app/mcp");
|
|
15765
16606
|
var MCP_SCOPE = "mcp:access";
|
|
15766
16607
|
var STATIC_CLIENT_ISSUER = new URL(MCP_RESOURCE.origin);
|
|
15767
|
-
var oauthEnvSchema =
|
|
15768
|
-
MCP_REMOTE_AUTH_MODE:
|
|
15769
|
-
MCP_AUTH0_ISSUER:
|
|
15770
|
-
MCP_AUTH0_AUDIENCE:
|
|
16608
|
+
var oauthEnvSchema = z73.object({
|
|
16609
|
+
MCP_REMOTE_AUTH_MODE: z73.literal("oauth"),
|
|
16610
|
+
MCP_AUTH0_ISSUER: z73.string().trim().min(1),
|
|
16611
|
+
MCP_AUTH0_AUDIENCE: z73.string().trim().refine((value) => value === MCP_RESOURCE.href, {
|
|
15771
16612
|
message: `must equal ${MCP_RESOURCE.href}`
|
|
15772
16613
|
}),
|
|
15773
|
-
MCP_AUTH0_CLIENT_ID:
|
|
15774
|
-
MCP_AUTH0_CLIENT_SECRET:
|
|
15775
|
-
PM_API_AUDIENCE:
|
|
15776
|
-
AUTH0_AUDIENCE:
|
|
15777
|
-
MCP_STATIC_CLIENT_ID:
|
|
15778
|
-
MCP_STATIC_CLIENT_SECRET:
|
|
16614
|
+
MCP_AUTH0_CLIENT_ID: z73.string().trim().min(1),
|
|
16615
|
+
MCP_AUTH0_CLIENT_SECRET: z73.string().trim().min(1),
|
|
16616
|
+
PM_API_AUDIENCE: z73.string().trim().min(1),
|
|
16617
|
+
AUTH0_AUDIENCE: z73.string().trim().min(1),
|
|
16618
|
+
MCP_STATIC_CLIENT_ID: z73.string().trim().min(1).optional(),
|
|
16619
|
+
MCP_STATIC_CLIENT_SECRET: z73.string().trim().min(1).optional()
|
|
15779
16620
|
});
|
|
15780
16621
|
function formatZodIssues(error) {
|
|
15781
16622
|
return error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
|
|
@@ -16059,7 +16900,7 @@ function badRequest(res, description) {
|
|
|
16059
16900
|
__name(badRequest, "badRequest");
|
|
16060
16901
|
function createOAuthProxyRouter(options) {
|
|
16061
16902
|
const router = express.Router();
|
|
16062
|
-
const
|
|
16903
|
+
const stateKey3 = deriveStateKey(options.staticClient.clientSecret);
|
|
16063
16904
|
const now = options.now ?? (() => Date.now());
|
|
16064
16905
|
router.get(OAUTH_PROXY_PATHS.authorize, (req, res) => {
|
|
16065
16906
|
const redirectUri = firstQueryValue(req.query.redirect_uri);
|
|
@@ -16088,7 +16929,7 @@ function createOAuthProxyRouter(options) {
|
|
|
16088
16929
|
}
|
|
16089
16930
|
}
|
|
16090
16931
|
upstream.searchParams.set("redirect_uri", PROXY_CALLBACK_URL);
|
|
16091
|
-
upstream.searchParams.set("state", sealState(
|
|
16932
|
+
upstream.searchParams.set("state", sealState(stateKey3, {
|
|
16092
16933
|
redirectUri,
|
|
16093
16934
|
...firstQueryValue(req.query.state) === void 0 ? {} : {
|
|
16094
16935
|
clientState: firstQueryValue(req.query.state)
|
|
@@ -16098,7 +16939,7 @@ function createOAuthProxyRouter(options) {
|
|
|
16098
16939
|
});
|
|
16099
16940
|
router.get(OAUTH_PROXY_PATHS.callback, (req, res) => {
|
|
16100
16941
|
const sealed = firstQueryValue(req.query.state);
|
|
16101
|
-
const opened = sealed === void 0 ? void 0 : openState(
|
|
16942
|
+
const opened = sealed === void 0 ? void 0 : openState(stateKey3, sealed, now());
|
|
16102
16943
|
if (!opened) {
|
|
16103
16944
|
badRequest(res, "state is missing, tampered with, or expired");
|
|
16104
16945
|
return;
|
|
@@ -16882,7 +17723,7 @@ var ApiClient = class {
|
|
|
16882
17723
|
};
|
|
16883
17724
|
|
|
16884
17725
|
// src/index.ts
|
|
16885
|
-
var MCP_VERSION = "8.
|
|
17726
|
+
var MCP_VERSION = "8.2.0";
|
|
16886
17727
|
|
|
16887
17728
|
// src/meta-upload-app.ts
|
|
16888
17729
|
import { readFileSync } from "fs";
|
|
@@ -16954,7 +17795,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
|
|
|
16954
17795
|
__name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
|
|
16955
17796
|
|
|
16956
17797
|
// src/tools/tasks.ts
|
|
16957
|
-
import { z as
|
|
17798
|
+
import { z as z77 } from "zod";
|
|
16958
17799
|
|
|
16959
17800
|
// src/resolve-image.ts
|
|
16960
17801
|
import { lookup as dnsLookup } from "dns/promises";
|
|
@@ -17515,10 +18356,10 @@ async function resolveMediaRef(ref, opts) {
|
|
|
17515
18356
|
__name(resolveMediaRef, "resolveMediaRef");
|
|
17516
18357
|
|
|
17517
18358
|
// src/tools/shared.ts
|
|
17518
|
-
import { z as
|
|
17519
|
-
var Lang =
|
|
17520
|
-
var Country =
|
|
17521
|
-
var LandingStrategyEnum =
|
|
18359
|
+
import { z as z74 } from "zod";
|
|
18360
|
+
var Lang = z74.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);
|
|
18361
|
+
var Country = z74.string().min(2).max(3);
|
|
18362
|
+
var LandingStrategyEnum = z74.enum([
|
|
17522
18363
|
"auto",
|
|
17523
18364
|
"classic",
|
|
17524
18365
|
"pain_solution",
|
|
@@ -17527,12 +18368,12 @@ var LandingStrategyEnum = z70.enum([
|
|
|
17527
18368
|
"offer_value",
|
|
17528
18369
|
"lifestyle_identity"
|
|
17529
18370
|
]);
|
|
17530
|
-
var LandingImageFormatEnum =
|
|
18371
|
+
var LandingImageFormatEnum = z74.enum([
|
|
17531
18372
|
"9:16",
|
|
17532
18373
|
"4:5",
|
|
17533
18374
|
"1:1"
|
|
17534
18375
|
]);
|
|
17535
|
-
var VideoPresetEnum =
|
|
18376
|
+
var VideoPresetEnum = z74.enum([
|
|
17536
18377
|
"auto",
|
|
17537
18378
|
"ugc_dynamic",
|
|
17538
18379
|
"ugc_how_to",
|
|
@@ -17545,21 +18386,21 @@ var VideoPresetEnum = z70.enum([
|
|
|
17545
18386
|
"pixar_problem",
|
|
17546
18387
|
"pixar_sassy"
|
|
17547
18388
|
]);
|
|
17548
|
-
var VideoStructureEnum =
|
|
18389
|
+
var VideoStructureEnum = z74.enum([
|
|
17549
18390
|
"single_take",
|
|
17550
18391
|
"multi_scene"
|
|
17551
18392
|
]);
|
|
17552
|
-
var VideoQualityEnum =
|
|
18393
|
+
var VideoQualityEnum = z74.enum([
|
|
17553
18394
|
"economy",
|
|
17554
18395
|
"medium",
|
|
17555
18396
|
"pro"
|
|
17556
18397
|
]);
|
|
17557
|
-
var VideoRouteIdEnum =
|
|
18398
|
+
var VideoRouteIdEnum = z74.enum([
|
|
17558
18399
|
"single_take",
|
|
17559
18400
|
"multi_scene",
|
|
17560
18401
|
"free"
|
|
17561
18402
|
]);
|
|
17562
|
-
var TaskCreativeVariantVideoPresetEnum =
|
|
18403
|
+
var TaskCreativeVariantVideoPresetEnum = z74.enum([
|
|
17563
18404
|
"auto",
|
|
17564
18405
|
"ugc_dynamic",
|
|
17565
18406
|
"ugc_how_to",
|
|
@@ -17576,53 +18417,43 @@ var VIDEO_PRESET_RESOLUTION = {
|
|
|
17576
18417
|
auto: null,
|
|
17577
18418
|
ugc_dynamic: {
|
|
17578
18419
|
videoStyle: "ai_dynamic",
|
|
17579
|
-
narrativeStyle: "review"
|
|
17580
|
-
videoModel: "veo"
|
|
18420
|
+
narrativeStyle: "review"
|
|
17581
18421
|
},
|
|
17582
18422
|
ugc_how_to: {
|
|
17583
18423
|
videoStyle: "ai_dynamic",
|
|
17584
|
-
narrativeStyle: "ugc_how_to"
|
|
17585
|
-
videoModel: "veo"
|
|
18424
|
+
narrativeStyle: "ugc_how_to"
|
|
17586
18425
|
},
|
|
17587
18426
|
ugc_unboxing_chaos: {
|
|
17588
18427
|
videoStyle: "ai_dynamic",
|
|
17589
|
-
narrativeStyle: "ugc_unboxing_chaos"
|
|
17590
|
-
videoModel: "veo"
|
|
18428
|
+
narrativeStyle: "ugc_unboxing_chaos"
|
|
17591
18429
|
},
|
|
17592
18430
|
problem_solution: {
|
|
17593
18431
|
videoStyle: "ai_dynamic",
|
|
17594
|
-
narrativeStyle: "problem_product_cta"
|
|
17595
|
-
videoModel: "kling"
|
|
18432
|
+
narrativeStyle: "problem_product_cta"
|
|
17596
18433
|
},
|
|
17597
18434
|
pixar_problem: {
|
|
17598
18435
|
videoStyle: "ai_dynamic",
|
|
17599
|
-
narrativeStyle: "animated_problem_pixar"
|
|
17600
|
-
videoModel: "kling"
|
|
18436
|
+
narrativeStyle: "animated_problem_pixar"
|
|
17601
18437
|
},
|
|
17602
18438
|
pixar_sassy: {
|
|
17603
18439
|
videoStyle: "ai_dynamic",
|
|
17604
|
-
narrativeStyle: "sassy_product_pixar"
|
|
17605
|
-
videoModel: "seedance"
|
|
18440
|
+
narrativeStyle: "sassy_product_pixar"
|
|
17606
18441
|
},
|
|
17607
18442
|
product_showcase: {
|
|
17608
18443
|
videoStyle: "product_only",
|
|
17609
|
-
narrativeStyle: "product_showcase"
|
|
17610
|
-
videoModel: "veo"
|
|
18444
|
+
narrativeStyle: "product_showcase"
|
|
17611
18445
|
},
|
|
17612
18446
|
wearable_showcase: {
|
|
17613
18447
|
videoStyle: "ugc",
|
|
17614
|
-
narrativeStyle: "wearable_showcase"
|
|
17615
|
-
videoModel: "veo"
|
|
18448
|
+
narrativeStyle: "wearable_showcase"
|
|
17616
18449
|
},
|
|
17617
18450
|
cinematic: {
|
|
17618
18451
|
videoStyle: "product_only",
|
|
17619
|
-
narrativeStyle: "cinematic"
|
|
17620
|
-
videoModel: "grok"
|
|
18452
|
+
narrativeStyle: "cinematic"
|
|
17621
18453
|
},
|
|
17622
18454
|
wild_card: {
|
|
17623
18455
|
videoStyle: "product_only",
|
|
17624
|
-
narrativeStyle: "wild_card"
|
|
17625
|
-
videoModel: "grok"
|
|
18456
|
+
narrativeStyle: "wild_card"
|
|
17626
18457
|
}
|
|
17627
18458
|
};
|
|
17628
18459
|
function resolveVideoPreset(preset) {
|
|
@@ -17630,7 +18461,7 @@ function resolveVideoPreset(preset) {
|
|
|
17630
18461
|
return VIDEO_PRESET_RESOLUTION[preset] ?? null;
|
|
17631
18462
|
}
|
|
17632
18463
|
__name(resolveVideoPreset, "resolveVideoPreset");
|
|
17633
|
-
var VideoTierEnum =
|
|
18464
|
+
var VideoTierEnum = z74.enum([
|
|
17634
18465
|
"basic"
|
|
17635
18466
|
]);
|
|
17636
18467
|
function resolveVideoTier(_tier) {
|
|
@@ -17670,22 +18501,22 @@ function assertSemanticVideoDurationCompatibility(structure, quality, durationSe
|
|
|
17670
18501
|
}
|
|
17671
18502
|
}
|
|
17672
18503
|
__name(assertSemanticVideoDurationCompatibility, "assertSemanticVideoDurationCompatibility");
|
|
17673
|
-
var VideoResolutionEnum =
|
|
18504
|
+
var VideoResolutionEnum = z74.enum([
|
|
17674
18505
|
"480p",
|
|
17675
18506
|
"720p"
|
|
17676
18507
|
]);
|
|
17677
|
-
var CreativeGenderEnum =
|
|
18508
|
+
var CreativeGenderEnum = z74.enum([
|
|
17678
18509
|
"female",
|
|
17679
18510
|
"male",
|
|
17680
18511
|
"mixed"
|
|
17681
18512
|
]);
|
|
17682
|
-
var VideoStyleEnum =
|
|
18513
|
+
var VideoStyleEnum = z74.enum([
|
|
17683
18514
|
"ugc",
|
|
17684
18515
|
"cartoon_3d",
|
|
17685
18516
|
"product_only",
|
|
17686
18517
|
"ai_dynamic"
|
|
17687
18518
|
]);
|
|
17688
|
-
var NarrativeStyleEnum =
|
|
18519
|
+
var NarrativeStyleEnum = z74.enum([
|
|
17689
18520
|
"review",
|
|
17690
18521
|
"ugc_how_to",
|
|
17691
18522
|
"problem_product_cta",
|
|
@@ -17703,7 +18534,7 @@ var NarrativeStyleEnum = z70.enum([
|
|
|
17703
18534
|
"ugc_demo_review",
|
|
17704
18535
|
"market"
|
|
17705
18536
|
]);
|
|
17706
|
-
var PublicNarrativeStyleEnum =
|
|
18537
|
+
var PublicNarrativeStyleEnum = z74.enum([
|
|
17707
18538
|
"review",
|
|
17708
18539
|
"ugc_how_to",
|
|
17709
18540
|
"ugc_unboxing_chaos",
|
|
@@ -17716,7 +18547,7 @@ var PublicNarrativeStyleEnum = z70.enum([
|
|
|
17716
18547
|
"sassy_product_pixar",
|
|
17717
18548
|
"market"
|
|
17718
18549
|
]);
|
|
17719
|
-
var
|
|
18550
|
+
var TaskVideoModelEnum = z74.enum([
|
|
17720
18551
|
"veo",
|
|
17721
18552
|
"wan",
|
|
17722
18553
|
"bytedance",
|
|
@@ -17724,29 +18555,29 @@ var VideoModelEnum = z70.enum([
|
|
|
17724
18555
|
"grok",
|
|
17725
18556
|
"kling"
|
|
17726
18557
|
]);
|
|
17727
|
-
var ProductReferenceUserChoiceEnum =
|
|
18558
|
+
var ProductReferenceUserChoiceEnum = z74.enum([
|
|
17728
18559
|
"same_product",
|
|
17729
18560
|
"variants",
|
|
17730
18561
|
"different_products",
|
|
17731
18562
|
"combo_distinct"
|
|
17732
18563
|
]);
|
|
17733
|
-
var ProductReferenceCandidateGroupingEnum =
|
|
18564
|
+
var ProductReferenceCandidateGroupingEnum = z74.enum([
|
|
17734
18565
|
"same_product_same_variant",
|
|
17735
18566
|
"same_product_different_variants",
|
|
17736
18567
|
"different_products",
|
|
17737
18568
|
"unclear"
|
|
17738
18569
|
]);
|
|
17739
|
-
var ProductReferenceScopeEnum =
|
|
18570
|
+
var ProductReferenceScopeEnum = z74.enum([
|
|
17740
18571
|
"base",
|
|
17741
18572
|
"video_view_pack"
|
|
17742
18573
|
]);
|
|
17743
|
-
var ProductReferenceResolutionDecisionEnum =
|
|
18574
|
+
var ProductReferenceResolutionDecisionEnum = z74.enum([
|
|
17744
18575
|
"approve",
|
|
17745
18576
|
"reject",
|
|
17746
18577
|
"observed_only",
|
|
17747
18578
|
"correct_view"
|
|
17748
18579
|
]);
|
|
17749
|
-
var ProductReferenceRejectionReasonEnum =
|
|
18580
|
+
var ProductReferenceRejectionReasonEnum = z74.enum([
|
|
17750
18581
|
"replacement_requested",
|
|
17751
18582
|
"wrong_product_identity",
|
|
17752
18583
|
"wrong_variant",
|
|
@@ -17757,13 +18588,13 @@ var ProductReferenceRejectionReasonEnum = z70.enum([
|
|
|
17757
18588
|
"not_a_product_photo",
|
|
17758
18589
|
"other"
|
|
17759
18590
|
]);
|
|
17760
|
-
var GapDurationChoiceMirror =
|
|
17761
|
-
angleIndex:
|
|
17762
|
-
recommendedSec:
|
|
17763
|
-
|
|
17764
|
-
|
|
18591
|
+
var GapDurationChoiceMirror = z74.object({
|
|
18592
|
+
angleIndex: z74.number().int().nonnegative(),
|
|
18593
|
+
recommendedSec: z74.union([
|
|
18594
|
+
z74.literal(15),
|
|
18595
|
+
z74.literal(30)
|
|
17765
18596
|
]),
|
|
17766
|
-
estimatedDeltaCredits:
|
|
18597
|
+
estimatedDeltaCredits: z74.number().int().nonnegative().optional()
|
|
17767
18598
|
});
|
|
17768
18599
|
function buildSelectedImageUrlsHash(urls) {
|
|
17769
18600
|
const input = [
|
|
@@ -17773,13 +18604,13 @@ function buildSelectedImageUrlsHash(urls) {
|
|
|
17773
18604
|
return `fnv1a:${hash.toString(16).padStart(8, "0")}:${urls.length}`;
|
|
17774
18605
|
}
|
|
17775
18606
|
__name(buildSelectedImageUrlsHash, "buildSelectedImageUrlsHash");
|
|
17776
|
-
var ImageCreativeStyleEnum =
|
|
18607
|
+
var ImageCreativeStyleEnum = z74.enum([
|
|
17777
18608
|
"studio",
|
|
17778
18609
|
"floating",
|
|
17779
18610
|
"ingredients",
|
|
17780
18611
|
"in_use"
|
|
17781
18612
|
]);
|
|
17782
|
-
var ImageCreativeArchetypeEnum =
|
|
18613
|
+
var ImageCreativeArchetypeEnum = z74.enum([
|
|
17783
18614
|
"direct_response_product_ad",
|
|
17784
18615
|
"hero_outcome",
|
|
17785
18616
|
"offer_value_prop",
|
|
@@ -17788,20 +18619,20 @@ var ImageCreativeArchetypeEnum = z70.enum([
|
|
|
17788
18619
|
"problem_solution",
|
|
17789
18620
|
"lifestyle_identity"
|
|
17790
18621
|
]);
|
|
17791
|
-
var ImageCreativeVisualTreatmentEnum =
|
|
18622
|
+
var ImageCreativeVisualTreatmentEnum = z74.enum([
|
|
17792
18623
|
"performance_product_ad",
|
|
17793
18624
|
"premium_dtc_carousel"
|
|
17794
18625
|
]);
|
|
17795
|
-
var ImageCreativeAspectRatioEnum =
|
|
18626
|
+
var ImageCreativeAspectRatioEnum = z74.enum([
|
|
17796
18627
|
"1:1",
|
|
17797
18628
|
"4:5",
|
|
17798
18629
|
"9:16",
|
|
17799
18630
|
"16:9"
|
|
17800
18631
|
]);
|
|
17801
|
-
var ImageRefSchema =
|
|
17802
|
-
url:
|
|
17803
|
-
path:
|
|
17804
|
-
assetId:
|
|
18632
|
+
var ImageRefSchema = z74.object({
|
|
18633
|
+
url: z74.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.'),
|
|
18634
|
+
path: z74.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`.'),
|
|
18635
|
+
assetId: z74.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.")
|
|
17805
18636
|
}).refine((v) => [
|
|
17806
18637
|
v.url,
|
|
17807
18638
|
v.path,
|
|
@@ -17809,11 +18640,11 @@ var ImageRefSchema = z70.object({
|
|
|
17809
18640
|
].filter(Boolean).length === 1, {
|
|
17810
18641
|
message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
|
|
17811
18642
|
});
|
|
17812
|
-
var ImagesInput =
|
|
18643
|
+
var ImagesInput = z74.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
|
|
17813
18644
|
const assetCount = images.filter((image) => Boolean(image.assetId)).length;
|
|
17814
18645
|
if (assetCount > 0 && assetCount !== images.length) {
|
|
17815
18646
|
ctx.addIssue({
|
|
17816
|
-
code:
|
|
18647
|
+
code: z74.ZodIssueCode.custom,
|
|
17817
18648
|
message: "all image entries must use assetId, or all must use URL/path sources"
|
|
17818
18649
|
});
|
|
17819
18650
|
}
|
|
@@ -17881,14 +18712,14 @@ async function submitCreative(api, opts) {
|
|
|
17881
18712
|
});
|
|
17882
18713
|
}
|
|
17883
18714
|
__name(submitCreative, "submitCreative");
|
|
17884
|
-
var ResearchTargetCountryEnum =
|
|
18715
|
+
var ResearchTargetCountryEnum = z74.enum([
|
|
17885
18716
|
"CO",
|
|
17886
18717
|
"MX",
|
|
17887
18718
|
"PE",
|
|
17888
18719
|
"EC",
|
|
17889
18720
|
"CL"
|
|
17890
18721
|
]);
|
|
17891
|
-
var ResearchCategoryEnum =
|
|
18722
|
+
var ResearchCategoryEnum = z74.enum([
|
|
17892
18723
|
"auto",
|
|
17893
18724
|
"automotive",
|
|
17894
18725
|
"kitchen",
|
|
@@ -17957,7 +18788,7 @@ var OVERWRITES_EXTERNAL = {
|
|
|
17957
18788
|
idempotentHint: false,
|
|
17958
18789
|
openWorldHint: false
|
|
17959
18790
|
};
|
|
17960
|
-
var DailyControlStatusEnum =
|
|
18791
|
+
var DailyControlStatusEnum = z74.enum([
|
|
17961
18792
|
"ok",
|
|
17962
18793
|
"sales_unavailable",
|
|
17963
18794
|
"timezone_unavailable",
|
|
@@ -17970,19 +18801,19 @@ var DailyControlStatusEnum = z70.enum([
|
|
|
17970
18801
|
"product_missing",
|
|
17971
18802
|
"store_unreachable"
|
|
17972
18803
|
]);
|
|
17973
|
-
var DailyControlLightEnum =
|
|
18804
|
+
var DailyControlLightEnum = z74.enum([
|
|
17974
18805
|
"green",
|
|
17975
18806
|
"amber",
|
|
17976
18807
|
"red",
|
|
17977
18808
|
"none"
|
|
17978
18809
|
]);
|
|
17979
|
-
var DailyControlVerdictEnum =
|
|
18810
|
+
var DailyControlVerdictEnum = z74.enum([
|
|
17980
18811
|
"scale",
|
|
17981
18812
|
"hold",
|
|
17982
18813
|
"kill",
|
|
17983
18814
|
"insufficient_sample"
|
|
17984
18815
|
]);
|
|
17985
|
-
var DailyControlSourceEnum =
|
|
18816
|
+
var DailyControlSourceEnum = z74.enum([
|
|
17986
18817
|
"shopify",
|
|
17987
18818
|
"shopify_settling",
|
|
17988
18819
|
"user",
|
|
@@ -19070,29 +19901,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
|
|
|
19070
19901
|
__name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
|
|
19071
19902
|
|
|
19072
19903
|
// src/tools/media-presentation.ts
|
|
19073
|
-
import { z as
|
|
19074
|
-
var HttpsPresentationUrlSchema =
|
|
19904
|
+
import { z as z75 } from "zod";
|
|
19905
|
+
var HttpsPresentationUrlSchema = z75.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
|
|
19075
19906
|
var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
|
|
19076
19907
|
const hostname = new URL(value).hostname.toLowerCase();
|
|
19077
19908
|
return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
|
|
19078
19909
|
}, "preview URL must be owned by ProductMaker");
|
|
19079
|
-
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) =>
|
|
19080
|
-
var PresentationImageSchema =
|
|
19081
|
-
kind:
|
|
19910
|
+
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z75.number().int().positive().max(maximum), "positiveIntAtMost");
|
|
19911
|
+
var PresentationImageSchema = z75.object({
|
|
19912
|
+
kind: z75.literal("image"),
|
|
19082
19913
|
url: HttpsPresentationUrlSchema,
|
|
19083
|
-
mimeType:
|
|
19914
|
+
mimeType: z75.enum([
|
|
19084
19915
|
"image/jpeg",
|
|
19085
19916
|
"image/png"
|
|
19086
19917
|
]),
|
|
19087
19918
|
byteSize: positiveIntAtMost(5 * 1024 * 1024),
|
|
19088
19919
|
width: positiveIntAtMost(16384),
|
|
19089
19920
|
height: positiveIntAtMost(16384),
|
|
19090
|
-
alt:
|
|
19921
|
+
alt: z75.string().trim().min(1).max(240)
|
|
19091
19922
|
}).strict();
|
|
19092
19923
|
var McpMediaPresentationSchema = PresentationImageSchema;
|
|
19093
|
-
var GalleryImageSchema =
|
|
19924
|
+
var GalleryImageSchema = z75.object({
|
|
19094
19925
|
url: ProductMakerPreviewUrlSchema,
|
|
19095
|
-
alt:
|
|
19926
|
+
alt: z75.string().trim().min(1).max(240)
|
|
19096
19927
|
});
|
|
19097
19928
|
var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
|
|
19098
19929
|
async function imageBlocks(image, transport) {
|
|
@@ -19242,10 +20073,10 @@ ${summary}`,
|
|
|
19242
20073
|
__name(requirePaidCreativeConfirmation, "requirePaidCreativeConfirmation");
|
|
19243
20074
|
|
|
19244
20075
|
// src/tools/winning-product-image.ts
|
|
19245
|
-
import { z as
|
|
19246
|
-
var WinnerReferenceInput =
|
|
19247
|
-
runId:
|
|
19248
|
-
candidateSourceId:
|
|
20076
|
+
import { z as z76 } from "zod";
|
|
20077
|
+
var WinnerReferenceInput = z76.object({
|
|
20078
|
+
runId: z76.string().uuid(),
|
|
20079
|
+
candidateSourceId: z76.string().trim().min(1).max(160)
|
|
19249
20080
|
}).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
|
|
19250
20081
|
async function resolveWinnerImages(api, winnerReference, images) {
|
|
19251
20082
|
if (!winnerReference) return images;
|
|
@@ -19282,59 +20113,59 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
|
|
|
19282
20113
|
var createServiceVideoGuidance = getProductMakerCapabilityModelGuidance("create_service_video");
|
|
19283
20114
|
var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
|
|
19284
20115
|
var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
|
|
19285
|
-
var CreateProductTaskInput =
|
|
20116
|
+
var CreateProductTaskInput = z77.object({
|
|
19286
20117
|
images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
|
|
19287
20118
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
19288
|
-
projectId:
|
|
19289
|
-
productUrl:
|
|
20119
|
+
projectId: z77.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
|
|
20120
|
+
productUrl: z77.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."),
|
|
19290
20121
|
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.'),
|
|
19291
20122
|
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.'),
|
|
19292
|
-
price:
|
|
19293
|
-
compareAtPrice:
|
|
19294
|
-
offer:
|
|
19295
|
-
paymentMethods:
|
|
19296
|
-
productContext:
|
|
19297
|
-
productLabel:
|
|
20123
|
+
price: z77.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.'),
|
|
20124
|
+
compareAtPrice: z77.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".'),
|
|
20125
|
+
offer: z77.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.'),
|
|
20126
|
+
paymentMethods: z77.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.'),
|
|
20127
|
+
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."),
|
|
20128
|
+
productLabel: z77.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.'),
|
|
19298
20129
|
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.'),
|
|
19299
|
-
durationSeconds:
|
|
19300
|
-
|
|
19301
|
-
|
|
20130
|
+
durationSeconds: z77.union([
|
|
20131
|
+
z77.literal(15),
|
|
20132
|
+
z77.literal(30)
|
|
19302
20133
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
19303
|
-
pauseForAngleReview:
|
|
19304
|
-
aiDecidesAll:
|
|
20134
|
+
pauseForAngleReview: z77.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."),
|
|
20135
|
+
aiDecidesAll: z77.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."),
|
|
19305
20136
|
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.'),
|
|
19306
20137
|
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.'),
|
|
19307
20138
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
19308
20139
|
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).'),
|
|
19309
|
-
videoAngleCount:
|
|
20140
|
+
videoAngleCount: z77.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."),
|
|
19310
20141
|
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.'),
|
|
19311
|
-
outputs:
|
|
20142
|
+
outputs: z77.array(z77.enum([
|
|
19312
20143
|
"landing",
|
|
19313
20144
|
"video",
|
|
19314
20145
|
"image"
|
|
19315
20146
|
])).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}`),
|
|
19316
|
-
competitorScanEnabled:
|
|
19317
|
-
replicateWinnerWhenFound:
|
|
19318
|
-
brandId:
|
|
19319
|
-
actorId:
|
|
20147
|
+
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). 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."),
|
|
20148
|
+
replicateWinnerWhenFound: z77.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."),
|
|
20149
|
+
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 los outputs generados."),
|
|
20150
|
+
actorId: z77.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."),
|
|
19320
20151
|
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.'),
|
|
19321
|
-
creativeDirection:
|
|
19322
|
-
headline:
|
|
19323
|
-
subheadline:
|
|
20152
|
+
creativeDirection: z77.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.'),
|
|
20153
|
+
headline: z77.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."),
|
|
20154
|
+
subheadline: z77.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."),
|
|
19324
20155
|
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".'),
|
|
19325
20156
|
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".')
|
|
19326
20157
|
}).strict();
|
|
19327
|
-
var CreateServiceVideoInput =
|
|
19328
|
-
landingUrl:
|
|
19329
|
-
additionalContext:
|
|
20158
|
+
var CreateServiceVideoInput = z77.object({
|
|
20159
|
+
landingUrl: z77.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
|
|
20160
|
+
additionalContext: z77.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
|
|
19330
20161
|
language: Lang.describe("Idioma del video: es, en o pt."),
|
|
19331
|
-
voiceId:
|
|
19332
|
-
brandId:
|
|
19333
|
-
reviewMode:
|
|
20162
|
+
voiceId: z77.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.'),
|
|
20163
|
+
brandId: z77.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
|
|
20164
|
+
reviewMode: z77.enum([
|
|
19334
20165
|
"automatic",
|
|
19335
20166
|
"guided"
|
|
19336
20167
|
]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
|
|
19337
|
-
videoPreset:
|
|
20168
|
+
videoPreset: z77.enum([
|
|
19338
20169
|
"auto",
|
|
19339
20170
|
"ugc_dynamic",
|
|
19340
20171
|
"ugc_how_to",
|
|
@@ -19344,128 +20175,128 @@ var CreateServiceVideoInput = z73.object({
|
|
|
19344
20175
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
19345
20176
|
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.')
|
|
19346
20177
|
}).strict();
|
|
19347
|
-
var GetTaskStatusInput =
|
|
19348
|
-
taskId:
|
|
19349
|
-
waitSeconds:
|
|
20178
|
+
var GetTaskStatusInput = z77.object({
|
|
20179
|
+
taskId: z77.string().min(1),
|
|
20180
|
+
waitSeconds: z77.number().int().min(0).max(120).optional()
|
|
19350
20181
|
});
|
|
19351
|
-
var ListTasksInput =
|
|
19352
|
-
limit:
|
|
19353
|
-
offset:
|
|
19354
|
-
search:
|
|
20182
|
+
var ListTasksInput = z77.object({
|
|
20183
|
+
limit: z77.number().int().min(1).max(50).optional(),
|
|
20184
|
+
offset: z77.number().int().min(0).optional(),
|
|
20185
|
+
search: z77.string().optional()
|
|
19355
20186
|
});
|
|
19356
20187
|
var MCP_REVIEW_LIST_FIELD_MAX = 1500;
|
|
19357
20188
|
var MCP_REVIEW_FEATURE_ITEM_MAX = 240;
|
|
19358
|
-
var EditTaskDraftInput =
|
|
19359
|
-
taskId:
|
|
19360
|
-
angleIndex:
|
|
19361
|
-
angle:
|
|
19362
|
-
angle:
|
|
19363
|
-
buyerPersona:
|
|
19364
|
-
actor:
|
|
19365
|
-
actorId:
|
|
19366
|
-
gender:
|
|
20189
|
+
var EditTaskDraftInput = z77.object({
|
|
20190
|
+
taskId: z77.string().min(1),
|
|
20191
|
+
angleIndex: z77.number().int().min(0),
|
|
20192
|
+
angle: z77.object({
|
|
20193
|
+
angle: z77.string().min(1).max(480),
|
|
20194
|
+
buyerPersona: z77.string().min(1).max(360),
|
|
20195
|
+
actor: z77.string().min(1).max(360).optional(),
|
|
20196
|
+
actorId: z77.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."),
|
|
20197
|
+
gender: z77.enum([
|
|
19367
20198
|
"female",
|
|
19368
20199
|
"male"
|
|
19369
20200
|
]).optional(),
|
|
19370
|
-
scriptNotes:
|
|
20201
|
+
scriptNotes: z77.string().max(2e3).optional()
|
|
19371
20202
|
})
|
|
19372
20203
|
});
|
|
19373
|
-
var PendingActionPayload =
|
|
19374
|
-
|
|
19375
|
-
kind:
|
|
20204
|
+
var PendingActionPayload = z77.discriminatedUnion("kind", [
|
|
20205
|
+
z77.object({
|
|
20206
|
+
kind: z77.literal("product_reference_set_approval"),
|
|
19376
20207
|
scope: ProductReferenceScopeEnum.optional(),
|
|
19377
|
-
scopeKey:
|
|
19378
|
-
scopeSnapshotId:
|
|
19379
|
-
expectedScopeHash:
|
|
20208
|
+
scopeKey: z77.string().min(1).max(120).optional(),
|
|
20209
|
+
scopeSnapshotId: z77.string().uuid().optional(),
|
|
20210
|
+
expectedScopeHash: z77.string().min(1).max(128).optional(),
|
|
19380
20211
|
decision: ProductReferenceResolutionDecisionEnum,
|
|
19381
20212
|
reason: ProductReferenceRejectionReasonEnum.optional(),
|
|
19382
|
-
affectedRefKeys:
|
|
19383
|
-
affectedPhotoNumbers:
|
|
19384
|
-
recoveryAction:
|
|
20213
|
+
affectedRefKeys: z77.array(z77.string().min(1).max(200)).min(1).optional(),
|
|
20214
|
+
affectedPhotoNumbers: z77.array(z77.number().int().positive()).min(1).optional(),
|
|
20215
|
+
recoveryAction: z77.enum([
|
|
19385
20216
|
"remove",
|
|
19386
20217
|
"replace",
|
|
19387
20218
|
"upload",
|
|
19388
20219
|
"return_to_selection"
|
|
19389
20220
|
]).optional()
|
|
19390
20221
|
}),
|
|
19391
|
-
|
|
19392
|
-
kind:
|
|
19393
|
-
selectedPhotoNumbers:
|
|
20222
|
+
z77.object({
|
|
20223
|
+
kind: z77.literal("product_reference_confirmation"),
|
|
20224
|
+
selectedPhotoNumbers: z77.array(z77.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."),
|
|
19394
20225
|
userChoice: ProductReferenceUserChoiceEnum.optional(),
|
|
19395
|
-
confirmedProductNames:
|
|
20226
|
+
confirmedProductNames: z77.array(z77.string().min(1).max(120)).min(2).max(8).optional(),
|
|
19396
20227
|
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."),
|
|
19397
20228
|
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."),
|
|
19398
|
-
useMultiSceneShowcase:
|
|
20229
|
+
useMultiSceneShowcase: z77.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
|
|
19399
20230
|
}),
|
|
19400
|
-
|
|
19401
|
-
kind:
|
|
20231
|
+
z77.object({
|
|
20232
|
+
kind: z77.literal("angle_review_approval"),
|
|
19402
20233
|
// All edits are optional — empty action body just approves the
|
|
19403
20234
|
// backend-generated draft as-is. Field shapes mirror the angle-review
|
|
19404
20235
|
// request contracts in @packages/types/wizard.ts; the handler routes to
|
|
19405
20236
|
// the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
|
|
19406
|
-
customAngle:
|
|
20237
|
+
customAngle: z77.string().min(1).max(480).optional(),
|
|
19407
20238
|
// Keep the shared MCP action within the strictest downstream contract:
|
|
19408
20239
|
// autopilot/image resume endpoints cap these fields at 1500 characters.
|
|
19409
|
-
painPoints:
|
|
19410
|
-
benefits:
|
|
20240
|
+
painPoints: z77.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
20241
|
+
benefits: z77.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
19411
20242
|
// Same policy as the two fields above: the strictest downstream contract
|
|
19412
20243
|
// wins. The image endpoint caps each feature at 240 while landing/video
|
|
19413
20244
|
// accept 300, and this single action routes to whichever the task is — so
|
|
19414
20245
|
// accepting 300 here turns a 250-character feature on an image task into
|
|
19415
20246
|
// an opaque HTTP 400 after the model already believed it had been saved.
|
|
19416
|
-
features:
|
|
19417
|
-
buyerPersona:
|
|
20247
|
+
features: z77.array(z77.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
|
|
20248
|
+
buyerPersona: z77.string().min(1).max(360).optional(),
|
|
19418
20249
|
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.'),
|
|
19419
|
-
actor:
|
|
19420
|
-
actorId:
|
|
19421
|
-
creativeDirection:
|
|
19422
|
-
selectedAngleNumbers:
|
|
19423
|
-
angleEdits:
|
|
19424
|
-
angleNumber:
|
|
19425
|
-
narrativeSelection:
|
|
20250
|
+
actor: z77.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."),
|
|
20251
|
+
actorId: z77.string().max(120).nullable().optional(),
|
|
20252
|
+
creativeDirection: z77.string().max(2e3).optional(),
|
|
20253
|
+
selectedAngleNumbers: z77.array(z77.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."),
|
|
20254
|
+
angleEdits: z77.array(z77.object({
|
|
20255
|
+
angleNumber: z77.number().int().positive(),
|
|
20256
|
+
narrativeSelection: z77.enum([
|
|
19426
20257
|
"market",
|
|
19427
20258
|
"guided"
|
|
19428
20259
|
]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
|
|
19429
|
-
angle:
|
|
19430
|
-
buyerPersona:
|
|
20260
|
+
angle: z77.string().min(1).max(480).optional(),
|
|
20261
|
+
buyerPersona: z77.string().min(1).max(360).optional(),
|
|
19431
20262
|
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.'),
|
|
19432
|
-
actor:
|
|
19433
|
-
actorId:
|
|
19434
|
-
creativeDirection:
|
|
20263
|
+
actor: z77.string().min(1).max(360).optional(),
|
|
20264
|
+
actorId: z77.string().max(120).nullable().optional(),
|
|
20265
|
+
creativeDirection: z77.string().max(2e3).optional()
|
|
19435
20266
|
}).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)."),
|
|
19436
|
-
gapDurationSeconds:
|
|
19437
|
-
|
|
19438
|
-
|
|
20267
|
+
gapDurationSeconds: z77.union([
|
|
20268
|
+
z77.literal(15),
|
|
20269
|
+
z77.literal(30)
|
|
19439
20270
|
]).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.")
|
|
19440
20271
|
}),
|
|
19441
|
-
|
|
19442
|
-
kind:
|
|
19443
|
-
angleId:
|
|
19444
|
-
angleNumber:
|
|
19445
|
-
content:
|
|
19446
|
-
creativeDirection:
|
|
19447
|
-
actor:
|
|
20272
|
+
z77.object({
|
|
20273
|
+
kind: z77.literal("service_angle_approval"),
|
|
20274
|
+
angleId: z77.string().uuid().optional(),
|
|
20275
|
+
angleNumber: z77.number().int().positive().optional(),
|
|
20276
|
+
content: z77.string().min(1).max(480).optional(),
|
|
20277
|
+
creativeDirection: z77.string().min(1).max(1500).optional(),
|
|
20278
|
+
actor: z77.string().min(1).max(360).optional()
|
|
19448
20279
|
}),
|
|
19449
|
-
|
|
19450
|
-
kind:
|
|
19451
|
-
voiceovers:
|
|
19452
|
-
visualDirections:
|
|
19453
|
-
voiceoversByScene:
|
|
19454
|
-
visualDirectionsByScene:
|
|
20280
|
+
z77.object({
|
|
20281
|
+
kind: z77.literal("service_script_approval"),
|
|
20282
|
+
voiceovers: z77.record(z77.string(), z77.string().min(1).max(600)).optional(),
|
|
20283
|
+
visualDirections: z77.record(z77.string(), z77.string().min(1).max(1200)).optional(),
|
|
20284
|
+
voiceoversByScene: z77.record(z77.string(), z77.string().min(1).max(600)).optional(),
|
|
20285
|
+
visualDirectionsByScene: z77.record(z77.string(), z77.string().min(1).max(1200)).optional()
|
|
19455
20286
|
})
|
|
19456
20287
|
]);
|
|
19457
|
-
var ResolvePendingActionInput =
|
|
19458
|
-
taskId:
|
|
20288
|
+
var ResolvePendingActionInput = z77.object({
|
|
20289
|
+
taskId: z77.string().min(1),
|
|
19459
20290
|
action: PendingActionPayload
|
|
19460
20291
|
}).strict();
|
|
19461
20292
|
function resolveVariantConfirmVideoTier(action) {
|
|
19462
20293
|
return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
|
|
19463
20294
|
}
|
|
19464
20295
|
__name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
|
|
19465
|
-
var StatusForResolveSchema =
|
|
20296
|
+
var StatusForResolveSchema = z77.object({
|
|
19466
20297
|
// Metadata used to select the backend resume contract. Older API responses
|
|
19467
20298
|
// may omit these fields, so the resolver keeps the generic fallback.
|
|
19468
|
-
kind:
|
|
20299
|
+
kind: z77.enum([
|
|
19469
20300
|
"autopilot",
|
|
19470
20301
|
"video",
|
|
19471
20302
|
"image",
|
|
@@ -19473,18 +20304,18 @@ var StatusForResolveSchema = z73.object({
|
|
|
19473
20304
|
"mix",
|
|
19474
20305
|
"service"
|
|
19475
20306
|
]).optional(),
|
|
19476
|
-
selectedOutputs:
|
|
20307
|
+
selectedOutputs: z77.array(z77.enum([
|
|
19477
20308
|
"landing",
|
|
19478
20309
|
"video",
|
|
19479
20310
|
"image"
|
|
19480
20311
|
])).optional(),
|
|
19481
|
-
videoAngleCount:
|
|
19482
|
-
ugcFormat:
|
|
20312
|
+
videoAngleCount: z77.number().int().min(1).max(3).optional(),
|
|
20313
|
+
ugcFormat: z77.enum([
|
|
19483
20314
|
"single_8s",
|
|
19484
20315
|
"single_15s",
|
|
19485
20316
|
"double_30s"
|
|
19486
20317
|
]).optional(),
|
|
19487
|
-
videoStyle:
|
|
20318
|
+
videoStyle: z77.enum([
|
|
19488
20319
|
"ugc",
|
|
19489
20320
|
"cartoon_3d",
|
|
19490
20321
|
"product_only",
|
|
@@ -19493,79 +20324,72 @@ var StatusForResolveSchema = z73.object({
|
|
|
19493
20324
|
videoStructure: VideoStructureEnum.optional(),
|
|
19494
20325
|
videoQuality: VideoQualityEnum.optional(),
|
|
19495
20326
|
videoRouteId: VideoRouteIdEnum.optional(),
|
|
19496
|
-
videoModel:
|
|
19497
|
-
|
|
19498
|
-
"wan",
|
|
19499
|
-
"bytedance",
|
|
19500
|
-
"seedance",
|
|
19501
|
-
"grok",
|
|
19502
|
-
"kling"
|
|
19503
|
-
]).optional(),
|
|
19504
|
-
videoTier: z73.enum([
|
|
20327
|
+
videoModel: TaskVideoModelEnum.optional(),
|
|
20328
|
+
videoTier: z77.enum([
|
|
19505
20329
|
"legacy",
|
|
19506
20330
|
"standard",
|
|
19507
20331
|
"pro",
|
|
19508
20332
|
"single_call"
|
|
19509
20333
|
]).optional(),
|
|
19510
|
-
videoResolution:
|
|
20334
|
+
videoResolution: z77.enum([
|
|
19511
20335
|
"480p",
|
|
19512
20336
|
"720p"
|
|
19513
20337
|
]).optional(),
|
|
19514
20338
|
narrativeStyle: NarrativeStyleEnum.optional(),
|
|
19515
|
-
pauseForVideoScriptReview:
|
|
19516
|
-
pendingUserAction:
|
|
19517
|
-
kind:
|
|
19518
|
-
candidateGrouping:
|
|
19519
|
-
selectedImageUrls:
|
|
19520
|
-
proposedProductNames:
|
|
20339
|
+
pauseForVideoScriptReview: z77.boolean().optional(),
|
|
20340
|
+
pendingUserAction: z77.object({
|
|
20341
|
+
kind: z77.string(),
|
|
20342
|
+
candidateGrouping: z77.string().optional(),
|
|
20343
|
+
selectedImageUrls: z77.array(z77.string()).optional(),
|
|
20344
|
+
proposedProductNames: z77.array(z77.string()).optional(),
|
|
19521
20345
|
// Adaptive reference questions are server-owned. Echo only the evidence
|
|
19522
20346
|
// identity and the choices shown by the current snapshot; never accept a
|
|
19523
20347
|
// client-supplied reference set as authorization.
|
|
19524
|
-
options:
|
|
19525
|
-
mode:
|
|
20348
|
+
options: z77.array(ProductReferenceUserChoiceEnum).max(4).optional(),
|
|
20349
|
+
mode: z77.enum([
|
|
19526
20350
|
"question",
|
|
19527
20351
|
"visual_recovery"
|
|
19528
20352
|
]).optional(),
|
|
19529
20353
|
/** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
|
|
19530
|
-
canKeepSelection:
|
|
19531
|
-
decisionKey:
|
|
19532
|
-
questionOrdinal:
|
|
19533
|
-
questionCeiling:
|
|
19534
|
-
|
|
19535
|
-
|
|
20354
|
+
canKeepSelection: z77.boolean().optional(),
|
|
20355
|
+
decisionKey: z77.string().optional(),
|
|
20356
|
+
questionOrdinal: z77.number().int().min(1).max(5).optional(),
|
|
20357
|
+
questionCeiling: z77.union([
|
|
20358
|
+
z77.literal(3),
|
|
20359
|
+
z77.literal(5)
|
|
19536
20360
|
]).optional(),
|
|
19537
|
-
referenceEvidenceVersion:
|
|
19538
|
-
expectedEvidenceHash:
|
|
19539
|
-
question:
|
|
19540
|
-
prompt:
|
|
19541
|
-
helpText:
|
|
19542
|
-
options:
|
|
20361
|
+
referenceEvidenceVersion: z77.number().int().positive().optional(),
|
|
20362
|
+
expectedEvidenceHash: z77.string().optional(),
|
|
20363
|
+
question: z77.object({
|
|
20364
|
+
prompt: z77.string().min(1).max(240),
|
|
20365
|
+
helpText: z77.string().min(1).max(300).optional(),
|
|
20366
|
+
options: z77.array(z77.object({
|
|
19543
20367
|
value: ProductReferenceUserChoiceEnum,
|
|
19544
|
-
label:
|
|
19545
|
-
description:
|
|
20368
|
+
label: z77.string().min(1).max(120),
|
|
20369
|
+
description: z77.string().min(1).max(240).optional()
|
|
19546
20370
|
})).min(2).max(4)
|
|
19547
20371
|
}).optional(),
|
|
19548
20372
|
scope: ProductReferenceScopeEnum.optional(),
|
|
19549
|
-
scopeKey:
|
|
19550
|
-
scopeSnapshotId:
|
|
19551
|
-
scopeHash:
|
|
19552
|
-
baseReferenceSetHash:
|
|
19553
|
-
phase:
|
|
20373
|
+
scopeKey: z77.string().optional(),
|
|
20374
|
+
scopeSnapshotId: z77.string().uuid().optional(),
|
|
20375
|
+
scopeHash: z77.string().optional(),
|
|
20376
|
+
baseReferenceSetHash: z77.string().optional(),
|
|
20377
|
+
phase: z77.enum([
|
|
19554
20378
|
"preparation",
|
|
19555
20379
|
"final"
|
|
19556
20380
|
]).optional(),
|
|
19557
|
-
selectedRefKeys:
|
|
19558
|
-
allowedDecisions:
|
|
19559
|
-
previews:
|
|
19560
|
-
refKey:
|
|
20381
|
+
selectedRefKeys: z77.array(z77.string().min(1).max(200)).optional(),
|
|
20382
|
+
allowedDecisions: z77.array(ProductReferenceResolutionDecisionEnum).optional(),
|
|
20383
|
+
previews: z77.array(z77.object({
|
|
20384
|
+
refKey: z77.string().min(1).max(200)
|
|
19561
20385
|
}).passthrough()).optional(),
|
|
19562
|
-
customAngleDraft:
|
|
19563
|
-
painPointsDraft:
|
|
19564
|
-
benefitsDraft:
|
|
19565
|
-
featuresDraft:
|
|
19566
|
-
angleOptions:
|
|
19567
|
-
index:
|
|
19568
|
-
angle:
|
|
20386
|
+
customAngleDraft: z77.string().optional(),
|
|
20387
|
+
painPointsDraft: z77.string().optional(),
|
|
20388
|
+
benefitsDraft: z77.string().optional(),
|
|
20389
|
+
featuresDraft: z77.array(z77.string()).optional(),
|
|
20390
|
+
angleOptions: z77.array(z77.object({
|
|
20391
|
+
index: z77.number().int().nonnegative(),
|
|
20392
|
+
angle: z77.string().min(1)
|
|
19569
20393
|
}).passthrough()).min(1).max(5).optional(),
|
|
19570
20394
|
// Recommendation consumed only when the caller explicitly sends
|
|
19571
20395
|
// gapDurationSeconds: 30 in the angle approval action.
|
|
@@ -19575,17 +20399,17 @@ var StatusForResolveSchema = z73.object({
|
|
|
19575
20399
|
// keys. `actorId` (the saved custom actor the picker stored) was silently
|
|
19576
20400
|
// dropped here, so the approval handler below could not echo it back on the
|
|
19577
20401
|
// PATCH — the selection looked accepted and reached no render.
|
|
19578
|
-
angles:
|
|
19579
|
-
id:
|
|
19580
|
-
content:
|
|
19581
|
-
creativeDirection:
|
|
19582
|
-
actor:
|
|
19583
|
-
actorId:
|
|
20402
|
+
angles: z77.array(z77.object({
|
|
20403
|
+
id: z77.string().uuid(),
|
|
20404
|
+
content: z77.string(),
|
|
20405
|
+
creativeDirection: z77.string(),
|
|
20406
|
+
actor: z77.string(),
|
|
20407
|
+
actorId: z77.string().nullable().optional()
|
|
19584
20408
|
}).passthrough()).optional(),
|
|
19585
|
-
panels:
|
|
19586
|
-
beatId:
|
|
19587
|
-
voiceover:
|
|
19588
|
-
visualDirection:
|
|
20409
|
+
panels: z77.array(z77.object({
|
|
20410
|
+
beatId: z77.string(),
|
|
20411
|
+
voiceover: z77.string(),
|
|
20412
|
+
visualDirection: z77.string()
|
|
19589
20413
|
}).passthrough()).optional()
|
|
19590
20414
|
}).optional()
|
|
19591
20415
|
}).passthrough();
|
|
@@ -20420,7 +21244,7 @@ __name(registerTaskTools, "registerTaskTools");
|
|
|
20420
21244
|
|
|
20421
21245
|
// src/tools/creatives.ts
|
|
20422
21246
|
import { randomUUID } from "crypto";
|
|
20423
|
-
import { z as
|
|
21247
|
+
import { z as z78 } from "zod";
|
|
20424
21248
|
var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
|
|
20425
21249
|
var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
|
|
20426
21250
|
var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
|
|
@@ -20430,70 +21254,70 @@ var CreativeRefs = {
|
|
|
20430
21254
|
images: ImagesInput,
|
|
20431
21255
|
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.'),
|
|
20432
21256
|
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.'),
|
|
20433
|
-
price:
|
|
20434
|
-
offer:
|
|
20435
|
-
compareAtPrice:
|
|
20436
|
-
productContext:
|
|
20437
|
-
productLabel:
|
|
20438
|
-
buyerPersona:
|
|
20439
|
-
isCombo:
|
|
20440
|
-
competitorScanEnabled:
|
|
20441
|
-
brandId:
|
|
21257
|
+
price: z78.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.'),
|
|
21258
|
+
offer: z78.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.'),
|
|
21259
|
+
compareAtPrice: z78.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
|
|
21260
|
+
productContext: z78.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."),
|
|
21261
|
+
productLabel: z78.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.'),
|
|
21262
|
+
buyerPersona: z78.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.'),
|
|
21263
|
+
isCombo: z78.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
|
|
21264
|
+
competitorScanEnabled: z78.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."),
|
|
21265
|
+
brandId: z78.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.")
|
|
20442
21266
|
};
|
|
20443
|
-
var VideoPresenter =
|
|
20444
|
-
|
|
20445
|
-
mode:
|
|
21267
|
+
var VideoPresenter = z78.discriminatedUnion("mode", [
|
|
21268
|
+
z78.object({
|
|
21269
|
+
mode: z78.literal("none")
|
|
20446
21270
|
}).strict(),
|
|
20447
|
-
|
|
20448
|
-
mode:
|
|
20449
|
-
actorId:
|
|
21271
|
+
z78.object({
|
|
21272
|
+
mode: z78.literal("saved_actor"),
|
|
21273
|
+
actorId: z78.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
|
|
20450
21274
|
}).strict(),
|
|
20451
|
-
|
|
20452
|
-
mode:
|
|
20453
|
-
description:
|
|
21275
|
+
z78.object({
|
|
21276
|
+
mode: z78.literal("described"),
|
|
21277
|
+
description: z78.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
|
|
20454
21278
|
}).strict()
|
|
20455
21279
|
]);
|
|
20456
|
-
var VideoCreativeSetup =
|
|
20457
|
-
|
|
20458
|
-
mode:
|
|
21280
|
+
var VideoCreativeSetup = z78.discriminatedUnion("mode", [
|
|
21281
|
+
z78.object({
|
|
21282
|
+
mode: z78.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
|
|
20459
21283
|
}).strict(),
|
|
20460
|
-
|
|
20461
|
-
mode:
|
|
21284
|
+
z78.object({
|
|
21285
|
+
mode: z78.literal("guided"),
|
|
20462
21286
|
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.'),
|
|
20463
|
-
buyerPersona:
|
|
21287
|
+
buyerPersona: z78.string().trim().min(1).max(360),
|
|
20464
21288
|
presenter: VideoPresenter,
|
|
20465
|
-
creativeDirection:
|
|
21289
|
+
creativeDirection: z78.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
|
|
20466
21290
|
}).strict()
|
|
20467
21291
|
]);
|
|
20468
|
-
var VideoInput =
|
|
21292
|
+
var VideoInput = z78.object({
|
|
20469
21293
|
images: CreativeRefs.images.optional(),
|
|
20470
21294
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
20471
|
-
title:
|
|
20472
|
-
primaryAngle:
|
|
21295
|
+
title: z78.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
|
|
21296
|
+
primaryAngle: z78.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".'),
|
|
20473
21297
|
language: CreativeRefs.language,
|
|
20474
21298
|
country: CreativeRefs.country,
|
|
20475
|
-
aspectRatio:
|
|
21299
|
+
aspectRatio: z78.enum([
|
|
20476
21300
|
"9:16",
|
|
20477
21301
|
"16:9",
|
|
20478
21302
|
"Auto"
|
|
20479
21303
|
]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
|
|
20480
|
-
durationSeconds:
|
|
20481
|
-
videoAngleCount:
|
|
21304
|
+
durationSeconds: z78.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."),
|
|
21305
|
+
videoAngleCount: z78.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."),
|
|
20482
21306
|
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.'),
|
|
20483
21307
|
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."),
|
|
20484
21308
|
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.'),
|
|
20485
21309
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
|
|
20486
21310
|
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.'),
|
|
20487
|
-
features:
|
|
21311
|
+
features: z78.array(z78.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
|
|
20488
21312
|
price: CreativeRefs.price,
|
|
20489
21313
|
offer: CreativeRefs.offer,
|
|
20490
21314
|
productContext: CreativeRefs.productContext,
|
|
20491
21315
|
productLabel: CreativeRefs.productLabel,
|
|
20492
|
-
cta:
|
|
20493
|
-
scriptNotes:
|
|
21316
|
+
cta: z78.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.'),
|
|
21317
|
+
scriptNotes: z78.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.'),
|
|
20494
21318
|
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.'),
|
|
20495
21319
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
20496
|
-
replicateWinnerWhenFound:
|
|
21320
|
+
replicateWinnerWhenFound: z78.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."),
|
|
20497
21321
|
brandId: CreativeRefs.brandId
|
|
20498
21322
|
}).strict();
|
|
20499
21323
|
var FreeVideoQualityEnum = VideoQualityEnum;
|
|
@@ -20511,7 +21335,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
|
|
|
20511
21335
|
length: 29
|
|
20512
21336
|
}, (_, index) => index + 2)
|
|
20513
21337
|
};
|
|
20514
|
-
var FreeVideoModelIdEnum =
|
|
21338
|
+
var FreeVideoModelIdEnum = z78.enum([
|
|
20515
21339
|
"grok-imagine-video-1-5-preview",
|
|
20516
21340
|
"minimax-h3/reference-to-video",
|
|
20517
21341
|
"wan/3-0-video",
|
|
@@ -20522,70 +21346,65 @@ var FREE_SELECTABLE_MODEL_IDS = [
|
|
|
20522
21346
|
"minimax-h3/reference-to-video",
|
|
20523
21347
|
"wan/3-0-video"
|
|
20524
21348
|
];
|
|
20525
|
-
var FreeVideoInput =
|
|
21349
|
+
var FreeVideoInput = z78.object({
|
|
20526
21350
|
images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
|
|
20527
|
-
rawPrompt:
|
|
21351
|
+
rawPrompt: z78.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."),
|
|
20528
21352
|
language: CreativeRefs.language,
|
|
20529
21353
|
quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
|
|
20530
21354
|
// Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
|
|
20531
21355
|
// parsed ONLY so the handler can reject it with a message naming its
|
|
20532
21356
|
// replacement — dropping it silently would turn a caller's explicit
|
|
20533
21357
|
// Pro++ pick into a quiet fallback to Wan.
|
|
20534
|
-
freeProModel:
|
|
21358
|
+
freeProModel: z78.enum([
|
|
20535
21359
|
"wan",
|
|
20536
21360
|
"seedance"
|
|
20537
21361
|
]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
|
|
20538
21362
|
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.'),
|
|
20539
|
-
durationSeconds:
|
|
21363
|
+
durationSeconds: z78.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."),
|
|
20540
21364
|
videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
|
|
20541
|
-
generateAiMusic:
|
|
20542
|
-
addSubtitles:
|
|
20543
|
-
idempotencyKey:
|
|
21365
|
+
generateAiMusic: z78.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
|
|
21366
|
+
addSubtitles: z78.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
|
|
21367
|
+
idempotencyKey: z78.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.")
|
|
20544
21368
|
}).strict();
|
|
20545
21369
|
var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
|
|
20546
|
-
var ImageCreativeSetup =
|
|
20547
|
-
|
|
20548
|
-
mode:
|
|
21370
|
+
var ImageCreativeSetup = z78.discriminatedUnion("mode", [
|
|
21371
|
+
z78.object({
|
|
21372
|
+
mode: z78.literal("automatic")
|
|
20549
21373
|
}).strict(),
|
|
20550
|
-
|
|
20551
|
-
mode:
|
|
20552
|
-
creativeArchetype:
|
|
21374
|
+
z78.object({
|
|
21375
|
+
mode: z78.literal("guided"),
|
|
21376
|
+
creativeArchetype: z78.union([
|
|
20553
21377
|
ImageCreativeArchetypeEnum,
|
|
20554
|
-
|
|
21378
|
+
z78.literal("ai_decides")
|
|
20555
21379
|
]),
|
|
20556
|
-
visualTreatment:
|
|
21380
|
+
visualTreatment: z78.union([
|
|
20557
21381
|
ImageCreativeVisualTreatmentEnum,
|
|
20558
|
-
|
|
21382
|
+
z78.literal("ai_decides")
|
|
20559
21383
|
]),
|
|
20560
21384
|
aspectRatio: ImageCreativeAspectRatioEnum,
|
|
20561
|
-
nVariants:
|
|
20562
|
-
|
|
20563
|
-
|
|
20564
|
-
|
|
20565
|
-
|
|
20566
|
-
|
|
20567
|
-
]),
|
|
20568
|
-
imageModel: z74.enum([
|
|
20569
|
-
"gpt-image-2-5:1k",
|
|
20570
|
-
"gpt-image-2-5:2k",
|
|
20571
|
-
"gpt-image-2:1k",
|
|
20572
|
-
"gpt-image-2:2k"
|
|
21385
|
+
nVariants: z78.union([
|
|
21386
|
+
z78.literal(1),
|
|
21387
|
+
z78.literal(2),
|
|
21388
|
+
z78.literal(3),
|
|
21389
|
+
z78.literal(4),
|
|
21390
|
+
z78.literal(6)
|
|
20573
21391
|
]),
|
|
20574
|
-
|
|
20575
|
-
|
|
20576
|
-
|
|
20577
|
-
|
|
20578
|
-
|
|
20579
|
-
|
|
20580
|
-
|
|
20581
|
-
|
|
21392
|
+
imageModel: z78.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.'),
|
|
21393
|
+
styleMix: z78.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
|
|
21394
|
+
generateAdCopy: z78.boolean(),
|
|
21395
|
+
competitorScanEnabled: z78.boolean(),
|
|
21396
|
+
productContext: z78.string().trim().min(1).max(3e3).nullable(),
|
|
21397
|
+
creativeDirection: z78.string().trim().min(1).max(500).nullable(),
|
|
21398
|
+
brandColors: z78.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.'),
|
|
21399
|
+
headline: z78.string().trim().min(1).max(120).nullable(),
|
|
21400
|
+
subheadline: z78.string().trim().min(1).max(160).nullable()
|
|
20582
21401
|
}).strict()
|
|
20583
21402
|
]).superRefine((setup, context) => {
|
|
20584
21403
|
if (setup.mode !== "guided") return;
|
|
20585
21404
|
const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
|
|
20586
21405
|
if (needsStyleMix && setup.styleMix === null) {
|
|
20587
21406
|
context.addIssue({
|
|
20588
|
-
code:
|
|
21407
|
+
code: z78.ZodIssueCode.custom,
|
|
20589
21408
|
path: [
|
|
20590
21409
|
"styleMix"
|
|
20591
21410
|
],
|
|
@@ -20594,16 +21413,16 @@ var ImageCreativeSetup = z74.discriminatedUnion("mode", [
|
|
|
20594
21413
|
}
|
|
20595
21414
|
if (!needsStyleMix && setup.styleMix !== null) {
|
|
20596
21415
|
context.addIssue({
|
|
20597
|
-
code:
|
|
21416
|
+
code: z78.ZodIssueCode.custom,
|
|
20598
21417
|
path: [
|
|
20599
21418
|
"styleMix"
|
|
20600
21419
|
],
|
|
20601
21420
|
message: "styleMix debe ser null cuando nVariants es 1 o 6."
|
|
20602
21421
|
});
|
|
20603
21422
|
}
|
|
20604
|
-
if ((setup.imageModel === "
|
|
21423
|
+
if (imageResolutionOf(setup.imageModel) === "2k" && setup.aspectRatio === "4:5") {
|
|
20605
21424
|
context.addIssue({
|
|
20606
|
-
code:
|
|
21425
|
+
code: z78.ZodIssueCode.custom,
|
|
20607
21426
|
path: [
|
|
20608
21427
|
"aspectRatio"
|
|
20609
21428
|
],
|
|
@@ -20611,53 +21430,53 @@ var ImageCreativeSetup = z74.discriminatedUnion("mode", [
|
|
|
20611
21430
|
});
|
|
20612
21431
|
}
|
|
20613
21432
|
});
|
|
20614
|
-
var LandingCreativeSetup =
|
|
20615
|
-
|
|
20616
|
-
mode:
|
|
21433
|
+
var LandingCreativeSetup = z78.discriminatedUnion("mode", [
|
|
21434
|
+
z78.object({
|
|
21435
|
+
mode: z78.literal("automatic")
|
|
20617
21436
|
}).strict(),
|
|
20618
|
-
|
|
20619
|
-
mode:
|
|
21437
|
+
z78.object({
|
|
21438
|
+
mode: z78.literal("guided"),
|
|
20620
21439
|
landingStrategy: LandingStrategyEnum,
|
|
20621
21440
|
landingImageFormat: LandingImageFormatEnum,
|
|
20622
|
-
competitorScanEnabled:
|
|
20623
|
-
paymentMethods:
|
|
20624
|
-
productContext:
|
|
20625
|
-
creativeDirection:
|
|
20626
|
-
headline:
|
|
20627
|
-
subheadline:
|
|
21441
|
+
competitorScanEnabled: z78.boolean(),
|
|
21442
|
+
paymentMethods: z78.string().trim().min(1).max(240).nullable(),
|
|
21443
|
+
productContext: z78.string().trim().min(1).max(3e3).nullable(),
|
|
21444
|
+
creativeDirection: z78.string().trim().min(1).max(500).nullable(),
|
|
21445
|
+
headline: z78.string().trim().min(1).max(120).nullable(),
|
|
21446
|
+
subheadline: z78.string().trim().min(1).max(160).nullable()
|
|
20628
21447
|
}).strict()
|
|
20629
21448
|
]);
|
|
20630
|
-
var ImageInput =
|
|
21449
|
+
var ImageInput = z78.object({
|
|
20631
21450
|
images: CreativeRefs.images.optional(),
|
|
20632
21451
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
20633
|
-
productTitle:
|
|
20634
|
-
primaryAngle:
|
|
21452
|
+
productTitle: z78.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
|
|
21453
|
+
primaryAngle: z78.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.'),
|
|
20635
21454
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
20636
21455
|
language: CreativeRefs.language,
|
|
20637
21456
|
country: CreativeRefs.country,
|
|
20638
21457
|
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."),
|
|
20639
21458
|
imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
|
|
20640
|
-
features:
|
|
21459
|
+
features: z78.array(z78.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
|
|
20641
21460
|
price: CreativeRefs.price,
|
|
20642
|
-
omitPrice:
|
|
21461
|
+
omitPrice: z78.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."),
|
|
20643
21462
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
20644
21463
|
offer: CreativeRefs.offer,
|
|
20645
21464
|
productLabel: CreativeRefs.productLabel,
|
|
20646
21465
|
isCombo: CreativeRefs.isCombo,
|
|
20647
21466
|
brandId: CreativeRefs.brandId
|
|
20648
21467
|
});
|
|
20649
|
-
var EditImageCreativeInput =
|
|
20650
|
-
taskId:
|
|
20651
|
-
variantIndex:
|
|
20652
|
-
instruction:
|
|
21468
|
+
var EditImageCreativeInput = z78.object({
|
|
21469
|
+
taskId: z78.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
|
|
21470
|
+
variantIndex: z78.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
|
|
21471
|
+
instruction: z78.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".')
|
|
20653
21472
|
});
|
|
20654
|
-
var LandingInput =
|
|
21473
|
+
var LandingInput = z78.object({
|
|
20655
21474
|
images: CreativeRefs.images.optional(),
|
|
20656
21475
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
20657
21476
|
language: CreativeRefs.language,
|
|
20658
21477
|
country: CreativeRefs.country,
|
|
20659
21478
|
creativeSetup: LandingCreativeSetup.describe("Configuraci\xF3n obligatoria de landing cl\xE1sica equivalente al wizard web. No expone landing editable/code mientras siga siendo admin-only."),
|
|
20660
|
-
salesAngle:
|
|
21479
|
+
salesAngle: z78.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.'),
|
|
20661
21480
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
20662
21481
|
price: CreativeRefs.price,
|
|
20663
21482
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
@@ -20676,7 +21495,7 @@ function resolveImageSetup(setup) {
|
|
|
20676
21495
|
},
|
|
20677
21496
|
aspectRatio: setup.aspectRatio,
|
|
20678
21497
|
nVariants: setup.nVariants,
|
|
20679
|
-
imageModel: setup.imageModel,
|
|
21498
|
+
imageModel: canonicalImageModelInput(setup.imageModel),
|
|
20680
21499
|
...setup.nVariants === 6 ? {
|
|
20681
21500
|
styleMix: true
|
|
20682
21501
|
} : setup.styleMix === null ? {} : {
|
|
@@ -20919,10 +21738,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
20919
21738
|
__name(registerCreativeTools, "registerCreativeTools");
|
|
20920
21739
|
|
|
20921
21740
|
// src/tools/creative-variants.ts
|
|
20922
|
-
import { z as
|
|
21741
|
+
import { z as z79 } from "zod";
|
|
20923
21742
|
var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
|
|
20924
21743
|
var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
|
|
20925
|
-
var LandingSectionKeyEnum =
|
|
21744
|
+
var LandingSectionKeyEnum = z79.enum([
|
|
20926
21745
|
"problem_hook",
|
|
20927
21746
|
"problem_cost",
|
|
20928
21747
|
"solution_mechanism",
|
|
@@ -20962,24 +21781,24 @@ var LandingSectionKeyEnum = z75.enum([
|
|
|
20962
21781
|
"lifestyle_fit",
|
|
20963
21782
|
"join_lifestyle"
|
|
20964
21783
|
]);
|
|
20965
|
-
var CreativeVariantKindEnum =
|
|
21784
|
+
var CreativeVariantKindEnum = z79.enum([
|
|
20966
21785
|
"video",
|
|
20967
21786
|
"image",
|
|
20968
21787
|
"landing"
|
|
20969
21788
|
]);
|
|
20970
|
-
var EstimateCreativeVariantInputBase =
|
|
20971
|
-
sourceTaskId:
|
|
21789
|
+
var EstimateCreativeVariantInputBase = z79.object({
|
|
21790
|
+
sourceTaskId: z79.string().uuid().describe("ID de la tarea original completada."),
|
|
20972
21791
|
kind: CreativeVariantKindEnum,
|
|
20973
21792
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
|
|
20974
21793
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
|
|
20975
|
-
nVariants:
|
|
21794
|
+
nVariants: z79.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
20976
21795
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
|
|
20977
|
-
instructions:
|
|
21796
|
+
instructions: z79.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.")
|
|
20978
21797
|
}).strict();
|
|
20979
21798
|
var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
20980
21799
|
if (input.kind === "video" && input.nVariants !== void 0) {
|
|
20981
21800
|
ctx.addIssue({
|
|
20982
|
-
code:
|
|
21801
|
+
code: z79.ZodIssueCode.custom,
|
|
20983
21802
|
path: [
|
|
20984
21803
|
"nVariants"
|
|
20985
21804
|
],
|
|
@@ -20989,7 +21808,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
20989
21808
|
if (input.kind !== "video") {
|
|
20990
21809
|
if (input.videoPreset !== void 0) {
|
|
20991
21810
|
ctx.addIssue({
|
|
20992
|
-
code:
|
|
21811
|
+
code: z79.ZodIssueCode.custom,
|
|
20993
21812
|
path: [
|
|
20994
21813
|
"videoPreset"
|
|
20995
21814
|
],
|
|
@@ -20998,7 +21817,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
20998
21817
|
}
|
|
20999
21818
|
if (input.videoResolution !== void 0) {
|
|
21000
21819
|
ctx.addIssue({
|
|
21001
|
-
code:
|
|
21820
|
+
code: z79.ZodIssueCode.custom,
|
|
21002
21821
|
path: [
|
|
21003
21822
|
"videoResolution"
|
|
21004
21823
|
],
|
|
@@ -21008,7 +21827,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
21008
21827
|
}
|
|
21009
21828
|
if (input.kind !== "image" && input.nVariants !== void 0) {
|
|
21010
21829
|
ctx.addIssue({
|
|
21011
|
-
code:
|
|
21830
|
+
code: z79.ZodIssueCode.custom,
|
|
21012
21831
|
path: [
|
|
21013
21832
|
"nVariants"
|
|
21014
21833
|
],
|
|
@@ -21018,7 +21837,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
21018
21837
|
if (input.kind !== "landing") {
|
|
21019
21838
|
if (input.sectionKey !== void 0) {
|
|
21020
21839
|
ctx.addIssue({
|
|
21021
|
-
code:
|
|
21840
|
+
code: z79.ZodIssueCode.custom,
|
|
21022
21841
|
path: [
|
|
21023
21842
|
"sectionKey"
|
|
21024
21843
|
],
|
|
@@ -21027,7 +21846,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
21027
21846
|
}
|
|
21028
21847
|
if (input.instructions !== void 0) {
|
|
21029
21848
|
ctx.addIssue({
|
|
21030
|
-
code:
|
|
21849
|
+
code: z79.ZodIssueCode.custom,
|
|
21031
21850
|
path: [
|
|
21032
21851
|
"instructions"
|
|
21033
21852
|
],
|
|
@@ -21036,31 +21855,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
21036
21855
|
}
|
|
21037
21856
|
}
|
|
21038
21857
|
});
|
|
21039
|
-
var CreateCreativeVariantInputBase =
|
|
21040
|
-
sourceTaskId:
|
|
21858
|
+
var CreateCreativeVariantInputBase = z79.object({
|
|
21859
|
+
sourceTaskId: z79.string().uuid().describe("ID de la tarea original completada."),
|
|
21041
21860
|
kind: CreativeVariantKindEnum,
|
|
21042
|
-
confirm:
|
|
21043
|
-
clientRequestId:
|
|
21044
|
-
angle:
|
|
21045
|
-
buyerPersona:
|
|
21046
|
-
scriptNotes:
|
|
21047
|
-
creativeDirection:
|
|
21861
|
+
confirm: z79.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
|
|
21862
|
+
clientRequestId: z79.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."),
|
|
21863
|
+
angle: z79.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
|
|
21864
|
+
buyerPersona: z79.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
|
|
21865
|
+
scriptNotes: z79.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
|
|
21866
|
+
creativeDirection: z79.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
|
|
21048
21867
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
|
|
21049
21868
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
|
|
21050
|
-
generateAiMusic:
|
|
21051
|
-
nVariants:
|
|
21869
|
+
generateAiMusic: z79.boolean().optional().describe("Opcional para video."),
|
|
21870
|
+
nVariants: z79.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
21052
21871
|
imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
|
|
21053
21872
|
creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
|
|
21054
21873
|
visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
|
|
21055
21874
|
aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
|
|
21056
|
-
styleMix:
|
|
21875
|
+
styleMix: z79.boolean().optional().describe("Opcional para imagen."),
|
|
21057
21876
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
|
|
21058
|
-
instructions:
|
|
21877
|
+
instructions: z79.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.")
|
|
21059
21878
|
}).strict();
|
|
21060
21879
|
var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
21061
21880
|
if ((input.kind === "video" || input.kind === "image") && !input.angle) {
|
|
21062
21881
|
ctx.addIssue({
|
|
21063
|
-
code:
|
|
21882
|
+
code: z79.ZodIssueCode.custom,
|
|
21064
21883
|
path: [
|
|
21065
21884
|
"angle"
|
|
21066
21885
|
],
|
|
@@ -21069,7 +21888,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
21069
21888
|
}
|
|
21070
21889
|
if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
|
|
21071
21890
|
ctx.addIssue({
|
|
21072
|
-
code:
|
|
21891
|
+
code: z79.ZodIssueCode.custom,
|
|
21073
21892
|
path: [
|
|
21074
21893
|
"instructions"
|
|
21075
21894
|
],
|
|
@@ -21115,7 +21934,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
21115
21934
|
for (const field of fieldsByKind[input.kind]) {
|
|
21116
21935
|
if (input[field] !== void 0) {
|
|
21117
21936
|
ctx.addIssue({
|
|
21118
|
-
code:
|
|
21937
|
+
code: z79.ZodIssueCode.custom,
|
|
21119
21938
|
path: [
|
|
21120
21939
|
field
|
|
21121
21940
|
],
|
|
@@ -21232,32 +22051,32 @@ function registerCreativeVariantTools(server, api) {
|
|
|
21232
22051
|
__name(registerCreativeVariantTools, "registerCreativeVariantTools");
|
|
21233
22052
|
|
|
21234
22053
|
// src/tools/script-review.ts
|
|
21235
|
-
import { z as
|
|
22054
|
+
import { z as z80 } from "zod";
|
|
21236
22055
|
var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
|
|
21237
22056
|
var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
|
|
21238
22057
|
var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
|
|
21239
|
-
var GetVideoScriptInput =
|
|
21240
|
-
taskId:
|
|
21241
|
-
angleKey:
|
|
22058
|
+
var GetVideoScriptInput = z80.object({
|
|
22059
|
+
taskId: z80.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
|
|
22060
|
+
angleKey: z80.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.')
|
|
21242
22061
|
}).strict();
|
|
21243
22062
|
var VIDEO_SCRIPT_APPROVAL_MAX_SCENES2 = 50;
|
|
21244
22063
|
var VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2 = 2e3;
|
|
21245
|
-
var ApproveSceneEdit =
|
|
21246
|
-
index:
|
|
21247
|
-
dialogue:
|
|
22064
|
+
var ApproveSceneEdit = z80.object({
|
|
22065
|
+
index: z80.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
|
|
22066
|
+
dialogue: z80.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
|
|
21248
22067
|
message: "dialogue no puede ser s\xF3lo espacios"
|
|
21249
22068
|
}).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.")
|
|
21250
22069
|
}).strict();
|
|
21251
|
-
var ApproveVideoScriptInput =
|
|
21252
|
-
taskId:
|
|
21253
|
-
angleKey:
|
|
21254
|
-
scenes:
|
|
22070
|
+
var ApproveVideoScriptInput = z80.object({
|
|
22071
|
+
taskId: z80.string().min(1).describe("ID de la tarea."),
|
|
22072
|
+
angleKey: z80.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.'),
|
|
22073
|
+
scenes: z80.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.")
|
|
21255
22074
|
}).strict();
|
|
21256
|
-
var RegenerateVideoScriptInput =
|
|
21257
|
-
taskId:
|
|
21258
|
-
angleKey:
|
|
22075
|
+
var RegenerateVideoScriptInput = z80.object({
|
|
22076
|
+
taskId: z80.string().min(1).describe("ID de la tarea."),
|
|
22077
|
+
angleKey: z80.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.'),
|
|
21259
22078
|
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).'),
|
|
21260
|
-
narrativeSelection:
|
|
22079
|
+
narrativeSelection: z80.enum([
|
|
21261
22080
|
"market",
|
|
21262
22081
|
"guided"
|
|
21263
22082
|
]).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.")
|
|
@@ -21338,14 +22157,14 @@ function registerScriptReviewTools(server, api) {
|
|
|
21338
22157
|
__name(registerScriptReviewTools, "registerScriptReviewTools");
|
|
21339
22158
|
|
|
21340
22159
|
// src/tools/connections.ts
|
|
21341
|
-
import { z as
|
|
22160
|
+
import { z as z81 } from "zod";
|
|
21342
22161
|
var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
|
|
21343
22162
|
var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
|
|
21344
22163
|
var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
|
|
21345
22164
|
var listMetaDestinationsGuidance = getProductMakerCapabilityModelGuidance("list_meta_destinations");
|
|
21346
22165
|
var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list_tiktok_advertisers");
|
|
21347
22166
|
function registerConnectionTools(server, api) {
|
|
21348
|
-
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.",
|
|
22167
|
+
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.", z81.object({}).shape, READS_INTERNAL, async () => {
|
|
21349
22168
|
try {
|
|
21350
22169
|
const r = await api.getJson("/v1/shopify/shops");
|
|
21351
22170
|
return asText(r);
|
|
@@ -21353,10 +22172,10 @@ function registerConnectionTools(server, api) {
|
|
|
21353
22172
|
throw translateError(e);
|
|
21354
22173
|
}
|
|
21355
22174
|
});
|
|
21356
|
-
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.',
|
|
21357
|
-
shopDomain:
|
|
21358
|
-
query:
|
|
21359
|
-
taskId:
|
|
22175
|
+
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.', z81.object({
|
|
22176
|
+
shopDomain: z81.string().min(3).max(120),
|
|
22177
|
+
query: z81.string().trim().max(120).optional(),
|
|
22178
|
+
taskId: z81.string().uuid().optional()
|
|
21360
22179
|
}).shape, READS_EXTERNAL, async ({ shopDomain, query, taskId }) => {
|
|
21361
22180
|
try {
|
|
21362
22181
|
const params = new URLSearchParams({
|
|
@@ -21370,7 +22189,7 @@ function registerConnectionTools(server, api) {
|
|
|
21370
22189
|
throw translateError(e);
|
|
21371
22190
|
}
|
|
21372
22191
|
});
|
|
21373
|
-
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.",
|
|
22192
|
+
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.", z81.object({}).shape, READS_EXTERNAL, async () => {
|
|
21374
22193
|
try {
|
|
21375
22194
|
const r = await api.getJson("/v1/facebook/ad-accounts");
|
|
21376
22195
|
return asText(r);
|
|
@@ -21380,7 +22199,7 @@ function registerConnectionTools(server, api) {
|
|
|
21380
22199
|
});
|
|
21381
22200
|
server.registerTool("list_meta_destinations", {
|
|
21382
22201
|
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.",
|
|
21383
|
-
inputSchema:
|
|
22202
|
+
inputSchema: z81.object({}).shape,
|
|
21384
22203
|
annotations: READS_EXTERNAL,
|
|
21385
22204
|
_meta: {
|
|
21386
22205
|
"openai/widgetAccessible": true
|
|
@@ -21393,7 +22212,7 @@ function registerConnectionTools(server, api) {
|
|
|
21393
22212
|
throw translateError(e);
|
|
21394
22213
|
}
|
|
21395
22214
|
});
|
|
21396
|
-
server.tool("list_tiktok_advertisers", listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.",
|
|
22215
|
+
server.tool("list_tiktok_advertisers", listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.", z81.object({}).shape, READS_EXTERNAL, async () => {
|
|
21397
22216
|
try {
|
|
21398
22217
|
const r = await api.getJson("/v1/tiktok/advertisers");
|
|
21399
22218
|
return asText(r);
|
|
@@ -21405,10 +22224,10 @@ function registerConnectionTools(server, api) {
|
|
|
21405
22224
|
__name(registerConnectionTools, "registerConnectionTools");
|
|
21406
22225
|
|
|
21407
22226
|
// src/tools/actors.ts
|
|
21408
|
-
import { z as
|
|
22227
|
+
import { z as z82 } from "zod";
|
|
21409
22228
|
var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
|
|
21410
22229
|
function registerActorTools(server, api) {
|
|
21411
|
-
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.",
|
|
22230
|
+
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.", z82.object({}).shape, READS_INTERNAL, async () => {
|
|
21412
22231
|
try {
|
|
21413
22232
|
const rows = await api.getJson("/v1/actors");
|
|
21414
22233
|
const actors = (Array.isArray(rows) ? rows : []).filter((actor) => actor.status === "ready").map(({ id, name, description, gender, voiceId }) => ({
|
|
@@ -21429,7 +22248,7 @@ function registerActorTools(server, api) {
|
|
|
21429
22248
|
__name(registerActorTools, "registerActorTools");
|
|
21430
22249
|
|
|
21431
22250
|
// src/tools/publish.ts
|
|
21432
|
-
import { z as
|
|
22251
|
+
import { z as z83 } from "zod";
|
|
21433
22252
|
|
|
21434
22253
|
// src/tools/stable-uuid.ts
|
|
21435
22254
|
import { createHash as createHash3 } from "crypto";
|
|
@@ -21501,40 +22320,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
|
|
|
21501
22320
|
var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
|
|
21502
22321
|
var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
|
|
21503
22322
|
var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
|
|
21504
|
-
var ShopifyInput =
|
|
21505
|
-
taskId:
|
|
21506
|
-
shopDomain:
|
|
22323
|
+
var ShopifyInput = z83.object({
|
|
22324
|
+
taskId: z83.string().min(1),
|
|
22325
|
+
shopDomain: z83.string().min(1),
|
|
21507
22326
|
/** Override: number of landing images to include. Default = ALL images the
|
|
21508
22327
|
* task generated (the MCP fetches /v1/results first to count). Bounded
|
|
21509
22328
|
* generously here; the backend validates each index against
|
|
21510
22329
|
* landing.images.length and rejects out-of-range. */
|
|
21511
|
-
numLandingImages:
|
|
21512
|
-
variantIndex:
|
|
22330
|
+
numLandingImages: z83.number().int().min(1).max(20).optional(),
|
|
22331
|
+
variantIndex: z83.number().int().min(0).optional(),
|
|
21513
22332
|
/** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
|
|
21514
22333
|
* When true, the landing renders variant-picker pills; when false, it ships
|
|
21515
22334
|
* a single-option product page. Defaults to false. */
|
|
21516
|
-
showVariantPicker:
|
|
22335
|
+
showVariantPicker: z83.boolean().optional(),
|
|
21517
22336
|
/** Default `auto` updates the product previously published for this task and
|
|
21518
22337
|
* shop. Use `existing` with targetProductId to choose another product, or
|
|
21519
22338
|
* `new` only when the user explicitly wants a duplicate/new listing. */
|
|
21520
|
-
publicationMode:
|
|
22339
|
+
publicationMode: z83.enum([
|
|
21521
22340
|
"auto",
|
|
21522
22341
|
"existing",
|
|
21523
22342
|
"new"
|
|
21524
22343
|
]).optional(),
|
|
21525
22344
|
/** Shopify product GID, numeric id, or admin product URL. Required when
|
|
21526
22345
|
* publicationMode is `existing`. */
|
|
21527
|
-
targetProductId:
|
|
22346
|
+
targetProductId: z83.string().trim().min(1).max(300).optional(),
|
|
21528
22347
|
/** Add an announcement bar text above add-to-cart (optional). */
|
|
21529
|
-
announcementBarEnabled:
|
|
21530
|
-
announcementBarText:
|
|
22348
|
+
announcementBarEnabled: z83.boolean().optional(),
|
|
22349
|
+
announcementBarText: z83.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
|
|
21531
22350
|
commerceCorrection: PublishCommerceCorrectionSchema.optional().describe("Complete seller-confirmed commerce values, with the revision and fingerprint returned in recovery. Never invent missing prices or convert currency."),
|
|
21532
|
-
confirmed:
|
|
22351
|
+
confirmed: z83.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
|
|
21533
22352
|
});
|
|
21534
22353
|
var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
|
|
21535
22354
|
if (value.commerceCorrection && value.confirmed !== true) {
|
|
21536
22355
|
ctx.addIssue({
|
|
21537
|
-
code:
|
|
22356
|
+
code: z83.ZodIssueCode.custom,
|
|
21538
22357
|
path: [
|
|
21539
22358
|
"confirmed"
|
|
21540
22359
|
],
|
|
@@ -21543,7 +22362,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
21543
22362
|
}
|
|
21544
22363
|
if (value.announcementBarEnabled && !value.announcementBarText) {
|
|
21545
22364
|
ctx.addIssue({
|
|
21546
|
-
code:
|
|
22365
|
+
code: z83.ZodIssueCode.custom,
|
|
21547
22366
|
path: [
|
|
21548
22367
|
"announcementBarText"
|
|
21549
22368
|
],
|
|
@@ -21552,7 +22371,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
21552
22371
|
}
|
|
21553
22372
|
if (!value.announcementBarEnabled && value.announcementBarText) {
|
|
21554
22373
|
ctx.addIssue({
|
|
21555
|
-
code:
|
|
22374
|
+
code: z83.ZodIssueCode.custom,
|
|
21556
22375
|
path: [
|
|
21557
22376
|
"announcementBarText"
|
|
21558
22377
|
],
|
|
@@ -21566,91 +22385,91 @@ function parseShopifyInput(rawInput) {
|
|
|
21566
22385
|
return parsed.data;
|
|
21567
22386
|
}
|
|
21568
22387
|
__name(parseShopifyInput, "parseShopifyInput");
|
|
21569
|
-
var McpCampaignConfig =
|
|
22388
|
+
var McpCampaignConfig = z83.object({
|
|
21570
22389
|
/** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
|
|
21571
22390
|
* converts to the account currency server-side. Do NOT pre-convert: on a COP
|
|
21572
22391
|
* account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
|
|
21573
|
-
dailyBudgetUsd:
|
|
22392
|
+
dailyBudgetUsd: z83.number().positive().optional(),
|
|
21574
22393
|
/** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
|
|
21575
22394
|
* normalizes at validation). Meta accepts max 1 (single-country ad set).
|
|
21576
22395
|
* TikTok takes only the first entry. */
|
|
21577
|
-
targetCountries:
|
|
21578
|
-
campaignName:
|
|
22396
|
+
targetCountries: z83.array(CountryIso2Schema).max(1).optional(),
|
|
22397
|
+
campaignName: z83.string().trim().min(1).max(100).optional()
|
|
21579
22398
|
});
|
|
21580
22399
|
var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
|
|
21581
|
-
var MetaInput =
|
|
21582
|
-
taskId:
|
|
22400
|
+
var MetaInput = z83.object({
|
|
22401
|
+
taskId: z83.string().min(1),
|
|
21583
22402
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
21584
|
-
portfolioId:
|
|
22403
|
+
portfolioId: z83.string().trim().min(1),
|
|
21585
22404
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
21586
|
-
pageId:
|
|
22405
|
+
pageId: z83.string().trim().min(1),
|
|
21587
22406
|
adAccountId: McpAdAccountId,
|
|
21588
|
-
pixelId:
|
|
21589
|
-
landingUrl:
|
|
22407
|
+
pixelId: z83.string().min(1).optional(),
|
|
22408
|
+
landingUrl: z83.string().url().optional(),
|
|
21590
22409
|
/** Select which angles to publish by 0-based index. Omit to publish all
|
|
21591
22410
|
* successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
|
|
21592
|
-
angleIndexes:
|
|
22411
|
+
angleIndexes: z83.array(z83.number().int().nonnegative()).optional(),
|
|
21593
22412
|
campaignConfig: McpCampaignConfig.optional(),
|
|
21594
22413
|
/** Override the ad's primary text (body copy). If omitted, ProductMaker
|
|
21595
22414
|
* uses the auto-generated copy attached to the task. Capped at 500 chars
|
|
21596
22415
|
* (Meta's primary-text limit). */
|
|
21597
|
-
primaryText:
|
|
22416
|
+
primaryText: z83.string().trim().min(1).max(500).optional(),
|
|
21598
22417
|
/** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
|
|
21599
22418
|
* (wa.me) instead of a landing page. */
|
|
21600
|
-
phoneNumber:
|
|
22419
|
+
phoneNumber: z83.string().min(8).max(32).optional()
|
|
21601
22420
|
});
|
|
21602
|
-
var GroupedTaskSource =
|
|
21603
|
-
type:
|
|
21604
|
-
taskId:
|
|
21605
|
-
angleIndex:
|
|
21606
|
-
videoVariant:
|
|
22421
|
+
var GroupedTaskSource = z83.object({
|
|
22422
|
+
type: z83.literal("task"),
|
|
22423
|
+
taskId: z83.string().min(1),
|
|
22424
|
+
angleIndex: z83.number().int().min(0).optional(),
|
|
22425
|
+
videoVariant: z83.enum([
|
|
21607
22426
|
"with_subtitles",
|
|
21608
22427
|
"without_subtitles"
|
|
21609
22428
|
]).optional(),
|
|
21610
|
-
imageVariantIndex:
|
|
21611
|
-
});
|
|
21612
|
-
var GroupedMediaSource =
|
|
21613
|
-
type:
|
|
21614
|
-
url:
|
|
21615
|
-
path:
|
|
21616
|
-
thumbnailUrl:
|
|
21617
|
-
thumbnailPath:
|
|
22429
|
+
imageVariantIndex: z83.number().int().min(0).optional()
|
|
22430
|
+
});
|
|
22431
|
+
var GroupedMediaSource = z83.object({
|
|
22432
|
+
type: z83.literal("media"),
|
|
22433
|
+
url: z83.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
|
|
22434
|
+
path: z83.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".'),
|
|
22435
|
+
thumbnailUrl: z83.string().url().optional(),
|
|
22436
|
+
thumbnailPath: z83.string().min(1).optional()
|
|
21618
22437
|
}).refine((value) => Boolean(value.url) !== Boolean(value.path), {
|
|
21619
22438
|
message: "media source needs exactly one of `url` or `path`"
|
|
21620
22439
|
}).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
|
|
21621
22440
|
message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
|
|
21622
22441
|
});
|
|
21623
|
-
var GroupedUploadedAssetSource =
|
|
21624
|
-
type:
|
|
22442
|
+
var GroupedUploadedAssetSource = z83.object({
|
|
22443
|
+
type: z83.literal("asset"),
|
|
21625
22444
|
/** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
|
|
21626
|
-
assetId:
|
|
21627
|
-
thumbnailAssetId:
|
|
22445
|
+
assetId: z83.string().uuid(),
|
|
22446
|
+
thumbnailAssetId: z83.string().uuid().optional()
|
|
21628
22447
|
});
|
|
21629
|
-
var GroupedCreative =
|
|
21630
|
-
type:
|
|
22448
|
+
var GroupedCreative = z83.object({
|
|
22449
|
+
type: z83.enum([
|
|
21631
22450
|
"image",
|
|
21632
22451
|
"video"
|
|
21633
22452
|
]),
|
|
21634
|
-
source:
|
|
22453
|
+
source: z83.union([
|
|
21635
22454
|
GroupedTaskSource,
|
|
21636
22455
|
GroupedMediaSource,
|
|
21637
22456
|
GroupedUploadedAssetSource
|
|
21638
22457
|
]),
|
|
21639
|
-
title:
|
|
21640
|
-
description:
|
|
22458
|
+
title: z83.string().max(120).optional(),
|
|
22459
|
+
description: z83.string().max(500).optional(),
|
|
21641
22460
|
cta: MetaCtaType.optional(),
|
|
21642
|
-
creativeId:
|
|
22461
|
+
creativeId: z83.string().min(1).optional()
|
|
21643
22462
|
});
|
|
21644
|
-
var GroupedCampaignConfigBase =
|
|
22463
|
+
var GroupedCampaignConfigBase = z83.object({
|
|
21645
22464
|
campaignType: MetaCampaignType.default("sales"),
|
|
21646
22465
|
optimizationMode: MetaOptimizationMode.default("advantage_plus"),
|
|
21647
22466
|
budgetMode: MetaBudgetMode.optional(),
|
|
21648
|
-
campaignDailyBudget:
|
|
21649
|
-
adSets:
|
|
21650
|
-
tempId:
|
|
21651
|
-
name:
|
|
21652
|
-
dailyBudget:
|
|
21653
|
-
creativeIds:
|
|
22467
|
+
campaignDailyBudget: z83.number().int().positive().optional(),
|
|
22468
|
+
adSets: z83.array(z83.object({
|
|
22469
|
+
tempId: z83.string().min(1).max(80),
|
|
22470
|
+
name: z83.string().min(1).max(100),
|
|
22471
|
+
dailyBudget: z83.number().int().positive().optional(),
|
|
22472
|
+
creativeIds: z83.array(z83.string().min(1)).min(1)
|
|
21654
22473
|
})).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
|
|
21655
22474
|
/**
|
|
21656
22475
|
* Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
|
|
@@ -21658,17 +22477,17 @@ var GroupedCampaignConfigBase = z79.object({
|
|
|
21658
22477
|
* opaque `invalid_literal` and made the WhatsApp destination — supported by
|
|
21659
22478
|
* the API since #849 — unreachable from this tool.
|
|
21660
22479
|
*/
|
|
21661
|
-
destination:
|
|
21662
|
-
|
|
21663
|
-
type:
|
|
21664
|
-
landingUrl:
|
|
22480
|
+
destination: z83.discriminatedUnion("type", [
|
|
22481
|
+
z83.object({
|
|
22482
|
+
type: z83.literal("landing"),
|
|
22483
|
+
landingUrl: z83.string().url()
|
|
21665
22484
|
}),
|
|
21666
|
-
|
|
21667
|
-
type:
|
|
21668
|
-
phoneNumber:
|
|
22485
|
+
z83.object({
|
|
22486
|
+
type: z83.literal("whatsapp"),
|
|
22487
|
+
phoneNumber: z83.string().min(8).max(32)
|
|
21669
22488
|
})
|
|
21670
22489
|
]),
|
|
21671
|
-
saveAsDefault:
|
|
22490
|
+
saveAsDefault: z83.boolean().default(false),
|
|
21672
22491
|
budgetPolicy: MetaBudgetPolicy.optional()
|
|
21673
22492
|
});
|
|
21674
22493
|
function resolveBudgetMode(value) {
|
|
@@ -21682,7 +22501,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
21682
22501
|
const budgetMode = resolveBudgetMode(value);
|
|
21683
22502
|
if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
|
|
21684
22503
|
ctx.addIssue({
|
|
21685
|
-
code:
|
|
22504
|
+
code: z83.ZodIssueCode.custom,
|
|
21686
22505
|
path: [
|
|
21687
22506
|
"campaignDailyBudget"
|
|
21688
22507
|
],
|
|
@@ -21693,7 +22512,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
21693
22512
|
value.adSets.forEach((adSet, index) => {
|
|
21694
22513
|
if (adSet.dailyBudget === void 0) {
|
|
21695
22514
|
ctx.addIssue({
|
|
21696
|
-
code:
|
|
22515
|
+
code: z83.ZodIssueCode.custom,
|
|
21697
22516
|
path: [
|
|
21698
22517
|
"adSets",
|
|
21699
22518
|
index,
|
|
@@ -21708,28 +22527,28 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
21708
22527
|
...value,
|
|
21709
22528
|
budgetMode: resolveBudgetMode(value)
|
|
21710
22529
|
}));
|
|
21711
|
-
var PublishCreativesToMetaInputBase =
|
|
21712
|
-
creatives:
|
|
22530
|
+
var PublishCreativesToMetaInputBase = z83.object({
|
|
22531
|
+
creatives: z83.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
|
|
21713
22532
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
21714
|
-
portfolioId:
|
|
22533
|
+
portfolioId: z83.string().trim().min(1),
|
|
21715
22534
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
21716
|
-
pageId:
|
|
22535
|
+
pageId: z83.string().trim().min(1),
|
|
21717
22536
|
adAccountId: McpAdAccountId,
|
|
21718
|
-
pixelId:
|
|
22537
|
+
pixelId: z83.string().min(1).optional(),
|
|
21719
22538
|
/** Required unless `campaignConfig.destination` is whatsapp — see the
|
|
21720
22539
|
* superRefine below. Mirrors the API's `FacebookCreateCampaignFromTasksBodySchema`. */
|
|
21721
|
-
landingUrl:
|
|
22540
|
+
landingUrl: z83.string().url().optional(),
|
|
21722
22541
|
/** ISO-2 code or resolvable country name — mirrors the API contract
|
|
21723
22542
|
* (CountryIso2Schema), which normalizes names to alpha-2 at validation. */
|
|
21724
22543
|
targetCountry: CountryIso2Schema,
|
|
21725
|
-
campaignName:
|
|
22544
|
+
campaignName: z83.string().trim().min(1).max(100),
|
|
21726
22545
|
campaignConfig: GroupedCampaignConfig.optional()
|
|
21727
22546
|
});
|
|
21728
22547
|
var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
|
|
21729
22548
|
const destination = value.campaignConfig?.destination;
|
|
21730
22549
|
if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
|
|
21731
22550
|
ctx.addIssue({
|
|
21732
|
-
code:
|
|
22551
|
+
code: z83.ZodIssueCode.custom,
|
|
21733
22552
|
path: [
|
|
21734
22553
|
"landingUrl"
|
|
21735
22554
|
],
|
|
@@ -21738,7 +22557,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
21738
22557
|
}
|
|
21739
22558
|
if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
|
|
21740
22559
|
ctx.addIssue({
|
|
21741
|
-
code:
|
|
22560
|
+
code: z83.ZodIssueCode.custom,
|
|
21742
22561
|
path: [
|
|
21743
22562
|
"campaignConfig",
|
|
21744
22563
|
"destination",
|
|
@@ -21757,16 +22576,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
21757
22576
|
}
|
|
21758
22577
|
return value;
|
|
21759
22578
|
});
|
|
21760
|
-
var PresignUploadResponseSchema =
|
|
21761
|
-
uploadUrl:
|
|
22579
|
+
var PresignUploadResponseSchema = z83.object({
|
|
22580
|
+
uploadUrl: z83.string().url().refine((value) => {
|
|
21762
22581
|
const url = new URL(value);
|
|
21763
22582
|
return !url.username && !url.password && url.protocol === "https:";
|
|
21764
22583
|
}, "presigned upload URL must be HTTPS without embedded credentials"),
|
|
21765
|
-
publicUrl:
|
|
22584
|
+
publicUrl: z83.string().url().refine((value) => {
|
|
21766
22585
|
const url = new URL(value);
|
|
21767
22586
|
return !url.username && !url.password;
|
|
21768
22587
|
}, "public media URL must not contain embedded credentials"),
|
|
21769
|
-
stagingAssetId:
|
|
22588
|
+
stagingAssetId: z83.string().uuid()
|
|
21770
22589
|
});
|
|
21771
22590
|
async function uploadResolvedMedia(api, media, assetRole) {
|
|
21772
22591
|
if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
|
|
@@ -21791,16 +22610,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
|
|
|
21791
22610
|
return uploadResolvedMedia(api, media, assetRole);
|
|
21792
22611
|
}
|
|
21793
22612
|
__name(resolveAndUploadMedia, "resolveAndUploadMedia");
|
|
21794
|
-
var TikTokInput =
|
|
21795
|
-
taskId:
|
|
21796
|
-
advertiserId:
|
|
21797
|
-
pixelId:
|
|
21798
|
-
landingUrl:
|
|
21799
|
-
angleIndexes:
|
|
22613
|
+
var TikTokInput = z83.object({
|
|
22614
|
+
taskId: z83.string().min(1),
|
|
22615
|
+
advertiserId: z83.string().min(1),
|
|
22616
|
+
pixelId: z83.string().min(1).optional(),
|
|
22617
|
+
landingUrl: z83.string().url().optional(),
|
|
22618
|
+
angleIndexes: z83.array(z83.number().int().nonnegative()).optional(),
|
|
21800
22619
|
campaignConfig: McpCampaignConfig.optional(),
|
|
21801
22620
|
/** Override the ad's description (TikTok's body copy). If omitted,
|
|
21802
22621
|
* ProductMaker uses the auto-generated copy attached to the task. */
|
|
21803
|
-
primaryText:
|
|
22622
|
+
primaryText: z83.string().trim().min(1).max(500).optional()
|
|
21804
22623
|
});
|
|
21805
22624
|
function registerPublishTools(server, api, opts = {}) {
|
|
21806
22625
|
const transport = opts.transport ?? "http";
|
|
@@ -22128,39 +22947,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
|
|
|
22128
22947
|
|
|
22129
22948
|
// src/tools/meta-upload.ts
|
|
22130
22949
|
import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
|
|
22131
|
-
import { z as
|
|
22950
|
+
import { z as z84 } from "zod";
|
|
22132
22951
|
var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
|
|
22133
|
-
var UploadSessionInputBase =
|
|
22134
|
-
mediaKind:
|
|
22952
|
+
var UploadSessionInputBase = z84.object({
|
|
22953
|
+
mediaKind: z84.enum([
|
|
22135
22954
|
"image",
|
|
22136
22955
|
"video",
|
|
22137
22956
|
"mixed"
|
|
22138
22957
|
]).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."),
|
|
22139
|
-
assetRole:
|
|
22958
|
+
assetRole: z84.enum([
|
|
22140
22959
|
"media",
|
|
22141
22960
|
"thumbnail"
|
|
22142
22961
|
]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
|
|
22143
|
-
uploadPurpose:
|
|
22962
|
+
uploadPurpose: z84.enum([
|
|
22144
22963
|
"product_reference",
|
|
22145
22964
|
"creative",
|
|
22146
22965
|
"generic"
|
|
22147
22966
|
]).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."),
|
|
22148
|
-
maxFiles:
|
|
22967
|
+
maxFiles: z84.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
|
|
22149
22968
|
});
|
|
22150
|
-
var OpenAiFileReference =
|
|
22151
|
-
download_url:
|
|
22152
|
-
file_id:
|
|
22153
|
-
mime_type:
|
|
22154
|
-
file_name:
|
|
22969
|
+
var OpenAiFileReference = z84.object({
|
|
22970
|
+
download_url: z84.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."),
|
|
22971
|
+
file_id: z84.string().min(1),
|
|
22972
|
+
mime_type: z84.string().min(1).optional(),
|
|
22973
|
+
file_name: z84.string().min(1).optional()
|
|
22155
22974
|
});
|
|
22156
22975
|
var UploadSessionToolInputShape = {
|
|
22157
22976
|
...UploadSessionInputBase.shape,
|
|
22158
|
-
files:
|
|
22977
|
+
files: z84.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.")
|
|
22159
22978
|
};
|
|
22160
|
-
var UploadSessionToolInput =
|
|
22979
|
+
var UploadSessionToolInput = z84.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
|
|
22161
22980
|
if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
|
|
22162
22981
|
ctx.addIssue({
|
|
22163
|
-
code:
|
|
22982
|
+
code: z84.ZodIssueCode.custom,
|
|
22164
22983
|
path: [
|
|
22165
22984
|
"mediaKind"
|
|
22166
22985
|
],
|
|
@@ -22169,7 +22988,7 @@ var UploadSessionToolInput = z80.object(UploadSessionToolInputShape).superRefine
|
|
|
22169
22988
|
}
|
|
22170
22989
|
if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
|
|
22171
22990
|
ctx.addIssue({
|
|
22172
|
-
code:
|
|
22991
|
+
code: z84.ZodIssueCode.custom,
|
|
22173
22992
|
path: [
|
|
22174
22993
|
"maxFiles"
|
|
22175
22994
|
],
|
|
@@ -22178,7 +22997,7 @@ var UploadSessionToolInput = z80.object(UploadSessionToolInputShape).superRefine
|
|
|
22178
22997
|
}
|
|
22179
22998
|
if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
|
|
22180
22999
|
ctx.addIssue({
|
|
22181
|
-
code:
|
|
23000
|
+
code: z84.ZodIssueCode.custom,
|
|
22182
23001
|
path: [
|
|
22183
23002
|
"maxFiles"
|
|
22184
23003
|
],
|
|
@@ -22186,38 +23005,38 @@ var UploadSessionToolInput = z80.object(UploadSessionToolInputShape).superRefine
|
|
|
22186
23005
|
});
|
|
22187
23006
|
}
|
|
22188
23007
|
});
|
|
22189
|
-
var UploadSessionResponse =
|
|
22190
|
-
sessionId:
|
|
22191
|
-
uploadPageUrl:
|
|
22192
|
-
mediaKind:
|
|
23008
|
+
var UploadSessionResponse = z84.object({
|
|
23009
|
+
sessionId: z84.string().uuid(),
|
|
23010
|
+
uploadPageUrl: z84.string().url(),
|
|
23011
|
+
mediaKind: z84.enum([
|
|
22193
23012
|
"image",
|
|
22194
23013
|
"video",
|
|
22195
23014
|
"mixed"
|
|
22196
23015
|
]),
|
|
22197
|
-
assetRole:
|
|
23016
|
+
assetRole: z84.enum([
|
|
22198
23017
|
"media",
|
|
22199
23018
|
"thumbnail"
|
|
22200
23019
|
]),
|
|
22201
|
-
maxFiles:
|
|
22202
|
-
expiresAt:
|
|
23020
|
+
maxFiles: z84.number().int().positive(),
|
|
23021
|
+
expiresAt: z84.string().datetime()
|
|
22203
23022
|
});
|
|
22204
|
-
var UploadStatusInput =
|
|
22205
|
-
sessionId:
|
|
23023
|
+
var UploadStatusInput = z84.object({
|
|
23024
|
+
sessionId: z84.string().uuid().describe("The sessionId returned by request_media_upload.")
|
|
22206
23025
|
});
|
|
22207
|
-
var UniversalUploadStatusResponse =
|
|
22208
|
-
|
|
22209
|
-
status:
|
|
22210
|
-
assets:
|
|
23026
|
+
var UniversalUploadStatusResponse = z84.discriminatedUnion("status", [
|
|
23027
|
+
z84.object({
|
|
23028
|
+
status: z84.literal("pending"),
|
|
23029
|
+
assets: z84.array(z84.never()).length(0)
|
|
22211
23030
|
}),
|
|
22212
|
-
|
|
22213
|
-
status:
|
|
22214
|
-
assets:
|
|
22215
|
-
assetId:
|
|
22216
|
-
mediaKind:
|
|
23031
|
+
z84.object({
|
|
23032
|
+
status: z84.literal("uploaded"),
|
|
23033
|
+
assets: z84.array(z84.object({
|
|
23034
|
+
assetId: z84.string().uuid(),
|
|
23035
|
+
mediaKind: z84.enum([
|
|
22217
23036
|
"image",
|
|
22218
23037
|
"video"
|
|
22219
23038
|
]),
|
|
22220
|
-
assetRole:
|
|
23039
|
+
assetRole: z84.enum([
|
|
22221
23040
|
"media",
|
|
22222
23041
|
"thumbnail"
|
|
22223
23042
|
])
|
|
@@ -22225,13 +23044,13 @@ var UniversalUploadStatusResponse = z80.discriminatedUnion("status", [
|
|
|
22225
23044
|
})
|
|
22226
23045
|
]);
|
|
22227
23046
|
var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
|
|
22228
|
-
uploadPurpose:
|
|
23047
|
+
uploadPurpose: z84.enum([
|
|
22229
23048
|
"product_reference",
|
|
22230
23049
|
"creative",
|
|
22231
23050
|
"generic"
|
|
22232
23051
|
]),
|
|
22233
|
-
checkToolName:
|
|
22234
|
-
resolveEndpoint:
|
|
23052
|
+
checkToolName: z84.literal("check_media_upload"),
|
|
23053
|
+
resolveEndpoint: z84.string().url()
|
|
22235
23054
|
});
|
|
22236
23055
|
function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
|
|
22237
23056
|
const url = new URL(uploadPageUrl);
|
|
@@ -22322,15 +23141,15 @@ function registerMediaUploadTools(server, api) {
|
|
|
22322
23141
|
__name(registerMediaUploadTools, "registerMediaUploadTools");
|
|
22323
23142
|
|
|
22324
23143
|
// src/tools/campaigns.ts
|
|
22325
|
-
import { z as
|
|
23144
|
+
import { z as z85 } from "zod";
|
|
22326
23145
|
var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
|
|
22327
23146
|
var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
|
|
22328
|
-
var MetaStatusInput =
|
|
22329
|
-
campaignId:
|
|
23147
|
+
var MetaStatusInput = z85.object({
|
|
23148
|
+
campaignId: z85.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
|
|
22330
23149
|
});
|
|
22331
|
-
var TikTokStatusInput =
|
|
22332
|
-
campaignId:
|
|
22333
|
-
advertiserId:
|
|
23150
|
+
var TikTokStatusInput = z85.object({
|
|
23151
|
+
campaignId: z85.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
|
|
23152
|
+
advertiserId: z85.string().min(1).describe("The same advertiserId used to publish the campaign.")
|
|
22334
23153
|
});
|
|
22335
23154
|
function registerCampaignTools(server, api) {
|
|
22336
23155
|
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) => {
|
|
@@ -22427,10 +23246,10 @@ function renderTikTokStatusMarkdown(r) {
|
|
|
22427
23246
|
__name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
|
|
22428
23247
|
|
|
22429
23248
|
// ../../packages/product-economics/src/product-costing.ts
|
|
22430
|
-
import { z as
|
|
23249
|
+
import { z as z87 } from "zod";
|
|
22431
23250
|
|
|
22432
23251
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
22433
|
-
import { z as
|
|
23252
|
+
import { z as z86 } from "zod";
|
|
22434
23253
|
|
|
22435
23254
|
// ../../packages/product-economics/src/product-costing-shipping-references.json
|
|
22436
23255
|
var product_costing_shipping_references_default = {
|
|
@@ -22494,21 +23313,21 @@ var product_costing_shipping_references_default = {
|
|
|
22494
23313
|
};
|
|
22495
23314
|
|
|
22496
23315
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
22497
|
-
var ShippingReferenceSchema =
|
|
22498
|
-
reference:
|
|
22499
|
-
min:
|
|
22500
|
-
max:
|
|
22501
|
-
updatedAt:
|
|
22502
|
-
confidence:
|
|
23316
|
+
var ShippingReferenceSchema = z86.object({
|
|
23317
|
+
reference: z86.number().positive(),
|
|
23318
|
+
min: z86.number().nonnegative(),
|
|
23319
|
+
max: z86.number().positive(),
|
|
23320
|
+
updatedAt: z86.string().date(),
|
|
23321
|
+
confidence: z86.enum([
|
|
22503
23322
|
"high",
|
|
22504
23323
|
"medium",
|
|
22505
23324
|
"medium-low"
|
|
22506
23325
|
]),
|
|
22507
|
-
sources:
|
|
23326
|
+
sources: z86.array(z86.string().url().startsWith("https://")).min(1).max(3)
|
|
22508
23327
|
}).superRefine(({ reference, min, max }, context) => {
|
|
22509
23328
|
if (min > reference || reference > max) {
|
|
22510
23329
|
context.addIssue({
|
|
22511
|
-
code:
|
|
23330
|
+
code: z86.ZodIssueCode.custom,
|
|
22512
23331
|
message: "shipping_reference_outside_range",
|
|
22513
23332
|
path: [
|
|
22514
23333
|
"reference"
|
|
@@ -22516,7 +23335,7 @@ var ShippingReferenceSchema = z82.object({
|
|
|
22516
23335
|
});
|
|
22517
23336
|
}
|
|
22518
23337
|
});
|
|
22519
|
-
var SHIPPING_REFERENCES =
|
|
23338
|
+
var SHIPPING_REFERENCES = z86.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
|
|
22520
23339
|
var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
|
|
22521
23340
|
var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
|
|
22522
23341
|
"MX",
|
|
@@ -22698,18 +23517,18 @@ function getProductCostingCountryName(country) {
|
|
|
22698
23517
|
__name(getProductCostingCountryName, "getProductCostingCountryName");
|
|
22699
23518
|
|
|
22700
23519
|
// ../../packages/product-economics/src/product-costing.ts
|
|
22701
|
-
var ProductCostingInputSchema =
|
|
22702
|
-
country:
|
|
22703
|
-
supplierCost:
|
|
22704
|
-
shippingCost:
|
|
22705
|
-
returnRate:
|
|
22706
|
-
cancellationRate:
|
|
22707
|
-
adsManagerCpa:
|
|
22708
|
-
desiredMargin:
|
|
23520
|
+
var ProductCostingInputSchema = z87.object({
|
|
23521
|
+
country: z87.string().refine(isProductCostingCountryCode, "unsupported_country"),
|
|
23522
|
+
supplierCost: z87.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
|
|
23523
|
+
shippingCost: z87.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
|
|
23524
|
+
returnRate: z87.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
23525
|
+
cancellationRate: z87.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
23526
|
+
adsManagerCpa: z87.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
|
|
23527
|
+
desiredMargin: z87.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
|
|
22709
23528
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
22710
23529
|
if (returnRate + cancellationRate >= 1) {
|
|
22711
23530
|
context.addIssue({
|
|
22712
|
-
code:
|
|
23531
|
+
code: z87.ZodIssueCode.custom,
|
|
22713
23532
|
message: "delivery_rate_positive",
|
|
22714
23533
|
path: [
|
|
22715
23534
|
"cancellationRate"
|
|
@@ -22806,15 +23625,15 @@ function calculateProductCosting(rawInput) {
|
|
|
22806
23625
|
__name(calculateProductCosting, "calculateProductCosting");
|
|
22807
23626
|
|
|
22808
23627
|
// src/tools/product-costing.ts
|
|
22809
|
-
import { z as
|
|
23628
|
+
import { z as z88 } from "zod";
|
|
22810
23629
|
var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
|
|
22811
|
-
var optionalAmount = /* @__PURE__ */ __name((description) =>
|
|
22812
|
-
var optionalPercent = /* @__PURE__ */ __name((description) =>
|
|
22813
|
-
var ProductCostingToolInput =
|
|
22814
|
-
country:
|
|
23630
|
+
var optionalAmount = /* @__PURE__ */ __name((description) => z88.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
|
|
23631
|
+
var optionalPercent = /* @__PURE__ */ __name((description) => z88.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
|
|
23632
|
+
var ProductCostingToolInput = z88.object({
|
|
23633
|
+
country: z88.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
|
|
22815
23634
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
22816
23635
|
}).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
|
|
22817
|
-
supplierCost:
|
|
23636
|
+
supplierCost: z88.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."),
|
|
22818
23637
|
supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
|
|
22819
23638
|
shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
|
|
22820
23639
|
shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
|
|
@@ -22973,7 +23792,7 @@ function formatPercent(value) {
|
|
|
22973
23792
|
__name(formatPercent, "formatPercent");
|
|
22974
23793
|
|
|
22975
23794
|
// src/tools/product-research.ts
|
|
22976
|
-
import { z as
|
|
23795
|
+
import { z as z89 } from "zod";
|
|
22977
23796
|
|
|
22978
23797
|
// src/tools/product-research-idempotency.ts
|
|
22979
23798
|
var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
|
|
@@ -23344,35 +24163,35 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
|
|
|
23344
24163
|
]);
|
|
23345
24164
|
var POLL_INTERVAL_MS = 5e3;
|
|
23346
24165
|
var MAX_WAIT_SECONDS = 120;
|
|
23347
|
-
var FindInput =
|
|
24166
|
+
var FindInput = z89.object({
|
|
23348
24167
|
targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
|
|
23349
24168
|
categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
|
|
23350
|
-
confirmed:
|
|
23351
|
-
waitSeconds:
|
|
24169
|
+
confirmed: z89.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
|
|
24170
|
+
waitSeconds: z89.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
|
|
23352
24171
|
});
|
|
23353
|
-
var GetInput =
|
|
23354
|
-
runId:
|
|
24172
|
+
var GetInput = z89.object({
|
|
24173
|
+
runId: z89.string().uuid().describe("ID del run devuelto por find_winning_products.")
|
|
23355
24174
|
});
|
|
23356
|
-
var ListInput =
|
|
23357
|
-
limit:
|
|
24175
|
+
var ListInput = z89.object({
|
|
24176
|
+
limit: z89.number().int().min(1).max(20).default(10)
|
|
23358
24177
|
});
|
|
23359
|
-
function textResult(
|
|
24178
|
+
function textResult(text2) {
|
|
23360
24179
|
return {
|
|
23361
24180
|
content: [
|
|
23362
24181
|
{
|
|
23363
24182
|
type: "text",
|
|
23364
|
-
text
|
|
24183
|
+
text: text2
|
|
23365
24184
|
}
|
|
23366
24185
|
]
|
|
23367
24186
|
};
|
|
23368
24187
|
}
|
|
23369
24188
|
__name(textResult, "textResult");
|
|
23370
|
-
function researchResult(run,
|
|
24189
|
+
function researchResult(run, text2) {
|
|
23371
24190
|
return {
|
|
23372
24191
|
content: [
|
|
23373
24192
|
{
|
|
23374
24193
|
type: "text",
|
|
23375
|
-
text
|
|
24194
|
+
text: text2
|
|
23376
24195
|
}
|
|
23377
24196
|
],
|
|
23378
24197
|
structuredContent: run
|
|
@@ -23477,17 +24296,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
|
|
|
23477
24296
|
__name(registerProductResearchTools, "registerProductResearchTools");
|
|
23478
24297
|
|
|
23479
24298
|
// src/tools/dropshipping-projects.ts
|
|
23480
|
-
import { z as
|
|
24299
|
+
import { z as z90 } from "zod";
|
|
23481
24300
|
var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
|
|
23482
24301
|
var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
|
|
23483
24302
|
var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
|
|
23484
|
-
var ProjectId =
|
|
23485
|
-
var DropshippingProjectStatus =
|
|
24303
|
+
var ProjectId = z90.string().uuid();
|
|
24304
|
+
var DropshippingProjectStatus = z90.enum([
|
|
23486
24305
|
"active",
|
|
23487
24306
|
"completed",
|
|
23488
24307
|
"archived"
|
|
23489
24308
|
]);
|
|
23490
|
-
var DropshippingProjectPhase =
|
|
24309
|
+
var DropshippingProjectPhase = z90.enum([
|
|
23491
24310
|
"research",
|
|
23492
24311
|
"costing",
|
|
23493
24312
|
"media",
|
|
@@ -23496,21 +24315,21 @@ var DropshippingProjectPhase = z86.enum([
|
|
|
23496
24315
|
"advertising",
|
|
23497
24316
|
"complete"
|
|
23498
24317
|
]);
|
|
23499
|
-
var DropshippingRewardMilestone =
|
|
24318
|
+
var DropshippingRewardMilestone = z90.enum([
|
|
23500
24319
|
"product_selected",
|
|
23501
24320
|
"costing_saved",
|
|
23502
24321
|
"product_media_ready",
|
|
23503
24322
|
"creatives_completed",
|
|
23504
24323
|
"campaign_created"
|
|
23505
24324
|
]);
|
|
23506
|
-
var TargetCountry =
|
|
24325
|
+
var TargetCountry = z90.enum([
|
|
23507
24326
|
"CO",
|
|
23508
24327
|
"MX",
|
|
23509
24328
|
"PE",
|
|
23510
24329
|
"EC",
|
|
23511
24330
|
"CL"
|
|
23512
24331
|
]);
|
|
23513
|
-
var ResearchCategory =
|
|
24332
|
+
var ResearchCategory = z90.enum([
|
|
23514
24333
|
"auto",
|
|
23515
24334
|
"automotive",
|
|
23516
24335
|
"kitchen",
|
|
@@ -23525,7 +24344,7 @@ var ResearchCategory = z86.enum([
|
|
|
23525
24344
|
"garden",
|
|
23526
24345
|
"cleaning"
|
|
23527
24346
|
]);
|
|
23528
|
-
var HttpUrl3 =
|
|
24347
|
+
var HttpUrl3 = z90.string().url().max(2e3).refine((value) => {
|
|
23529
24348
|
try {
|
|
23530
24349
|
return [
|
|
23531
24350
|
"http:",
|
|
@@ -23535,45 +24354,45 @@ var HttpUrl3 = z86.string().url().max(2e3).refine((value) => {
|
|
|
23535
24354
|
return false;
|
|
23536
24355
|
}
|
|
23537
24356
|
}, "URL must use HTTP(S)");
|
|
23538
|
-
var ResearchCandidateOrigin =
|
|
23539
|
-
type:
|
|
24357
|
+
var ResearchCandidateOrigin = z90.object({
|
|
24358
|
+
type: z90.literal("research_candidate"),
|
|
23540
24359
|
runId: ProjectId,
|
|
23541
|
-
candidateSourceId:
|
|
24360
|
+
candidateSourceId: z90.string().min(1).max(160)
|
|
23542
24361
|
});
|
|
23543
|
-
var TaskOrigin =
|
|
23544
|
-
type:
|
|
24362
|
+
var TaskOrigin = z90.object({
|
|
24363
|
+
type: z90.literal("task"),
|
|
23545
24364
|
taskId: ProjectId
|
|
23546
24365
|
});
|
|
23547
|
-
var ManualOrigin =
|
|
23548
|
-
type:
|
|
24366
|
+
var ManualOrigin = z90.object({
|
|
24367
|
+
type: z90.literal("manual"),
|
|
23549
24368
|
clientRequestId: ProjectId,
|
|
23550
|
-
country:
|
|
24369
|
+
country: z90.string().min(2).max(3).optional()
|
|
23551
24370
|
});
|
|
23552
|
-
var StartProjectInput =
|
|
23553
|
-
origin:
|
|
24371
|
+
var StartProjectInput = z90.object({
|
|
24372
|
+
origin: z90.discriminatedUnion("type", [
|
|
23554
24373
|
ResearchCandidateOrigin,
|
|
23555
24374
|
TaskOrigin,
|
|
23556
24375
|
ManualOrigin
|
|
23557
24376
|
]),
|
|
23558
|
-
productName:
|
|
24377
|
+
productName: z90.string().trim().min(1).max(240).optional(),
|
|
23559
24378
|
productUrl: HttpUrl3.optional(),
|
|
23560
|
-
country:
|
|
23561
|
-
languageCode:
|
|
24379
|
+
country: z90.string().min(2).max(3).optional(),
|
|
24380
|
+
languageCode: z90.string().min(2).max(16).optional()
|
|
23562
24381
|
}).strict();
|
|
23563
|
-
var CostProjectInput =
|
|
24382
|
+
var CostProjectInput = z90.object({
|
|
23564
24383
|
projectId: ProjectId,
|
|
23565
|
-
version:
|
|
23566
|
-
country:
|
|
24384
|
+
version: z90.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
|
|
24385
|
+
country: z90.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
|
|
23567
24386
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
23568
24387
|
}).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
|
|
23569
|
-
supplierCost:
|
|
23570
|
-
shippingCost:
|
|
23571
|
-
returnRate:
|
|
23572
|
-
cancellationRate:
|
|
23573
|
-
adsManagerCpa:
|
|
23574
|
-
desiredMargin:
|
|
23575
|
-
});
|
|
23576
|
-
var GuideInput =
|
|
24388
|
+
supplierCost: z90.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."),
|
|
24389
|
+
shippingCost: z90.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
|
|
24390
|
+
returnRate: z90.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."),
|
|
24391
|
+
cancellationRate: z90.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."),
|
|
24392
|
+
adsManagerCpa: z90.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
|
|
24393
|
+
desiredMargin: z90.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
|
|
24394
|
+
});
|
|
24395
|
+
var GuideInput = z90.object({
|
|
23577
24396
|
projectId: ProjectId.optional()
|
|
23578
24397
|
}).strict();
|
|
23579
24398
|
var NEXT_ACTION_KINDS = [
|
|
@@ -23591,29 +24410,29 @@ var NEXT_ACTION_KINDS = [
|
|
|
23591
24410
|
"repair_meta_campaign",
|
|
23592
24411
|
"review_paused_campaign"
|
|
23593
24412
|
];
|
|
23594
|
-
var DropshippingProjectNextAction =
|
|
23595
|
-
kind:
|
|
23596
|
-
href:
|
|
24413
|
+
var DropshippingProjectNextAction = z90.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z90.object({
|
|
24414
|
+
kind: z90.literal(kind),
|
|
24415
|
+
href: z90.string().min(1)
|
|
23597
24416
|
})));
|
|
23598
|
-
var CostingInputSchema =
|
|
23599
|
-
country:
|
|
23600
|
-
supplierCost:
|
|
23601
|
-
shippingCost:
|
|
23602
|
-
returnRate:
|
|
23603
|
-
cancellationRate:
|
|
23604
|
-
adsManagerCpa:
|
|
23605
|
-
desiredMargin:
|
|
24417
|
+
var CostingInputSchema = z90.object({
|
|
24418
|
+
country: z90.string().min(2).max(3),
|
|
24419
|
+
supplierCost: z90.number().finite().positive(),
|
|
24420
|
+
shippingCost: z90.number().finite().nonnegative(),
|
|
24421
|
+
returnRate: z90.number().finite().min(0).lt(1),
|
|
24422
|
+
cancellationRate: z90.number().finite().min(0).lt(1),
|
|
24423
|
+
adsManagerCpa: z90.number().finite().nonnegative(),
|
|
24424
|
+
desiredMargin: z90.number().finite().min(0).lt(1)
|
|
23606
24425
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
23607
24426
|
if (returnRate + cancellationRate >= 1) context.addIssue({
|
|
23608
|
-
code:
|
|
24427
|
+
code: z90.ZodIssueCode.custom,
|
|
23609
24428
|
path: [
|
|
23610
24429
|
"cancellationRate"
|
|
23611
24430
|
]
|
|
23612
24431
|
});
|
|
23613
24432
|
});
|
|
23614
|
-
var FiniteCostingNumber =
|
|
23615
|
-
var CostingResultSchema =
|
|
23616
|
-
country:
|
|
24433
|
+
var FiniteCostingNumber = z90.number().finite();
|
|
24434
|
+
var CostingResultSchema = z90.object({
|
|
24435
|
+
country: z90.string().min(2).max(3),
|
|
23617
24436
|
deliveryRate: FiniteCostingNumber,
|
|
23618
24437
|
adjustedShippingCost: FiniteCostingNumber,
|
|
23619
24438
|
adjustedCpa: FiniteCostingNumber,
|
|
@@ -23626,45 +24445,45 @@ var CostingResultSchema = z86.object({
|
|
|
23626
24445
|
estimatedProfit: FiniteCostingNumber,
|
|
23627
24446
|
actualMargin: FiniteCostingNumber,
|
|
23628
24447
|
breakEvenAdsManagerCpa: FiniteCostingNumber,
|
|
23629
|
-
wasPriceAutoAdjusted:
|
|
23630
|
-
profitabilityStatus:
|
|
23631
|
-
});
|
|
23632
|
-
var RewardProgressSchema =
|
|
23633
|
-
campaignKey:
|
|
23634
|
-
totalCredits:
|
|
23635
|
-
earnedCredits:
|
|
23636
|
-
milestones:
|
|
24448
|
+
wasPriceAutoAdjusted: z90.boolean(),
|
|
24449
|
+
profitabilityStatus: z90.literal("healthy")
|
|
24450
|
+
});
|
|
24451
|
+
var RewardProgressSchema = z90.object({
|
|
24452
|
+
campaignKey: z90.literal("dropshipping-launch-v1"),
|
|
24453
|
+
totalCredits: z90.number().int().positive(),
|
|
24454
|
+
earnedCredits: z90.number().int().nonnegative(),
|
|
24455
|
+
milestones: z90.array(z90.object({
|
|
23637
24456
|
milestone: DropshippingRewardMilestone,
|
|
23638
|
-
credits:
|
|
23639
|
-
available:
|
|
23640
|
-
earned:
|
|
24457
|
+
credits: z90.number().int().positive(),
|
|
24458
|
+
available: z90.boolean().optional(),
|
|
24459
|
+
earned: z90.boolean(),
|
|
23641
24460
|
grantId: ProjectId.nullable(),
|
|
23642
|
-
grantedAt:
|
|
24461
|
+
grantedAt: z90.string().datetime().nullable()
|
|
23643
24462
|
})).length(DropshippingRewardMilestone.options.length)
|
|
23644
24463
|
});
|
|
23645
|
-
var ProjectResponseSchema =
|
|
24464
|
+
var ProjectResponseSchema = z90.object({
|
|
23646
24465
|
id: ProjectId,
|
|
23647
24466
|
taskId: ProjectId.nullable(),
|
|
23648
24467
|
status: DropshippingProjectStatus,
|
|
23649
|
-
originKey:
|
|
24468
|
+
originKey: z90.string().min(1),
|
|
23650
24469
|
researchRunId: ProjectId.nullable(),
|
|
23651
|
-
candidateSourceId:
|
|
23652
|
-
productName:
|
|
24470
|
+
candidateSourceId: z90.string().nullable(),
|
|
24471
|
+
productName: z90.string().nullable(),
|
|
23653
24472
|
productUrl: HttpUrl3.nullable(),
|
|
23654
24473
|
referenceImageUrl: HttpUrl3.nullable(),
|
|
23655
|
-
targetCountry:
|
|
23656
|
-
languageCode:
|
|
23657
|
-
hasReferenceImage:
|
|
23658
|
-
hasWinnerReferenceImage:
|
|
24474
|
+
targetCountry: z90.string().nullable(),
|
|
24475
|
+
languageCode: z90.string().nullable(),
|
|
24476
|
+
hasReferenceImage: z90.boolean(),
|
|
24477
|
+
hasWinnerReferenceImage: z90.boolean(),
|
|
23659
24478
|
costingInput: CostingInputSchema.nullable(),
|
|
23660
24479
|
costingResult: CostingResultSchema.nullable(),
|
|
23661
|
-
costingVersion:
|
|
23662
|
-
version:
|
|
24480
|
+
costingVersion: z90.number().int().positive().nullable(),
|
|
24481
|
+
version: z90.number().int().positive(),
|
|
23663
24482
|
phase: DropshippingProjectPhase,
|
|
23664
24483
|
nextAction: DropshippingProjectNextAction.nullable(),
|
|
23665
24484
|
rewards: RewardProgressSchema,
|
|
23666
|
-
createdAt:
|
|
23667
|
-
updatedAt:
|
|
24485
|
+
createdAt: z90.string().datetime(),
|
|
24486
|
+
updatedAt: z90.string().datetime()
|
|
23668
24487
|
}).passthrough();
|
|
23669
24488
|
var NEXT_ACTION_GUIDANCE = {
|
|
23670
24489
|
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.",
|
|
@@ -23782,58 +24601,58 @@ function registerDropshippingProjectTools(server, api) {
|
|
|
23782
24601
|
__name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
|
|
23783
24602
|
|
|
23784
24603
|
// src/tools/daily-control.ts
|
|
23785
|
-
import { z as
|
|
24604
|
+
import { z as z91 } from "zod";
|
|
23786
24605
|
var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
|
|
23787
24606
|
var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
|
|
23788
24607
|
var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
|
|
23789
|
-
var ProviderCampaignIdentifier =
|
|
23790
|
-
var DateOnly =
|
|
23791
|
-
var DailyControlInput =
|
|
24608
|
+
var ProviderCampaignIdentifier = z91.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
|
|
24609
|
+
var DateOnly = z91.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
24610
|
+
var DailyControlInput = z91.object({
|
|
23792
24611
|
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."),
|
|
23793
|
-
days:
|
|
23794
|
-
projectId:
|
|
24612
|
+
days: z91.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
|
|
24613
|
+
projectId: z91.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
|
|
23795
24614
|
}).strict();
|
|
23796
|
-
var LinkCampaignInput =
|
|
23797
|
-
projectId:
|
|
23798
|
-
provider:
|
|
24615
|
+
var LinkCampaignInput = z91.object({
|
|
24616
|
+
projectId: z91.string().uuid(),
|
|
24617
|
+
provider: z91.enum([
|
|
23799
24618
|
"meta",
|
|
23800
24619
|
"tiktok"
|
|
23801
24620
|
]),
|
|
23802
24621
|
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."),
|
|
23803
24622
|
campaignId: ProviderCampaignIdentifier
|
|
23804
24623
|
}).strict();
|
|
23805
|
-
var ReportReturnsInput =
|
|
23806
|
-
projectId:
|
|
24624
|
+
var ReportReturnsInput = z91.object({
|
|
24625
|
+
projectId: z91.string().uuid(),
|
|
23807
24626
|
date: DateOnly,
|
|
23808
|
-
returnedOrders:
|
|
23809
|
-
note:
|
|
24627
|
+
returnedOrders: z91.number().int().min(0).max(1e5),
|
|
24628
|
+
note: z91.string().trim().max(280).optional()
|
|
23810
24629
|
}).strict();
|
|
23811
|
-
var DailyControlStatusMirror = DailyControlStatusEnum.or(
|
|
23812
|
-
var DailyControlLightMirror = DailyControlLightEnum.or(
|
|
23813
|
-
var DailyControlSourceMirror = DailyControlSourceEnum.or(
|
|
23814
|
-
var DailyControlVerdictMirror = DailyControlVerdictEnum.or(
|
|
23815
|
-
var DailyControlDayMirror =
|
|
23816
|
-
date:
|
|
23817
|
-
returnedOrders:
|
|
24630
|
+
var DailyControlStatusMirror = DailyControlStatusEnum.or(z91.string());
|
|
24631
|
+
var DailyControlLightMirror = DailyControlLightEnum.or(z91.string());
|
|
24632
|
+
var DailyControlSourceMirror = DailyControlSourceEnum.or(z91.string());
|
|
24633
|
+
var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z91.string());
|
|
24634
|
+
var DailyControlDayMirror = z91.object({
|
|
24635
|
+
date: z91.string(),
|
|
24636
|
+
returnedOrders: z91.number(),
|
|
23818
24637
|
returnedSource: DailyControlSourceMirror,
|
|
23819
24638
|
cancelledSource: DailyControlSourceMirror,
|
|
23820
|
-
hasEstimates:
|
|
24639
|
+
hasEstimates: z91.boolean(),
|
|
23821
24640
|
light: DailyControlLightMirror
|
|
23822
24641
|
}).passthrough();
|
|
23823
|
-
var DailyControlProductMirror =
|
|
23824
|
-
projectId:
|
|
23825
|
-
productName:
|
|
24642
|
+
var DailyControlProductMirror = z91.object({
|
|
24643
|
+
projectId: z91.string().uuid(),
|
|
24644
|
+
productName: z91.string().nullable(),
|
|
23826
24645
|
status: DailyControlStatusMirror,
|
|
23827
|
-
statusMessage:
|
|
23828
|
-
days:
|
|
24646
|
+
statusMessage: z91.string().nullable(),
|
|
24647
|
+
days: z91.array(DailyControlDayMirror),
|
|
23829
24648
|
verdict: DailyControlVerdictMirror.nullable(),
|
|
23830
|
-
rationale:
|
|
24649
|
+
rationale: z91.string().nullable()
|
|
23831
24650
|
}).passthrough();
|
|
23832
|
-
var DailyControlResponseMirror =
|
|
23833
|
-
since:
|
|
23834
|
-
until:
|
|
23835
|
-
products:
|
|
23836
|
-
archivedProjectSpend:
|
|
24651
|
+
var DailyControlResponseMirror = z91.object({
|
|
24652
|
+
since: z91.string(),
|
|
24653
|
+
until: z91.string(),
|
|
24654
|
+
products: z91.array(DailyControlProductMirror),
|
|
24655
|
+
archivedProjectSpend: z91.array(z91.unknown())
|
|
23837
24656
|
}).passthrough();
|
|
23838
24657
|
var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
|
|
23839
24658
|
function withWarnings(response) {
|
|
@@ -23917,42 +24736,42 @@ function registerDailyControlTools(server, api) {
|
|
|
23917
24736
|
__name(registerDailyControlTools, "registerDailyControlTools");
|
|
23918
24737
|
|
|
23919
24738
|
// src/tools/product-control.ts
|
|
23920
|
-
import { z as
|
|
24739
|
+
import { z as z92 } from "zod";
|
|
23921
24740
|
var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
|
|
23922
24741
|
var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
|
|
23923
24742
|
var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
|
|
23924
24743
|
var setProductCostingGuidance = getProductMakerCapabilityModelGuidance("set_product_costing");
|
|
23925
24744
|
var reportProductCountsGuidance = getProductMakerCapabilityModelGuidance("report_product_counts");
|
|
23926
|
-
var DateOnly2 =
|
|
24745
|
+
var DateOnly2 = z92.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
23927
24746
|
var IMPORT_BATCH_MAX2 = 50;
|
|
23928
|
-
var ProductControlListInput =
|
|
23929
|
-
days:
|
|
24747
|
+
var ProductControlListInput = z92.object({
|
|
24748
|
+
days: z92.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
|
|
23930
24749
|
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."),
|
|
23931
|
-
shopDomain:
|
|
24750
|
+
shopDomain: z92.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
|
|
23932
24751
|
}).strict();
|
|
23933
|
-
var ImportableProductsInput =
|
|
23934
|
-
q:
|
|
23935
|
-
after:
|
|
23936
|
-
shopDomain:
|
|
24752
|
+
var ImportableProductsInput = z92.object({
|
|
24753
|
+
q: z92.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
|
|
24754
|
+
after: z92.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
|
|
24755
|
+
shopDomain: z92.string().min(1).optional()
|
|
23937
24756
|
}).strict();
|
|
23938
|
-
var ImportProductControlsInput =
|
|
23939
|
-
shopifyProductIds:
|
|
24757
|
+
var ImportProductControlsInput = z92.object({
|
|
24758
|
+
shopifyProductIds: z92.array(z92.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."),
|
|
23940
24759
|
// Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
|
|
23941
24760
|
// sin decir a cuál archivaría el producto bajo la tienda equivocada.
|
|
23942
|
-
shopDomain:
|
|
24761
|
+
shopDomain: z92.string().min(1)
|
|
23943
24762
|
}).strict();
|
|
23944
|
-
var SetProductCostingInput =
|
|
23945
|
-
shopDomain:
|
|
23946
|
-
shopifyProductId:
|
|
23947
|
-
targetCountry:
|
|
23948
|
-
supplierCost:
|
|
23949
|
-
shippingCost:
|
|
23950
|
-
returnRate:
|
|
23951
|
-
cancellationRate:
|
|
24763
|
+
var SetProductCostingInput = z92.object({
|
|
24764
|
+
shopDomain: z92.string().min(1),
|
|
24765
|
+
shopifyProductId: z92.string().min(1).max(64),
|
|
24766
|
+
targetCountry: z92.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
|
|
24767
|
+
supplierCost: z92.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
|
|
24768
|
+
shippingCost: z92.number().finite().nonnegative(),
|
|
24769
|
+
returnRate: z92.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
|
|
24770
|
+
cancellationRate: z92.number().finite().min(0).lt(1)
|
|
23952
24771
|
}).strict();
|
|
23953
|
-
var Count =
|
|
23954
|
-
var ReportProductCountsInput =
|
|
23955
|
-
productControlId:
|
|
24772
|
+
var Count = z92.number().int().min(0).max(1e5).nullable().optional();
|
|
24773
|
+
var ReportProductCountsInput = z92.object({
|
|
24774
|
+
productControlId: z92.string().uuid().describe("El identificador que devuelve get_product_control."),
|
|
23956
24775
|
date: DateOnly2,
|
|
23957
24776
|
orders: Count.describe("Pedidos que entraron ese d\xEDa."),
|
|
23958
24777
|
cancelledOrders: Count,
|