@productmaker/mcp 8.0.0 → 8.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/http.js +1632 -802
- package/dist/stdio.js +1616 -786
- package/package.json +1 -1
package/dist/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(),
|
|
@@ -6918,7 +7098,10 @@ var ServiceCreativeEstimationOptions = z34.object({
|
|
|
6918
7098
|
uploadedVideoDurationSeconds: z34.number().min(0).max(240).optional(),
|
|
6919
7099
|
/** Quality the panels render at (its registry model sets the per-second
|
|
6920
7100
|
* price). Absent = economy, the pre-quality service default. */
|
|
6921
|
-
videoQuality: VideoQuality.optional()
|
|
7101
|
+
videoQuality: VideoQuality.optional(),
|
|
7102
|
+
/** Semantic resolution the panels render at (H3 maps 480p/720p to its
|
|
7103
|
+
* native 768P/2K). Absent = 480p, the pre-resolution service default. */
|
|
7104
|
+
videoResolution: VideoResolution.optional()
|
|
6922
7105
|
});
|
|
6923
7106
|
var ActorGridEstimationOptions = z34.object({}).strict();
|
|
6924
7107
|
var CostEstimationRequest = z34.discriminatedUnion("type", [
|
|
@@ -7266,7 +7449,8 @@ var IMAGE_QA_GATES = [
|
|
|
7266
7449
|
"limb",
|
|
7267
7450
|
"device_panel",
|
|
7268
7451
|
"critical_feature",
|
|
7269
|
-
"cross_section"
|
|
7452
|
+
"cross_section",
|
|
7453
|
+
"usage_fidelity"
|
|
7270
7454
|
];
|
|
7271
7455
|
var ImageQaGate = z36.enum(IMAGE_QA_GATES);
|
|
7272
7456
|
var ImageQaGateOutcome = z36.enum([
|
|
@@ -8312,6 +8496,10 @@ var GEMINI_OMNI_FLAT_USER_PRICE_CENTS = 168;
|
|
|
8312
8496
|
// ../../packages/types/src/pricing.ts
|
|
8313
8497
|
var CREDITS_PER_USD_CENT = 10;
|
|
8314
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
|
+
};
|
|
8315
8503
|
var KALODATA_USD_CENTS_PER_PROVIDER_CREDIT = 9;
|
|
8316
8504
|
var KALODATA_PROVIDER_CREDITS_PER_SOURCE_CEILING = 7.5;
|
|
8317
8505
|
var DEFAULT_PRICING = {
|
|
@@ -9270,6 +9458,27 @@ var DEFAULT_PRICING = {
|
|
|
9270
9458
|
ourCostCents: 1.88,
|
|
9271
9459
|
userPriceCents: 3.76
|
|
9272
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
|
+
},
|
|
9273
9482
|
// Landing commercial-facts extraction (gemini-3.8-flash, ONE text-only call over
|
|
9274
9483
|
// the seller's offer/context/features). Sized off the image-QA key beside it,
|
|
9275
9484
|
// which measured 1.88¢ at ~11.1K prompt tokens: this prompt is capped at ~3K in
|
|
@@ -10008,6 +10217,24 @@ var DEFAULT_PRICING = {
|
|
|
10008
10217
|
ourCostCents: 0.2,
|
|
10009
10218
|
userPriceCents: 0.4
|
|
10010
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
|
+
},
|
|
10011
10238
|
// Unit = one reference-grouping pass over the user's product images (0.1241¢).
|
|
10012
10239
|
"openrouter:product-reference-grouping": {
|
|
10013
10240
|
ourCostCents: 0.15,
|
|
@@ -13352,7 +13579,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13352
13579
|
"task",
|
|
13353
13580
|
"product"
|
|
13354
13581
|
]),
|
|
13355
|
-
defineCapability("create_service_video", "
|
|
13582
|
+
defineCapability("create_service_video", "c3d81a4f698e01658fa04ebb613a91c8ba43320d21cacda522e72d198036eb21", "credit_consuming", "creative", [
|
|
13356
13583
|
"credit_consuming",
|
|
13357
13584
|
"state_change"
|
|
13358
13585
|
], [
|
|
@@ -13380,6 +13607,9 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13380
13607
|
// MCP-only for now: WhatsApp's service flow keeps the economy default.
|
|
13381
13608
|
slot("video_quality", false, [
|
|
13382
13609
|
"videoQuality"
|
|
13610
|
+
], []),
|
|
13611
|
+
slot("video_resolution", false, [
|
|
13612
|
+
"videoResolution"
|
|
13383
13613
|
], [])
|
|
13384
13614
|
], [
|
|
13385
13615
|
"service_context"
|
|
@@ -13522,7 +13752,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13522
13752
|
"video"
|
|
13523
13753
|
]
|
|
13524
13754
|
),
|
|
13525
|
-
defineCapability("generate_image_creatives", "
|
|
13755
|
+
defineCapability("generate_image_creatives", "2f1698b623d98645b7c618a17988f3aac30f403a9c3f3dc26eb5bdbd9c6ef23e", "credit_consuming", "creative", [
|
|
13526
13756
|
"credit_consuming",
|
|
13527
13757
|
"state_change"
|
|
13528
13758
|
], [
|
|
@@ -15173,79 +15403,696 @@ var WhatsAppPresentationManifestSchema = z67.object({
|
|
|
15173
15403
|
}
|
|
15174
15404
|
});
|
|
15175
15405
|
|
|
15176
|
-
// ../../packages/types/src/
|
|
15406
|
+
// ../../packages/types/src/usage-decision.ts
|
|
15177
15407
|
import { z as z68 } from "zod";
|
|
15178
|
-
|
|
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([
|
|
15179
16026
|
"initial",
|
|
15180
16027
|
"regeneration",
|
|
15181
16028
|
"edit",
|
|
15182
16029
|
"retry"
|
|
15183
16030
|
]);
|
|
15184
|
-
var FlightRecorderProviderSchema =
|
|
16031
|
+
var FlightRecorderProviderSchema = z72.enum([
|
|
15185
16032
|
"kie",
|
|
15186
16033
|
"fal"
|
|
15187
16034
|
]);
|
|
15188
|
-
var FlightRecorderElementSchema =
|
|
15189
|
-
name:
|
|
15190
|
-
description:
|
|
15191
|
-
frontalImageUrl:
|
|
15192
|
-
referenceImageUrls:
|
|
15193
|
-
videoUrl:
|
|
15194
|
-
});
|
|
15195
|
-
var FlightRecorderDistillationSchema =
|
|
15196
|
-
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([
|
|
15197
16044
|
"female",
|
|
15198
16045
|
"male",
|
|
15199
16046
|
"mixed"
|
|
15200
|
-
]).or(
|
|
15201
|
-
voiceId:
|
|
15202
|
-
cameraMotion:
|
|
15203
|
-
}).catchall(
|
|
15204
|
-
var FlightRecorderEntrySchema =
|
|
15205
|
-
schemaVersion:
|
|
15206
|
-
id:
|
|
15207
|
-
taskId:
|
|
15208
|
-
runId:
|
|
15209
|
-
sequence:
|
|
15210
|
-
timestamp:
|
|
15211
|
-
provider: FlightRecorderProviderSchema.or(
|
|
15212
|
-
model:
|
|
15213
|
-
prompt:
|
|
15214
|
-
durationSeconds:
|
|
15215
|
-
aspectRatio:
|
|
15216
|
-
resolution:
|
|
15217
|
-
startImageUrl:
|
|
15218
|
-
endImageUrl:
|
|
15219
|
-
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(),
|
|
15220
16067
|
// Correlation & pipeline metadata
|
|
15221
|
-
angleKey:
|
|
15222
|
-
sceneIndex:
|
|
16068
|
+
angleKey: z72.string().optional(),
|
|
16069
|
+
sceneIndex: z72.number().int().nonnegative().optional(),
|
|
15223
16070
|
generationType: FlightRecorderGenerationTypeSchema,
|
|
15224
|
-
operationId:
|
|
15225
|
-
revisionId:
|
|
15226
|
-
attemptNumber:
|
|
16071
|
+
operationId: z72.string().min(1).optional(),
|
|
16072
|
+
revisionId: z72.string().min(1).optional(),
|
|
16073
|
+
attemptNumber: z72.number().int().nonnegative().default(1),
|
|
15227
16074
|
// Elements & Distillation
|
|
15228
|
-
elements:
|
|
16075
|
+
elements: z72.array(FlightRecorderElementSchema).optional(),
|
|
15229
16076
|
distillation: FlightRecorderDistillationSchema.optional(),
|
|
15230
16077
|
// Raw payload (sanitized of secrets)
|
|
15231
|
-
rawPayload:
|
|
16078
|
+
rawPayload: z72.record(z72.unknown())
|
|
15232
16079
|
});
|
|
15233
|
-
var FlightRecorderQuerySchema =
|
|
15234
|
-
taskId:
|
|
15235
|
-
runId:
|
|
15236
|
-
sceneIndex:
|
|
15237
|
-
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(),
|
|
15238
16085
|
generationType: FlightRecorderGenerationTypeSchema.optional(),
|
|
15239
|
-
cursor:
|
|
15240
|
-
limit:
|
|
16086
|
+
cursor: z72.number().int().nonnegative().optional(),
|
|
16087
|
+
limit: z72.number().int().positive().optional()
|
|
15241
16088
|
});
|
|
15242
|
-
var FlightRecorderResponseSchema =
|
|
15243
|
-
taskId:
|
|
15244
|
-
runId:
|
|
15245
|
-
entries:
|
|
16089
|
+
var FlightRecorderResponseSchema = z72.object({
|
|
16090
|
+
taskId: z72.string().min(1),
|
|
16091
|
+
runId: z72.string().min(1),
|
|
16092
|
+
entries: z72.array(FlightRecorderEntrySchema),
|
|
15246
16093
|
lastCall: FlightRecorderEntrySchema.nullable(),
|
|
15247
|
-
count:
|
|
15248
|
-
nextCursor:
|
|
16094
|
+
count: z72.number().int().nonnegative(),
|
|
16095
|
+
nextCursor: z72.number().int().nonnegative().nullable()
|
|
15249
16096
|
});
|
|
15250
16097
|
|
|
15251
16098
|
// src/http.ts
|
|
@@ -15420,8 +16267,8 @@ async function readResponseText(response, maxBytes) {
|
|
|
15420
16267
|
}
|
|
15421
16268
|
__name(readResponseText, "readResponseText");
|
|
15422
16269
|
async function readResponseJson(response, maxBytes) {
|
|
15423
|
-
const
|
|
15424
|
-
return JSON.parse(
|
|
16270
|
+
const text2 = await readResponseText(response, maxBytes);
|
|
16271
|
+
return JSON.parse(text2);
|
|
15425
16272
|
}
|
|
15426
16273
|
__name(readResponseJson, "readResponseJson");
|
|
15427
16274
|
|
|
@@ -15754,22 +16601,22 @@ import { InsufficientScopeError, InvalidTokenError } from "@modelcontextprotocol
|
|
|
15754
16601
|
import { createRemoteJWKSet as createRemoteJWKSet2, jwtVerify as jwtVerify2 } from "jose";
|
|
15755
16602
|
|
|
15756
16603
|
// src/auth/oauth-config.ts
|
|
15757
|
-
import { z as
|
|
16604
|
+
import { z as z73 } from "zod";
|
|
15758
16605
|
var MCP_RESOURCE = new URL("https://mcp.productmaker.app/mcp");
|
|
15759
16606
|
var MCP_SCOPE = "mcp:access";
|
|
15760
16607
|
var STATIC_CLIENT_ISSUER = new URL(MCP_RESOURCE.origin);
|
|
15761
|
-
var oauthEnvSchema =
|
|
15762
|
-
MCP_REMOTE_AUTH_MODE:
|
|
15763
|
-
MCP_AUTH0_ISSUER:
|
|
15764
|
-
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, {
|
|
15765
16612
|
message: `must equal ${MCP_RESOURCE.href}`
|
|
15766
16613
|
}),
|
|
15767
|
-
MCP_AUTH0_CLIENT_ID:
|
|
15768
|
-
MCP_AUTH0_CLIENT_SECRET:
|
|
15769
|
-
PM_API_AUDIENCE:
|
|
15770
|
-
AUTH0_AUDIENCE:
|
|
15771
|
-
MCP_STATIC_CLIENT_ID:
|
|
15772
|
-
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()
|
|
15773
16620
|
});
|
|
15774
16621
|
function formatZodIssues(error) {
|
|
15775
16622
|
return error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
|
|
@@ -16053,7 +16900,7 @@ function badRequest(res, description) {
|
|
|
16053
16900
|
__name(badRequest, "badRequest");
|
|
16054
16901
|
function createOAuthProxyRouter(options) {
|
|
16055
16902
|
const router = express.Router();
|
|
16056
|
-
const
|
|
16903
|
+
const stateKey3 = deriveStateKey(options.staticClient.clientSecret);
|
|
16057
16904
|
const now = options.now ?? (() => Date.now());
|
|
16058
16905
|
router.get(OAUTH_PROXY_PATHS.authorize, (req, res) => {
|
|
16059
16906
|
const redirectUri = firstQueryValue(req.query.redirect_uri);
|
|
@@ -16082,7 +16929,7 @@ function createOAuthProxyRouter(options) {
|
|
|
16082
16929
|
}
|
|
16083
16930
|
}
|
|
16084
16931
|
upstream.searchParams.set("redirect_uri", PROXY_CALLBACK_URL);
|
|
16085
|
-
upstream.searchParams.set("state", sealState(
|
|
16932
|
+
upstream.searchParams.set("state", sealState(stateKey3, {
|
|
16086
16933
|
redirectUri,
|
|
16087
16934
|
...firstQueryValue(req.query.state) === void 0 ? {} : {
|
|
16088
16935
|
clientState: firstQueryValue(req.query.state)
|
|
@@ -16092,7 +16939,7 @@ function createOAuthProxyRouter(options) {
|
|
|
16092
16939
|
});
|
|
16093
16940
|
router.get(OAUTH_PROXY_PATHS.callback, (req, res) => {
|
|
16094
16941
|
const sealed = firstQueryValue(req.query.state);
|
|
16095
|
-
const opened = sealed === void 0 ? void 0 : openState(
|
|
16942
|
+
const opened = sealed === void 0 ? void 0 : openState(stateKey3, sealed, now());
|
|
16096
16943
|
if (!opened) {
|
|
16097
16944
|
badRequest(res, "state is missing, tampered with, or expired");
|
|
16098
16945
|
return;
|
|
@@ -16876,7 +17723,7 @@ var ApiClient = class {
|
|
|
16876
17723
|
};
|
|
16877
17724
|
|
|
16878
17725
|
// src/index.ts
|
|
16879
|
-
var MCP_VERSION = "8.
|
|
17726
|
+
var MCP_VERSION = "8.2.0";
|
|
16880
17727
|
|
|
16881
17728
|
// src/meta-upload-app.ts
|
|
16882
17729
|
import { readFileSync } from "fs";
|
|
@@ -16948,7 +17795,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
|
|
|
16948
17795
|
__name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
|
|
16949
17796
|
|
|
16950
17797
|
// src/tools/tasks.ts
|
|
16951
|
-
import { z as
|
|
17798
|
+
import { z as z77 } from "zod";
|
|
16952
17799
|
|
|
16953
17800
|
// src/resolve-image.ts
|
|
16954
17801
|
import { lookup as dnsLookup } from "dns/promises";
|
|
@@ -17509,10 +18356,10 @@ async function resolveMediaRef(ref, opts) {
|
|
|
17509
18356
|
__name(resolveMediaRef, "resolveMediaRef");
|
|
17510
18357
|
|
|
17511
18358
|
// src/tools/shared.ts
|
|
17512
|
-
import { z as
|
|
17513
|
-
var Lang =
|
|
17514
|
-
var Country =
|
|
17515
|
-
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([
|
|
17516
18363
|
"auto",
|
|
17517
18364
|
"classic",
|
|
17518
18365
|
"pain_solution",
|
|
@@ -17521,12 +18368,12 @@ var LandingStrategyEnum = z70.enum([
|
|
|
17521
18368
|
"offer_value",
|
|
17522
18369
|
"lifestyle_identity"
|
|
17523
18370
|
]);
|
|
17524
|
-
var LandingImageFormatEnum =
|
|
18371
|
+
var LandingImageFormatEnum = z74.enum([
|
|
17525
18372
|
"9:16",
|
|
17526
18373
|
"4:5",
|
|
17527
18374
|
"1:1"
|
|
17528
18375
|
]);
|
|
17529
|
-
var VideoPresetEnum =
|
|
18376
|
+
var VideoPresetEnum = z74.enum([
|
|
17530
18377
|
"auto",
|
|
17531
18378
|
"ugc_dynamic",
|
|
17532
18379
|
"ugc_how_to",
|
|
@@ -17539,21 +18386,21 @@ var VideoPresetEnum = z70.enum([
|
|
|
17539
18386
|
"pixar_problem",
|
|
17540
18387
|
"pixar_sassy"
|
|
17541
18388
|
]);
|
|
17542
|
-
var VideoStructureEnum =
|
|
18389
|
+
var VideoStructureEnum = z74.enum([
|
|
17543
18390
|
"single_take",
|
|
17544
18391
|
"multi_scene"
|
|
17545
18392
|
]);
|
|
17546
|
-
var VideoQualityEnum =
|
|
18393
|
+
var VideoQualityEnum = z74.enum([
|
|
17547
18394
|
"economy",
|
|
17548
18395
|
"medium",
|
|
17549
18396
|
"pro"
|
|
17550
18397
|
]);
|
|
17551
|
-
var VideoRouteIdEnum =
|
|
18398
|
+
var VideoRouteIdEnum = z74.enum([
|
|
17552
18399
|
"single_take",
|
|
17553
18400
|
"multi_scene",
|
|
17554
18401
|
"free"
|
|
17555
18402
|
]);
|
|
17556
|
-
var TaskCreativeVariantVideoPresetEnum =
|
|
18403
|
+
var TaskCreativeVariantVideoPresetEnum = z74.enum([
|
|
17557
18404
|
"auto",
|
|
17558
18405
|
"ugc_dynamic",
|
|
17559
18406
|
"ugc_how_to",
|
|
@@ -17570,53 +18417,43 @@ var VIDEO_PRESET_RESOLUTION = {
|
|
|
17570
18417
|
auto: null,
|
|
17571
18418
|
ugc_dynamic: {
|
|
17572
18419
|
videoStyle: "ai_dynamic",
|
|
17573
|
-
narrativeStyle: "review"
|
|
17574
|
-
videoModel: "veo"
|
|
18420
|
+
narrativeStyle: "review"
|
|
17575
18421
|
},
|
|
17576
18422
|
ugc_how_to: {
|
|
17577
18423
|
videoStyle: "ai_dynamic",
|
|
17578
|
-
narrativeStyle: "ugc_how_to"
|
|
17579
|
-
videoModel: "veo"
|
|
18424
|
+
narrativeStyle: "ugc_how_to"
|
|
17580
18425
|
},
|
|
17581
18426
|
ugc_unboxing_chaos: {
|
|
17582
18427
|
videoStyle: "ai_dynamic",
|
|
17583
|
-
narrativeStyle: "ugc_unboxing_chaos"
|
|
17584
|
-
videoModel: "veo"
|
|
18428
|
+
narrativeStyle: "ugc_unboxing_chaos"
|
|
17585
18429
|
},
|
|
17586
18430
|
problem_solution: {
|
|
17587
18431
|
videoStyle: "ai_dynamic",
|
|
17588
|
-
narrativeStyle: "problem_product_cta"
|
|
17589
|
-
videoModel: "kling"
|
|
18432
|
+
narrativeStyle: "problem_product_cta"
|
|
17590
18433
|
},
|
|
17591
18434
|
pixar_problem: {
|
|
17592
18435
|
videoStyle: "ai_dynamic",
|
|
17593
|
-
narrativeStyle: "animated_problem_pixar"
|
|
17594
|
-
videoModel: "kling"
|
|
18436
|
+
narrativeStyle: "animated_problem_pixar"
|
|
17595
18437
|
},
|
|
17596
18438
|
pixar_sassy: {
|
|
17597
18439
|
videoStyle: "ai_dynamic",
|
|
17598
|
-
narrativeStyle: "sassy_product_pixar"
|
|
17599
|
-
videoModel: "seedance"
|
|
18440
|
+
narrativeStyle: "sassy_product_pixar"
|
|
17600
18441
|
},
|
|
17601
18442
|
product_showcase: {
|
|
17602
18443
|
videoStyle: "product_only",
|
|
17603
|
-
narrativeStyle: "product_showcase"
|
|
17604
|
-
videoModel: "veo"
|
|
18444
|
+
narrativeStyle: "product_showcase"
|
|
17605
18445
|
},
|
|
17606
18446
|
wearable_showcase: {
|
|
17607
18447
|
videoStyle: "ugc",
|
|
17608
|
-
narrativeStyle: "wearable_showcase"
|
|
17609
|
-
videoModel: "veo"
|
|
18448
|
+
narrativeStyle: "wearable_showcase"
|
|
17610
18449
|
},
|
|
17611
18450
|
cinematic: {
|
|
17612
18451
|
videoStyle: "product_only",
|
|
17613
|
-
narrativeStyle: "cinematic"
|
|
17614
|
-
videoModel: "grok"
|
|
18452
|
+
narrativeStyle: "cinematic"
|
|
17615
18453
|
},
|
|
17616
18454
|
wild_card: {
|
|
17617
18455
|
videoStyle: "product_only",
|
|
17618
|
-
narrativeStyle: "wild_card"
|
|
17619
|
-
videoModel: "grok"
|
|
18456
|
+
narrativeStyle: "wild_card"
|
|
17620
18457
|
}
|
|
17621
18458
|
};
|
|
17622
18459
|
function resolveVideoPreset(preset) {
|
|
@@ -17624,7 +18461,7 @@ function resolveVideoPreset(preset) {
|
|
|
17624
18461
|
return VIDEO_PRESET_RESOLUTION[preset] ?? null;
|
|
17625
18462
|
}
|
|
17626
18463
|
__name(resolveVideoPreset, "resolveVideoPreset");
|
|
17627
|
-
var VideoTierEnum =
|
|
18464
|
+
var VideoTierEnum = z74.enum([
|
|
17628
18465
|
"basic"
|
|
17629
18466
|
]);
|
|
17630
18467
|
function resolveVideoTier(_tier) {
|
|
@@ -17664,22 +18501,22 @@ function assertSemanticVideoDurationCompatibility(structure, quality, durationSe
|
|
|
17664
18501
|
}
|
|
17665
18502
|
}
|
|
17666
18503
|
__name(assertSemanticVideoDurationCompatibility, "assertSemanticVideoDurationCompatibility");
|
|
17667
|
-
var VideoResolutionEnum =
|
|
18504
|
+
var VideoResolutionEnum = z74.enum([
|
|
17668
18505
|
"480p",
|
|
17669
18506
|
"720p"
|
|
17670
18507
|
]);
|
|
17671
|
-
var CreativeGenderEnum =
|
|
18508
|
+
var CreativeGenderEnum = z74.enum([
|
|
17672
18509
|
"female",
|
|
17673
18510
|
"male",
|
|
17674
18511
|
"mixed"
|
|
17675
18512
|
]);
|
|
17676
|
-
var VideoStyleEnum =
|
|
18513
|
+
var VideoStyleEnum = z74.enum([
|
|
17677
18514
|
"ugc",
|
|
17678
18515
|
"cartoon_3d",
|
|
17679
18516
|
"product_only",
|
|
17680
18517
|
"ai_dynamic"
|
|
17681
18518
|
]);
|
|
17682
|
-
var NarrativeStyleEnum =
|
|
18519
|
+
var NarrativeStyleEnum = z74.enum([
|
|
17683
18520
|
"review",
|
|
17684
18521
|
"ugc_how_to",
|
|
17685
18522
|
"problem_product_cta",
|
|
@@ -17697,7 +18534,7 @@ var NarrativeStyleEnum = z70.enum([
|
|
|
17697
18534
|
"ugc_demo_review",
|
|
17698
18535
|
"market"
|
|
17699
18536
|
]);
|
|
17700
|
-
var PublicNarrativeStyleEnum =
|
|
18537
|
+
var PublicNarrativeStyleEnum = z74.enum([
|
|
17701
18538
|
"review",
|
|
17702
18539
|
"ugc_how_to",
|
|
17703
18540
|
"ugc_unboxing_chaos",
|
|
@@ -17710,7 +18547,7 @@ var PublicNarrativeStyleEnum = z70.enum([
|
|
|
17710
18547
|
"sassy_product_pixar",
|
|
17711
18548
|
"market"
|
|
17712
18549
|
]);
|
|
17713
|
-
var
|
|
18550
|
+
var TaskVideoModelEnum = z74.enum([
|
|
17714
18551
|
"veo",
|
|
17715
18552
|
"wan",
|
|
17716
18553
|
"bytedance",
|
|
@@ -17718,29 +18555,29 @@ var VideoModelEnum = z70.enum([
|
|
|
17718
18555
|
"grok",
|
|
17719
18556
|
"kling"
|
|
17720
18557
|
]);
|
|
17721
|
-
var ProductReferenceUserChoiceEnum =
|
|
18558
|
+
var ProductReferenceUserChoiceEnum = z74.enum([
|
|
17722
18559
|
"same_product",
|
|
17723
18560
|
"variants",
|
|
17724
18561
|
"different_products",
|
|
17725
18562
|
"combo_distinct"
|
|
17726
18563
|
]);
|
|
17727
|
-
var ProductReferenceCandidateGroupingEnum =
|
|
18564
|
+
var ProductReferenceCandidateGroupingEnum = z74.enum([
|
|
17728
18565
|
"same_product_same_variant",
|
|
17729
18566
|
"same_product_different_variants",
|
|
17730
18567
|
"different_products",
|
|
17731
18568
|
"unclear"
|
|
17732
18569
|
]);
|
|
17733
|
-
var ProductReferenceScopeEnum =
|
|
18570
|
+
var ProductReferenceScopeEnum = z74.enum([
|
|
17734
18571
|
"base",
|
|
17735
18572
|
"video_view_pack"
|
|
17736
18573
|
]);
|
|
17737
|
-
var ProductReferenceResolutionDecisionEnum =
|
|
18574
|
+
var ProductReferenceResolutionDecisionEnum = z74.enum([
|
|
17738
18575
|
"approve",
|
|
17739
18576
|
"reject",
|
|
17740
18577
|
"observed_only",
|
|
17741
18578
|
"correct_view"
|
|
17742
18579
|
]);
|
|
17743
|
-
var ProductReferenceRejectionReasonEnum =
|
|
18580
|
+
var ProductReferenceRejectionReasonEnum = z74.enum([
|
|
17744
18581
|
"replacement_requested",
|
|
17745
18582
|
"wrong_product_identity",
|
|
17746
18583
|
"wrong_variant",
|
|
@@ -17751,13 +18588,13 @@ var ProductReferenceRejectionReasonEnum = z70.enum([
|
|
|
17751
18588
|
"not_a_product_photo",
|
|
17752
18589
|
"other"
|
|
17753
18590
|
]);
|
|
17754
|
-
var GapDurationChoiceMirror =
|
|
17755
|
-
angleIndex:
|
|
17756
|
-
recommendedSec:
|
|
17757
|
-
|
|
17758
|
-
|
|
18591
|
+
var GapDurationChoiceMirror = z74.object({
|
|
18592
|
+
angleIndex: z74.number().int().nonnegative(),
|
|
18593
|
+
recommendedSec: z74.union([
|
|
18594
|
+
z74.literal(15),
|
|
18595
|
+
z74.literal(30)
|
|
17759
18596
|
]),
|
|
17760
|
-
estimatedDeltaCredits:
|
|
18597
|
+
estimatedDeltaCredits: z74.number().int().nonnegative().optional()
|
|
17761
18598
|
});
|
|
17762
18599
|
function buildSelectedImageUrlsHash(urls) {
|
|
17763
18600
|
const input = [
|
|
@@ -17767,13 +18604,13 @@ function buildSelectedImageUrlsHash(urls) {
|
|
|
17767
18604
|
return `fnv1a:${hash.toString(16).padStart(8, "0")}:${urls.length}`;
|
|
17768
18605
|
}
|
|
17769
18606
|
__name(buildSelectedImageUrlsHash, "buildSelectedImageUrlsHash");
|
|
17770
|
-
var ImageCreativeStyleEnum =
|
|
18607
|
+
var ImageCreativeStyleEnum = z74.enum([
|
|
17771
18608
|
"studio",
|
|
17772
18609
|
"floating",
|
|
17773
18610
|
"ingredients",
|
|
17774
18611
|
"in_use"
|
|
17775
18612
|
]);
|
|
17776
|
-
var ImageCreativeArchetypeEnum =
|
|
18613
|
+
var ImageCreativeArchetypeEnum = z74.enum([
|
|
17777
18614
|
"direct_response_product_ad",
|
|
17778
18615
|
"hero_outcome",
|
|
17779
18616
|
"offer_value_prop",
|
|
@@ -17782,20 +18619,20 @@ var ImageCreativeArchetypeEnum = z70.enum([
|
|
|
17782
18619
|
"problem_solution",
|
|
17783
18620
|
"lifestyle_identity"
|
|
17784
18621
|
]);
|
|
17785
|
-
var ImageCreativeVisualTreatmentEnum =
|
|
18622
|
+
var ImageCreativeVisualTreatmentEnum = z74.enum([
|
|
17786
18623
|
"performance_product_ad",
|
|
17787
18624
|
"premium_dtc_carousel"
|
|
17788
18625
|
]);
|
|
17789
|
-
var ImageCreativeAspectRatioEnum =
|
|
18626
|
+
var ImageCreativeAspectRatioEnum = z74.enum([
|
|
17790
18627
|
"1:1",
|
|
17791
18628
|
"4:5",
|
|
17792
18629
|
"9:16",
|
|
17793
18630
|
"16:9"
|
|
17794
18631
|
]);
|
|
17795
|
-
var ImageRefSchema =
|
|
17796
|
-
url:
|
|
17797
|
-
path:
|
|
17798
|
-
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.")
|
|
17799
18636
|
}).refine((v) => [
|
|
17800
18637
|
v.url,
|
|
17801
18638
|
v.path,
|
|
@@ -17803,11 +18640,11 @@ var ImageRefSchema = z70.object({
|
|
|
17803
18640
|
].filter(Boolean).length === 1, {
|
|
17804
18641
|
message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
|
|
17805
18642
|
});
|
|
17806
|
-
var ImagesInput =
|
|
18643
|
+
var ImagesInput = z74.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
|
|
17807
18644
|
const assetCount = images.filter((image) => Boolean(image.assetId)).length;
|
|
17808
18645
|
if (assetCount > 0 && assetCount !== images.length) {
|
|
17809
18646
|
ctx.addIssue({
|
|
17810
|
-
code:
|
|
18647
|
+
code: z74.ZodIssueCode.custom,
|
|
17811
18648
|
message: "all image entries must use assetId, or all must use URL/path sources"
|
|
17812
18649
|
});
|
|
17813
18650
|
}
|
|
@@ -17875,14 +18712,14 @@ async function submitCreative(api, opts) {
|
|
|
17875
18712
|
});
|
|
17876
18713
|
}
|
|
17877
18714
|
__name(submitCreative, "submitCreative");
|
|
17878
|
-
var ResearchTargetCountryEnum =
|
|
18715
|
+
var ResearchTargetCountryEnum = z74.enum([
|
|
17879
18716
|
"CO",
|
|
17880
18717
|
"MX",
|
|
17881
18718
|
"PE",
|
|
17882
18719
|
"EC",
|
|
17883
18720
|
"CL"
|
|
17884
18721
|
]);
|
|
17885
|
-
var ResearchCategoryEnum =
|
|
18722
|
+
var ResearchCategoryEnum = z74.enum([
|
|
17886
18723
|
"auto",
|
|
17887
18724
|
"automotive",
|
|
17888
18725
|
"kitchen",
|
|
@@ -17951,7 +18788,7 @@ var OVERWRITES_EXTERNAL = {
|
|
|
17951
18788
|
idempotentHint: false,
|
|
17952
18789
|
openWorldHint: false
|
|
17953
18790
|
};
|
|
17954
|
-
var DailyControlStatusEnum =
|
|
18791
|
+
var DailyControlStatusEnum = z74.enum([
|
|
17955
18792
|
"ok",
|
|
17956
18793
|
"sales_unavailable",
|
|
17957
18794
|
"timezone_unavailable",
|
|
@@ -17964,19 +18801,19 @@ var DailyControlStatusEnum = z70.enum([
|
|
|
17964
18801
|
"product_missing",
|
|
17965
18802
|
"store_unreachable"
|
|
17966
18803
|
]);
|
|
17967
|
-
var DailyControlLightEnum =
|
|
18804
|
+
var DailyControlLightEnum = z74.enum([
|
|
17968
18805
|
"green",
|
|
17969
18806
|
"amber",
|
|
17970
18807
|
"red",
|
|
17971
18808
|
"none"
|
|
17972
18809
|
]);
|
|
17973
|
-
var DailyControlVerdictEnum =
|
|
18810
|
+
var DailyControlVerdictEnum = z74.enum([
|
|
17974
18811
|
"scale",
|
|
17975
18812
|
"hold",
|
|
17976
18813
|
"kill",
|
|
17977
18814
|
"insufficient_sample"
|
|
17978
18815
|
]);
|
|
17979
|
-
var DailyControlSourceEnum =
|
|
18816
|
+
var DailyControlSourceEnum = z74.enum([
|
|
17980
18817
|
"shopify",
|
|
17981
18818
|
"shopify_settling",
|
|
17982
18819
|
"user",
|
|
@@ -19064,29 +19901,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
|
|
|
19064
19901
|
__name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
|
|
19065
19902
|
|
|
19066
19903
|
// src/tools/media-presentation.ts
|
|
19067
|
-
import { z as
|
|
19068
|
-
var HttpsPresentationUrlSchema =
|
|
19904
|
+
import { z as z75 } from "zod";
|
|
19905
|
+
var HttpsPresentationUrlSchema = z75.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
|
|
19069
19906
|
var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
|
|
19070
19907
|
const hostname = new URL(value).hostname.toLowerCase();
|
|
19071
19908
|
return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
|
|
19072
19909
|
}, "preview URL must be owned by ProductMaker");
|
|
19073
|
-
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) =>
|
|
19074
|
-
var PresentationImageSchema =
|
|
19075
|
-
kind:
|
|
19910
|
+
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z75.number().int().positive().max(maximum), "positiveIntAtMost");
|
|
19911
|
+
var PresentationImageSchema = z75.object({
|
|
19912
|
+
kind: z75.literal("image"),
|
|
19076
19913
|
url: HttpsPresentationUrlSchema,
|
|
19077
|
-
mimeType:
|
|
19914
|
+
mimeType: z75.enum([
|
|
19078
19915
|
"image/jpeg",
|
|
19079
19916
|
"image/png"
|
|
19080
19917
|
]),
|
|
19081
19918
|
byteSize: positiveIntAtMost(5 * 1024 * 1024),
|
|
19082
19919
|
width: positiveIntAtMost(16384),
|
|
19083
19920
|
height: positiveIntAtMost(16384),
|
|
19084
|
-
alt:
|
|
19921
|
+
alt: z75.string().trim().min(1).max(240)
|
|
19085
19922
|
}).strict();
|
|
19086
19923
|
var McpMediaPresentationSchema = PresentationImageSchema;
|
|
19087
|
-
var GalleryImageSchema =
|
|
19924
|
+
var GalleryImageSchema = z75.object({
|
|
19088
19925
|
url: ProductMakerPreviewUrlSchema,
|
|
19089
|
-
alt:
|
|
19926
|
+
alt: z75.string().trim().min(1).max(240)
|
|
19090
19927
|
});
|
|
19091
19928
|
var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
|
|
19092
19929
|
async function imageBlocks(image, transport) {
|
|
@@ -19236,10 +20073,10 @@ ${summary}`,
|
|
|
19236
20073
|
__name(requirePaidCreativeConfirmation, "requirePaidCreativeConfirmation");
|
|
19237
20074
|
|
|
19238
20075
|
// src/tools/winning-product-image.ts
|
|
19239
|
-
import { z as
|
|
19240
|
-
var WinnerReferenceInput =
|
|
19241
|
-
runId:
|
|
19242
|
-
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)
|
|
19243
20080
|
}).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
|
|
19244
20081
|
async function resolveWinnerImages(api, winnerReference, images) {
|
|
19245
20082
|
if (!winnerReference) return images;
|
|
@@ -19276,189 +20113,190 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
|
|
|
19276
20113
|
var createServiceVideoGuidance = getProductMakerCapabilityModelGuidance("create_service_video");
|
|
19277
20114
|
var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
|
|
19278
20115
|
var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
|
|
19279
|
-
var CreateProductTaskInput =
|
|
20116
|
+
var CreateProductTaskInput = z77.object({
|
|
19280
20117
|
images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
|
|
19281
20118
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
19282
|
-
projectId:
|
|
19283
|
-
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."),
|
|
19284
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.'),
|
|
19285
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.'),
|
|
19286
|
-
price:
|
|
19287
|
-
compareAtPrice:
|
|
19288
|
-
offer:
|
|
19289
|
-
paymentMethods:
|
|
19290
|
-
productContext:
|
|
19291
|
-
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.'),
|
|
19292
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.'),
|
|
19293
|
-
durationSeconds:
|
|
19294
|
-
|
|
19295
|
-
|
|
20130
|
+
durationSeconds: z77.union([
|
|
20131
|
+
z77.literal(15),
|
|
20132
|
+
z77.literal(30)
|
|
19296
20133
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
19297
|
-
pauseForAngleReview:
|
|
19298
|
-
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."),
|
|
19299
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.'),
|
|
19300
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.'),
|
|
19301
20138
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
19302
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).'),
|
|
19303
|
-
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."),
|
|
19304
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.'),
|
|
19305
|
-
outputs:
|
|
20142
|
+
outputs: z77.array(z77.enum([
|
|
19306
20143
|
"landing",
|
|
19307
20144
|
"video",
|
|
19308
20145
|
"image"
|
|
19309
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}`),
|
|
19310
|
-
competitorScanEnabled:
|
|
19311
|
-
replicateWinnerWhenFound:
|
|
19312
|
-
brandId:
|
|
19313
|
-
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."),
|
|
19314
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.'),
|
|
19315
|
-
creativeDirection:
|
|
19316
|
-
headline:
|
|
19317
|
-
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."),
|
|
19318
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".'),
|
|
19319
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".')
|
|
19320
20157
|
}).strict();
|
|
19321
|
-
var CreateServiceVideoInput =
|
|
19322
|
-
landingUrl:
|
|
19323
|
-
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.'),
|
|
19324
20161
|
language: Lang.describe("Idioma del video: es, en o pt."),
|
|
19325
|
-
voiceId:
|
|
19326
|
-
brandId:
|
|
19327
|
-
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([
|
|
19328
20165
|
"automatic",
|
|
19329
20166
|
"guided"
|
|
19330
20167
|
]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
|
|
19331
|
-
videoPreset:
|
|
20168
|
+
videoPreset: z77.enum([
|
|
19332
20169
|
"auto",
|
|
19333
20170
|
"ugc_dynamic",
|
|
19334
20171
|
"ugc_how_to",
|
|
19335
20172
|
"cinematic",
|
|
19336
20173
|
"wild_card"
|
|
19337
20174
|
]).default("auto"),
|
|
19338
|
-
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.')
|
|
20175
|
+
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
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.')
|
|
19339
20177
|
}).strict();
|
|
19340
|
-
var GetTaskStatusInput =
|
|
19341
|
-
taskId:
|
|
19342
|
-
waitSeconds:
|
|
20178
|
+
var GetTaskStatusInput = z77.object({
|
|
20179
|
+
taskId: z77.string().min(1),
|
|
20180
|
+
waitSeconds: z77.number().int().min(0).max(120).optional()
|
|
19343
20181
|
});
|
|
19344
|
-
var ListTasksInput =
|
|
19345
|
-
limit:
|
|
19346
|
-
offset:
|
|
19347
|
-
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()
|
|
19348
20186
|
});
|
|
19349
20187
|
var MCP_REVIEW_LIST_FIELD_MAX = 1500;
|
|
19350
20188
|
var MCP_REVIEW_FEATURE_ITEM_MAX = 240;
|
|
19351
|
-
var EditTaskDraftInput =
|
|
19352
|
-
taskId:
|
|
19353
|
-
angleIndex:
|
|
19354
|
-
angle:
|
|
19355
|
-
angle:
|
|
19356
|
-
buyerPersona:
|
|
19357
|
-
actor:
|
|
19358
|
-
actorId:
|
|
19359
|
-
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([
|
|
19360
20198
|
"female",
|
|
19361
20199
|
"male"
|
|
19362
20200
|
]).optional(),
|
|
19363
|
-
scriptNotes:
|
|
20201
|
+
scriptNotes: z77.string().max(2e3).optional()
|
|
19364
20202
|
})
|
|
19365
20203
|
});
|
|
19366
|
-
var PendingActionPayload =
|
|
19367
|
-
|
|
19368
|
-
kind:
|
|
20204
|
+
var PendingActionPayload = z77.discriminatedUnion("kind", [
|
|
20205
|
+
z77.object({
|
|
20206
|
+
kind: z77.literal("product_reference_set_approval"),
|
|
19369
20207
|
scope: ProductReferenceScopeEnum.optional(),
|
|
19370
|
-
scopeKey:
|
|
19371
|
-
scopeSnapshotId:
|
|
19372
|
-
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(),
|
|
19373
20211
|
decision: ProductReferenceResolutionDecisionEnum,
|
|
19374
20212
|
reason: ProductReferenceRejectionReasonEnum.optional(),
|
|
19375
|
-
affectedRefKeys:
|
|
19376
|
-
affectedPhotoNumbers:
|
|
19377
|
-
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([
|
|
19378
20216
|
"remove",
|
|
19379
20217
|
"replace",
|
|
19380
20218
|
"upload",
|
|
19381
20219
|
"return_to_selection"
|
|
19382
20220
|
]).optional()
|
|
19383
20221
|
}),
|
|
19384
|
-
|
|
19385
|
-
kind:
|
|
19386
|
-
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."),
|
|
19387
20225
|
userChoice: ProductReferenceUserChoiceEnum.optional(),
|
|
19388
|
-
confirmedProductNames:
|
|
20226
|
+
confirmedProductNames: z77.array(z77.string().min(1).max(120)).min(2).max(8).optional(),
|
|
19389
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."),
|
|
19390
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."),
|
|
19391
|
-
useMultiSceneShowcase:
|
|
20229
|
+
useMultiSceneShowcase: z77.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
|
|
19392
20230
|
}),
|
|
19393
|
-
|
|
19394
|
-
kind:
|
|
20231
|
+
z77.object({
|
|
20232
|
+
kind: z77.literal("angle_review_approval"),
|
|
19395
20233
|
// All edits are optional — empty action body just approves the
|
|
19396
20234
|
// backend-generated draft as-is. Field shapes mirror the angle-review
|
|
19397
20235
|
// request contracts in @packages/types/wizard.ts; the handler routes to
|
|
19398
20236
|
// the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
|
|
19399
|
-
customAngle:
|
|
20237
|
+
customAngle: z77.string().min(1).max(480).optional(),
|
|
19400
20238
|
// Keep the shared MCP action within the strictest downstream contract:
|
|
19401
20239
|
// autopilot/image resume endpoints cap these fields at 1500 characters.
|
|
19402
|
-
painPoints:
|
|
19403
|
-
benefits:
|
|
20240
|
+
painPoints: z77.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
20241
|
+
benefits: z77.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
19404
20242
|
// Same policy as the two fields above: the strictest downstream contract
|
|
19405
20243
|
// wins. The image endpoint caps each feature at 240 while landing/video
|
|
19406
20244
|
// accept 300, and this single action routes to whichever the task is — so
|
|
19407
20245
|
// accepting 300 here turns a 250-character feature on an image task into
|
|
19408
20246
|
// an opaque HTTP 400 after the model already believed it had been saved.
|
|
19409
|
-
features:
|
|
19410
|
-
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(),
|
|
19411
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.'),
|
|
19412
|
-
actor:
|
|
19413
|
-
actorId:
|
|
19414
|
-
creativeDirection:
|
|
19415
|
-
selectedAngleNumbers:
|
|
19416
|
-
angleEdits:
|
|
19417
|
-
angleNumber:
|
|
19418
|
-
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([
|
|
19419
20257
|
"market",
|
|
19420
20258
|
"guided"
|
|
19421
20259
|
]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
|
|
19422
|
-
angle:
|
|
19423
|
-
buyerPersona:
|
|
20260
|
+
angle: z77.string().min(1).max(480).optional(),
|
|
20261
|
+
buyerPersona: z77.string().min(1).max(360).optional(),
|
|
19424
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.'),
|
|
19425
|
-
actor:
|
|
19426
|
-
actorId:
|
|
19427
|
-
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()
|
|
19428
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)."),
|
|
19429
|
-
gapDurationSeconds:
|
|
19430
|
-
|
|
19431
|
-
|
|
20267
|
+
gapDurationSeconds: z77.union([
|
|
20268
|
+
z77.literal(15),
|
|
20269
|
+
z77.literal(30)
|
|
19432
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.")
|
|
19433
20271
|
}),
|
|
19434
|
-
|
|
19435
|
-
kind:
|
|
19436
|
-
angleId:
|
|
19437
|
-
angleNumber:
|
|
19438
|
-
content:
|
|
19439
|
-
creativeDirection:
|
|
19440
|
-
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()
|
|
19441
20279
|
}),
|
|
19442
|
-
|
|
19443
|
-
kind:
|
|
19444
|
-
voiceovers:
|
|
19445
|
-
visualDirections:
|
|
19446
|
-
voiceoversByScene:
|
|
19447
|
-
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()
|
|
19448
20286
|
})
|
|
19449
20287
|
]);
|
|
19450
|
-
var ResolvePendingActionInput =
|
|
19451
|
-
taskId:
|
|
20288
|
+
var ResolvePendingActionInput = z77.object({
|
|
20289
|
+
taskId: z77.string().min(1),
|
|
19452
20290
|
action: PendingActionPayload
|
|
19453
20291
|
}).strict();
|
|
19454
20292
|
function resolveVariantConfirmVideoTier(action) {
|
|
19455
20293
|
return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
|
|
19456
20294
|
}
|
|
19457
20295
|
__name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
|
|
19458
|
-
var StatusForResolveSchema =
|
|
20296
|
+
var StatusForResolveSchema = z77.object({
|
|
19459
20297
|
// Metadata used to select the backend resume contract. Older API responses
|
|
19460
20298
|
// may omit these fields, so the resolver keeps the generic fallback.
|
|
19461
|
-
kind:
|
|
20299
|
+
kind: z77.enum([
|
|
19462
20300
|
"autopilot",
|
|
19463
20301
|
"video",
|
|
19464
20302
|
"image",
|
|
@@ -19466,18 +20304,18 @@ var StatusForResolveSchema = z73.object({
|
|
|
19466
20304
|
"mix",
|
|
19467
20305
|
"service"
|
|
19468
20306
|
]).optional(),
|
|
19469
|
-
selectedOutputs:
|
|
20307
|
+
selectedOutputs: z77.array(z77.enum([
|
|
19470
20308
|
"landing",
|
|
19471
20309
|
"video",
|
|
19472
20310
|
"image"
|
|
19473
20311
|
])).optional(),
|
|
19474
|
-
videoAngleCount:
|
|
19475
|
-
ugcFormat:
|
|
20312
|
+
videoAngleCount: z77.number().int().min(1).max(3).optional(),
|
|
20313
|
+
ugcFormat: z77.enum([
|
|
19476
20314
|
"single_8s",
|
|
19477
20315
|
"single_15s",
|
|
19478
20316
|
"double_30s"
|
|
19479
20317
|
]).optional(),
|
|
19480
|
-
videoStyle:
|
|
20318
|
+
videoStyle: z77.enum([
|
|
19481
20319
|
"ugc",
|
|
19482
20320
|
"cartoon_3d",
|
|
19483
20321
|
"product_only",
|
|
@@ -19486,79 +20324,72 @@ var StatusForResolveSchema = z73.object({
|
|
|
19486
20324
|
videoStructure: VideoStructureEnum.optional(),
|
|
19487
20325
|
videoQuality: VideoQualityEnum.optional(),
|
|
19488
20326
|
videoRouteId: VideoRouteIdEnum.optional(),
|
|
19489
|
-
videoModel:
|
|
19490
|
-
|
|
19491
|
-
"wan",
|
|
19492
|
-
"bytedance",
|
|
19493
|
-
"seedance",
|
|
19494
|
-
"grok",
|
|
19495
|
-
"kling"
|
|
19496
|
-
]).optional(),
|
|
19497
|
-
videoTier: z73.enum([
|
|
20327
|
+
videoModel: TaskVideoModelEnum.optional(),
|
|
20328
|
+
videoTier: z77.enum([
|
|
19498
20329
|
"legacy",
|
|
19499
20330
|
"standard",
|
|
19500
20331
|
"pro",
|
|
19501
20332
|
"single_call"
|
|
19502
20333
|
]).optional(),
|
|
19503
|
-
videoResolution:
|
|
20334
|
+
videoResolution: z77.enum([
|
|
19504
20335
|
"480p",
|
|
19505
20336
|
"720p"
|
|
19506
20337
|
]).optional(),
|
|
19507
20338
|
narrativeStyle: NarrativeStyleEnum.optional(),
|
|
19508
|
-
pauseForVideoScriptReview:
|
|
19509
|
-
pendingUserAction:
|
|
19510
|
-
kind:
|
|
19511
|
-
candidateGrouping:
|
|
19512
|
-
selectedImageUrls:
|
|
19513
|
-
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(),
|
|
19514
20345
|
// Adaptive reference questions are server-owned. Echo only the evidence
|
|
19515
20346
|
// identity and the choices shown by the current snapshot; never accept a
|
|
19516
20347
|
// client-supplied reference set as authorization.
|
|
19517
|
-
options:
|
|
19518
|
-
mode:
|
|
20348
|
+
options: z77.array(ProductReferenceUserChoiceEnum).max(4).optional(),
|
|
20349
|
+
mode: z77.enum([
|
|
19519
20350
|
"question",
|
|
19520
20351
|
"visual_recovery"
|
|
19521
20352
|
]).optional(),
|
|
19522
20353
|
/** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
|
|
19523
|
-
canKeepSelection:
|
|
19524
|
-
decisionKey:
|
|
19525
|
-
questionOrdinal:
|
|
19526
|
-
questionCeiling:
|
|
19527
|
-
|
|
19528
|
-
|
|
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)
|
|
19529
20360
|
]).optional(),
|
|
19530
|
-
referenceEvidenceVersion:
|
|
19531
|
-
expectedEvidenceHash:
|
|
19532
|
-
question:
|
|
19533
|
-
prompt:
|
|
19534
|
-
helpText:
|
|
19535
|
-
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({
|
|
19536
20367
|
value: ProductReferenceUserChoiceEnum,
|
|
19537
|
-
label:
|
|
19538
|
-
description:
|
|
20368
|
+
label: z77.string().min(1).max(120),
|
|
20369
|
+
description: z77.string().min(1).max(240).optional()
|
|
19539
20370
|
})).min(2).max(4)
|
|
19540
20371
|
}).optional(),
|
|
19541
20372
|
scope: ProductReferenceScopeEnum.optional(),
|
|
19542
|
-
scopeKey:
|
|
19543
|
-
scopeSnapshotId:
|
|
19544
|
-
scopeHash:
|
|
19545
|
-
baseReferenceSetHash:
|
|
19546
|
-
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([
|
|
19547
20378
|
"preparation",
|
|
19548
20379
|
"final"
|
|
19549
20380
|
]).optional(),
|
|
19550
|
-
selectedRefKeys:
|
|
19551
|
-
allowedDecisions:
|
|
19552
|
-
previews:
|
|
19553
|
-
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)
|
|
19554
20385
|
}).passthrough()).optional(),
|
|
19555
|
-
customAngleDraft:
|
|
19556
|
-
painPointsDraft:
|
|
19557
|
-
benefitsDraft:
|
|
19558
|
-
featuresDraft:
|
|
19559
|
-
angleOptions:
|
|
19560
|
-
index:
|
|
19561
|
-
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)
|
|
19562
20393
|
}).passthrough()).min(1).max(5).optional(),
|
|
19563
20394
|
// Recommendation consumed only when the caller explicitly sends
|
|
19564
20395
|
// gapDurationSeconds: 30 in the angle approval action.
|
|
@@ -19568,17 +20399,17 @@ var StatusForResolveSchema = z73.object({
|
|
|
19568
20399
|
// keys. `actorId` (the saved custom actor the picker stored) was silently
|
|
19569
20400
|
// dropped here, so the approval handler below could not echo it back on the
|
|
19570
20401
|
// PATCH — the selection looked accepted and reached no render.
|
|
19571
|
-
angles:
|
|
19572
|
-
id:
|
|
19573
|
-
content:
|
|
19574
|
-
creativeDirection:
|
|
19575
|
-
actor:
|
|
19576
|
-
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()
|
|
19577
20408
|
}).passthrough()).optional(),
|
|
19578
|
-
panels:
|
|
19579
|
-
beatId:
|
|
19580
|
-
voiceover:
|
|
19581
|
-
visualDirection:
|
|
20409
|
+
panels: z77.array(z77.object({
|
|
20410
|
+
beatId: z77.string(),
|
|
20411
|
+
voiceover: z77.string(),
|
|
20412
|
+
visualDirection: z77.string()
|
|
19582
20413
|
}).passthrough()).optional()
|
|
19583
20414
|
}).optional()
|
|
19584
20415
|
}).passthrough();
|
|
@@ -19792,6 +20623,9 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
19792
20623
|
});
|
|
19793
20624
|
server.tool("create_service_video", createServiceVideoGuidance.summary + " Esta acci\xF3n consume cr\xE9ditos: confirma la intenci\xF3n del usuario antes de llamarla. `automatic` genera directamente; `guided` devuelve conceptos para que el usuario apruebe uno mediante `resolve_pending_action`. La web tambi\xE9n acepta demos y anuncios de referencia; el transporte MCP de video adjunto todav\xEDa falla cerrado hasta poder subir bytes de forma segura.", CreateServiceVideoInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
|
|
19794
20625
|
try {
|
|
20626
|
+
if (input.videoQuality === "medium" && input.videoResolution === "720p") {
|
|
20627
|
+
throw mcp(McpErrorCode.INVALID_INPUT, 'videoResolution "720p" no est\xE1 disponible con videoQuality "medium" en videos de servicio (Medio = 768P). Usa "480p" o elige "economy"/"pro".');
|
|
20628
|
+
}
|
|
19795
20629
|
await requirePaidCreativeConfirmation(server, `Video de servicio en ${input.language}. Modo: ${input.reviewMode === "automatic" ? "la IA decide todo" : "reviews conversacionales"}.`);
|
|
19796
20630
|
const created = await api.postJson("/v2/ingest", {
|
|
19797
20631
|
taskType: "service",
|
|
@@ -19805,6 +20639,7 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
19805
20639
|
} : {},
|
|
19806
20640
|
videoPreset: input.videoPreset,
|
|
19807
20641
|
videoQuality: input.videoQuality,
|
|
20642
|
+
videoResolution: input.videoResolution,
|
|
19808
20643
|
reviewMode: input.reviewMode,
|
|
19809
20644
|
...input.brandId ? {
|
|
19810
20645
|
brandId: input.brandId
|
|
@@ -20409,7 +21244,7 @@ __name(registerTaskTools, "registerTaskTools");
|
|
|
20409
21244
|
|
|
20410
21245
|
// src/tools/creatives.ts
|
|
20411
21246
|
import { randomUUID } from "crypto";
|
|
20412
|
-
import { z as
|
|
21247
|
+
import { z as z78 } from "zod";
|
|
20413
21248
|
var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
|
|
20414
21249
|
var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
|
|
20415
21250
|
var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
|
|
@@ -20419,70 +21254,70 @@ var CreativeRefs = {
|
|
|
20419
21254
|
images: ImagesInput,
|
|
20420
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.'),
|
|
20421
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.'),
|
|
20422
|
-
price:
|
|
20423
|
-
offer:
|
|
20424
|
-
compareAtPrice:
|
|
20425
|
-
productContext:
|
|
20426
|
-
productLabel:
|
|
20427
|
-
buyerPersona:
|
|
20428
|
-
isCombo:
|
|
20429
|
-
competitorScanEnabled:
|
|
20430
|
-
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.")
|
|
20431
21266
|
};
|
|
20432
|
-
var VideoPresenter =
|
|
20433
|
-
|
|
20434
|
-
mode:
|
|
21267
|
+
var VideoPresenter = z78.discriminatedUnion("mode", [
|
|
21268
|
+
z78.object({
|
|
21269
|
+
mode: z78.literal("none")
|
|
20435
21270
|
}).strict(),
|
|
20436
|
-
|
|
20437
|
-
mode:
|
|
20438
|
-
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.")
|
|
20439
21274
|
}).strict(),
|
|
20440
|
-
|
|
20441
|
-
mode:
|
|
20442
|
-
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.")
|
|
20443
21278
|
}).strict()
|
|
20444
21279
|
]);
|
|
20445
|
-
var VideoCreativeSetup =
|
|
20446
|
-
|
|
20447
|
-
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".')
|
|
20448
21283
|
}).strict(),
|
|
20449
|
-
|
|
20450
|
-
mode:
|
|
21284
|
+
z78.object({
|
|
21285
|
+
mode: z78.literal("guided"),
|
|
20451
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.'),
|
|
20452
|
-
buyerPersona:
|
|
21287
|
+
buyerPersona: z78.string().trim().min(1).max(360),
|
|
20453
21288
|
presenter: VideoPresenter,
|
|
20454
|
-
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.")
|
|
20455
21290
|
}).strict()
|
|
20456
21291
|
]);
|
|
20457
|
-
var VideoInput =
|
|
21292
|
+
var VideoInput = z78.object({
|
|
20458
21293
|
images: CreativeRefs.images.optional(),
|
|
20459
21294
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
20460
|
-
title:
|
|
20461
|
-
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".'),
|
|
20462
21297
|
language: CreativeRefs.language,
|
|
20463
21298
|
country: CreativeRefs.country,
|
|
20464
|
-
aspectRatio:
|
|
21299
|
+
aspectRatio: z78.enum([
|
|
20465
21300
|
"9:16",
|
|
20466
21301
|
"16:9",
|
|
20467
21302
|
"Auto"
|
|
20468
21303
|
]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
|
|
20469
|
-
durationSeconds:
|
|
20470
|
-
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."),
|
|
20471
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.'),
|
|
20472
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."),
|
|
20473
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.'),
|
|
20474
21309
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
|
|
20475
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.'),
|
|
20476
|
-
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"].'),
|
|
20477
21312
|
price: CreativeRefs.price,
|
|
20478
21313
|
offer: CreativeRefs.offer,
|
|
20479
21314
|
productContext: CreativeRefs.productContext,
|
|
20480
21315
|
productLabel: CreativeRefs.productLabel,
|
|
20481
|
-
cta:
|
|
20482
|
-
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.'),
|
|
20483
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.'),
|
|
20484
21319
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
20485
|
-
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."),
|
|
20486
21321
|
brandId: CreativeRefs.brandId
|
|
20487
21322
|
}).strict();
|
|
20488
21323
|
var FreeVideoQualityEnum = VideoQualityEnum;
|
|
@@ -20500,7 +21335,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
|
|
|
20500
21335
|
length: 29
|
|
20501
21336
|
}, (_, index) => index + 2)
|
|
20502
21337
|
};
|
|
20503
|
-
var FreeVideoModelIdEnum =
|
|
21338
|
+
var FreeVideoModelIdEnum = z78.enum([
|
|
20504
21339
|
"grok-imagine-video-1-5-preview",
|
|
20505
21340
|
"minimax-h3/reference-to-video",
|
|
20506
21341
|
"wan/3-0-video",
|
|
@@ -20511,70 +21346,65 @@ var FREE_SELECTABLE_MODEL_IDS = [
|
|
|
20511
21346
|
"minimax-h3/reference-to-video",
|
|
20512
21347
|
"wan/3-0-video"
|
|
20513
21348
|
];
|
|
20514
|
-
var FreeVideoInput =
|
|
21349
|
+
var FreeVideoInput = z78.object({
|
|
20515
21350
|
images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
|
|
20516
|
-
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."),
|
|
20517
21352
|
language: CreativeRefs.language,
|
|
20518
21353
|
quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
|
|
20519
21354
|
// Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
|
|
20520
21355
|
// parsed ONLY so the handler can reject it with a message naming its
|
|
20521
21356
|
// replacement — dropping it silently would turn a caller's explicit
|
|
20522
21357
|
// Pro++ pick into a quiet fallback to Wan.
|
|
20523
|
-
freeProModel:
|
|
21358
|
+
freeProModel: z78.enum([
|
|
20524
21359
|
"wan",
|
|
20525
21360
|
"seedance"
|
|
20526
21361
|
]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
|
|
20527
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.'),
|
|
20528
|
-
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."),
|
|
20529
21364
|
videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
|
|
20530
|
-
generateAiMusic:
|
|
20531
|
-
addSubtitles:
|
|
20532
|
-
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.")
|
|
20533
21368
|
}).strict();
|
|
20534
21369
|
var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
|
|
20535
|
-
var ImageCreativeSetup =
|
|
20536
|
-
|
|
20537
|
-
mode:
|
|
21370
|
+
var ImageCreativeSetup = z78.discriminatedUnion("mode", [
|
|
21371
|
+
z78.object({
|
|
21372
|
+
mode: z78.literal("automatic")
|
|
20538
21373
|
}).strict(),
|
|
20539
|
-
|
|
20540
|
-
mode:
|
|
20541
|
-
creativeArchetype:
|
|
21374
|
+
z78.object({
|
|
21375
|
+
mode: z78.literal("guided"),
|
|
21376
|
+
creativeArchetype: z78.union([
|
|
20542
21377
|
ImageCreativeArchetypeEnum,
|
|
20543
|
-
|
|
21378
|
+
z78.literal("ai_decides")
|
|
20544
21379
|
]),
|
|
20545
|
-
visualTreatment:
|
|
21380
|
+
visualTreatment: z78.union([
|
|
20546
21381
|
ImageCreativeVisualTreatmentEnum,
|
|
20547
|
-
|
|
21382
|
+
z78.literal("ai_decides")
|
|
20548
21383
|
]),
|
|
20549
21384
|
aspectRatio: ImageCreativeAspectRatioEnum,
|
|
20550
|
-
nVariants:
|
|
20551
|
-
|
|
20552
|
-
|
|
20553
|
-
|
|
20554
|
-
|
|
20555
|
-
|
|
20556
|
-
]),
|
|
20557
|
-
imageModel: z74.enum([
|
|
20558
|
-
"gpt-image-2-5:1k",
|
|
20559
|
-
"gpt-image-2-5:2k",
|
|
20560
|
-
"gpt-image-2:1k",
|
|
20561
|
-
"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)
|
|
20562
21391
|
]),
|
|
20563
|
-
|
|
20564
|
-
|
|
20565
|
-
|
|
20566
|
-
|
|
20567
|
-
|
|
20568
|
-
|
|
20569
|
-
|
|
20570
|
-
|
|
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()
|
|
20571
21401
|
}).strict()
|
|
20572
21402
|
]).superRefine((setup, context) => {
|
|
20573
21403
|
if (setup.mode !== "guided") return;
|
|
20574
21404
|
const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
|
|
20575
21405
|
if (needsStyleMix && setup.styleMix === null) {
|
|
20576
21406
|
context.addIssue({
|
|
20577
|
-
code:
|
|
21407
|
+
code: z78.ZodIssueCode.custom,
|
|
20578
21408
|
path: [
|
|
20579
21409
|
"styleMix"
|
|
20580
21410
|
],
|
|
@@ -20583,16 +21413,16 @@ var ImageCreativeSetup = z74.discriminatedUnion("mode", [
|
|
|
20583
21413
|
}
|
|
20584
21414
|
if (!needsStyleMix && setup.styleMix !== null) {
|
|
20585
21415
|
context.addIssue({
|
|
20586
|
-
code:
|
|
21416
|
+
code: z78.ZodIssueCode.custom,
|
|
20587
21417
|
path: [
|
|
20588
21418
|
"styleMix"
|
|
20589
21419
|
],
|
|
20590
21420
|
message: "styleMix debe ser null cuando nVariants es 1 o 6."
|
|
20591
21421
|
});
|
|
20592
21422
|
}
|
|
20593
|
-
if ((setup.imageModel === "
|
|
21423
|
+
if (imageResolutionOf(setup.imageModel) === "2k" && setup.aspectRatio === "4:5") {
|
|
20594
21424
|
context.addIssue({
|
|
20595
|
-
code:
|
|
21425
|
+
code: z78.ZodIssueCode.custom,
|
|
20596
21426
|
path: [
|
|
20597
21427
|
"aspectRatio"
|
|
20598
21428
|
],
|
|
@@ -20600,53 +21430,53 @@ var ImageCreativeSetup = z74.discriminatedUnion("mode", [
|
|
|
20600
21430
|
});
|
|
20601
21431
|
}
|
|
20602
21432
|
});
|
|
20603
|
-
var LandingCreativeSetup =
|
|
20604
|
-
|
|
20605
|
-
mode:
|
|
21433
|
+
var LandingCreativeSetup = z78.discriminatedUnion("mode", [
|
|
21434
|
+
z78.object({
|
|
21435
|
+
mode: z78.literal("automatic")
|
|
20606
21436
|
}).strict(),
|
|
20607
|
-
|
|
20608
|
-
mode:
|
|
21437
|
+
z78.object({
|
|
21438
|
+
mode: z78.literal("guided"),
|
|
20609
21439
|
landingStrategy: LandingStrategyEnum,
|
|
20610
21440
|
landingImageFormat: LandingImageFormatEnum,
|
|
20611
|
-
competitorScanEnabled:
|
|
20612
|
-
paymentMethods:
|
|
20613
|
-
productContext:
|
|
20614
|
-
creativeDirection:
|
|
20615
|
-
headline:
|
|
20616
|
-
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()
|
|
20617
21447
|
}).strict()
|
|
20618
21448
|
]);
|
|
20619
|
-
var ImageInput =
|
|
21449
|
+
var ImageInput = z78.object({
|
|
20620
21450
|
images: CreativeRefs.images.optional(),
|
|
20621
21451
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
20622
|
-
productTitle:
|
|
20623
|
-
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.'),
|
|
20624
21454
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
20625
21455
|
language: CreativeRefs.language,
|
|
20626
21456
|
country: CreativeRefs.country,
|
|
20627
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."),
|
|
20628
21458
|
imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
|
|
20629
|
-
features:
|
|
21459
|
+
features: z78.array(z78.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
|
|
20630
21460
|
price: CreativeRefs.price,
|
|
20631
|
-
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."),
|
|
20632
21462
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
20633
21463
|
offer: CreativeRefs.offer,
|
|
20634
21464
|
productLabel: CreativeRefs.productLabel,
|
|
20635
21465
|
isCombo: CreativeRefs.isCombo,
|
|
20636
21466
|
brandId: CreativeRefs.brandId
|
|
20637
21467
|
});
|
|
20638
|
-
var EditImageCreativeInput =
|
|
20639
|
-
taskId:
|
|
20640
|
-
variantIndex:
|
|
20641
|
-
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".')
|
|
20642
21472
|
});
|
|
20643
|
-
var LandingInput =
|
|
21473
|
+
var LandingInput = z78.object({
|
|
20644
21474
|
images: CreativeRefs.images.optional(),
|
|
20645
21475
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
20646
21476
|
language: CreativeRefs.language,
|
|
20647
21477
|
country: CreativeRefs.country,
|
|
20648
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."),
|
|
20649
|
-
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.'),
|
|
20650
21480
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
20651
21481
|
price: CreativeRefs.price,
|
|
20652
21482
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
@@ -20665,7 +21495,7 @@ function resolveImageSetup(setup) {
|
|
|
20665
21495
|
},
|
|
20666
21496
|
aspectRatio: setup.aspectRatio,
|
|
20667
21497
|
nVariants: setup.nVariants,
|
|
20668
|
-
imageModel: setup.imageModel,
|
|
21498
|
+
imageModel: canonicalImageModelInput(setup.imageModel),
|
|
20669
21499
|
...setup.nVariants === 6 ? {
|
|
20670
21500
|
styleMix: true
|
|
20671
21501
|
} : setup.styleMix === null ? {} : {
|
|
@@ -20908,10 +21738,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
20908
21738
|
__name(registerCreativeTools, "registerCreativeTools");
|
|
20909
21739
|
|
|
20910
21740
|
// src/tools/creative-variants.ts
|
|
20911
|
-
import { z as
|
|
21741
|
+
import { z as z79 } from "zod";
|
|
20912
21742
|
var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
|
|
20913
21743
|
var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
|
|
20914
|
-
var LandingSectionKeyEnum =
|
|
21744
|
+
var LandingSectionKeyEnum = z79.enum([
|
|
20915
21745
|
"problem_hook",
|
|
20916
21746
|
"problem_cost",
|
|
20917
21747
|
"solution_mechanism",
|
|
@@ -20951,24 +21781,24 @@ var LandingSectionKeyEnum = z75.enum([
|
|
|
20951
21781
|
"lifestyle_fit",
|
|
20952
21782
|
"join_lifestyle"
|
|
20953
21783
|
]);
|
|
20954
|
-
var CreativeVariantKindEnum =
|
|
21784
|
+
var CreativeVariantKindEnum = z79.enum([
|
|
20955
21785
|
"video",
|
|
20956
21786
|
"image",
|
|
20957
21787
|
"landing"
|
|
20958
21788
|
]);
|
|
20959
|
-
var EstimateCreativeVariantInputBase =
|
|
20960
|
-
sourceTaskId:
|
|
21789
|
+
var EstimateCreativeVariantInputBase = z79.object({
|
|
21790
|
+
sourceTaskId: z79.string().uuid().describe("ID de la tarea original completada."),
|
|
20961
21791
|
kind: CreativeVariantKindEnum,
|
|
20962
21792
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
|
|
20963
21793
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
|
|
20964
|
-
nVariants:
|
|
21794
|
+
nVariants: z79.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
20965
21795
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
|
|
20966
|
-
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.")
|
|
20967
21797
|
}).strict();
|
|
20968
21798
|
var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
20969
21799
|
if (input.kind === "video" && input.nVariants !== void 0) {
|
|
20970
21800
|
ctx.addIssue({
|
|
20971
|
-
code:
|
|
21801
|
+
code: z79.ZodIssueCode.custom,
|
|
20972
21802
|
path: [
|
|
20973
21803
|
"nVariants"
|
|
20974
21804
|
],
|
|
@@ -20978,7 +21808,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
20978
21808
|
if (input.kind !== "video") {
|
|
20979
21809
|
if (input.videoPreset !== void 0) {
|
|
20980
21810
|
ctx.addIssue({
|
|
20981
|
-
code:
|
|
21811
|
+
code: z79.ZodIssueCode.custom,
|
|
20982
21812
|
path: [
|
|
20983
21813
|
"videoPreset"
|
|
20984
21814
|
],
|
|
@@ -20987,7 +21817,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
20987
21817
|
}
|
|
20988
21818
|
if (input.videoResolution !== void 0) {
|
|
20989
21819
|
ctx.addIssue({
|
|
20990
|
-
code:
|
|
21820
|
+
code: z79.ZodIssueCode.custom,
|
|
20991
21821
|
path: [
|
|
20992
21822
|
"videoResolution"
|
|
20993
21823
|
],
|
|
@@ -20997,7 +21827,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
20997
21827
|
}
|
|
20998
21828
|
if (input.kind !== "image" && input.nVariants !== void 0) {
|
|
20999
21829
|
ctx.addIssue({
|
|
21000
|
-
code:
|
|
21830
|
+
code: z79.ZodIssueCode.custom,
|
|
21001
21831
|
path: [
|
|
21002
21832
|
"nVariants"
|
|
21003
21833
|
],
|
|
@@ -21007,7 +21837,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
21007
21837
|
if (input.kind !== "landing") {
|
|
21008
21838
|
if (input.sectionKey !== void 0) {
|
|
21009
21839
|
ctx.addIssue({
|
|
21010
|
-
code:
|
|
21840
|
+
code: z79.ZodIssueCode.custom,
|
|
21011
21841
|
path: [
|
|
21012
21842
|
"sectionKey"
|
|
21013
21843
|
],
|
|
@@ -21016,7 +21846,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
21016
21846
|
}
|
|
21017
21847
|
if (input.instructions !== void 0) {
|
|
21018
21848
|
ctx.addIssue({
|
|
21019
|
-
code:
|
|
21849
|
+
code: z79.ZodIssueCode.custom,
|
|
21020
21850
|
path: [
|
|
21021
21851
|
"instructions"
|
|
21022
21852
|
],
|
|
@@ -21025,31 +21855,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
21025
21855
|
}
|
|
21026
21856
|
}
|
|
21027
21857
|
});
|
|
21028
|
-
var CreateCreativeVariantInputBase =
|
|
21029
|
-
sourceTaskId:
|
|
21858
|
+
var CreateCreativeVariantInputBase = z79.object({
|
|
21859
|
+
sourceTaskId: z79.string().uuid().describe("ID de la tarea original completada."),
|
|
21030
21860
|
kind: CreativeVariantKindEnum,
|
|
21031
|
-
confirm:
|
|
21032
|
-
clientRequestId:
|
|
21033
|
-
angle:
|
|
21034
|
-
buyerPersona:
|
|
21035
|
-
scriptNotes:
|
|
21036
|
-
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."),
|
|
21037
21867
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
|
|
21038
21868
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
|
|
21039
|
-
generateAiMusic:
|
|
21040
|
-
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)."),
|
|
21041
21871
|
imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
|
|
21042
21872
|
creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
|
|
21043
21873
|
visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
|
|
21044
21874
|
aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
|
|
21045
|
-
styleMix:
|
|
21875
|
+
styleMix: z79.boolean().optional().describe("Opcional para imagen."),
|
|
21046
21876
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
|
|
21047
|
-
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.")
|
|
21048
21878
|
}).strict();
|
|
21049
21879
|
var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
21050
21880
|
if ((input.kind === "video" || input.kind === "image") && !input.angle) {
|
|
21051
21881
|
ctx.addIssue({
|
|
21052
|
-
code:
|
|
21882
|
+
code: z79.ZodIssueCode.custom,
|
|
21053
21883
|
path: [
|
|
21054
21884
|
"angle"
|
|
21055
21885
|
],
|
|
@@ -21058,7 +21888,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
21058
21888
|
}
|
|
21059
21889
|
if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
|
|
21060
21890
|
ctx.addIssue({
|
|
21061
|
-
code:
|
|
21891
|
+
code: z79.ZodIssueCode.custom,
|
|
21062
21892
|
path: [
|
|
21063
21893
|
"instructions"
|
|
21064
21894
|
],
|
|
@@ -21104,7 +21934,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
21104
21934
|
for (const field of fieldsByKind[input.kind]) {
|
|
21105
21935
|
if (input[field] !== void 0) {
|
|
21106
21936
|
ctx.addIssue({
|
|
21107
|
-
code:
|
|
21937
|
+
code: z79.ZodIssueCode.custom,
|
|
21108
21938
|
path: [
|
|
21109
21939
|
field
|
|
21110
21940
|
],
|
|
@@ -21221,32 +22051,32 @@ function registerCreativeVariantTools(server, api) {
|
|
|
21221
22051
|
__name(registerCreativeVariantTools, "registerCreativeVariantTools");
|
|
21222
22052
|
|
|
21223
22053
|
// src/tools/script-review.ts
|
|
21224
|
-
import { z as
|
|
22054
|
+
import { z as z80 } from "zod";
|
|
21225
22055
|
var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
|
|
21226
22056
|
var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
|
|
21227
22057
|
var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
|
|
21228
|
-
var GetVideoScriptInput =
|
|
21229
|
-
taskId:
|
|
21230
|
-
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.')
|
|
21231
22061
|
}).strict();
|
|
21232
22062
|
var VIDEO_SCRIPT_APPROVAL_MAX_SCENES2 = 50;
|
|
21233
22063
|
var VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2 = 2e3;
|
|
21234
|
-
var ApproveSceneEdit =
|
|
21235
|
-
index:
|
|
21236
|
-
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, {
|
|
21237
22067
|
message: "dialogue no puede ser s\xF3lo espacios"
|
|
21238
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.")
|
|
21239
22069
|
}).strict();
|
|
21240
|
-
var ApproveVideoScriptInput =
|
|
21241
|
-
taskId:
|
|
21242
|
-
angleKey:
|
|
21243
|
-
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.")
|
|
21244
22074
|
}).strict();
|
|
21245
|
-
var RegenerateVideoScriptInput =
|
|
21246
|
-
taskId:
|
|
21247
|
-
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.'),
|
|
21248
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).'),
|
|
21249
|
-
narrativeSelection:
|
|
22079
|
+
narrativeSelection: z80.enum([
|
|
21250
22080
|
"market",
|
|
21251
22081
|
"guided"
|
|
21252
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.")
|
|
@@ -21327,14 +22157,14 @@ function registerScriptReviewTools(server, api) {
|
|
|
21327
22157
|
__name(registerScriptReviewTools, "registerScriptReviewTools");
|
|
21328
22158
|
|
|
21329
22159
|
// src/tools/connections.ts
|
|
21330
|
-
import { z as
|
|
22160
|
+
import { z as z81 } from "zod";
|
|
21331
22161
|
var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
|
|
21332
22162
|
var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
|
|
21333
22163
|
var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
|
|
21334
22164
|
var listMetaDestinationsGuidance = getProductMakerCapabilityModelGuidance("list_meta_destinations");
|
|
21335
22165
|
var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list_tiktok_advertisers");
|
|
21336
22166
|
function registerConnectionTools(server, api) {
|
|
21337
|
-
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 () => {
|
|
21338
22168
|
try {
|
|
21339
22169
|
const r = await api.getJson("/v1/shopify/shops");
|
|
21340
22170
|
return asText(r);
|
|
@@ -21342,10 +22172,10 @@ function registerConnectionTools(server, api) {
|
|
|
21342
22172
|
throw translateError(e);
|
|
21343
22173
|
}
|
|
21344
22174
|
});
|
|
21345
|
-
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.',
|
|
21346
|
-
shopDomain:
|
|
21347
|
-
query:
|
|
21348
|
-
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()
|
|
21349
22179
|
}).shape, READS_EXTERNAL, async ({ shopDomain, query, taskId }) => {
|
|
21350
22180
|
try {
|
|
21351
22181
|
const params = new URLSearchParams({
|
|
@@ -21359,7 +22189,7 @@ function registerConnectionTools(server, api) {
|
|
|
21359
22189
|
throw translateError(e);
|
|
21360
22190
|
}
|
|
21361
22191
|
});
|
|
21362
|
-
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 () => {
|
|
21363
22193
|
try {
|
|
21364
22194
|
const r = await api.getJson("/v1/facebook/ad-accounts");
|
|
21365
22195
|
return asText(r);
|
|
@@ -21369,7 +22199,7 @@ function registerConnectionTools(server, api) {
|
|
|
21369
22199
|
});
|
|
21370
22200
|
server.registerTool("list_meta_destinations", {
|
|
21371
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.",
|
|
21372
|
-
inputSchema:
|
|
22202
|
+
inputSchema: z81.object({}).shape,
|
|
21373
22203
|
annotations: READS_EXTERNAL,
|
|
21374
22204
|
_meta: {
|
|
21375
22205
|
"openai/widgetAccessible": true
|
|
@@ -21382,7 +22212,7 @@ function registerConnectionTools(server, api) {
|
|
|
21382
22212
|
throw translateError(e);
|
|
21383
22213
|
}
|
|
21384
22214
|
});
|
|
21385
|
-
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 () => {
|
|
21386
22216
|
try {
|
|
21387
22217
|
const r = await api.getJson("/v1/tiktok/advertisers");
|
|
21388
22218
|
return asText(r);
|
|
@@ -21394,10 +22224,10 @@ function registerConnectionTools(server, api) {
|
|
|
21394
22224
|
__name(registerConnectionTools, "registerConnectionTools");
|
|
21395
22225
|
|
|
21396
22226
|
// src/tools/actors.ts
|
|
21397
|
-
import { z as
|
|
22227
|
+
import { z as z82 } from "zod";
|
|
21398
22228
|
var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
|
|
21399
22229
|
function registerActorTools(server, api) {
|
|
21400
|
-
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 () => {
|
|
21401
22231
|
try {
|
|
21402
22232
|
const rows = await api.getJson("/v1/actors");
|
|
21403
22233
|
const actors = (Array.isArray(rows) ? rows : []).filter((actor) => actor.status === "ready").map(({ id, name, description, gender, voiceId }) => ({
|
|
@@ -21418,7 +22248,7 @@ function registerActorTools(server, api) {
|
|
|
21418
22248
|
__name(registerActorTools, "registerActorTools");
|
|
21419
22249
|
|
|
21420
22250
|
// src/tools/publish.ts
|
|
21421
|
-
import { z as
|
|
22251
|
+
import { z as z83 } from "zod";
|
|
21422
22252
|
|
|
21423
22253
|
// src/tools/stable-uuid.ts
|
|
21424
22254
|
import { createHash as createHash3 } from "crypto";
|
|
@@ -21490,40 +22320,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
|
|
|
21490
22320
|
var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
|
|
21491
22321
|
var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
|
|
21492
22322
|
var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
|
|
21493
|
-
var ShopifyInput =
|
|
21494
|
-
taskId:
|
|
21495
|
-
shopDomain:
|
|
22323
|
+
var ShopifyInput = z83.object({
|
|
22324
|
+
taskId: z83.string().min(1),
|
|
22325
|
+
shopDomain: z83.string().min(1),
|
|
21496
22326
|
/** Override: number of landing images to include. Default = ALL images the
|
|
21497
22327
|
* task generated (the MCP fetches /v1/results first to count). Bounded
|
|
21498
22328
|
* generously here; the backend validates each index against
|
|
21499
22329
|
* landing.images.length and rejects out-of-range. */
|
|
21500
|
-
numLandingImages:
|
|
21501
|
-
variantIndex:
|
|
22330
|
+
numLandingImages: z83.number().int().min(1).max(20).optional(),
|
|
22331
|
+
variantIndex: z83.number().int().min(0).optional(),
|
|
21502
22332
|
/** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
|
|
21503
22333
|
* When true, the landing renders variant-picker pills; when false, it ships
|
|
21504
22334
|
* a single-option product page. Defaults to false. */
|
|
21505
|
-
showVariantPicker:
|
|
22335
|
+
showVariantPicker: z83.boolean().optional(),
|
|
21506
22336
|
/** Default `auto` updates the product previously published for this task and
|
|
21507
22337
|
* shop. Use `existing` with targetProductId to choose another product, or
|
|
21508
22338
|
* `new` only when the user explicitly wants a duplicate/new listing. */
|
|
21509
|
-
publicationMode:
|
|
22339
|
+
publicationMode: z83.enum([
|
|
21510
22340
|
"auto",
|
|
21511
22341
|
"existing",
|
|
21512
22342
|
"new"
|
|
21513
22343
|
]).optional(),
|
|
21514
22344
|
/** Shopify product GID, numeric id, or admin product URL. Required when
|
|
21515
22345
|
* publicationMode is `existing`. */
|
|
21516
|
-
targetProductId:
|
|
22346
|
+
targetProductId: z83.string().trim().min(1).max(300).optional(),
|
|
21517
22347
|
/** Add an announcement bar text above add-to-cart (optional). */
|
|
21518
|
-
announcementBarEnabled:
|
|
21519
|
-
announcementBarText:
|
|
22348
|
+
announcementBarEnabled: z83.boolean().optional(),
|
|
22349
|
+
announcementBarText: z83.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
|
|
21520
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."),
|
|
21521
|
-
confirmed:
|
|
22351
|
+
confirmed: z83.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
|
|
21522
22352
|
});
|
|
21523
22353
|
var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
|
|
21524
22354
|
if (value.commerceCorrection && value.confirmed !== true) {
|
|
21525
22355
|
ctx.addIssue({
|
|
21526
|
-
code:
|
|
22356
|
+
code: z83.ZodIssueCode.custom,
|
|
21527
22357
|
path: [
|
|
21528
22358
|
"confirmed"
|
|
21529
22359
|
],
|
|
@@ -21532,7 +22362,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
21532
22362
|
}
|
|
21533
22363
|
if (value.announcementBarEnabled && !value.announcementBarText) {
|
|
21534
22364
|
ctx.addIssue({
|
|
21535
|
-
code:
|
|
22365
|
+
code: z83.ZodIssueCode.custom,
|
|
21536
22366
|
path: [
|
|
21537
22367
|
"announcementBarText"
|
|
21538
22368
|
],
|
|
@@ -21541,7 +22371,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
21541
22371
|
}
|
|
21542
22372
|
if (!value.announcementBarEnabled && value.announcementBarText) {
|
|
21543
22373
|
ctx.addIssue({
|
|
21544
|
-
code:
|
|
22374
|
+
code: z83.ZodIssueCode.custom,
|
|
21545
22375
|
path: [
|
|
21546
22376
|
"announcementBarText"
|
|
21547
22377
|
],
|
|
@@ -21555,91 +22385,91 @@ function parseShopifyInput(rawInput) {
|
|
|
21555
22385
|
return parsed.data;
|
|
21556
22386
|
}
|
|
21557
22387
|
__name(parseShopifyInput, "parseShopifyInput");
|
|
21558
|
-
var McpCampaignConfig =
|
|
22388
|
+
var McpCampaignConfig = z83.object({
|
|
21559
22389
|
/** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
|
|
21560
22390
|
* converts to the account currency server-side. Do NOT pre-convert: on a COP
|
|
21561
22391
|
* account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
|
|
21562
|
-
dailyBudgetUsd:
|
|
22392
|
+
dailyBudgetUsd: z83.number().positive().optional(),
|
|
21563
22393
|
/** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
|
|
21564
22394
|
* normalizes at validation). Meta accepts max 1 (single-country ad set).
|
|
21565
22395
|
* TikTok takes only the first entry. */
|
|
21566
|
-
targetCountries:
|
|
21567
|
-
campaignName:
|
|
22396
|
+
targetCountries: z83.array(CountryIso2Schema).max(1).optional(),
|
|
22397
|
+
campaignName: z83.string().trim().min(1).max(100).optional()
|
|
21568
22398
|
});
|
|
21569
22399
|
var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
|
|
21570
|
-
var MetaInput =
|
|
21571
|
-
taskId:
|
|
22400
|
+
var MetaInput = z83.object({
|
|
22401
|
+
taskId: z83.string().min(1),
|
|
21572
22402
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
21573
|
-
portfolioId:
|
|
22403
|
+
portfolioId: z83.string().trim().min(1),
|
|
21574
22404
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
21575
|
-
pageId:
|
|
22405
|
+
pageId: z83.string().trim().min(1),
|
|
21576
22406
|
adAccountId: McpAdAccountId,
|
|
21577
|
-
pixelId:
|
|
21578
|
-
landingUrl:
|
|
22407
|
+
pixelId: z83.string().min(1).optional(),
|
|
22408
|
+
landingUrl: z83.string().url().optional(),
|
|
21579
22409
|
/** Select which angles to publish by 0-based index. Omit to publish all
|
|
21580
22410
|
* successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
|
|
21581
|
-
angleIndexes:
|
|
22411
|
+
angleIndexes: z83.array(z83.number().int().nonnegative()).optional(),
|
|
21582
22412
|
campaignConfig: McpCampaignConfig.optional(),
|
|
21583
22413
|
/** Override the ad's primary text (body copy). If omitted, ProductMaker
|
|
21584
22414
|
* uses the auto-generated copy attached to the task. Capped at 500 chars
|
|
21585
22415
|
* (Meta's primary-text limit). */
|
|
21586
|
-
primaryText:
|
|
22416
|
+
primaryText: z83.string().trim().min(1).max(500).optional(),
|
|
21587
22417
|
/** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
|
|
21588
22418
|
* (wa.me) instead of a landing page. */
|
|
21589
|
-
phoneNumber:
|
|
22419
|
+
phoneNumber: z83.string().min(8).max(32).optional()
|
|
21590
22420
|
});
|
|
21591
|
-
var GroupedTaskSource =
|
|
21592
|
-
type:
|
|
21593
|
-
taskId:
|
|
21594
|
-
angleIndex:
|
|
21595
|
-
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([
|
|
21596
22426
|
"with_subtitles",
|
|
21597
22427
|
"without_subtitles"
|
|
21598
22428
|
]).optional(),
|
|
21599
|
-
imageVariantIndex:
|
|
21600
|
-
});
|
|
21601
|
-
var GroupedMediaSource =
|
|
21602
|
-
type:
|
|
21603
|
-
url:
|
|
21604
|
-
path:
|
|
21605
|
-
thumbnailUrl:
|
|
21606
|
-
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()
|
|
21607
22437
|
}).refine((value) => Boolean(value.url) !== Boolean(value.path), {
|
|
21608
22438
|
message: "media source needs exactly one of `url` or `path`"
|
|
21609
22439
|
}).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
|
|
21610
22440
|
message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
|
|
21611
22441
|
});
|
|
21612
|
-
var GroupedUploadedAssetSource =
|
|
21613
|
-
type:
|
|
22442
|
+
var GroupedUploadedAssetSource = z83.object({
|
|
22443
|
+
type: z83.literal("asset"),
|
|
21614
22444
|
/** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
|
|
21615
|
-
assetId:
|
|
21616
|
-
thumbnailAssetId:
|
|
22445
|
+
assetId: z83.string().uuid(),
|
|
22446
|
+
thumbnailAssetId: z83.string().uuid().optional()
|
|
21617
22447
|
});
|
|
21618
|
-
var GroupedCreative =
|
|
21619
|
-
type:
|
|
22448
|
+
var GroupedCreative = z83.object({
|
|
22449
|
+
type: z83.enum([
|
|
21620
22450
|
"image",
|
|
21621
22451
|
"video"
|
|
21622
22452
|
]),
|
|
21623
|
-
source:
|
|
22453
|
+
source: z83.union([
|
|
21624
22454
|
GroupedTaskSource,
|
|
21625
22455
|
GroupedMediaSource,
|
|
21626
22456
|
GroupedUploadedAssetSource
|
|
21627
22457
|
]),
|
|
21628
|
-
title:
|
|
21629
|
-
description:
|
|
22458
|
+
title: z83.string().max(120).optional(),
|
|
22459
|
+
description: z83.string().max(500).optional(),
|
|
21630
22460
|
cta: MetaCtaType.optional(),
|
|
21631
|
-
creativeId:
|
|
22461
|
+
creativeId: z83.string().min(1).optional()
|
|
21632
22462
|
});
|
|
21633
|
-
var GroupedCampaignConfigBase =
|
|
22463
|
+
var GroupedCampaignConfigBase = z83.object({
|
|
21634
22464
|
campaignType: MetaCampaignType.default("sales"),
|
|
21635
22465
|
optimizationMode: MetaOptimizationMode.default("advantage_plus"),
|
|
21636
22466
|
budgetMode: MetaBudgetMode.optional(),
|
|
21637
|
-
campaignDailyBudget:
|
|
21638
|
-
adSets:
|
|
21639
|
-
tempId:
|
|
21640
|
-
name:
|
|
21641
|
-
dailyBudget:
|
|
21642
|
-
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)
|
|
21643
22473
|
})).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
|
|
21644
22474
|
/**
|
|
21645
22475
|
* Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
|
|
@@ -21647,17 +22477,17 @@ var GroupedCampaignConfigBase = z79.object({
|
|
|
21647
22477
|
* opaque `invalid_literal` and made the WhatsApp destination — supported by
|
|
21648
22478
|
* the API since #849 — unreachable from this tool.
|
|
21649
22479
|
*/
|
|
21650
|
-
destination:
|
|
21651
|
-
|
|
21652
|
-
type:
|
|
21653
|
-
landingUrl:
|
|
22480
|
+
destination: z83.discriminatedUnion("type", [
|
|
22481
|
+
z83.object({
|
|
22482
|
+
type: z83.literal("landing"),
|
|
22483
|
+
landingUrl: z83.string().url()
|
|
21654
22484
|
}),
|
|
21655
|
-
|
|
21656
|
-
type:
|
|
21657
|
-
phoneNumber:
|
|
22485
|
+
z83.object({
|
|
22486
|
+
type: z83.literal("whatsapp"),
|
|
22487
|
+
phoneNumber: z83.string().min(8).max(32)
|
|
21658
22488
|
})
|
|
21659
22489
|
]),
|
|
21660
|
-
saveAsDefault:
|
|
22490
|
+
saveAsDefault: z83.boolean().default(false),
|
|
21661
22491
|
budgetPolicy: MetaBudgetPolicy.optional()
|
|
21662
22492
|
});
|
|
21663
22493
|
function resolveBudgetMode(value) {
|
|
@@ -21671,7 +22501,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
21671
22501
|
const budgetMode = resolveBudgetMode(value);
|
|
21672
22502
|
if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
|
|
21673
22503
|
ctx.addIssue({
|
|
21674
|
-
code:
|
|
22504
|
+
code: z83.ZodIssueCode.custom,
|
|
21675
22505
|
path: [
|
|
21676
22506
|
"campaignDailyBudget"
|
|
21677
22507
|
],
|
|
@@ -21682,7 +22512,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
21682
22512
|
value.adSets.forEach((adSet, index) => {
|
|
21683
22513
|
if (adSet.dailyBudget === void 0) {
|
|
21684
22514
|
ctx.addIssue({
|
|
21685
|
-
code:
|
|
22515
|
+
code: z83.ZodIssueCode.custom,
|
|
21686
22516
|
path: [
|
|
21687
22517
|
"adSets",
|
|
21688
22518
|
index,
|
|
@@ -21697,28 +22527,28 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
21697
22527
|
...value,
|
|
21698
22528
|
budgetMode: resolveBudgetMode(value)
|
|
21699
22529
|
}));
|
|
21700
|
-
var PublishCreativesToMetaInputBase =
|
|
21701
|
-
creatives:
|
|
22530
|
+
var PublishCreativesToMetaInputBase = z83.object({
|
|
22531
|
+
creatives: z83.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
|
|
21702
22532
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
21703
|
-
portfolioId:
|
|
22533
|
+
portfolioId: z83.string().trim().min(1),
|
|
21704
22534
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
21705
|
-
pageId:
|
|
22535
|
+
pageId: z83.string().trim().min(1),
|
|
21706
22536
|
adAccountId: McpAdAccountId,
|
|
21707
|
-
pixelId:
|
|
22537
|
+
pixelId: z83.string().min(1).optional(),
|
|
21708
22538
|
/** Required unless `campaignConfig.destination` is whatsapp — see the
|
|
21709
22539
|
* superRefine below. Mirrors the API's `FacebookCreateCampaignFromTasksBodySchema`. */
|
|
21710
|
-
landingUrl:
|
|
22540
|
+
landingUrl: z83.string().url().optional(),
|
|
21711
22541
|
/** ISO-2 code or resolvable country name — mirrors the API contract
|
|
21712
22542
|
* (CountryIso2Schema), which normalizes names to alpha-2 at validation. */
|
|
21713
22543
|
targetCountry: CountryIso2Schema,
|
|
21714
|
-
campaignName:
|
|
22544
|
+
campaignName: z83.string().trim().min(1).max(100),
|
|
21715
22545
|
campaignConfig: GroupedCampaignConfig.optional()
|
|
21716
22546
|
});
|
|
21717
22547
|
var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
|
|
21718
22548
|
const destination = value.campaignConfig?.destination;
|
|
21719
22549
|
if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
|
|
21720
22550
|
ctx.addIssue({
|
|
21721
|
-
code:
|
|
22551
|
+
code: z83.ZodIssueCode.custom,
|
|
21722
22552
|
path: [
|
|
21723
22553
|
"landingUrl"
|
|
21724
22554
|
],
|
|
@@ -21727,7 +22557,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
21727
22557
|
}
|
|
21728
22558
|
if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
|
|
21729
22559
|
ctx.addIssue({
|
|
21730
|
-
code:
|
|
22560
|
+
code: z83.ZodIssueCode.custom,
|
|
21731
22561
|
path: [
|
|
21732
22562
|
"campaignConfig",
|
|
21733
22563
|
"destination",
|
|
@@ -21746,16 +22576,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
21746
22576
|
}
|
|
21747
22577
|
return value;
|
|
21748
22578
|
});
|
|
21749
|
-
var PresignUploadResponseSchema =
|
|
21750
|
-
uploadUrl:
|
|
22579
|
+
var PresignUploadResponseSchema = z83.object({
|
|
22580
|
+
uploadUrl: z83.string().url().refine((value) => {
|
|
21751
22581
|
const url = new URL(value);
|
|
21752
22582
|
return !url.username && !url.password && url.protocol === "https:";
|
|
21753
22583
|
}, "presigned upload URL must be HTTPS without embedded credentials"),
|
|
21754
|
-
publicUrl:
|
|
22584
|
+
publicUrl: z83.string().url().refine((value) => {
|
|
21755
22585
|
const url = new URL(value);
|
|
21756
22586
|
return !url.username && !url.password;
|
|
21757
22587
|
}, "public media URL must not contain embedded credentials"),
|
|
21758
|
-
stagingAssetId:
|
|
22588
|
+
stagingAssetId: z83.string().uuid()
|
|
21759
22589
|
});
|
|
21760
22590
|
async function uploadResolvedMedia(api, media, assetRole) {
|
|
21761
22591
|
if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
|
|
@@ -21780,16 +22610,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
|
|
|
21780
22610
|
return uploadResolvedMedia(api, media, assetRole);
|
|
21781
22611
|
}
|
|
21782
22612
|
__name(resolveAndUploadMedia, "resolveAndUploadMedia");
|
|
21783
|
-
var TikTokInput =
|
|
21784
|
-
taskId:
|
|
21785
|
-
advertiserId:
|
|
21786
|
-
pixelId:
|
|
21787
|
-
landingUrl:
|
|
21788
|
-
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(),
|
|
21789
22619
|
campaignConfig: McpCampaignConfig.optional(),
|
|
21790
22620
|
/** Override the ad's description (TikTok's body copy). If omitted,
|
|
21791
22621
|
* ProductMaker uses the auto-generated copy attached to the task. */
|
|
21792
|
-
primaryText:
|
|
22622
|
+
primaryText: z83.string().trim().min(1).max(500).optional()
|
|
21793
22623
|
});
|
|
21794
22624
|
function registerPublishTools(server, api, opts = {}) {
|
|
21795
22625
|
const transport = opts.transport ?? "http";
|
|
@@ -22117,39 +22947,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
|
|
|
22117
22947
|
|
|
22118
22948
|
// src/tools/meta-upload.ts
|
|
22119
22949
|
import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
|
|
22120
|
-
import { z as
|
|
22950
|
+
import { z as z84 } from "zod";
|
|
22121
22951
|
var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
|
|
22122
|
-
var UploadSessionInputBase =
|
|
22123
|
-
mediaKind:
|
|
22952
|
+
var UploadSessionInputBase = z84.object({
|
|
22953
|
+
mediaKind: z84.enum([
|
|
22124
22954
|
"image",
|
|
22125
22955
|
"video",
|
|
22126
22956
|
"mixed"
|
|
22127
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."),
|
|
22128
|
-
assetRole:
|
|
22958
|
+
assetRole: z84.enum([
|
|
22129
22959
|
"media",
|
|
22130
22960
|
"thumbnail"
|
|
22131
22961
|
]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
|
|
22132
|
-
uploadPurpose:
|
|
22962
|
+
uploadPurpose: z84.enum([
|
|
22133
22963
|
"product_reference",
|
|
22134
22964
|
"creative",
|
|
22135
22965
|
"generic"
|
|
22136
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."),
|
|
22137
|
-
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.")
|
|
22138
22968
|
});
|
|
22139
|
-
var OpenAiFileReference =
|
|
22140
|
-
download_url:
|
|
22141
|
-
file_id:
|
|
22142
|
-
mime_type:
|
|
22143
|
-
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()
|
|
22144
22974
|
});
|
|
22145
22975
|
var UploadSessionToolInputShape = {
|
|
22146
22976
|
...UploadSessionInputBase.shape,
|
|
22147
|
-
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.")
|
|
22148
22978
|
};
|
|
22149
|
-
var UploadSessionToolInput =
|
|
22979
|
+
var UploadSessionToolInput = z84.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
|
|
22150
22980
|
if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
|
|
22151
22981
|
ctx.addIssue({
|
|
22152
|
-
code:
|
|
22982
|
+
code: z84.ZodIssueCode.custom,
|
|
22153
22983
|
path: [
|
|
22154
22984
|
"mediaKind"
|
|
22155
22985
|
],
|
|
@@ -22158,7 +22988,7 @@ var UploadSessionToolInput = z80.object(UploadSessionToolInputShape).superRefine
|
|
|
22158
22988
|
}
|
|
22159
22989
|
if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
|
|
22160
22990
|
ctx.addIssue({
|
|
22161
|
-
code:
|
|
22991
|
+
code: z84.ZodIssueCode.custom,
|
|
22162
22992
|
path: [
|
|
22163
22993
|
"maxFiles"
|
|
22164
22994
|
],
|
|
@@ -22167,7 +22997,7 @@ var UploadSessionToolInput = z80.object(UploadSessionToolInputShape).superRefine
|
|
|
22167
22997
|
}
|
|
22168
22998
|
if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
|
|
22169
22999
|
ctx.addIssue({
|
|
22170
|
-
code:
|
|
23000
|
+
code: z84.ZodIssueCode.custom,
|
|
22171
23001
|
path: [
|
|
22172
23002
|
"maxFiles"
|
|
22173
23003
|
],
|
|
@@ -22175,38 +23005,38 @@ var UploadSessionToolInput = z80.object(UploadSessionToolInputShape).superRefine
|
|
|
22175
23005
|
});
|
|
22176
23006
|
}
|
|
22177
23007
|
});
|
|
22178
|
-
var UploadSessionResponse =
|
|
22179
|
-
sessionId:
|
|
22180
|
-
uploadPageUrl:
|
|
22181
|
-
mediaKind:
|
|
23008
|
+
var UploadSessionResponse = z84.object({
|
|
23009
|
+
sessionId: z84.string().uuid(),
|
|
23010
|
+
uploadPageUrl: z84.string().url(),
|
|
23011
|
+
mediaKind: z84.enum([
|
|
22182
23012
|
"image",
|
|
22183
23013
|
"video",
|
|
22184
23014
|
"mixed"
|
|
22185
23015
|
]),
|
|
22186
|
-
assetRole:
|
|
23016
|
+
assetRole: z84.enum([
|
|
22187
23017
|
"media",
|
|
22188
23018
|
"thumbnail"
|
|
22189
23019
|
]),
|
|
22190
|
-
maxFiles:
|
|
22191
|
-
expiresAt:
|
|
23020
|
+
maxFiles: z84.number().int().positive(),
|
|
23021
|
+
expiresAt: z84.string().datetime()
|
|
22192
23022
|
});
|
|
22193
|
-
var UploadStatusInput =
|
|
22194
|
-
sessionId:
|
|
23023
|
+
var UploadStatusInput = z84.object({
|
|
23024
|
+
sessionId: z84.string().uuid().describe("The sessionId returned by request_media_upload.")
|
|
22195
23025
|
});
|
|
22196
|
-
var UniversalUploadStatusResponse =
|
|
22197
|
-
|
|
22198
|
-
status:
|
|
22199
|
-
assets:
|
|
23026
|
+
var UniversalUploadStatusResponse = z84.discriminatedUnion("status", [
|
|
23027
|
+
z84.object({
|
|
23028
|
+
status: z84.literal("pending"),
|
|
23029
|
+
assets: z84.array(z84.never()).length(0)
|
|
22200
23030
|
}),
|
|
22201
|
-
|
|
22202
|
-
status:
|
|
22203
|
-
assets:
|
|
22204
|
-
assetId:
|
|
22205
|
-
mediaKind:
|
|
23031
|
+
z84.object({
|
|
23032
|
+
status: z84.literal("uploaded"),
|
|
23033
|
+
assets: z84.array(z84.object({
|
|
23034
|
+
assetId: z84.string().uuid(),
|
|
23035
|
+
mediaKind: z84.enum([
|
|
22206
23036
|
"image",
|
|
22207
23037
|
"video"
|
|
22208
23038
|
]),
|
|
22209
|
-
assetRole:
|
|
23039
|
+
assetRole: z84.enum([
|
|
22210
23040
|
"media",
|
|
22211
23041
|
"thumbnail"
|
|
22212
23042
|
])
|
|
@@ -22214,13 +23044,13 @@ var UniversalUploadStatusResponse = z80.discriminatedUnion("status", [
|
|
|
22214
23044
|
})
|
|
22215
23045
|
]);
|
|
22216
23046
|
var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
|
|
22217
|
-
uploadPurpose:
|
|
23047
|
+
uploadPurpose: z84.enum([
|
|
22218
23048
|
"product_reference",
|
|
22219
23049
|
"creative",
|
|
22220
23050
|
"generic"
|
|
22221
23051
|
]),
|
|
22222
|
-
checkToolName:
|
|
22223
|
-
resolveEndpoint:
|
|
23052
|
+
checkToolName: z84.literal("check_media_upload"),
|
|
23053
|
+
resolveEndpoint: z84.string().url()
|
|
22224
23054
|
});
|
|
22225
23055
|
function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
|
|
22226
23056
|
const url = new URL(uploadPageUrl);
|
|
@@ -22311,15 +23141,15 @@ function registerMediaUploadTools(server, api) {
|
|
|
22311
23141
|
__name(registerMediaUploadTools, "registerMediaUploadTools");
|
|
22312
23142
|
|
|
22313
23143
|
// src/tools/campaigns.ts
|
|
22314
|
-
import { z as
|
|
23144
|
+
import { z as z85 } from "zod";
|
|
22315
23145
|
var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
|
|
22316
23146
|
var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
|
|
22317
|
-
var MetaStatusInput =
|
|
22318
|
-
campaignId:
|
|
23147
|
+
var MetaStatusInput = z85.object({
|
|
23148
|
+
campaignId: z85.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
|
|
22319
23149
|
});
|
|
22320
|
-
var TikTokStatusInput =
|
|
22321
|
-
campaignId:
|
|
22322
|
-
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.")
|
|
22323
23153
|
});
|
|
22324
23154
|
function registerCampaignTools(server, api) {
|
|
22325
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) => {
|
|
@@ -22416,10 +23246,10 @@ function renderTikTokStatusMarkdown(r) {
|
|
|
22416
23246
|
__name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
|
|
22417
23247
|
|
|
22418
23248
|
// ../../packages/product-economics/src/product-costing.ts
|
|
22419
|
-
import { z as
|
|
23249
|
+
import { z as z87 } from "zod";
|
|
22420
23250
|
|
|
22421
23251
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
22422
|
-
import { z as
|
|
23252
|
+
import { z as z86 } from "zod";
|
|
22423
23253
|
|
|
22424
23254
|
// ../../packages/product-economics/src/product-costing-shipping-references.json
|
|
22425
23255
|
var product_costing_shipping_references_default = {
|
|
@@ -22483,21 +23313,21 @@ var product_costing_shipping_references_default = {
|
|
|
22483
23313
|
};
|
|
22484
23314
|
|
|
22485
23315
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
22486
|
-
var ShippingReferenceSchema =
|
|
22487
|
-
reference:
|
|
22488
|
-
min:
|
|
22489
|
-
max:
|
|
22490
|
-
updatedAt:
|
|
22491
|
-
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([
|
|
22492
23322
|
"high",
|
|
22493
23323
|
"medium",
|
|
22494
23324
|
"medium-low"
|
|
22495
23325
|
]),
|
|
22496
|
-
sources:
|
|
23326
|
+
sources: z86.array(z86.string().url().startsWith("https://")).min(1).max(3)
|
|
22497
23327
|
}).superRefine(({ reference, min, max }, context) => {
|
|
22498
23328
|
if (min > reference || reference > max) {
|
|
22499
23329
|
context.addIssue({
|
|
22500
|
-
code:
|
|
23330
|
+
code: z86.ZodIssueCode.custom,
|
|
22501
23331
|
message: "shipping_reference_outside_range",
|
|
22502
23332
|
path: [
|
|
22503
23333
|
"reference"
|
|
@@ -22505,7 +23335,7 @@ var ShippingReferenceSchema = z82.object({
|
|
|
22505
23335
|
});
|
|
22506
23336
|
}
|
|
22507
23337
|
});
|
|
22508
|
-
var SHIPPING_REFERENCES =
|
|
23338
|
+
var SHIPPING_REFERENCES = z86.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
|
|
22509
23339
|
var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
|
|
22510
23340
|
var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
|
|
22511
23341
|
"MX",
|
|
@@ -22687,18 +23517,18 @@ function getProductCostingCountryName(country) {
|
|
|
22687
23517
|
__name(getProductCostingCountryName, "getProductCostingCountryName");
|
|
22688
23518
|
|
|
22689
23519
|
// ../../packages/product-economics/src/product-costing.ts
|
|
22690
|
-
var ProductCostingInputSchema =
|
|
22691
|
-
country:
|
|
22692
|
-
supplierCost:
|
|
22693
|
-
shippingCost:
|
|
22694
|
-
returnRate:
|
|
22695
|
-
cancellationRate:
|
|
22696
|
-
adsManagerCpa:
|
|
22697
|
-
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")
|
|
22698
23528
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
22699
23529
|
if (returnRate + cancellationRate >= 1) {
|
|
22700
23530
|
context.addIssue({
|
|
22701
|
-
code:
|
|
23531
|
+
code: z87.ZodIssueCode.custom,
|
|
22702
23532
|
message: "delivery_rate_positive",
|
|
22703
23533
|
path: [
|
|
22704
23534
|
"cancellationRate"
|
|
@@ -22795,15 +23625,15 @@ function calculateProductCosting(rawInput) {
|
|
|
22795
23625
|
__name(calculateProductCosting, "calculateProductCosting");
|
|
22796
23626
|
|
|
22797
23627
|
// src/tools/product-costing.ts
|
|
22798
|
-
import { z as
|
|
23628
|
+
import { z as z88 } from "zod";
|
|
22799
23629
|
var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
|
|
22800
|
-
var optionalAmount = /* @__PURE__ */ __name((description) =>
|
|
22801
|
-
var optionalPercent = /* @__PURE__ */ __name((description) =>
|
|
22802
|
-
var ProductCostingToolInput =
|
|
22803
|
-
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, {
|
|
22804
23634
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
22805
23635
|
}).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
|
|
22806
|
-
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."),
|
|
22807
23637
|
supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
|
|
22808
23638
|
shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
|
|
22809
23639
|
shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
|
|
@@ -22962,7 +23792,7 @@ function formatPercent(value) {
|
|
|
22962
23792
|
__name(formatPercent, "formatPercent");
|
|
22963
23793
|
|
|
22964
23794
|
// src/tools/product-research.ts
|
|
22965
|
-
import { z as
|
|
23795
|
+
import { z as z89 } from "zod";
|
|
22966
23796
|
|
|
22967
23797
|
// src/tools/product-research-idempotency.ts
|
|
22968
23798
|
var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
|
|
@@ -23333,35 +24163,35 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
|
|
|
23333
24163
|
]);
|
|
23334
24164
|
var POLL_INTERVAL_MS = 5e3;
|
|
23335
24165
|
var MAX_WAIT_SECONDS = 120;
|
|
23336
|
-
var FindInput =
|
|
24166
|
+
var FindInput = z89.object({
|
|
23337
24167
|
targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
|
|
23338
24168
|
categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
|
|
23339
|
-
confirmed:
|
|
23340
|
-
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.")
|
|
23341
24171
|
});
|
|
23342
|
-
var GetInput =
|
|
23343
|
-
runId:
|
|
24172
|
+
var GetInput = z89.object({
|
|
24173
|
+
runId: z89.string().uuid().describe("ID del run devuelto por find_winning_products.")
|
|
23344
24174
|
});
|
|
23345
|
-
var ListInput =
|
|
23346
|
-
limit:
|
|
24175
|
+
var ListInput = z89.object({
|
|
24176
|
+
limit: z89.number().int().min(1).max(20).default(10)
|
|
23347
24177
|
});
|
|
23348
|
-
function textResult(
|
|
24178
|
+
function textResult(text2) {
|
|
23349
24179
|
return {
|
|
23350
24180
|
content: [
|
|
23351
24181
|
{
|
|
23352
24182
|
type: "text",
|
|
23353
|
-
text
|
|
24183
|
+
text: text2
|
|
23354
24184
|
}
|
|
23355
24185
|
]
|
|
23356
24186
|
};
|
|
23357
24187
|
}
|
|
23358
24188
|
__name(textResult, "textResult");
|
|
23359
|
-
function researchResult(run,
|
|
24189
|
+
function researchResult(run, text2) {
|
|
23360
24190
|
return {
|
|
23361
24191
|
content: [
|
|
23362
24192
|
{
|
|
23363
24193
|
type: "text",
|
|
23364
|
-
text
|
|
24194
|
+
text: text2
|
|
23365
24195
|
}
|
|
23366
24196
|
],
|
|
23367
24197
|
structuredContent: run
|
|
@@ -23466,17 +24296,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
|
|
|
23466
24296
|
__name(registerProductResearchTools, "registerProductResearchTools");
|
|
23467
24297
|
|
|
23468
24298
|
// src/tools/dropshipping-projects.ts
|
|
23469
|
-
import { z as
|
|
24299
|
+
import { z as z90 } from "zod";
|
|
23470
24300
|
var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
|
|
23471
24301
|
var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
|
|
23472
24302
|
var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
|
|
23473
|
-
var ProjectId =
|
|
23474
|
-
var DropshippingProjectStatus =
|
|
24303
|
+
var ProjectId = z90.string().uuid();
|
|
24304
|
+
var DropshippingProjectStatus = z90.enum([
|
|
23475
24305
|
"active",
|
|
23476
24306
|
"completed",
|
|
23477
24307
|
"archived"
|
|
23478
24308
|
]);
|
|
23479
|
-
var DropshippingProjectPhase =
|
|
24309
|
+
var DropshippingProjectPhase = z90.enum([
|
|
23480
24310
|
"research",
|
|
23481
24311
|
"costing",
|
|
23482
24312
|
"media",
|
|
@@ -23485,21 +24315,21 @@ var DropshippingProjectPhase = z86.enum([
|
|
|
23485
24315
|
"advertising",
|
|
23486
24316
|
"complete"
|
|
23487
24317
|
]);
|
|
23488
|
-
var DropshippingRewardMilestone =
|
|
24318
|
+
var DropshippingRewardMilestone = z90.enum([
|
|
23489
24319
|
"product_selected",
|
|
23490
24320
|
"costing_saved",
|
|
23491
24321
|
"product_media_ready",
|
|
23492
24322
|
"creatives_completed",
|
|
23493
24323
|
"campaign_created"
|
|
23494
24324
|
]);
|
|
23495
|
-
var TargetCountry =
|
|
24325
|
+
var TargetCountry = z90.enum([
|
|
23496
24326
|
"CO",
|
|
23497
24327
|
"MX",
|
|
23498
24328
|
"PE",
|
|
23499
24329
|
"EC",
|
|
23500
24330
|
"CL"
|
|
23501
24331
|
]);
|
|
23502
|
-
var ResearchCategory =
|
|
24332
|
+
var ResearchCategory = z90.enum([
|
|
23503
24333
|
"auto",
|
|
23504
24334
|
"automotive",
|
|
23505
24335
|
"kitchen",
|
|
@@ -23514,7 +24344,7 @@ var ResearchCategory = z86.enum([
|
|
|
23514
24344
|
"garden",
|
|
23515
24345
|
"cleaning"
|
|
23516
24346
|
]);
|
|
23517
|
-
var HttpUrl3 =
|
|
24347
|
+
var HttpUrl3 = z90.string().url().max(2e3).refine((value) => {
|
|
23518
24348
|
try {
|
|
23519
24349
|
return [
|
|
23520
24350
|
"http:",
|
|
@@ -23524,45 +24354,45 @@ var HttpUrl3 = z86.string().url().max(2e3).refine((value) => {
|
|
|
23524
24354
|
return false;
|
|
23525
24355
|
}
|
|
23526
24356
|
}, "URL must use HTTP(S)");
|
|
23527
|
-
var ResearchCandidateOrigin =
|
|
23528
|
-
type:
|
|
24357
|
+
var ResearchCandidateOrigin = z90.object({
|
|
24358
|
+
type: z90.literal("research_candidate"),
|
|
23529
24359
|
runId: ProjectId,
|
|
23530
|
-
candidateSourceId:
|
|
24360
|
+
candidateSourceId: z90.string().min(1).max(160)
|
|
23531
24361
|
});
|
|
23532
|
-
var TaskOrigin =
|
|
23533
|
-
type:
|
|
24362
|
+
var TaskOrigin = z90.object({
|
|
24363
|
+
type: z90.literal("task"),
|
|
23534
24364
|
taskId: ProjectId
|
|
23535
24365
|
});
|
|
23536
|
-
var ManualOrigin =
|
|
23537
|
-
type:
|
|
24366
|
+
var ManualOrigin = z90.object({
|
|
24367
|
+
type: z90.literal("manual"),
|
|
23538
24368
|
clientRequestId: ProjectId,
|
|
23539
|
-
country:
|
|
24369
|
+
country: z90.string().min(2).max(3).optional()
|
|
23540
24370
|
});
|
|
23541
|
-
var StartProjectInput =
|
|
23542
|
-
origin:
|
|
24371
|
+
var StartProjectInput = z90.object({
|
|
24372
|
+
origin: z90.discriminatedUnion("type", [
|
|
23543
24373
|
ResearchCandidateOrigin,
|
|
23544
24374
|
TaskOrigin,
|
|
23545
24375
|
ManualOrigin
|
|
23546
24376
|
]),
|
|
23547
|
-
productName:
|
|
24377
|
+
productName: z90.string().trim().min(1).max(240).optional(),
|
|
23548
24378
|
productUrl: HttpUrl3.optional(),
|
|
23549
|
-
country:
|
|
23550
|
-
languageCode:
|
|
24379
|
+
country: z90.string().min(2).max(3).optional(),
|
|
24380
|
+
languageCode: z90.string().min(2).max(16).optional()
|
|
23551
24381
|
}).strict();
|
|
23552
|
-
var CostProjectInput =
|
|
24382
|
+
var CostProjectInput = z90.object({
|
|
23553
24383
|
projectId: ProjectId,
|
|
23554
|
-
version:
|
|
23555
|
-
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, {
|
|
23556
24386
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
23557
24387
|
}).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
|
|
23558
|
-
supplierCost:
|
|
23559
|
-
shippingCost:
|
|
23560
|
-
returnRate:
|
|
23561
|
-
cancellationRate:
|
|
23562
|
-
adsManagerCpa:
|
|
23563
|
-
desiredMargin:
|
|
23564
|
-
});
|
|
23565
|
-
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({
|
|
23566
24396
|
projectId: ProjectId.optional()
|
|
23567
24397
|
}).strict();
|
|
23568
24398
|
var NEXT_ACTION_KINDS = [
|
|
@@ -23580,29 +24410,29 @@ var NEXT_ACTION_KINDS = [
|
|
|
23580
24410
|
"repair_meta_campaign",
|
|
23581
24411
|
"review_paused_campaign"
|
|
23582
24412
|
];
|
|
23583
|
-
var DropshippingProjectNextAction =
|
|
23584
|
-
kind:
|
|
23585
|
-
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)
|
|
23586
24416
|
})));
|
|
23587
|
-
var CostingInputSchema =
|
|
23588
|
-
country:
|
|
23589
|
-
supplierCost:
|
|
23590
|
-
shippingCost:
|
|
23591
|
-
returnRate:
|
|
23592
|
-
cancellationRate:
|
|
23593
|
-
adsManagerCpa:
|
|
23594
|
-
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)
|
|
23595
24425
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
23596
24426
|
if (returnRate + cancellationRate >= 1) context.addIssue({
|
|
23597
|
-
code:
|
|
24427
|
+
code: z90.ZodIssueCode.custom,
|
|
23598
24428
|
path: [
|
|
23599
24429
|
"cancellationRate"
|
|
23600
24430
|
]
|
|
23601
24431
|
});
|
|
23602
24432
|
});
|
|
23603
|
-
var FiniteCostingNumber =
|
|
23604
|
-
var CostingResultSchema =
|
|
23605
|
-
country:
|
|
24433
|
+
var FiniteCostingNumber = z90.number().finite();
|
|
24434
|
+
var CostingResultSchema = z90.object({
|
|
24435
|
+
country: z90.string().min(2).max(3),
|
|
23606
24436
|
deliveryRate: FiniteCostingNumber,
|
|
23607
24437
|
adjustedShippingCost: FiniteCostingNumber,
|
|
23608
24438
|
adjustedCpa: FiniteCostingNumber,
|
|
@@ -23615,45 +24445,45 @@ var CostingResultSchema = z86.object({
|
|
|
23615
24445
|
estimatedProfit: FiniteCostingNumber,
|
|
23616
24446
|
actualMargin: FiniteCostingNumber,
|
|
23617
24447
|
breakEvenAdsManagerCpa: FiniteCostingNumber,
|
|
23618
|
-
wasPriceAutoAdjusted:
|
|
23619
|
-
profitabilityStatus:
|
|
23620
|
-
});
|
|
23621
|
-
var RewardProgressSchema =
|
|
23622
|
-
campaignKey:
|
|
23623
|
-
totalCredits:
|
|
23624
|
-
earnedCredits:
|
|
23625
|
-
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({
|
|
23626
24456
|
milestone: DropshippingRewardMilestone,
|
|
23627
|
-
credits:
|
|
23628
|
-
available:
|
|
23629
|
-
earned:
|
|
24457
|
+
credits: z90.number().int().positive(),
|
|
24458
|
+
available: z90.boolean().optional(),
|
|
24459
|
+
earned: z90.boolean(),
|
|
23630
24460
|
grantId: ProjectId.nullable(),
|
|
23631
|
-
grantedAt:
|
|
24461
|
+
grantedAt: z90.string().datetime().nullable()
|
|
23632
24462
|
})).length(DropshippingRewardMilestone.options.length)
|
|
23633
24463
|
});
|
|
23634
|
-
var ProjectResponseSchema =
|
|
24464
|
+
var ProjectResponseSchema = z90.object({
|
|
23635
24465
|
id: ProjectId,
|
|
23636
24466
|
taskId: ProjectId.nullable(),
|
|
23637
24467
|
status: DropshippingProjectStatus,
|
|
23638
|
-
originKey:
|
|
24468
|
+
originKey: z90.string().min(1),
|
|
23639
24469
|
researchRunId: ProjectId.nullable(),
|
|
23640
|
-
candidateSourceId:
|
|
23641
|
-
productName:
|
|
24470
|
+
candidateSourceId: z90.string().nullable(),
|
|
24471
|
+
productName: z90.string().nullable(),
|
|
23642
24472
|
productUrl: HttpUrl3.nullable(),
|
|
23643
24473
|
referenceImageUrl: HttpUrl3.nullable(),
|
|
23644
|
-
targetCountry:
|
|
23645
|
-
languageCode:
|
|
23646
|
-
hasReferenceImage:
|
|
23647
|
-
hasWinnerReferenceImage:
|
|
24474
|
+
targetCountry: z90.string().nullable(),
|
|
24475
|
+
languageCode: z90.string().nullable(),
|
|
24476
|
+
hasReferenceImage: z90.boolean(),
|
|
24477
|
+
hasWinnerReferenceImage: z90.boolean(),
|
|
23648
24478
|
costingInput: CostingInputSchema.nullable(),
|
|
23649
24479
|
costingResult: CostingResultSchema.nullable(),
|
|
23650
|
-
costingVersion:
|
|
23651
|
-
version:
|
|
24480
|
+
costingVersion: z90.number().int().positive().nullable(),
|
|
24481
|
+
version: z90.number().int().positive(),
|
|
23652
24482
|
phase: DropshippingProjectPhase,
|
|
23653
24483
|
nextAction: DropshippingProjectNextAction.nullable(),
|
|
23654
24484
|
rewards: RewardProgressSchema,
|
|
23655
|
-
createdAt:
|
|
23656
|
-
updatedAt:
|
|
24485
|
+
createdAt: z90.string().datetime(),
|
|
24486
|
+
updatedAt: z90.string().datetime()
|
|
23657
24487
|
}).passthrough();
|
|
23658
24488
|
var NEXT_ACTION_GUIDANCE = {
|
|
23659
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.",
|
|
@@ -23771,58 +24601,58 @@ function registerDropshippingProjectTools(server, api) {
|
|
|
23771
24601
|
__name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
|
|
23772
24602
|
|
|
23773
24603
|
// src/tools/daily-control.ts
|
|
23774
|
-
import { z as
|
|
24604
|
+
import { z as z91 } from "zod";
|
|
23775
24605
|
var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
|
|
23776
24606
|
var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
|
|
23777
24607
|
var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
|
|
23778
|
-
var ProviderCampaignIdentifier =
|
|
23779
|
-
var DateOnly =
|
|
23780
|
-
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({
|
|
23781
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."),
|
|
23782
|
-
days:
|
|
23783
|
-
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.")
|
|
23784
24614
|
}).strict();
|
|
23785
|
-
var LinkCampaignInput =
|
|
23786
|
-
projectId:
|
|
23787
|
-
provider:
|
|
24615
|
+
var LinkCampaignInput = z91.object({
|
|
24616
|
+
projectId: z91.string().uuid(),
|
|
24617
|
+
provider: z91.enum([
|
|
23788
24618
|
"meta",
|
|
23789
24619
|
"tiktok"
|
|
23790
24620
|
]),
|
|
23791
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."),
|
|
23792
24622
|
campaignId: ProviderCampaignIdentifier
|
|
23793
24623
|
}).strict();
|
|
23794
|
-
var ReportReturnsInput =
|
|
23795
|
-
projectId:
|
|
24624
|
+
var ReportReturnsInput = z91.object({
|
|
24625
|
+
projectId: z91.string().uuid(),
|
|
23796
24626
|
date: DateOnly,
|
|
23797
|
-
returnedOrders:
|
|
23798
|
-
note:
|
|
24627
|
+
returnedOrders: z91.number().int().min(0).max(1e5),
|
|
24628
|
+
note: z91.string().trim().max(280).optional()
|
|
23799
24629
|
}).strict();
|
|
23800
|
-
var DailyControlStatusMirror = DailyControlStatusEnum.or(
|
|
23801
|
-
var DailyControlLightMirror = DailyControlLightEnum.or(
|
|
23802
|
-
var DailyControlSourceMirror = DailyControlSourceEnum.or(
|
|
23803
|
-
var DailyControlVerdictMirror = DailyControlVerdictEnum.or(
|
|
23804
|
-
var DailyControlDayMirror =
|
|
23805
|
-
date:
|
|
23806
|
-
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(),
|
|
23807
24637
|
returnedSource: DailyControlSourceMirror,
|
|
23808
24638
|
cancelledSource: DailyControlSourceMirror,
|
|
23809
|
-
hasEstimates:
|
|
24639
|
+
hasEstimates: z91.boolean(),
|
|
23810
24640
|
light: DailyControlLightMirror
|
|
23811
24641
|
}).passthrough();
|
|
23812
|
-
var DailyControlProductMirror =
|
|
23813
|
-
projectId:
|
|
23814
|
-
productName:
|
|
24642
|
+
var DailyControlProductMirror = z91.object({
|
|
24643
|
+
projectId: z91.string().uuid(),
|
|
24644
|
+
productName: z91.string().nullable(),
|
|
23815
24645
|
status: DailyControlStatusMirror,
|
|
23816
|
-
statusMessage:
|
|
23817
|
-
days:
|
|
24646
|
+
statusMessage: z91.string().nullable(),
|
|
24647
|
+
days: z91.array(DailyControlDayMirror),
|
|
23818
24648
|
verdict: DailyControlVerdictMirror.nullable(),
|
|
23819
|
-
rationale:
|
|
24649
|
+
rationale: z91.string().nullable()
|
|
23820
24650
|
}).passthrough();
|
|
23821
|
-
var DailyControlResponseMirror =
|
|
23822
|
-
since:
|
|
23823
|
-
until:
|
|
23824
|
-
products:
|
|
23825
|
-
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())
|
|
23826
24656
|
}).passthrough();
|
|
23827
24657
|
var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
|
|
23828
24658
|
function withWarnings(response) {
|
|
@@ -23906,42 +24736,42 @@ function registerDailyControlTools(server, api) {
|
|
|
23906
24736
|
__name(registerDailyControlTools, "registerDailyControlTools");
|
|
23907
24737
|
|
|
23908
24738
|
// src/tools/product-control.ts
|
|
23909
|
-
import { z as
|
|
24739
|
+
import { z as z92 } from "zod";
|
|
23910
24740
|
var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
|
|
23911
24741
|
var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
|
|
23912
24742
|
var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
|
|
23913
24743
|
var setProductCostingGuidance = getProductMakerCapabilityModelGuidance("set_product_costing");
|
|
23914
24744
|
var reportProductCountsGuidance = getProductMakerCapabilityModelGuidance("report_product_counts");
|
|
23915
|
-
var DateOnly2 =
|
|
24745
|
+
var DateOnly2 = z92.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
23916
24746
|
var IMPORT_BATCH_MAX2 = 50;
|
|
23917
|
-
var ProductControlListInput =
|
|
23918
|
-
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."),
|
|
23919
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."),
|
|
23920
|
-
shopDomain:
|
|
24750
|
+
shopDomain: z92.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
|
|
23921
24751
|
}).strict();
|
|
23922
|
-
var ImportableProductsInput =
|
|
23923
|
-
q:
|
|
23924
|
-
after:
|
|
23925
|
-
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()
|
|
23926
24756
|
}).strict();
|
|
23927
|
-
var ImportProductControlsInput =
|
|
23928
|
-
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."),
|
|
23929
24759
|
// Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
|
|
23930
24760
|
// sin decir a cuál archivaría el producto bajo la tienda equivocada.
|
|
23931
|
-
shopDomain:
|
|
24761
|
+
shopDomain: z92.string().min(1)
|
|
23932
24762
|
}).strict();
|
|
23933
|
-
var SetProductCostingInput =
|
|
23934
|
-
shopDomain:
|
|
23935
|
-
shopifyProductId:
|
|
23936
|
-
targetCountry:
|
|
23937
|
-
supplierCost:
|
|
23938
|
-
shippingCost:
|
|
23939
|
-
returnRate:
|
|
23940
|
-
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)
|
|
23941
24771
|
}).strict();
|
|
23942
|
-
var Count =
|
|
23943
|
-
var ReportProductCountsInput =
|
|
23944
|
-
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."),
|
|
23945
24775
|
date: DateOnly2,
|
|
23946
24776
|
orders: Count.describe("Pedidos que entraron ese d\xEDa."),
|
|
23947
24777
|
cancelledOrders: Count,
|