@productmaker/mcp 6.1.0 → 6.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/http.js +787 -52
- package/dist/stdio.js +1637 -904
- package/package.json +1 -1
package/dist/http.js
CHANGED
|
@@ -9063,6 +9063,696 @@ var ServiceMediaAnalysisSchema = z45.object({
|
|
|
9063
9063
|
items: z45.array(ServiceMediaAnalysisItemSchema).max(15)
|
|
9064
9064
|
});
|
|
9065
9065
|
|
|
9066
|
+
// ../../packages/types/src/internal/deep-freeze.ts
|
|
9067
|
+
function deepFreeze(value) {
|
|
9068
|
+
if (value !== null && typeof value === "object") {
|
|
9069
|
+
for (const nested of Object.values(value)) {
|
|
9070
|
+
deepFreeze(nested);
|
|
9071
|
+
}
|
|
9072
|
+
Object.freeze(value);
|
|
9073
|
+
}
|
|
9074
|
+
return value;
|
|
9075
|
+
}
|
|
9076
|
+
__name(deepFreeze, "deepFreeze");
|
|
9077
|
+
|
|
9078
|
+
// ../../packages/types/src/productmaker-capability-model-guidance.ts
|
|
9079
|
+
var CAPABILITY_MODEL_GUIDANCE = {
|
|
9080
|
+
approve_video_script: {
|
|
9081
|
+
summary: "Aprueba el guion del video (con o sin ediciones).",
|
|
9082
|
+
useWhen: [
|
|
9083
|
+
"aprueba el guion del video",
|
|
9084
|
+
"la persona aprueba el guion del video, con o sin cambios"
|
|
9085
|
+
],
|
|
9086
|
+
avoidWhen: [
|
|
9087
|
+
"la persona quiere regenerar por completo el guion"
|
|
9088
|
+
],
|
|
9089
|
+
defaults: [
|
|
9090
|
+
"conserva las escenas que la persona no cambi\xF3"
|
|
9091
|
+
],
|
|
9092
|
+
disclosures: [
|
|
9093
|
+
"la aprobaci\xF3n inicia render pagado y requiere confirmaci\xF3n expl\xEDcita"
|
|
9094
|
+
]
|
|
9095
|
+
},
|
|
9096
|
+
check_meta_media_upload: {
|
|
9097
|
+
summary: "Comprueba si los medios preparados ya est\xE1n disponibles.",
|
|
9098
|
+
useWhen: [
|
|
9099
|
+
"ya termin\xE9 de subir los archivos de Meta",
|
|
9100
|
+
"la persona indica que termin\xF3 de preparar sus medios para Meta"
|
|
9101
|
+
],
|
|
9102
|
+
avoidWhen: [
|
|
9103
|
+
"todav\xEDa no existe una preparaci\xF3n de medios en curso"
|
|
9104
|
+
],
|
|
9105
|
+
defaults: [
|
|
9106
|
+
"si a\xFAn no est\xE1n disponibles, espera sin crear otra preparaci\xF3n"
|
|
9107
|
+
],
|
|
9108
|
+
disclosures: []
|
|
9109
|
+
},
|
|
9110
|
+
check_media_upload: {
|
|
9111
|
+
summary: "Comprueba si la preparaci\xF3n segura de medios termin\xF3.",
|
|
9112
|
+
useWhen: [
|
|
9113
|
+
"la persona indica que termin\xF3 de preparar sus medios"
|
|
9114
|
+
],
|
|
9115
|
+
avoidWhen: [
|
|
9116
|
+
"todav\xEDa no existe una preparaci\xF3n de medios en curso"
|
|
9117
|
+
],
|
|
9118
|
+
defaults: [
|
|
9119
|
+
"si a\xFAn no est\xE1n disponibles, espera sin crear otra preparaci\xF3n"
|
|
9120
|
+
],
|
|
9121
|
+
disclosures: []
|
|
9122
|
+
},
|
|
9123
|
+
cost_dropshipping_project: {
|
|
9124
|
+
summary: "Guarda el costeo de un proyecto guiado.",
|
|
9125
|
+
useWhen: [
|
|
9126
|
+
"calcula el margen de mi proyecto dropshipping",
|
|
9127
|
+
"la persona pide calcular el margen de su proyecto de dropshipping"
|
|
9128
|
+
],
|
|
9129
|
+
avoidWhen: [
|
|
9130
|
+
"la persona s\xF3lo quiere estimar un producto fuera de un proyecto"
|
|
9131
|
+
],
|
|
9132
|
+
defaults: [
|
|
9133
|
+
"recalcula el resultado can\xF3nico con los datos entregados"
|
|
9134
|
+
],
|
|
9135
|
+
disclosures: [
|
|
9136
|
+
"modifica el proyecto y requiere confirmaci\xF3n expl\xEDcita",
|
|
9137
|
+
"pide el costo real del proveedor y no lo inventes"
|
|
9138
|
+
]
|
|
9139
|
+
},
|
|
9140
|
+
cost_product: {
|
|
9141
|
+
summary: "Calcula GRATIS y sin cr\xE9ditos cu\xE1nto cobrar por un producto de dropshipping en cualquiera de los pa\xEDses disponibles en ProductMaker.",
|
|
9142
|
+
useWhen: [
|
|
9143
|
+
"cu\xE1nto cuesta este producto",
|
|
9144
|
+
"la persona pregunta cu\xE1nto cobrar, la rentabilidad o el margen de un producto"
|
|
9145
|
+
],
|
|
9146
|
+
avoidWhen: [
|
|
9147
|
+
"la persona quiere guardar el costeo de un proyecto guiado"
|
|
9148
|
+
],
|
|
9149
|
+
defaults: [
|
|
9150
|
+
"usa valores gu\xEDa editables salvo el costo real del proveedor"
|
|
9151
|
+
],
|
|
9152
|
+
disclosures: [
|
|
9153
|
+
"es una consulta gratuita y no crea tareas"
|
|
9154
|
+
]
|
|
9155
|
+
},
|
|
9156
|
+
create_creative_variant: {
|
|
9157
|
+
summary: "Crea un video, imagen o secci\xF3n de landing adicional dentro de una tarea existente.",
|
|
9158
|
+
useWhen: [
|
|
9159
|
+
"crea una variante de imagen",
|
|
9160
|
+
"la persona pide una variante creativa de una tarea existente"
|
|
9161
|
+
],
|
|
9162
|
+
avoidWhen: [
|
|
9163
|
+
"la persona todav\xEDa no tiene una tarea creativa de origen"
|
|
9164
|
+
],
|
|
9165
|
+
defaults: [
|
|
9166
|
+
"reutiliza el producto y referencias de la tarea de origen"
|
|
9167
|
+
],
|
|
9168
|
+
disclosures: [
|
|
9169
|
+
"es trabajo pagado; cotiza y espera confirmaci\xF3n expl\xEDcita"
|
|
9170
|
+
]
|
|
9171
|
+
},
|
|
9172
|
+
create_product_task: {
|
|
9173
|
+
summary: "Crea una tarea autopilot combinada.",
|
|
9174
|
+
useWhen: [
|
|
9175
|
+
"crea una landing y un video",
|
|
9176
|
+
"la persona pide expl\xEDcitamente al menos dos entregables entre landing, video e im\xE1genes creativas"
|
|
9177
|
+
],
|
|
9178
|
+
avoidWhen: [
|
|
9179
|
+
"la persona pide un solo entregable; usa su generador dedicado"
|
|
9180
|
+
],
|
|
9181
|
+
defaults: [
|
|
9182
|
+
"si la selecci\xF3n de resultados se omite, genera landing, video e im\xE1genes creativas en una misma tarea"
|
|
9183
|
+
],
|
|
9184
|
+
disclosures: [
|
|
9185
|
+
"debes resumir todos los resultados, cotizar y esperar confirmaci\xF3n expl\xEDcita"
|
|
9186
|
+
]
|
|
9187
|
+
},
|
|
9188
|
+
create_service_video: {
|
|
9189
|
+
summary: "Crea un video para un servicio desde su landing.",
|
|
9190
|
+
useWhen: [
|
|
9191
|
+
"crea un video para mi servicio",
|
|
9192
|
+
"la persona pide un video para promocionar un servicio"
|
|
9193
|
+
],
|
|
9194
|
+
avoidWhen: [
|
|
9195
|
+
"la persona pide un video de producto o un video libre"
|
|
9196
|
+
],
|
|
9197
|
+
defaults: [
|
|
9198
|
+
"usa la landing del servicio como contexto principal"
|
|
9199
|
+
],
|
|
9200
|
+
disclosures: [
|
|
9201
|
+
"es trabajo pagado y requiere confirmaci\xF3n expl\xEDcita"
|
|
9202
|
+
]
|
|
9203
|
+
},
|
|
9204
|
+
edit_image_creative: {
|
|
9205
|
+
summary: "Corrige UNA imagen ya generada de una tarea de creativos, sin regenerar el set completo.",
|
|
9206
|
+
useWhen: [
|
|
9207
|
+
"edita esta imagen creativa",
|
|
9208
|
+
"la persona pide editar una imagen creativa concreta"
|
|
9209
|
+
],
|
|
9210
|
+
avoidWhen: [
|
|
9211
|
+
"la persona pide regenerar todas las im\xE1genes"
|
|
9212
|
+
],
|
|
9213
|
+
defaults: [
|
|
9214
|
+
"modifica \xFAnicamente la imagen elegida"
|
|
9215
|
+
],
|
|
9216
|
+
disclosures: [
|
|
9217
|
+
"es trabajo pagado y requiere confirmaci\xF3n expl\xEDcita"
|
|
9218
|
+
]
|
|
9219
|
+
},
|
|
9220
|
+
edit_task_draft: {
|
|
9221
|
+
summary: "Edita el draft de un angle de marketing antes de la generaci\xF3n.",
|
|
9222
|
+
useWhen: [
|
|
9223
|
+
"edita el borrador del \xE1ngulo creativo",
|
|
9224
|
+
"la persona pide cambiar el borrador de un \xE1ngulo creativo"
|
|
9225
|
+
],
|
|
9226
|
+
avoidWhen: [
|
|
9227
|
+
"la generaci\xF3n ya termin\xF3"
|
|
9228
|
+
],
|
|
9229
|
+
defaults: [
|
|
9230
|
+
"conserva los campos que la persona no cambi\xF3"
|
|
9231
|
+
],
|
|
9232
|
+
disclosures: [
|
|
9233
|
+
"modifica el estado de la tarea y requiere confirmaci\xF3n expl\xEDcita"
|
|
9234
|
+
]
|
|
9235
|
+
},
|
|
9236
|
+
estimate_creative_variant: {
|
|
9237
|
+
summary: "Calcula el costo de crear una variante desde una tarea existente, sin consumir cr\xE9ditos.",
|
|
9238
|
+
useWhen: [
|
|
9239
|
+
"cu\xE1nto cuesta una variante creativa",
|
|
9240
|
+
"la persona pregunta cu\xE1nto cuesta una variante creativa"
|
|
9241
|
+
],
|
|
9242
|
+
avoidWhen: [
|
|
9243
|
+
"la persona ya confirm\xF3 que quiere crear la variante cotizada"
|
|
9244
|
+
],
|
|
9245
|
+
defaults: [
|
|
9246
|
+
"estima con la configuraci\xF3n real de la tarea de origen"
|
|
9247
|
+
],
|
|
9248
|
+
disclosures: [
|
|
9249
|
+
"la cotizaci\xF3n es gratuita y no crea la variante"
|
|
9250
|
+
]
|
|
9251
|
+
},
|
|
9252
|
+
find_winning_products: {
|
|
9253
|
+
summary: "Busca productos ganadores de dropshipping para un pa\xEDs y categor\xEDa, y explica POR QU\xC9 la IA eligi\xF3 cada uno (razones, riesgos y evidencia real de anuncios en Meta Ads).",
|
|
9254
|
+
useWhen: [
|
|
9255
|
+
"investiga productos ganadores para dropshipping",
|
|
9256
|
+
"la persona pide investigar productos ganadores para dropshipping"
|
|
9257
|
+
],
|
|
9258
|
+
avoidWhen: [
|
|
9259
|
+
"ya existe una investigaci\xF3n pagada \xFAtil para el mismo objetivo"
|
|
9260
|
+
],
|
|
9261
|
+
defaults: [
|
|
9262
|
+
"presenta razones, riesgos y evidencia por producto"
|
|
9263
|
+
],
|
|
9264
|
+
disclosures: [
|
|
9265
|
+
"cuesta 2000 cr\xE9ditos y requiere aceptaci\xF3n expl\xEDcita"
|
|
9266
|
+
]
|
|
9267
|
+
},
|
|
9268
|
+
generate_free_video: {
|
|
9269
|
+
summary: "Genera UN video libre con prompt/guion exacto, opcionalmente con imagen de referencia.",
|
|
9270
|
+
useWhen: [
|
|
9271
|
+
"genera un video libre creativo",
|
|
9272
|
+
"la persona pide un video libre con un prompt o guion espec\xEDfico"
|
|
9273
|
+
],
|
|
9274
|
+
avoidWhen: [
|
|
9275
|
+
"la persona pide un creativo de producto o de servicio"
|
|
9276
|
+
],
|
|
9277
|
+
defaults: [
|
|
9278
|
+
"respeta el prompt o guion entregado"
|
|
9279
|
+
],
|
|
9280
|
+
disclosures: [
|
|
9281
|
+
"es trabajo pagado; cotiza y espera confirmaci\xF3n expl\xEDcita"
|
|
9282
|
+
]
|
|
9283
|
+
},
|
|
9284
|
+
generate_image_creatives: {
|
|
9285
|
+
summary: "Genera variantes de imagen creativa.",
|
|
9286
|
+
useWhen: [
|
|
9287
|
+
"genera im\xE1genes creativas del producto",
|
|
9288
|
+
"la persona pide im\xE1genes creativas de un producto"
|
|
9289
|
+
],
|
|
9290
|
+
avoidWhen: [
|
|
9291
|
+
"la persona pide una sola edici\xF3n sobre una imagen existente"
|
|
9292
|
+
],
|
|
9293
|
+
defaults: [
|
|
9294
|
+
"genera s\xF3lo im\xE1genes creativas"
|
|
9295
|
+
],
|
|
9296
|
+
disclosures: [
|
|
9297
|
+
"es trabajo pagado; cotiza y espera confirmaci\xF3n expl\xEDcita"
|
|
9298
|
+
]
|
|
9299
|
+
},
|
|
9300
|
+
generate_landing: {
|
|
9301
|
+
summary: "Genera una landing page cl\xE1sica basada en im\xE1genes, lista para Shopify.",
|
|
9302
|
+
useWhen: [
|
|
9303
|
+
"genera una landing creativa",
|
|
9304
|
+
"quiero crear una landing page",
|
|
9305
|
+
"quiero crear una p\xE1gina de producto",
|
|
9306
|
+
"la persona pide \xFAnicamente una landing o p\xE1gina de producto"
|
|
9307
|
+
],
|
|
9308
|
+
avoidWhen: [
|
|
9309
|
+
"la persona pide un paquete combinado de dos o m\xE1s entregables"
|
|
9310
|
+
],
|
|
9311
|
+
defaults: [
|
|
9312
|
+
"genera \xFAnicamente la landing"
|
|
9313
|
+
],
|
|
9314
|
+
disclosures: [
|
|
9315
|
+
"es trabajo pagado y requiere cotizaci\xF3n y confirmaci\xF3n expl\xEDcita"
|
|
9316
|
+
]
|
|
9317
|
+
},
|
|
9318
|
+
generate_video_creative: {
|
|
9319
|
+
summary: "Genera entre 1 y 3 videos creativos independientes dentro de un mismo task.",
|
|
9320
|
+
useWhen: [
|
|
9321
|
+
"genera un video creativo",
|
|
9322
|
+
"la persona pide un video creativo de producto"
|
|
9323
|
+
],
|
|
9324
|
+
avoidWhen: [
|
|
9325
|
+
"la persona pide un paquete combinado o un video libre"
|
|
9326
|
+
],
|
|
9327
|
+
defaults: [
|
|
9328
|
+
"genera \xFAnicamente el video creativo"
|
|
9329
|
+
],
|
|
9330
|
+
disclosures: [
|
|
9331
|
+
"es trabajo pagado; cotiza y espera confirmaci\xF3n expl\xEDcita"
|
|
9332
|
+
]
|
|
9333
|
+
},
|
|
9334
|
+
get_meta_campaign_status: {
|
|
9335
|
+
summary: "Consulta el estado actual + m\xE9tricas lifetime (spend, impressions, clicks, reach) de una campa\xF1a Meta publicada.",
|
|
9336
|
+
useWhen: [
|
|
9337
|
+
"consulta el estado de la campa\xF1a Meta",
|
|
9338
|
+
"la persona pregunta por el estado o rendimiento de una campa\xF1a Meta"
|
|
9339
|
+
],
|
|
9340
|
+
avoidWhen: [
|
|
9341
|
+
"la campa\xF1a a\xFAn no fue publicada"
|
|
9342
|
+
],
|
|
9343
|
+
defaults: [
|
|
9344
|
+
"devuelve m\xE9tricas acumuladas sin modificar la campa\xF1a"
|
|
9345
|
+
],
|
|
9346
|
+
disclosures: [
|
|
9347
|
+
"es una consulta de solo lectura"
|
|
9348
|
+
]
|
|
9349
|
+
},
|
|
9350
|
+
get_daily_control: {
|
|
9351
|
+
summary: "Muestra el control diario de rentabilidad por producto con m\xE9tricas, sem\xE1foro y veredicto.",
|
|
9352
|
+
useWhen: [
|
|
9353
|
+
"revisa la rentabilidad diaria de mis productos",
|
|
9354
|
+
"la persona quiere decidir si escalar, mantener o detener un producto"
|
|
9355
|
+
],
|
|
9356
|
+
avoidWhen: [
|
|
9357
|
+
"la persona quiere modificar una campa\xF1a publicitaria"
|
|
9358
|
+
],
|
|
9359
|
+
defaults: [
|
|
9360
|
+
"consulta los \xFAltimos tres d\xEDas cerrados"
|
|
9361
|
+
],
|
|
9362
|
+
disclosures: [
|
|
9363
|
+
"es una consulta de solo lectura y distingue cifras medidas de estimadas"
|
|
9364
|
+
]
|
|
9365
|
+
},
|
|
9366
|
+
get_product_research_run: {
|
|
9367
|
+
summary: "Devuelve el reporte completo de una investigaci\xF3n de productos ganadores: score, veredicto, confianza, razones, riesgos y evidencia de Meta Ads por producto.",
|
|
9368
|
+
useWhen: [
|
|
9369
|
+
"consulta el estado de la investigaci\xF3n",
|
|
9370
|
+
"la persona pide consultar una investigaci\xF3n existente"
|
|
9371
|
+
],
|
|
9372
|
+
avoidWhen: [
|
|
9373
|
+
"la persona quiere iniciar una investigaci\xF3n nueva"
|
|
9374
|
+
],
|
|
9375
|
+
defaults: [
|
|
9376
|
+
"devuelve el reporte completo disponible"
|
|
9377
|
+
],
|
|
9378
|
+
disclosures: [
|
|
9379
|
+
"es una consulta gratuita y de solo lectura"
|
|
9380
|
+
]
|
|
9381
|
+
},
|
|
9382
|
+
get_task_status: {
|
|
9383
|
+
summary: "Devuelve estado y entregables.",
|
|
9384
|
+
useWhen: [
|
|
9385
|
+
"consulta el estado de mi tarea",
|
|
9386
|
+
"la persona pide consultar el estado o resultado de una tarea"
|
|
9387
|
+
],
|
|
9388
|
+
avoidWhen: [
|
|
9389
|
+
"todav\xEDa no existe una tarea identificable"
|
|
9390
|
+
],
|
|
9391
|
+
defaults: [
|
|
9392
|
+
"contin\xFAa consultando hasta una revisi\xF3n o estado terminal cuando corresponda"
|
|
9393
|
+
],
|
|
9394
|
+
disclosures: [
|
|
9395
|
+
"es una consulta de solo lectura"
|
|
9396
|
+
]
|
|
9397
|
+
},
|
|
9398
|
+
get_tiktok_campaign_status: {
|
|
9399
|
+
summary: "Consulta el estado actual + reporte lifetime (spend, impressions, clicks, reach) de una campa\xF1a TikTok publicada.",
|
|
9400
|
+
useWhen: [
|
|
9401
|
+
"consulta el estado de la campa\xF1a TikTok",
|
|
9402
|
+
"la persona pregunta por el estado o rendimiento de una campa\xF1a TikTok"
|
|
9403
|
+
],
|
|
9404
|
+
avoidWhen: [
|
|
9405
|
+
"la campa\xF1a a\xFAn no fue publicada"
|
|
9406
|
+
],
|
|
9407
|
+
defaults: [
|
|
9408
|
+
"devuelve m\xE9tricas acumuladas sin modificar la campa\xF1a"
|
|
9409
|
+
],
|
|
9410
|
+
disclosures: [
|
|
9411
|
+
"es una consulta de solo lectura"
|
|
9412
|
+
]
|
|
9413
|
+
},
|
|
9414
|
+
get_video_script: {
|
|
9415
|
+
summary: "Lee el guion del video pendiente de revisi\xF3n.",
|
|
9416
|
+
useWhen: [
|
|
9417
|
+
"consulta el guion del video",
|
|
9418
|
+
"la persona pide consultar el guion de un video en revisi\xF3n"
|
|
9419
|
+
],
|
|
9420
|
+
avoidWhen: [
|
|
9421
|
+
"la tarea no tiene revisi\xF3n de guion pendiente"
|
|
9422
|
+
],
|
|
9423
|
+
defaults: [
|
|
9424
|
+
"conserva el contenido del guion sin modificarlo"
|
|
9425
|
+
],
|
|
9426
|
+
disclosures: [
|
|
9427
|
+
"es una consulta de solo lectura"
|
|
9428
|
+
]
|
|
9429
|
+
},
|
|
9430
|
+
guide_dropshipping_launch: {
|
|
9431
|
+
summary: "Gu\xEDa read-only de un recorrido COMPLETO de dropshipping, desde producto/costeo hasta creativos, tienda y publicidad.",
|
|
9432
|
+
useWhen: [
|
|
9433
|
+
"ay\xFAdame con mi proyecto dropshipping",
|
|
9434
|
+
"la persona pide ayuda para avanzar un proyecto completo de dropshipping"
|
|
9435
|
+
],
|
|
9436
|
+
avoidWhen: [
|
|
9437
|
+
"la persona pide una operaci\xF3n puntual"
|
|
9438
|
+
],
|
|
9439
|
+
defaults: [
|
|
9440
|
+
"propone el siguiente paso sin ejecutar cambios"
|
|
9441
|
+
],
|
|
9442
|
+
disclosures: [
|
|
9443
|
+
"es una gu\xEDa de solo lectura y no activa campa\xF1as"
|
|
9444
|
+
]
|
|
9445
|
+
},
|
|
9446
|
+
list_actors: {
|
|
9447
|
+
summary: "Lista los personajes guardados del usuario (personas creadas con IA que pueden protagonizar los videos e im\xE1genes).",
|
|
9448
|
+
useWhen: [
|
|
9449
|
+
"lista mis personajes disponibles",
|
|
9450
|
+
"la persona pide ver sus personajes disponibles"
|
|
9451
|
+
],
|
|
9452
|
+
avoidWhen: [
|
|
9453
|
+
"la persona quiere crear un personaje nuevo"
|
|
9454
|
+
],
|
|
9455
|
+
defaults: [
|
|
9456
|
+
"muestra \xFAnicamente personajes listos para usar"
|
|
9457
|
+
],
|
|
9458
|
+
disclosures: [
|
|
9459
|
+
"es una consulta de solo lectura"
|
|
9460
|
+
]
|
|
9461
|
+
},
|
|
9462
|
+
link_campaign_to_project: {
|
|
9463
|
+
summary: "Vincula una campa\xF1a publicitaria existente con un proyecto para incluir su gasto en el control diario.",
|
|
9464
|
+
useWhen: [
|
|
9465
|
+
"vincula esta campa\xF1a con mi proyecto",
|
|
9466
|
+
"la persona quiere medir una campa\xF1a creada fuera de ProductMaker"
|
|
9467
|
+
],
|
|
9468
|
+
avoidWhen: [
|
|
9469
|
+
"la campa\xF1a ya est\xE1 vinculada al proyecto correcto"
|
|
9470
|
+
],
|
|
9471
|
+
defaults: [
|
|
9472
|
+
"verifica la propiedad de la campa\xF1a antes de vincularla"
|
|
9473
|
+
],
|
|
9474
|
+
disclosures: [
|
|
9475
|
+
"modifica el proyecto y requiere confirmaci\xF3n expl\xEDcita; no modifica la campa\xF1a publicitaria"
|
|
9476
|
+
]
|
|
9477
|
+
},
|
|
9478
|
+
list_meta_ad_accounts: {
|
|
9479
|
+
summary: "Lista las cuentas publicitarias de Meta conectadas.",
|
|
9480
|
+
useWhen: [
|
|
9481
|
+
"lista mis cuentas publicitarias de Meta",
|
|
9482
|
+
"la persona pide ver sus cuentas publicitarias de Meta"
|
|
9483
|
+
],
|
|
9484
|
+
avoidWhen: [
|
|
9485
|
+
"la persona necesita elegir adem\xE1s portfolio y p\xE1gina"
|
|
9486
|
+
],
|
|
9487
|
+
defaults: [
|
|
9488
|
+
"muestra \xFAnicamente cuentas conectadas"
|
|
9489
|
+
],
|
|
9490
|
+
disclosures: [
|
|
9491
|
+
"es una consulta de solo lectura"
|
|
9492
|
+
]
|
|
9493
|
+
},
|
|
9494
|
+
list_meta_destinations: {
|
|
9495
|
+
summary: "Lista los destinos de publicaci\xF3n de Meta del usuario: Business portfolios, cuentas publicitarias dentro de cada portfolio y Facebook Pages disponibles.",
|
|
9496
|
+
useWhen: [
|
|
9497
|
+
"lista mis destinos de Meta",
|
|
9498
|
+
"la persona necesita elegir un destino antes de publicar en Meta"
|
|
9499
|
+
],
|
|
9500
|
+
avoidWhen: [
|
|
9501
|
+
"la persona s\xF3lo pregunta por el estado de una campa\xF1a"
|
|
9502
|
+
],
|
|
9503
|
+
defaults: [
|
|
9504
|
+
"presenta las opciones para que la persona elija"
|
|
9505
|
+
],
|
|
9506
|
+
disclosures: [
|
|
9507
|
+
"es una consulta de solo lectura y no elige silenciosamente"
|
|
9508
|
+
]
|
|
9509
|
+
},
|
|
9510
|
+
list_product_research_runs: {
|
|
9511
|
+
summary: "Lista las investigaciones de productos ganadores ya pagadas por el usuario, de la m\xE1s reciente a la m\xE1s antigua.",
|
|
9512
|
+
useWhen: [
|
|
9513
|
+
"lista mis investigaciones de productos",
|
|
9514
|
+
"la persona pide ver sus investigaciones de productos"
|
|
9515
|
+
],
|
|
9516
|
+
avoidWhen: [
|
|
9517
|
+
"la persona ya eligi\xF3 una investigaci\xF3n concreta para consultar"
|
|
9518
|
+
],
|
|
9519
|
+
defaults: [
|
|
9520
|
+
"ordena de la m\xE1s reciente a la m\xE1s antigua"
|
|
9521
|
+
],
|
|
9522
|
+
disclosures: [
|
|
9523
|
+
"es una consulta gratuita y de solo lectura"
|
|
9524
|
+
]
|
|
9525
|
+
},
|
|
9526
|
+
list_shopify_products: {
|
|
9527
|
+
summary: "Busca productos en una tienda Shopify conectada para elegir el target de una republicaci\xF3n.",
|
|
9528
|
+
useWhen: [
|
|
9529
|
+
"lista los productos de mi tienda Shopify",
|
|
9530
|
+
"la persona pide listar productos de su tienda Shopify"
|
|
9531
|
+
],
|
|
9532
|
+
avoidWhen: [
|
|
9533
|
+
"la persona s\xF3lo necesita listar sus tiendas conectadas"
|
|
9534
|
+
],
|
|
9535
|
+
defaults: [
|
|
9536
|
+
"no modifica ning\xFAn producto"
|
|
9537
|
+
],
|
|
9538
|
+
disclosures: [
|
|
9539
|
+
"es una consulta de solo lectura"
|
|
9540
|
+
]
|
|
9541
|
+
},
|
|
9542
|
+
list_shopify_shops: {
|
|
9543
|
+
summary: "Lista las tiendas Shopify conectadas por este usuario.",
|
|
9544
|
+
useWhen: [
|
|
9545
|
+
"lista mis tiendas Shopify conectadas",
|
|
9546
|
+
"la persona pide ver sus tiendas Shopify conectadas"
|
|
9547
|
+
],
|
|
9548
|
+
avoidWhen: [
|
|
9549
|
+
"la persona ya eligi\xF3 una tienda y busca un producto"
|
|
9550
|
+
],
|
|
9551
|
+
defaults: [
|
|
9552
|
+
"muestra \xFAnicamente tiendas conectadas"
|
|
9553
|
+
],
|
|
9554
|
+
disclosures: [
|
|
9555
|
+
"es una consulta de solo lectura"
|
|
9556
|
+
]
|
|
9557
|
+
},
|
|
9558
|
+
list_tasks: {
|
|
9559
|
+
summary: "Lista de forma read-only las tareas recientes del usuario.",
|
|
9560
|
+
useWhen: [
|
|
9561
|
+
"lista mis tareas recientes",
|
|
9562
|
+
"la persona pide listar o buscar sus tareas recientes"
|
|
9563
|
+
],
|
|
9564
|
+
avoidWhen: [
|
|
9565
|
+
"la persona ya identific\xF3 una tarea y pide su estado"
|
|
9566
|
+
],
|
|
9567
|
+
defaults: [
|
|
9568
|
+
"muestra las tareas recientes sin modificarlas"
|
|
9569
|
+
],
|
|
9570
|
+
disclosures: [
|
|
9571
|
+
"es una consulta de solo lectura"
|
|
9572
|
+
]
|
|
9573
|
+
},
|
|
9574
|
+
list_tiktok_advertisers: {
|
|
9575
|
+
summary: "Lista las cuentas de TikTok Ads conectadas.",
|
|
9576
|
+
useWhen: [
|
|
9577
|
+
"lista mis anunciantes TikTok conectados",
|
|
9578
|
+
"la persona pide ver sus anunciantes TikTok conectados"
|
|
9579
|
+
],
|
|
9580
|
+
avoidWhen: [
|
|
9581
|
+
"la persona s\xF3lo pregunta por el estado de una campa\xF1a"
|
|
9582
|
+
],
|
|
9583
|
+
defaults: [
|
|
9584
|
+
"muestra \xFAnicamente cuentas conectadas"
|
|
9585
|
+
],
|
|
9586
|
+
disclosures: [
|
|
9587
|
+
"es una consulta de solo lectura"
|
|
9588
|
+
]
|
|
9589
|
+
},
|
|
9590
|
+
publish_creatives_to_meta: {
|
|
9591
|
+
summary: "Crea UNA campa\xF1a de Meta Ads PAUSED agrupando hasta 10 creativos.",
|
|
9592
|
+
useWhen: [
|
|
9593
|
+
"publica estos creativos en Meta",
|
|
9594
|
+
"la persona pide publicar varios creativos juntos en Meta"
|
|
9595
|
+
],
|
|
9596
|
+
avoidWhen: [
|
|
9597
|
+
"la persona quiere publicar creativos de una sola tarea"
|
|
9598
|
+
],
|
|
9599
|
+
defaults: [
|
|
9600
|
+
"crea la campa\xF1a pausada con los creativos confirmados"
|
|
9601
|
+
],
|
|
9602
|
+
disclosures: [
|
|
9603
|
+
"requiere destino y confirmaci\xF3n expl\xEDcitos; el gasto publicitario es externo"
|
|
9604
|
+
]
|
|
9605
|
+
},
|
|
9606
|
+
publish_to_meta: {
|
|
9607
|
+
summary: "Publica tus creativos en Meta sin gastar cr\xE9ditos de ProductMaker.",
|
|
9608
|
+
useWhen: [
|
|
9609
|
+
"publica la campa\xF1a en Meta",
|
|
9610
|
+
"la persona pide publicar en Meta los creativos de una tarea"
|
|
9611
|
+
],
|
|
9612
|
+
avoidWhen: [
|
|
9613
|
+
"la persona quiere agrupar creativos de varias tareas"
|
|
9614
|
+
],
|
|
9615
|
+
defaults: [
|
|
9616
|
+
"crea la campa\xF1a pausada"
|
|
9617
|
+
],
|
|
9618
|
+
disclosures: [
|
|
9619
|
+
"requiere destino y confirmaci\xF3n expl\xEDcitos; el gasto publicitario es externo"
|
|
9620
|
+
]
|
|
9621
|
+
},
|
|
9622
|
+
publish_to_shopify: {
|
|
9623
|
+
summary: "Publica o actualiza la landing en una tienda Shopify conectada.",
|
|
9624
|
+
useWhen: [
|
|
9625
|
+
"publica el producto en Shopify",
|
|
9626
|
+
"la persona pide publicar un producto o landing en Shopify"
|
|
9627
|
+
],
|
|
9628
|
+
avoidWhen: [
|
|
9629
|
+
"la tarea todav\xEDa no est\xE1 completa"
|
|
9630
|
+
],
|
|
9631
|
+
defaults: [
|
|
9632
|
+
"actualiza la publicaci\xF3n existente de esa tarea o crea una nueva"
|
|
9633
|
+
],
|
|
9634
|
+
disclosures: [
|
|
9635
|
+
"requiere tienda, variantes y confirmaci\xF3n expl\xEDcitas"
|
|
9636
|
+
]
|
|
9637
|
+
},
|
|
9638
|
+
publish_to_tiktok: {
|
|
9639
|
+
summary: "Crea una campa\xF1a de TikTok Ads desde la tarea.",
|
|
9640
|
+
useWhen: [
|
|
9641
|
+
"publica la campa\xF1a en TikTok",
|
|
9642
|
+
"la persona pide publicar una campa\xF1a en TikTok"
|
|
9643
|
+
],
|
|
9644
|
+
avoidWhen: [
|
|
9645
|
+
"la tarea todav\xEDa no tiene creativos publicables"
|
|
9646
|
+
],
|
|
9647
|
+
defaults: [
|
|
9648
|
+
"crea la campa\xF1a pausada"
|
|
9649
|
+
],
|
|
9650
|
+
disclosures: [
|
|
9651
|
+
"requiere anunciante y confirmaci\xF3n expl\xEDcitos; el gasto publicitario es externo"
|
|
9652
|
+
]
|
|
9653
|
+
},
|
|
9654
|
+
regenerate_video_script: {
|
|
9655
|
+
summary: "Re-rolea (regenera) el guion del video pendiente de revisi\xF3n.",
|
|
9656
|
+
useWhen: [
|
|
9657
|
+
"regenera el guion del video creativo",
|
|
9658
|
+
"la persona pide regenerar el guion completo del video"
|
|
9659
|
+
],
|
|
9660
|
+
avoidWhen: [
|
|
9661
|
+
"la persona quiere editar s\xF3lo algunas escenas"
|
|
9662
|
+
],
|
|
9663
|
+
defaults: [
|
|
9664
|
+
"mantiene la tarea y reemplaza el guion pendiente"
|
|
9665
|
+
],
|
|
9666
|
+
disclosures: [
|
|
9667
|
+
"consume cr\xE9ditos y requiere confirmaci\xF3n expl\xEDcita salvo recuperaci\xF3n necesaria"
|
|
9668
|
+
]
|
|
9669
|
+
},
|
|
9670
|
+
report_daily_returns: {
|
|
9671
|
+
summary: "Registra el n\xFAmero real de pedidos devueltos de un producto en un d\xEDa concreto.",
|
|
9672
|
+
useWhen: [
|
|
9673
|
+
"registra las devoluciones reales de ayer",
|
|
9674
|
+
"la persona conoce el n\xFAmero real de devoluciones de un producto"
|
|
9675
|
+
],
|
|
9676
|
+
avoidWhen: [
|
|
9677
|
+
"la persona no conoce el dato exacto"
|
|
9678
|
+
],
|
|
9679
|
+
defaults: [
|
|
9680
|
+
"reemplaza la estimaci\xF3n de ese d\xEDa con el dato informado"
|
|
9681
|
+
],
|
|
9682
|
+
disclosures: [
|
|
9683
|
+
"modifica el control diario y requiere confirmaci\xF3n expl\xEDcita; nunca inventes el n\xFAmero"
|
|
9684
|
+
]
|
|
9685
|
+
},
|
|
9686
|
+
request_meta_media_upload: {
|
|
9687
|
+
summary: "Prepara im\xE1genes o videos del usuario para una publicaci\xF3n en Meta.",
|
|
9688
|
+
useWhen: [
|
|
9689
|
+
"quiero subir una imagen a Meta",
|
|
9690
|
+
"la persona necesita preparar im\xE1genes o videos para Meta"
|
|
9691
|
+
],
|
|
9692
|
+
avoidWhen: [
|
|
9693
|
+
"los medios ya est\xE1n disponibles para la publicaci\xF3n"
|
|
9694
|
+
],
|
|
9695
|
+
defaults: [
|
|
9696
|
+
"prepara s\xF3lo los medios solicitados"
|
|
9697
|
+
],
|
|
9698
|
+
disclosures: [
|
|
9699
|
+
"no genera creativos ni publica campa\xF1as"
|
|
9700
|
+
]
|
|
9701
|
+
},
|
|
9702
|
+
request_media_upload: {
|
|
9703
|
+
summary: "Abre el selector universal de ProductMaker para im\xE1genes o videos del usuario.",
|
|
9704
|
+
useWhen: [
|
|
9705
|
+
"la persona necesita preparar im\xE1genes o videos para otra capacidad"
|
|
9706
|
+
],
|
|
9707
|
+
avoidWhen: [
|
|
9708
|
+
"los medios ya est\xE1n disponibles para la capacidad solicitada"
|
|
9709
|
+
],
|
|
9710
|
+
defaults: [
|
|
9711
|
+
"prepara s\xF3lo los medios solicitados"
|
|
9712
|
+
],
|
|
9713
|
+
disclosures: [
|
|
9714
|
+
"no genera creativos, publica ni consume cr\xE9ditos"
|
|
9715
|
+
]
|
|
9716
|
+
},
|
|
9717
|
+
resolve_pending_action: {
|
|
9718
|
+
summary: "Resuelve la decisi\xF3n pendiente de una tarea usando la respuesta o delegaci\xF3n expl\xEDcita de la persona.",
|
|
9719
|
+
useWhen: [
|
|
9720
|
+
"confirma la acci\xF3n pendiente del video",
|
|
9721
|
+
"la persona responde o delega una decisi\xF3n pendiente"
|
|
9722
|
+
],
|
|
9723
|
+
avoidWhen: [
|
|
9724
|
+
"todav\xEDa no existe una decisi\xF3n pendiente o la persona no respondi\xF3"
|
|
9725
|
+
],
|
|
9726
|
+
defaults: [
|
|
9727
|
+
"aplica \xFAnicamente la decisi\xF3n expresada"
|
|
9728
|
+
],
|
|
9729
|
+
disclosures: [
|
|
9730
|
+
"puede iniciar trabajo pagado y requiere autoridad expl\xEDcita"
|
|
9731
|
+
]
|
|
9732
|
+
},
|
|
9733
|
+
start_dropshipping_project: {
|
|
9734
|
+
summary: "Inicia o reanuda un proyecto opcional de dropshipping.",
|
|
9735
|
+
useWhen: [
|
|
9736
|
+
"inicia un proyecto dropshipping",
|
|
9737
|
+
"la persona pide iniciar o continuar un proyecto de dropshipping"
|
|
9738
|
+
],
|
|
9739
|
+
avoidWhen: [
|
|
9740
|
+
"la persona s\xF3lo pide una operaci\xF3n puntual"
|
|
9741
|
+
],
|
|
9742
|
+
defaults: [
|
|
9743
|
+
"conserva el progreso existente cuando corresponde"
|
|
9744
|
+
],
|
|
9745
|
+
disclosures: [
|
|
9746
|
+
"modifica el proyecto, no consume cr\xE9ditos y requiere confirmaci\xF3n expl\xEDcita"
|
|
9747
|
+
]
|
|
9748
|
+
}
|
|
9749
|
+
};
|
|
9750
|
+
var PRODUCTMAKER_CAPABILITY_MODEL_GUIDANCE = deepFreeze(CAPABILITY_MODEL_GUIDANCE);
|
|
9751
|
+
function getProductMakerCapabilityModelGuidance(name) {
|
|
9752
|
+
return PRODUCTMAKER_CAPABILITY_MODEL_GUIDANCE[name];
|
|
9753
|
+
}
|
|
9754
|
+
__name(getProductMakerCapabilityModelGuidance, "getProductMakerCapabilityModelGuidance");
|
|
9755
|
+
|
|
9066
9756
|
// ../../packages/types/src/daily-control.ts
|
|
9067
9757
|
import { z as z46 } from "zod";
|
|
9068
9758
|
var DailyControlStatusSchema = z46.enum([
|
|
@@ -9432,6 +10122,7 @@ var WHATSAPP_ONLY_CHANNEL_EXPOSURE = {
|
|
|
9432
10122
|
function defineCapability(name, schemaHash, confirmation, routingDomain, effects, inputSlots, consumes, produces, channelExposure = SHARED_CHANNEL_EXPOSURE, conversationInputs) {
|
|
9433
10123
|
return {
|
|
9434
10124
|
name,
|
|
10125
|
+
modelGuidance: getProductMakerCapabilityModelGuidance(name),
|
|
9435
10126
|
schemaHash,
|
|
9436
10127
|
confirmation,
|
|
9437
10128
|
routingDomain,
|
|
@@ -9472,6 +10163,7 @@ function slot(name, required, mcp2, whatsapp = mcp2, source = "user") {
|
|
|
9472
10163
|
__name(slot, "slot");
|
|
9473
10164
|
var SERVER_SELECTED_OR_ARTIFACT_FIELDS = /* @__PURE__ */ new Set([
|
|
9474
10165
|
"actionKind",
|
|
10166
|
+
"accountId",
|
|
9475
10167
|
"actorId",
|
|
9476
10168
|
"adAccountId",
|
|
9477
10169
|
"advertiserId",
|
|
@@ -9479,6 +10171,7 @@ var SERVER_SELECTED_OR_ARTIFACT_FIELDS = /* @__PURE__ */ new Set([
|
|
|
9479
10171
|
"campaignId",
|
|
9480
10172
|
"projectId",
|
|
9481
10173
|
"pixelId",
|
|
10174
|
+
"provider",
|
|
9482
10175
|
"runId",
|
|
9483
10176
|
"sessionId",
|
|
9484
10177
|
"shopDomain",
|
|
@@ -9494,16 +10187,6 @@ function whatsappFieldAuthority(field, source) {
|
|
|
9494
10187
|
return SERVER_SELECTED_OR_ARTIFACT_FIELDS.has(field) ? "server_selected_or_artifact" : "user";
|
|
9495
10188
|
}
|
|
9496
10189
|
__name(whatsappFieldAuthority, "whatsappFieldAuthority");
|
|
9497
|
-
function deepFreeze(value) {
|
|
9498
|
-
if (value !== null && typeof value === "object") {
|
|
9499
|
-
for (const nested of Object.values(value)) {
|
|
9500
|
-
deepFreeze(nested);
|
|
9501
|
-
}
|
|
9502
|
-
Object.freeze(value);
|
|
9503
|
-
}
|
|
9504
|
-
return value;
|
|
9505
|
-
}
|
|
9506
|
-
__name(deepFreeze, "deepFreeze");
|
|
9507
10190
|
var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
9508
10191
|
defineCapability("approve_video_script", "bab794a9700a8d3f42b97f444a776e7ed4dcd833038c52588f951b50970ff3fa", "credit_consuming", "creative", [
|
|
9509
10192
|
"credit_consuming",
|
|
@@ -10515,7 +11198,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
10515
11198
|
"campaign_link"
|
|
10516
11199
|
], [
|
|
10517
11200
|
"daily_control_report"
|
|
10518
|
-
]
|
|
11201
|
+
]),
|
|
10519
11202
|
defineCapability("link_campaign_to_project", "42785a9781412e0ad7cf7095b7188f315dea4003002777d5a4b1b9cc79ea05e0", "state_change", "business", [
|
|
10520
11203
|
"state_change"
|
|
10521
11204
|
], [
|
|
@@ -10535,7 +11218,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
10535
11218
|
"dropshipping_project"
|
|
10536
11219
|
], [
|
|
10537
11220
|
"campaign_link"
|
|
10538
|
-
]
|
|
11221
|
+
]),
|
|
10539
11222
|
defineCapability("report_daily_returns", "7130d216656cc29a47fc972b4edad5003a6653fca48d95052fbf2b561636e91a", "state_change", "business", [
|
|
10540
11223
|
"state_change"
|
|
10541
11224
|
], [
|
|
@@ -10555,7 +11238,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
10555
11238
|
"dropshipping_project"
|
|
10556
11239
|
], [
|
|
10557
11240
|
"daily_control_report"
|
|
10558
|
-
]
|
|
11241
|
+
])
|
|
10559
11242
|
]);
|
|
10560
11243
|
var PRODUCTMAKER_CAPABILITY_NAMES = PRODUCTMAKER_CAPABILITY_REGISTRY.map((capability) => capability.name);
|
|
10561
11244
|
var PRODUCTMAKER_MCP_CAPABILITY_REGISTRY = PRODUCTMAKER_CAPABILITY_REGISTRY.filter((capability) => capability.channelExposure.mcp === "direct");
|
|
@@ -12233,7 +12916,7 @@ var ApiClient = class {
|
|
|
12233
12916
|
};
|
|
12234
12917
|
|
|
12235
12918
|
// src/index.ts
|
|
12236
|
-
var MCP_VERSION = "6.1.
|
|
12919
|
+
var MCP_VERSION = "6.1.1";
|
|
12237
12920
|
|
|
12238
12921
|
// src/meta-upload-app.ts
|
|
12239
12922
|
import { readFileSync } from "fs";
|
|
@@ -14244,6 +14927,21 @@ ${summary}`,
|
|
|
14244
14927
|
__name(requirePaidCreativeConfirmation, "requirePaidCreativeConfirmation");
|
|
14245
14928
|
|
|
14246
14929
|
// src/tools/tasks.ts
|
|
14930
|
+
var createProductTaskGuidance = getProductMakerCapabilityModelGuidance("create_product_task");
|
|
14931
|
+
function renderCreateProductTaskDefaultForMcp(fragment) {
|
|
14932
|
+
const outputs = fragment.match(/genera (landing), (video) e (imágenes creativas)/u);
|
|
14933
|
+
return outputs ? `Por defecto genera ${outputs[1]} + ${outputs[2]} + im\xE1genes en UN MISMO TASK.` : fragment;
|
|
14934
|
+
}
|
|
14935
|
+
__name(renderCreateProductTaskDefaultForMcp, "renderCreateProductTaskDefaultForMcp");
|
|
14936
|
+
function renderCreateProductTaskAvoidWhenForMcp(fragment) {
|
|
14937
|
+
return /un solo entregable/u.test(fragment) ? "Para 1 solo output, usa generate_landing / generate_video_creative / generate_image_creatives." : fragment;
|
|
14938
|
+
}
|
|
14939
|
+
__name(renderCreateProductTaskAvoidWhenForMcp, "renderCreateProductTaskAvoidWhenForMcp");
|
|
14940
|
+
var createProductTaskDefaultDescription = renderCreateProductTaskDefaultForMcp(createProductTaskGuidance.defaults[0]);
|
|
14941
|
+
var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenForMcp(createProductTaskGuidance.avoidWhen[0]);
|
|
14942
|
+
var createServiceVideoGuidance = getProductMakerCapabilityModelGuidance("create_service_video");
|
|
14943
|
+
var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
|
|
14944
|
+
var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
|
|
14247
14945
|
var CreateProductTaskInput = z52.object({
|
|
14248
14946
|
images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
|
|
14249
14947
|
projectId: z52.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
|
|
@@ -14271,7 +14969,7 @@ var CreateProductTaskInput = z52.object({
|
|
|
14271
14969
|
"landing",
|
|
14272
14970
|
"video",
|
|
14273
14971
|
"image"
|
|
14274
|
-
])).min(2).max(3).optional().describe(
|
|
14972
|
+
])).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}`),
|
|
14275
14973
|
competitorScanEnabled: z52.boolean().optional().describe("Opcional. Si true (default), el sistema analiza ads de competencia en Meta Ad Library y enriquece los \xE1ngulos generados con hooks y painPoints validados por el mercado (\u2248$0.20-0.48 extra por task \u2014 var\xEDa con cu\xE1ntas transcripciones de video se capturen). Si false, el pipeline genera \xE1ngulos sin esa se\xF1al \u2014 usa esto SOLO si el usuario ya tiene su propia investigaci\xF3n de mercado o quiere ahorrar costos en productos muy nicho sin presencia en Meta. Default true."),
|
|
14276
14974
|
replicateWinnerWhenFound: z52.boolean().optional().describe('Opcional. Consentimiento para que, si encontramos un anuncio GANADOR de la competencia que podemos replicar, ese ganador reemplace la narrativa concreta que el usuario eligi\xF3 (videoPreset). Default true: la r\xE9plica del ganador es el formato que mejor convierte y sigue ganando por defecto. P\xE1salo en false SOLO si el usuario dice expl\xEDcitamente que quiere conservar su estilo elegido pase lo que pase (ej. pidi\xF3 Pixar y quiere Pixar aunque haya un ganador live-action). Irrelevante cuando videoPreset es "auto" (no hay elecci\xF3n que respetar) o cuando competitorScanEnabled es false (nunca habr\xE1 ganador).'),
|
|
14277
14975
|
brandId: z52.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."),
|
|
@@ -14657,7 +15355,11 @@ function resolveServicePanelEdits(panels, editsByBeat, editsByScene, fieldLabel)
|
|
|
14657
15355
|
}
|
|
14658
15356
|
__name(resolveServicePanelEdits, "resolveServicePanelEdits");
|
|
14659
15357
|
function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http" } = {}) {
|
|
14660
|
-
server.tool("create_product_task",
|
|
15358
|
+
server.tool("create_product_task", createProductTaskGuidance.summary + ` ${createProductTaskDefaultDescription} \xDAsala cuando el usuario pide todo o varios outputs, no creando tareas individuales. Usa images para solicitudes directas. Usa projectId \xFAnicamente si el usuario pidi\xF3 expl\xEDcitamente continuar el proyecto guiado que acaba de costear; nunca busques, infieras ni menciones proyectos previos.
|
|
15359
|
+
|
|
15360
|
+
REQUERIDOS: images o projectId expl\xEDcito, language y country. Cuando los outputs incluyen video (tambi\xE9n por default), pregunta SIEMPRE videoAngleCount: 1, 2 o 3; es una decisi\xF3n de costo incluso con aiDecidesAll. Si falta una foto local, llama primero \`request_media_upload\`. Pregunta price, offer, paymentMethods y compareAtPrice cuando aplique; nunca asumas country/language.
|
|
15361
|
+
|
|
15362
|
+
ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explica que inicia trabajo pagado y espera confirmaci\xF3n expl\xEDcita. aiDecidesAll omitido/false pausa para reviews conversacionales; muestra todos los \xE1ngulos candidatos y permite escoger/editar hasta el m\xE1ximo autorizado. Usa aiDecidesAll=true s\xF3lo si el usuario pidi\xF3 \u201Cdecide todo\u201D o \u201Cno me preguntes\u201D.`, CreateProductTaskInput.shape, CREATES_EXTERNAL, async (input) => {
|
|
14661
15363
|
try {
|
|
14662
15364
|
const selectedOutputs = input.outputs ?? DEFAULT_PRODUCT_TASK_OUTPUTS;
|
|
14663
15365
|
if (!input.images && !input.projectId) {
|
|
@@ -14738,7 +15440,7 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
|
|
|
14738
15440
|
throw translateError(e);
|
|
14739
15441
|
}
|
|
14740
15442
|
});
|
|
14741
|
-
server.tool("create_service_video",
|
|
15443
|
+
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_EXTERNAL, async (input) => {
|
|
14742
15444
|
try {
|
|
14743
15445
|
await requirePaidCreativeConfirmation(server, `Video de servicio en ${input.language}. Modo: ${input.reviewMode === "automatic" ? "la IA decide todo" : "reviews conversacionales"}.`);
|
|
14744
15446
|
const created = await api.postJson("/v2/ingest", {
|
|
@@ -14864,7 +15566,7 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
|
|
|
14864
15566
|
throw translateError(e);
|
|
14865
15567
|
}
|
|
14866
15568
|
});
|
|
14867
|
-
server.tool("list_tasks",
|
|
15569
|
+
server.tool("list_tasks", listTasksGuidance.summary + " \xDAsala para encontrar una tarea previa por nombre o revisar el historial antes de pedir un taskId. Soporta paginaci\xF3n con limit/offset y filtro de texto. No crea, reanuda ni modifica tareas.", ListTasksInput.shape, READS_INTERNAL, async (input) => {
|
|
14868
15570
|
try {
|
|
14869
15571
|
const qs = new URLSearchParams();
|
|
14870
15572
|
if (input.limit != null) qs.set("limit", String(input.limit));
|
|
@@ -14877,7 +15579,7 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
|
|
|
14877
15579
|
throw translateError(e);
|
|
14878
15580
|
}
|
|
14879
15581
|
});
|
|
14880
|
-
server.tool("edit_task_draft",
|
|
15582
|
+
server.tool("edit_task_draft", editTaskDraftGuidance.summary + " Campos editables: angle (texto del angle), buyerPersona, actor (descripci\xF3n del personaje), actorId (ID de un personaje guardado; usa list_actors), gender (female|male), scriptNotes. Use this only before generation completes. Editing already-generated images or videos is not supported.", EditTaskDraftInput.shape, OVERWRITES_INTERNAL, async (input) => {
|
|
14881
15583
|
try {
|
|
14882
15584
|
const angle = await api.patchJson(`/v1/tasks/${encodeURIComponent(input.taskId)}/angles/${input.angleIndex}`, input.angle ?? {});
|
|
14883
15585
|
return asText({
|
|
@@ -15261,6 +15963,11 @@ __name(registerTaskTools, "registerTaskTools");
|
|
|
15261
15963
|
// src/tools/creatives.ts
|
|
15262
15964
|
import { randomUUID } from "crypto";
|
|
15263
15965
|
import { z as z53 } from "zod";
|
|
15966
|
+
var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
|
|
15967
|
+
var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
|
|
15968
|
+
var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
|
|
15969
|
+
var editImageCreativeGuidance = getProductMakerCapabilityModelGuidance("edit_image_creative");
|
|
15970
|
+
var generateLandingGuidance = getProductMakerCapabilityModelGuidance("generate_landing");
|
|
15264
15971
|
var CreativeRefs = {
|
|
15265
15972
|
images: ImagesInput,
|
|
15266
15973
|
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.'),
|
|
@@ -15542,7 +16249,7 @@ function resolveLandingSetup(setup) {
|
|
|
15542
16249
|
}
|
|
15543
16250
|
__name(resolveLandingSetup, "resolveLandingSetup");
|
|
15544
16251
|
function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
15545
|
-
server.tool("generate_free_video",
|
|
16252
|
+
server.tool("generate_free_video", generateFreeVideoGuidance.summary + ' Si el usuario adjunta o menciona una imagen local, llama primero request_media_upload con mediaKind=image y usa el assetId devuelto; no pidas path ni URL. Devuelve un taskId y procesa el job de forma as\xEDncrona.\n\nREQUERIDOS: rawPrompt, quality, durationSeconds y videoResolution.\n\nCALIDAD: "economical" = Econ\xF3mico y "high_detail" = Alto detalle. La duraci\xF3n debe pertenecer a la lista admitida por la calidad escogida; si el usuario pide otra, preg\xFAntale una duraci\xF3n v\xE1lida.\n\nSUBT\xCDTULOS: si addSubtitles=true, el rawPrompt completo se usa como texto exacto de subt\xEDtulos y debe tener m\xE1ximo 500 caracteres; no existe una pregunta adicional de transcripci\xF3n.\n\nPara videos normales con narrativa/\xE1ngulo usa generate_video_creative. Para tareas combinadas de producto usa create_product_task.', FreeVideoInput.shape, CREATES_EXTERNAL, async (input) => {
|
|
15546
16253
|
try {
|
|
15547
16254
|
const allowedDurations = FREE_VIDEO_DURATIONS_BY_QUALITY[input.quality];
|
|
15548
16255
|
if (!allowedDurations.includes(input.durationSeconds)) {
|
|
@@ -15573,7 +16280,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
15573
16280
|
throw translateError(e);
|
|
15574
16281
|
}
|
|
15575
16282
|
});
|
|
15576
|
-
server.tool("generate_video_creative",
|
|
16283
|
+
server.tool("generate_video_creative", generateVideoCreativeGuidance.summary + " Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), title, primaryAngle, language, country, aspectRatio, videoAngleCount y creativeSetup. Pregunta SIEMPRE cu\xE1ntos videos quiere (1, 2 o 3): la cantidad cambia el costo y no forma parte de \u2018la IA decide todo\u2019. Si falta una foto local, llama primero `request_media_upload` y usa los assetId; no pidas path ni URL. PREGUNTA price y offer si faltan; no asumas country/language.\n\nCONFIGURACI\xD3N: salvo que el usuario diga expl\xEDcitamente que la IA decida todo, usa creativeSetup.mode=guided y pregunta narrativa, p\xFAblico comprador, presentador (actor guardado, descripci\xF3n o ninguno) y direcci\xF3n creativa. creativeDirection=null s\xF3lo despu\xE9s de que el usuario delegue esa decisi\xF3n concreta. No inventes valores de setup.\n\nANTES de invocar, muestra un resumen compacto que incluya cantidad, esas cuatro decisiones y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. 15s usa Realista; 30s usa Multiescena y se factura por escena, as\xED que avisa ese mayor costo. Advierte tambi\xE9n que, si luego el usuario confirma que las fotos son de varios productos (combo), el pipeline r\xE1pido actualmente omite la pausa de guion aunque mantiene las dem\xE1s revisiones.\n\nREVIEWS: guided muestra los \xE1ngulos candidatos y permite escoger hasta videoAngleCount, editar cada \xE1ngulo y revisar sus guiones. automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite ambas reviews. scriptNotes agrega restricciones al guion; get_video_script y approve_video_script manejan la review palabra por palabra.", VideoInput.shape, CREATES_EXTERNAL, async (input) => {
|
|
15577
16284
|
try {
|
|
15578
16285
|
await requirePaidCreativeConfirmation(server, input.creativeSetup.mode === "automatic" ? `${input.videoAngleCount} video${input.videoAngleCount === 1 ? "" : "s"} de ${input.durationSeconds}s para \u201C${input.title}\u201D en ${input.country}. Configuraci\xF3n: la IA decide todo.` : `${input.videoAngleCount} video${input.videoAngleCount === 1 ? "" : "s"} de ${input.durationSeconds}s para \u201C${input.title}\u201D en ${input.country}. Narrativa: ${input.creativeSetup.videoPreset}. P\xFAblico: ${input.creativeSetup.buyerPersona}. Presentador: ${input.creativeSetup.presenter.mode}. Direcci\xF3n: ${input.creativeSetup.creativeDirection ?? "la IA decide"}. Si despu\xE9s confirmas que las fotos son de varios productos (combo), el pipeline r\xE1pido omite actualmente la pausa de revisi\xF3n del guion.`);
|
|
15579
16286
|
const guidedSetup = input.creativeSetup.mode === "guided" ? input.creativeSetup : null;
|
|
@@ -15621,7 +16328,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
15621
16328
|
throw translateError(e);
|
|
15622
16329
|
}
|
|
15623
16330
|
});
|
|
15624
|
-
server.tool("generate_image_creatives",
|
|
16331
|
+
server.tool("generate_image_creatives", generateImageCreativesGuidance.summary + " Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), productTitle, language, country y creativeSetup. Si falta una foto local, llama primero `request_media_upload` y usa los assetId. Pregunta price, offer y compareAtPrice cuando aplique; no asumas country/language. primaryAngle es opcional: si falta, ProductMaker lo genera y guided lo muestra para revisi\xF3n.\n\nCONFIGURACI\xD3N: usa guided salvo delegaci\xF3n total expl\xEDcita. No hagas un interrogatorio campo por campo: presenta UN checklist compacto con arquetipo, tratamiento visual, formato, cantidad, calidad, mezcla condicional, copy, competencia, contexto, direcci\xF3n, colores y copy exacto; propone los defaults recomendados y permite que el usuario delegue los campos con ai_decides o null donde el schema lo admite. La UI ofrece 1, 2, 3, 4 o 6 variantes: para 2\u20134 pregunta styleMix; para 1 o 6 usa null, y 6 activa autom\xE1ticamente una imagen de cada estilo. Premium 2K no admite 4:5.\n\nANTES de invocar, muestra el resumen de esas decisiones y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. guided pausa para revisar el \xE1ngulo; automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite la review.", ImageInput.shape, CREATES_EXTERNAL, async (input) => {
|
|
15625
16332
|
try {
|
|
15626
16333
|
const guidedSetup = input.creativeSetup.mode === "guided" ? input.creativeSetup : null;
|
|
15627
16334
|
const setupFields = guidedSetup ? resolveImageSetup(guidedSetup) : {};
|
|
@@ -15646,7 +16353,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
15646
16353
|
throw translateError(e);
|
|
15647
16354
|
}
|
|
15648
16355
|
});
|
|
15649
|
-
server.tool("edit_image_creative",
|
|
16356
|
+
server.tool("edit_image_creative", editImageCreativeGuidance.summary + "\n\nCUESTA CR\xC9DITOS: cobra una sola imagen (sin brief ni extracci\xF3n), mucho menos que volver a generar todo. ANTES de invocar, PREG\xDANTALE al usuario si quiere pagar esa correcci\xF3n.\n\nSolo funciona con la tarea en estado `done` \u2014 si a\xFAn est\xE1 procesando, espera con get_task_status. Una tarea en error terminal no se puede corregir.\n\nUsa variantIndex para elegir cu\xE1l de las im\xE1genes corregir (0 = la primera) e instruction para describir el cambio en lenguaje natural.", EditImageCreativeInput.shape, OVERWRITES_EXTERNAL, async (input) => {
|
|
15650
16357
|
try {
|
|
15651
16358
|
await requirePaidCreativeConfirmation(server, `Correcci\xF3n pagada de la imagen ${input.variantIndex + 1}.`);
|
|
15652
16359
|
const r = await api.postJson(`/v1/creatives/images/${encodeURIComponent(input.taskId)}/regenerate`, {
|
|
@@ -15658,7 +16365,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
15658
16365
|
throw translateError(e);
|
|
15659
16366
|
}
|
|
15660
16367
|
});
|
|
15661
|
-
server.tool("generate_landing",
|
|
16368
|
+
server.tool("generate_landing", generateLandingGuidance.summary + " No expone landing editable/code mientras siga siendo admin-only. Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), language, country y creativeSetup. Ante \u201Ccrea una landing con este producto\u201D y una foto local, llama primero `request_media_upload` y usa los assetId. Pregunta price, offer y compareAtPrice cuando aplique; no asumas country/language.\n\nCONFIGURACI\xD3N: usa guided salvo delegaci\xF3n total expl\xEDcita. Presenta UN checklist compacto \u2014no preguntas seriales\u2014 con estrategia, formato, competencia, m\xE9todos de pago, contexto, direcci\xF3n creativa y headline/subheadline exactos opcionales. Prop\xF3n defaults recomendados; null significa que el usuario deleg\xF3 esa decisi\xF3n concreta, nunca que el agente la olvid\xF3.\n\nANTES de invocar, muestra el resumen y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. guided pausa para revisar el \xE1ngulo; automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite la review.", LandingInput.shape, CREATES_EXTERNAL, async (input) => {
|
|
15662
16369
|
try {
|
|
15663
16370
|
const guidedSetup = input.creativeSetup.mode === "guided" ? input.creativeSetup : null;
|
|
15664
16371
|
const setupFields = guidedSetup ? resolveLandingSetup(guidedSetup) : {};
|
|
@@ -15688,6 +16395,8 @@ __name(registerCreativeTools, "registerCreativeTools");
|
|
|
15688
16395
|
|
|
15689
16396
|
// src/tools/creative-variants.ts
|
|
15690
16397
|
import { z as z54 } from "zod";
|
|
16398
|
+
var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
|
|
16399
|
+
var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
|
|
15691
16400
|
var LandingSectionKeyEnum = z54.enum([
|
|
15692
16401
|
"problem_hook",
|
|
15693
16402
|
"problem_cost",
|
|
@@ -15915,7 +16624,7 @@ function estimatePayload(input) {
|
|
|
15915
16624
|
}
|
|
15916
16625
|
__name(estimatePayload, "estimatePayload");
|
|
15917
16626
|
function registerCreativeVariantTools(server, api) {
|
|
15918
|
-
server.tool("estimate_creative_variant",
|
|
16627
|
+
server.tool("estimate_creative_variant", estimateCreativeVariantGuidance.summary + " Usa el task origen para resolver el modelo/tier real y devuelve m\xEDnimo, m\xE1ximo, saldo y si alcanza. Para landing env\xEDa las mismas instructions/sectionKey que usar\xE1s al crear: si hay instructions sin sectionKey, el rango incluye la clasificaci\xF3n pagada con IA. Llama esto antes de create_creative_variant y muestra el rango al usuario.", EstimateCreativeVariantInputBase.shape, READS_INTERNAL, async (input) => {
|
|
15919
16628
|
try {
|
|
15920
16629
|
const validatedInput = parseVariantInput(EstimateCreativeVariantInput, input);
|
|
15921
16630
|
const estimate = await api.postJson(`/v1/tasks/${encodeURIComponent(validatedInput.sourceTaskId)}/creative-variants/estimate`, estimatePayload(validatedInput));
|
|
@@ -15928,7 +16637,7 @@ function registerCreativeVariantTools(server, api) {
|
|
|
15928
16637
|
throw translateError(error);
|
|
15929
16638
|
}
|
|
15930
16639
|
});
|
|
15931
|
-
server.tool("create_creative_variant",
|
|
16640
|
+
server.tool("create_creative_variant", createCreativeVariantGuidance.summary + " ES UNA ACCI\xD3N DE PAGO: primero llama estimate_creative_variant, muestra el rango de cr\xE9ditos al usuario y solo despu\xE9s invoca este tool con confirm=true. Las recomendaciones IA tambi\xE9n son acciones pagas a 2x del costo real. clientRequestId es obligatorio: genera un UUID por intenci\xF3n y reutiliza el mismo ante timeouts o transporte ambiguo. Si recibes status=error, pide confirmaci\xF3n para un intento nuevo y usa otro UUID. Reutiliza el producto y referencias del task origen; crea un child task independiente y devuelve variantTaskId. Para landing puedes enviar instructions en texto libre y omitir sectionKey: el backend lo clasifica con IA. No expone ni permite cambiar videoModel, videoTier, videoStyle o narrativeStyle; esos valores se heredan del task origen.", CreateCreativeVariantInputBase.shape, CREATES_EXTERNAL, async (input) => {
|
|
15932
16641
|
try {
|
|
15933
16642
|
const validatedInput = parseVariantInput(CreateCreativeVariantInput, input);
|
|
15934
16643
|
const estimateInput = EstimateCreativeVariantInput.parse({
|
|
@@ -15999,6 +16708,9 @@ __name(registerCreativeVariantTools, "registerCreativeVariantTools");
|
|
|
15999
16708
|
|
|
16000
16709
|
// src/tools/script-review.ts
|
|
16001
16710
|
import { z as z55 } from "zod";
|
|
16711
|
+
var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
|
|
16712
|
+
var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
|
|
16713
|
+
var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
|
|
16002
16714
|
var GetVideoScriptInput = z55.object({
|
|
16003
16715
|
taskId: z55.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
|
|
16004
16716
|
angleKey: z55.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.')
|
|
@@ -16022,7 +16734,7 @@ var RegenerateVideoScriptInput = z55.object({
|
|
|
16022
16734
|
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).')
|
|
16023
16735
|
}).strict();
|
|
16024
16736
|
function registerScriptReviewTools(server, api) {
|
|
16025
|
-
server.tool("get_video_script",
|
|
16737
|
+
server.tool("get_video_script", getVideoScriptGuidance.summary + ' S\xF3lo funciona cuando la tarea fue creada con `pauseForVideoScriptReview: true` (via generate_video_creative). Devuelve { status, angleKey, perClipSeconds?, scenes: [{ index, dialogue, maxWords, minWords?, beatId?, persuasiveFunction?, winnerVisual?, expectedVisual? }], error? }. En escenas copiadas de un winner, `persuasiveFunction` explica qu\xE9 logra ese beat, `winnerVisual` conserva la observaci\xF3n fuente y `expectedVisual` describe nuestra adaptaci\xF3n localizada; muestra los tres junto al di\xE1logo para que una edici\xF3n no desaline\xE9 guion y visual. El campo `error` (cuando viene con status="ready") es el motivo legible por el que un intento previo de aprobaci\xF3n fue rechazado; mu\xE9straselo al usuario.\n\nREGLA DURA: status="ready" es un estado terminal de interacci\xF3n. Presenta el guion una sola vez y NO vuelvas a llamar get_video_script ni get_task_status hasta que el usuario responda aprobar, editar o regenerar. La respuesta a\xF1ade interactionState="awaiting_user_review" y nextAction="present_script_and_wait".\n\nCU\xC1NDO LLAMAR: no existe un status top-level "awaiting_script_review" en get_task_status. Si la tarea fue creada con pauseForVideoScriptReview=true, polea get_task_status hasta que `status === "processing"` y llama este tool; su campo `status` es la se\xF1al real:\n- "ready" \u2192 presenta todas las escenas y DETENTE hasta la respuesta del usuario.\n- "not_ready" \u2192 espera 5\u201310s y reintenta este tool.\n- "approved" \u2192 ya fue aprobado; en multi-angle consulta otro angleKey.\n- "skipped" \u2192 el usuario opt\xF3 por no revisar.\n- "error" \u2192 usa `regenerate_video_script` como recuperaci\xF3n.\n\nMULTI-ANGLE: pasa angleKey expl\xEDcito. Cuando uno est\xE9 ready, detente en ese \xE1ngulo y espera la decisi\xF3n antes de consultar otro.', GetVideoScriptInput.shape, READS_INTERNAL, async (input) => {
|
|
16026
16738
|
try {
|
|
16027
16739
|
const qs = input.angleKey ? `?angleKey=${encodeURIComponent(input.angleKey)}` : "";
|
|
16028
16740
|
const r = await api.getJson(`/v1/tasks/${encodeURIComponent(input.taskId)}/video-script${qs}`);
|
|
@@ -16054,7 +16766,7 @@ function registerScriptReviewTools(server, api) {
|
|
|
16054
16766
|
throw translateError(e);
|
|
16055
16767
|
}
|
|
16056
16768
|
});
|
|
16057
|
-
server.tool("regenerate_video_script",
|
|
16769
|
+
server.tool("regenerate_video_script", regenerateVideoScriptGuidance.summary + ' \xDAsalo cuando:\n- get_video_script devuelve status="error" (el LLM fall\xF3 al redactar).\n- El usuario rechaza el guion entero y prefiere reintentar (no editar l\xEDnea por l\xEDnea).\n- Quieres probar otra narrativa (pasa `narrativeStyle`).\n\nFlujo: llama este tool \u2192 polea get_video_script hasta que vuelva a status="ready" \u2192 mu\xE9strale el nuevo guion al usuario \u2192 approve_video_script.\n\nIMPORTANTE: regenerar CUESTA cr\xE9ditos de LLM. No lo invoques sin confirmaci\xF3n del usuario salvo que el status sea "error" (sin retry el usuario no tiene salida).\n\nMULTI-ANGLE: pasa el mismo `angleKey` que usaste con get_video_script.', RegenerateVideoScriptInput.shape, OVERWRITES_EXTERNAL, async (input) => {
|
|
16058
16770
|
try {
|
|
16059
16771
|
await requirePaidCreativeConfirmation(server, `Regeneraci\xF3n pagada del guion con narrativa ${input.narrativeStyle}.`);
|
|
16060
16772
|
const r = await api.postJson(`/v1/tasks/${encodeURIComponent(input.taskId)}/video-script/regenerate`, {
|
|
@@ -16068,7 +16780,7 @@ function registerScriptReviewTools(server, api) {
|
|
|
16068
16780
|
});
|
|
16069
16781
|
server.tool(
|
|
16070
16782
|
"approve_video_script",
|
|
16071
|
-
|
|
16783
|
+
approveVideoScriptGuidance.summary + ' Tras llamarlo, el render arranca y consume cr\xE9ditos.\n\nREGLAS DURAS:\n1. INCLUYE EN scenes[] S\xD3LO las escenas que cambian. El backend mergea por `index` \u2014 las escenas no incluidas conservan su di\xE1logo original. scenes vac\xEDo es rechazado con 400, as\xED que si el usuario no quiere editar nada, manda AL MENOS UNA escena con su `dialogue` original (ser\xE1 un no-op sem\xE1ntico pero satisface el min(1)).\n2. Para cada entrada incluida cuyo `dialogue` difiera del original, el backend valida `minWords \u2264 words(dialogue) \u2264 maxWords` (los rangos vienen en get_video_script). Si te sales del rango, rechaza con 400 \u2014 NO recortes en silencio; p\xEDdele al usuario que ajuste.\n3. Escenas con LLM-original ya fuera de rango: el backend NO valida el rango POR-ESCENA si no las incluyes (la regla #2 s\xF3lo aplica a escenas editadas).\n4. TOPE GLOBAL: adem\xE1s del rango por-escena, el backend rechaza con 400 ("El guion no cabe en el tiempo del video. Ac\xF3rtalo y vuelve a aprobar.") cuando el TOTAL de palabras de TODO el guion (incluidas las escenas que no editaste) supera el cupo de la voz \u2014 porque ese guion se pasar\xEDa del tope de duraci\xF3n al renderizar. Si lo ves, acorta las escenas m\xE1s largas (la suma de `maxWords` de get_video_script es el techo total) y reintenta; o usa regenerate_video_script. Este 400 es s\xEDncrono y NO consume render.\n5. NUNCA inventes ni reescribas el guion por tu cuenta. Aplica los cambios del usuario al pie de la letra dentro de los l\xEDmites de palabras.\n6. MULTI-ANGLE: pasa el mismo `angleKey` que usaste en get_video_script. Si lo omites, el backend resuelve a "angle_0" literal \u2014 puedes aprobar un \xE1ngulo equivocado.\n\nDevuelve { status }. status="approved" confirma la aprobaci\xF3n; otro valor significa que la pausa sigue activa.',
|
|
16072
16784
|
ApproveVideoScriptInput.shape,
|
|
16073
16785
|
// Not CREATES_INTERNAL: approving the script is what STARTS the render, so
|
|
16074
16786
|
// this call dispatches jobs to the video providers and burns credits. Its own
|
|
@@ -16095,8 +16807,13 @@ __name(registerScriptReviewTools, "registerScriptReviewTools");
|
|
|
16095
16807
|
|
|
16096
16808
|
// src/tools/connections.ts
|
|
16097
16809
|
import { z as z56 } from "zod";
|
|
16810
|
+
var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
|
|
16811
|
+
var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
|
|
16812
|
+
var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
|
|
16813
|
+
var listMetaDestinationsGuidance = getProductMakerCapabilityModelGuidance("list_meta_destinations");
|
|
16814
|
+
var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list_tiktok_advertisers");
|
|
16098
16815
|
function registerConnectionTools(server, api) {
|
|
16099
|
-
server.tool("list_shopify_shops",
|
|
16816
|
+
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.", z56.object({}).shape, READS_INTERNAL, async () => {
|
|
16100
16817
|
try {
|
|
16101
16818
|
const r = await api.getJson("/v1/shopify/shops");
|
|
16102
16819
|
return asText(r);
|
|
@@ -16104,7 +16821,7 @@ function registerConnectionTools(server, api) {
|
|
|
16104
16821
|
throw translateError(e);
|
|
16105
16822
|
}
|
|
16106
16823
|
});
|
|
16107
|
-
server.tool("list_shopify_products",
|
|
16824
|
+
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.', z56.object({
|
|
16108
16825
|
shopDomain: z56.string().min(3).max(120),
|
|
16109
16826
|
query: z56.string().trim().max(120).optional(),
|
|
16110
16827
|
taskId: z56.string().uuid().optional()
|
|
@@ -16121,7 +16838,7 @@ function registerConnectionTools(server, api) {
|
|
|
16121
16838
|
throw translateError(e);
|
|
16122
16839
|
}
|
|
16123
16840
|
});
|
|
16124
|
-
server.tool("list_meta_ad_accounts",
|
|
16841
|
+
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.", z56.object({}).shape, READS_EXTERNAL, async () => {
|
|
16125
16842
|
try {
|
|
16126
16843
|
const r = await api.getJson("/v1/facebook/ad-accounts");
|
|
16127
16844
|
return asText(r);
|
|
@@ -16130,7 +16847,7 @@ function registerConnectionTools(server, api) {
|
|
|
16130
16847
|
}
|
|
16131
16848
|
});
|
|
16132
16849
|
server.registerTool("list_meta_destinations", {
|
|
16133
|
-
description:
|
|
16850
|
+
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.",
|
|
16134
16851
|
inputSchema: z56.object({}).shape,
|
|
16135
16852
|
annotations: READS_EXTERNAL,
|
|
16136
16853
|
_meta: {
|
|
@@ -16144,7 +16861,7 @@ function registerConnectionTools(server, api) {
|
|
|
16144
16861
|
throw translateError(e);
|
|
16145
16862
|
}
|
|
16146
16863
|
});
|
|
16147
|
-
server.tool("list_tiktok_advertisers",
|
|
16864
|
+
server.tool("list_tiktok_advertisers", listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.", z56.object({}).shape, READS_EXTERNAL, async () => {
|
|
16148
16865
|
try {
|
|
16149
16866
|
const r = await api.getJson("/v1/tiktok/advertisers");
|
|
16150
16867
|
return asText(r);
|
|
@@ -16157,8 +16874,9 @@ __name(registerConnectionTools, "registerConnectionTools");
|
|
|
16157
16874
|
|
|
16158
16875
|
// src/tools/actors.ts
|
|
16159
16876
|
import { z as z57 } from "zod";
|
|
16877
|
+
var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
|
|
16160
16878
|
function registerActorTools(server, api) {
|
|
16161
|
-
server.tool("list_actors",
|
|
16879
|
+
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.", z57.object({}).shape, READS_INTERNAL, async () => {
|
|
16162
16880
|
try {
|
|
16163
16881
|
const rows = await api.getJson("/v1/actors");
|
|
16164
16882
|
const actors = (Array.isArray(rows) ? rows : []).filter((actor) => actor.status === "ready").map(({ id, name, description, gender, voiceId }) => ({
|
|
@@ -16231,6 +16949,10 @@ function deriveMetaPublishAttemptId(input) {
|
|
|
16231
16949
|
__name(deriveMetaPublishAttemptId, "deriveMetaPublishAttemptId");
|
|
16232
16950
|
|
|
16233
16951
|
// src/tools/publish.ts
|
|
16952
|
+
var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_to_shopify");
|
|
16953
|
+
var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
|
|
16954
|
+
var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
|
|
16955
|
+
var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
|
|
16234
16956
|
var ShopifyInput = z58.object({
|
|
16235
16957
|
taskId: z58.string().min(1),
|
|
16236
16958
|
shopDomain: z58.string().min(1),
|
|
@@ -16520,7 +17242,7 @@ var TikTokInput = z58.object({
|
|
|
16520
17242
|
});
|
|
16521
17243
|
function registerPublishTools(server, api, opts = {}) {
|
|
16522
17244
|
const transport = opts.transport ?? "http";
|
|
16523
|
-
server.tool("publish_to_shopify",
|
|
17245
|
+
server.tool("publish_to_shopify", publishToShopifyGuidance.summary + " Precondici\xF3n: la tarea debe estar en status='complete' \u2014 usa `get_task_status` antes. Por defecto `publicationMode=auto`: si esta tarea ya fue publicada en esa tienda, actualiza ESE MISMO producto y conserva URL, precio, variantes, inventario y SKU; si no, crea uno. Usa `existing` + `targetProductId` cuando el usuario elija otro producto y `new` s\xF3lo si pide crear uno nuevo. ANTES de llamar preg\xFAntale \"\xBFTu producto tiene variantes (talla, color, etc.)?\" y pasa `showVariantPicker: true` si responde que s\xED. Por defecto publica TODAS las im\xE1genes generadas; pasa `numLandingImages` s\xF3lo si el usuario pide menos. La respuesta es markdown con el link a la landing y al producto.", ShopifyInput.shape, OVERWRITES_EXTERNAL, async (input) => {
|
|
16524
17246
|
try {
|
|
16525
17247
|
const parsed = parseShopifyInput(input);
|
|
16526
17248
|
if (parsed.publicationMode === "existing" && !parsed.targetProductId) {
|
|
@@ -16558,7 +17280,7 @@ function registerPublishTools(server, api, opts = {}) {
|
|
|
16558
17280
|
throw translateError(e);
|
|
16559
17281
|
}
|
|
16560
17282
|
});
|
|
16561
|
-
server.tool("publish_to_meta",
|
|
17283
|
+
server.tool("publish_to_meta", publishToMetaGuidance.summary + " El presupuesto de anuncios se paga directamente desde tu cuenta de Meta. Crear creativos o copy con IA sigue usando cr\xE9ditos. Crea una campa\xF1a de Meta Ads (Facebook/Instagram) desde UNA sola tarea. Antes llama `list_meta_destinations`, deja que el usuario elija el `portfolioId` (Business portfolio), el `adAccountId` y el `pageId` exactos, y env\xEDa esos tres valores; no adivines ni uses la primera p\xE1gina. Si quieres juntar creativos de VARIAS tareas usa `publish_creatives_to_meta`. La campa\xF1a se crea SIEMPRE PAUSED y el usuario la activa manualmente. `pixelId` es opcional. `angleIndexes` permite seleccionar \xE1ngulos. `campaignConfig` admite presupuesto en USD, pa\xEDses ISO-2 y nombre. `primaryText` permite reemplazar el copy y `phoneNumber` configura WhatsApp. Despu\xE9s usa `get_meta_campaign_status`. Si el resultado es ambiguo, NO reenv\xEDes: revisa Meta Ads Manager.", MetaInput.shape, CREATES_EXTERNAL, async (rawInput, extra) => {
|
|
16562
17284
|
try {
|
|
16563
17285
|
const parsed = MetaInput.safeParse(rawInput);
|
|
16564
17286
|
if (!parsed.success) throw invalidInputFromZod(parsed.error);
|
|
@@ -16595,7 +17317,7 @@ function registerPublishTools(server, api, opts = {}) {
|
|
|
16595
17317
|
throw translateError(e);
|
|
16596
17318
|
}
|
|
16597
17319
|
});
|
|
16598
|
-
server.tool("publish_creatives_to_meta",
|
|
17320
|
+
server.tool("publish_creatives_to_meta", publishCreativesToMetaGuidance.summary + ' Publica tus creativos en Meta sin gastar cr\xE9ditos de ProductMaker. El presupuesto de anuncios se paga directamente desde tu cuenta de Meta. Crear creativos o copy con IA sigue usando cr\xE9ditos. Si la petici\xF3n natural adjunta o menciona archivos locales, llama primero `request_media_upload`; tras OK usa cada resultado como `source.type="asset"` con su `assetId` y el `type` que coincide con `mediaKind`. No pidas path ni URL. Despu\xE9s llama `list_meta_destinations` y pregunta en el chat por el `portfolioId`, `adAccountId` y `pageId` exactos; el App es solo para archivos. Si la carga fue parcial, conserva los assets confirmados, procesa s\xF3lo los pendientes y publica \xFAnicamente assets confirmados; nunca inventes assets ni superes diez creativos. Las rutas locales s\xF3lo funcionan con MCP stdio. Los medios propios se eliminan despu\xE9s de publicar correctamente; si falla antes de enviar una mutaci\xF3n a Meta, quedan durante el TTL. Para videos la miniatura es opcional y ProductMaker puede generarla con FFmpeg. `campaignConfig.destination` acepta landing o WhatsApp. Para landing basta `campaignConfig.destination.landingUrl`; no dupliques la URL arriba. Si omites `budgetMode`, se infiere `ad_set` cuando cada ad set trae `dailyBudget`, o `campaign` cuando env\xEDas `campaignDailyBudget`. No actives la campa\xF1a autom\xE1ticamente. Si el resultado es ambiguo, NO reenv\xEDes: revisa Meta Ads Manager.', PublishCreativesToMetaInputBase.shape, CREATES_EXTERNAL, async (rawInput, extra) => {
|
|
16599
17321
|
try {
|
|
16600
17322
|
const parsed = PublishCreativesToMetaInput.safeParse(rawInput);
|
|
16601
17323
|
if (!parsed.success) throw invalidInputFromZod(parsed.error);
|
|
@@ -16691,7 +17413,7 @@ function registerPublishTools(server, api, opts = {}) {
|
|
|
16691
17413
|
throw translateError(e);
|
|
16692
17414
|
}
|
|
16693
17415
|
});
|
|
16694
|
-
server.tool("publish_to_tiktok",
|
|
17416
|
+
server.tool("publish_to_tiktok", publishToTikTokGuidance.summary + " La campa\xF1a se crea SIEMPRE en estado PAUSED \u2014 el usuario la activa manualmente en TikTok Ads Manager. Use `list_tiktok_advertisers` antes para un advertiserId v\xE1lido. `pixelId` opcional pero recomendado para tracking. `angleIndexes` (opcional): selecciona qu\xE9 \xE1ngulos publicar \u2014 ej. [0,2]; omitir = publicar todos. `campaignConfig` (opcional): `dailyBudgetUsd` (presupuesto diario SIEMPRE en d\xF3lares, ej. 25 \u2014 nunca el n\xFAmero en moneda local), `targetCountries` (c\xF3digos ISO-2, primero se usa), `campaignName` (m\xE1x 100 chars). `primaryText` (opcional, m\xE1x 500 chars): override del copy del anuncio \u2014 solo \xFAsalo si el usuario te pas\xF3 un texto espec\xEDfico; si no, ProductMaker usa el copy auto-generado de la tarea. Despu\xE9s de publicar usa `get_tiktok_campaign_status` para chequear el estado.", TikTokInput.shape, CREATES_EXTERNAL, async ({ taskId, campaignConfig, primaryText, ...rest }) => {
|
|
16695
17417
|
try {
|
|
16696
17418
|
const body = {
|
|
16697
17419
|
...rest
|
|
@@ -16782,6 +17504,7 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
|
|
|
16782
17504
|
// src/tools/meta-upload.ts
|
|
16783
17505
|
import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
|
|
16784
17506
|
import { z as z59 } from "zod";
|
|
17507
|
+
var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
|
|
16785
17508
|
var UploadSessionInputBase = z59.object({
|
|
16786
17509
|
mediaKind: z59.enum([
|
|
16787
17510
|
"image",
|
|
@@ -16915,7 +17638,7 @@ __name(resolveEndpointForSession, "resolveEndpointForSession");
|
|
|
16915
17638
|
function registerMediaUploadTools(server, api) {
|
|
16916
17639
|
registerAppTool(server, "request_media_upload", {
|
|
16917
17640
|
title: "Subir archivos",
|
|
16918
|
-
description:
|
|
17641
|
+
description: requestMediaUploadGuidance.summary + " Cuando la foto o el video sea el siguiente dato faltante, ll\xE1malo en esa misma respuesta: no te limites a pedir que lo adjunte en el chat y esperar otro turno. Ll\xE1malo tambi\xE9n autom\xE1ticamente y antes de preguntar por campos faltantes adicionales cuando una petici\xF3n natural adjunte o mencione un archivo local, por ejemplo \u2018crea una landing con este producto\u2019, \u2018haz creativos con esta foto\u2019 o \u2018sube este video a Meta\u2019; hazlo aunque el usuario diga que todav\xEDa no generes ni publiques, porque esta herramienta solo prepara el archivo y no consume cr\xE9ditos, salvo que proh\xEDba expl\xEDcitamente subir, compartir o almacenar el archivo; no pidas una ruta local ni URL. Es la \xFAnica ruta de carga para create_product_task, generate_image_creatives, generate_video_creative, generate_free_video, generate_landing y publish_creatives_to_meta. Pasa las referencias opcionales de ChatGPT en files; si el host no puede transferirlas, el mismo App muestra el selector inline. Usa uploadPurpose=product_reference para fotos de producto y landings, creative para creativos o anuncios, y generic solo cuando ninguno aplique. Usa mediaKind=image para referencias de producto y landings; mixed solo cuando el consumidor acepte ambos tipos. El App NO te avisa cuando termina: en cuanto el usuario diga que ya subi\xF3 el archivo o que sigas, llama `check_media_upload` con este sessionId para obtener los assetId, y reanuda la intenci\xF3n original usando \xFAnicamente assetId y mediaKind, sin pedir que vuelva a subir ni mostrar datos t\xE9cnicos. El enlace externo es fallback solo si el App inline falla. Esta herramienta no genera, publica ni consume cr\xE9ditos.",
|
|
16919
17642
|
inputSchema: UploadSessionToolInputShape,
|
|
16920
17643
|
annotations: CREATES_INTERNAL,
|
|
16921
17644
|
outputSchema: UniversalUploadStructuredResponse.shape,
|
|
@@ -16975,6 +17698,8 @@ __name(registerMediaUploadTools, "registerMediaUploadTools");
|
|
|
16975
17698
|
|
|
16976
17699
|
// src/tools/campaigns.ts
|
|
16977
17700
|
import { z as z60 } from "zod";
|
|
17701
|
+
var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
|
|
17702
|
+
var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
|
|
16978
17703
|
var MetaStatusInput = z60.object({
|
|
16979
17704
|
campaignId: z60.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
|
|
16980
17705
|
});
|
|
@@ -16983,7 +17708,7 @@ var TikTokStatusInput = z60.object({
|
|
|
16983
17708
|
advertiserId: z60.string().min(1).describe("The same advertiserId used to publish the campaign.")
|
|
16984
17709
|
});
|
|
16985
17710
|
function registerCampaignTools(server, api) {
|
|
16986
|
-
server.tool("get_meta_campaign_status",
|
|
17711
|
+
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) => {
|
|
16987
17712
|
try {
|
|
16988
17713
|
const r = await api.getJson(`/v1/facebook/campaigns/${encodeURIComponent(input.campaignId)}`);
|
|
16989
17714
|
return renderMetaStatusMarkdown(r);
|
|
@@ -16991,7 +17716,7 @@ function registerCampaignTools(server, api) {
|
|
|
16991
17716
|
throw translateError(e);
|
|
16992
17717
|
}
|
|
16993
17718
|
});
|
|
16994
|
-
server.tool("get_tiktok_campaign_status",
|
|
17719
|
+
server.tool("get_tiktok_campaign_status", getTikTokCampaignStatusGuidance.summary + " Requiere `advertiserId` (el mismo con el que se cre\xF3). Llama esto DESPU\xC9S de `publish_to_tiktok` para confirmar creaci\xF3n correcta y reportar performance. Es read-only.", TikTokStatusInput.shape, READS_EXTERNAL, async (input) => {
|
|
16995
17720
|
try {
|
|
16996
17721
|
const r = await api.getJson(`/v1/tiktok/campaigns/${encodeURIComponent(input.campaignId)}?advertiserId=${encodeURIComponent(input.advertiserId)}`);
|
|
16997
17722
|
return renderTikTokStatusMarkdown(r);
|
|
@@ -17427,6 +18152,7 @@ __name(calculateProductCosting, "calculateProductCosting");
|
|
|
17427
18152
|
|
|
17428
18153
|
// src/tools/product-costing.ts
|
|
17429
18154
|
import { z as z63 } from "zod";
|
|
18155
|
+
var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
|
|
17430
18156
|
var optionalAmount = /* @__PURE__ */ __name((description) => z63.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
|
|
17431
18157
|
var optionalPercent = /* @__PURE__ */ __name((description) => z63.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
|
|
17432
18158
|
var ProductCostingToolInput = z63.object({
|
|
@@ -17444,7 +18170,7 @@ var ProductCostingToolInput = z63.object({
|
|
|
17444
18170
|
desiredMarginPercent: optionalPercent("Margen de ganancia deseado. Ejemplo: 10 significa 10%. Omite para usar el valor gu\xEDa editable del pa\xEDs.")
|
|
17445
18171
|
});
|
|
17446
18172
|
function registerProductCostingTools(server) {
|
|
17447
|
-
server.tool("cost_product",
|
|
18173
|
+
server.tool("cost_product", costProductGuidance.summary + " Ll\xE1mala siempre que el usuario pida calcular cu\xE1nto cobrar, la rentabilidad o el margen de un producto concreto; no hagas el c\xE1lculo ni reconstruyas la f\xF3rmula por tu cuenta. Es READ-ONLY: no crea tareas ni publica nada. Pide country y el costo real del proveedor; los dem\xE1s campos pueden usar valores gu\xEDa editables del pa\xEDs. Devuelve `price` y `compareAtPrice` listos para `create_product_task`. No inventes un costo de proveedor.", ProductCostingToolInput.shape, READS_INTERNAL, async (input) => {
|
|
17448
18174
|
if (input.country !== void 0 && input.country !== "CO" && [
|
|
17449
18175
|
input.supplierCostCop,
|
|
17450
18176
|
input.shippingCostCop,
|
|
@@ -17656,6 +18382,9 @@ function renderResearchReport(run) {
|
|
|
17656
18382
|
__name(renderResearchReport, "renderResearchReport");
|
|
17657
18383
|
|
|
17658
18384
|
// src/tools/product-research.ts
|
|
18385
|
+
var findWinningProductsGuidance = getProductMakerCapabilityModelGuidance("find_winning_products");
|
|
18386
|
+
var getProductResearchRunGuidance = getProductMakerCapabilityModelGuidance("get_product_research_run");
|
|
18387
|
+
var listProductResearchRunsGuidance = getProductMakerCapabilityModelGuidance("list_product_research_runs");
|
|
17659
18388
|
var PRICE_CREDITS = 2e3;
|
|
17660
18389
|
var TERMINAL2 = /* @__PURE__ */ new Set([
|
|
17661
18390
|
"ready",
|
|
@@ -17699,7 +18428,7 @@ async function pollUntilTerminal(api, runId, waitSeconds) {
|
|
|
17699
18428
|
}
|
|
17700
18429
|
__name(pollUntilTerminal, "pollUntilTerminal");
|
|
17701
18430
|
function registerProductResearchTools(server, api) {
|
|
17702
|
-
server.tool("find_winning_products",
|
|
18431
|
+
server.tool("find_winning_products", `${findWinningProductsGuidance.summary} CUESTA ${PRICE_CREDITS} CR\xC9DITOS por ejecuci\xF3n. ANTES de invocar, dile al usuario el costo y espera su aceptaci\xF3n expl\xEDcita; s\xF3lo entonces pasa confirmed: true. Consulta primero list_product_research_runs (GRATIS) \u2014 puede que el usuario ya tenga un reporte pagado para ese pa\xEDs/categor\xEDa y no necesites cobrar de nuevo. Pa\xEDses disponibles: CO, MX, PE, EC, CL. Tarda varios minutos: usa waitSeconds para esperar, y si expira consulta el resultado con get_product_research_run \u2014 el reporte NO se pierde.`, FindInput.shape, CREATES_EXTERNAL, async (input) => {
|
|
17703
18432
|
const parsed = FindInput.parse(input);
|
|
17704
18433
|
if (!parsed.confirmed) {
|
|
17705
18434
|
throw mcp(McpErrorCode.INVALID_INPUT, `This research run costs ${PRICE_CREDITS} credits. Tell the user the cost, get an explicit yes, then call again with confirmed: true.`);
|
|
@@ -17733,7 +18462,7 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
|
|
|
17733
18462
|
throw translateError(error);
|
|
17734
18463
|
}
|
|
17735
18464
|
});
|
|
17736
|
-
server.tool("get_product_research_run",
|
|
18465
|
+
server.tool("get_product_research_run", getProductResearchRunGuidance.summary + " GRATIS y read-only. \xDAsalo cuando find_winning_products expir\xF3 la espera, o para releer un reporte anterior encontrado con list_product_research_runs.", GetInput.shape, READS_INTERNAL, async (input) => {
|
|
17737
18466
|
const parsed = GetInput.parse(input);
|
|
17738
18467
|
try {
|
|
17739
18468
|
const run = await api.getJson(`/v1/product-research/runs/${parsed.runId}`);
|
|
@@ -17753,7 +18482,7 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
|
|
|
17753
18482
|
throw translateError(error);
|
|
17754
18483
|
}
|
|
17755
18484
|
});
|
|
17756
|
-
server.tool("list_product_research_runs",
|
|
18485
|
+
server.tool("list_product_research_runs", listProductResearchRunsGuidance.summary + " GRATIS y read-only. Cons\xFAltalo ANTES de lanzar una nueva: un reporte ya pagado se relee gratis con get_product_research_run.", ListInput.shape, READS_INTERNAL, async (input) => {
|
|
17757
18486
|
const parsed = ListInput.parse(input);
|
|
17758
18487
|
try {
|
|
17759
18488
|
const runs = await api.getJson(`/v1/product-research/runs?limit=${parsed.limit}`);
|
|
@@ -17767,6 +18496,9 @@ __name(registerProductResearchTools, "registerProductResearchTools");
|
|
|
17767
18496
|
|
|
17768
18497
|
// src/tools/dropshipping-projects.ts
|
|
17769
18498
|
import { z as z65 } from "zod";
|
|
18499
|
+
var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
|
|
18500
|
+
var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
|
|
18501
|
+
var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
|
|
17770
18502
|
var ProjectId = z65.string().uuid();
|
|
17771
18503
|
var DropshippingProjectStatus = z65.enum([
|
|
17772
18504
|
"active",
|
|
@@ -17996,7 +18728,7 @@ function projectText(raw) {
|
|
|
17996
18728
|
}
|
|
17997
18729
|
__name(projectText, "projectText");
|
|
17998
18730
|
function registerDropshippingProjectTools(server, api) {
|
|
17999
|
-
server.tool("start_dropshipping_project",
|
|
18731
|
+
server.tool("start_dropshipping_project", startDropshippingProjectGuidance.summary + " \xDAsalo cuando el usuario quiera seguir un producto hasta publicarlo; para una operaci\xF3n puntual usa el tool directo. La creaci\xF3n es idempotente y no cobra cr\xE9ditos.", StartProjectInput.shape, CREATES_INTERNAL, async (input) => {
|
|
18000
18732
|
try {
|
|
18001
18733
|
return projectText(await api.postJson("/v1/dropshipping-projects", input));
|
|
18002
18734
|
} catch (error) {
|
|
@@ -18005,7 +18737,7 @@ function registerDropshippingProjectTools(server, api) {
|
|
|
18005
18737
|
});
|
|
18006
18738
|
server.tool(
|
|
18007
18739
|
"cost_dropshipping_project",
|
|
18008
|
-
|
|
18740
|
+
costDropshippingProjectGuidance.summary + " Escribe solo inputs; el backend recalcula el resultado can\xF3nico y controla la versi\xF3n. Pide al usuario el costo real del proveedor: nunca lo inventes. No crea tarea ni publica nada.",
|
|
18009
18741
|
CostProjectInput.shape,
|
|
18010
18742
|
// Overwrites the costing inputs already saved on the project — the same
|
|
18011
18743
|
// "previous values are gone" case as edit_task_draft, so destructive.
|
|
@@ -18027,7 +18759,7 @@ function registerDropshippingProjectTools(server, api) {
|
|
|
18027
18759
|
}
|
|
18028
18760
|
}
|
|
18029
18761
|
);
|
|
18030
|
-
server.tool("guide_dropshipping_launch",
|
|
18762
|
+
server.tool("guide_dropshipping_launch", guideDropshippingLaunchGuidance.summary + " No uses este tool para subir o publicar un creativo puntual en Meta: llama directamente `request_media_upload`, `list_meta_destinations` y `publish_creatives_to_meta`. Sin projectId explica cu\xE1ndo usar un flujo directo versus uno guiado; con projectId devuelve la fase y la \xFAnica nextAction calculada por ProductMaker. Despu\xE9s de cada mutaci\xF3n vuelve a llamar este tool o lee el proyecto. Nunca activa Meta.", GuideInput.shape, READS_INTERNAL, async (input) => {
|
|
18031
18763
|
try {
|
|
18032
18764
|
if (!input.projectId) {
|
|
18033
18765
|
return asText({
|
|
@@ -18048,6 +18780,9 @@ __name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
|
|
|
18048
18780
|
|
|
18049
18781
|
// src/tools/daily-control.ts
|
|
18050
18782
|
import { z as z66 } from "zod";
|
|
18783
|
+
var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
|
|
18784
|
+
var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
|
|
18785
|
+
var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
|
|
18051
18786
|
var ProviderCampaignIdentifier = z66.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
|
|
18052
18787
|
var DateOnly = z66.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
18053
18788
|
var DailyControlInput = z66.object({
|
|
@@ -18124,7 +18859,7 @@ __name(withWarnings, "withWarnings");
|
|
|
18124
18859
|
function registerDailyControlTools(server, api) {
|
|
18125
18860
|
server.tool(
|
|
18126
18861
|
"get_daily_control",
|
|
18127
|
-
|
|
18862
|
+
getDailyControlGuidance.summary + ' Compara el costo real por venta contra lo que el producto puede aguantar, con sem\xE1foro (verde/\xE1mbar/rojo/ninguno) y veredicto (escalar, mantener, matar, muestra insuficiente). Es READ-ONLY sobre publicidad: nunca pausa, activa ni modifica ninguna campa\xF1a \u2014 esa decisi\xF3n es siempre del usuario. Si un producto vuelve con `status` distinto de "ok", NO tiene m\xE9tricas (`days` vac\xEDo, `verdict` null): explica el motivo (`statusMessage`) al usuario y no inventes ni estimes n\xFAmeros para reemplazarlo. Cuando un d\xEDa trae `returnedSource: "estimated"`, esa cifra de devoluciones NO fue medida \u2014 asume la tasa de devoluci\xF3n que el usuario configur\xF3 al costear el producto; dilo as\xED y ofrece registrar el dato real con report_daily_returns. `status: "no_campaign_linked"` significa que ese producto no tiene ninguna campa\xF1a vinculada: no hay gasto que leer, as\xED que NO existe costo por venta \u2014 ofrece link_campaign_to_project si el usuario est\xE1 pautando por fuera. Un d\xEDa con `cancelledSource: "shopify_settling"` est\xE1 medido pero todav\xEDa no cerrado (las cancelaciones de contra-entrega llegan d\xEDas despu\xE9s): ese resultado solo puede empeorar, no lo presentes como definitivo. Y `cancelledSource: "estimated"` es lo NORMAL en contra-entrega con fulfillment por fuera: la cancelaci\xF3n ocurre por WhatsApp o en la puerta y Shopify nunca se entera, as\xED que esa cifra asume la tasa de cancelaci\xF3n que el usuario configur\xF3 al costear \u2014 dilo as\xED y no la presentes como medida.',
|
|
18128
18863
|
DailyControlInput.shape,
|
|
18129
18864
|
// Reads live spend from Meta/TikTok and orders from Shopify through our API;
|
|
18130
18865
|
// it cannot modify anything on any of them.
|
|
@@ -18146,7 +18881,7 @@ function registerDailyControlTools(server, api) {
|
|
|
18146
18881
|
);
|
|
18147
18882
|
server.tool(
|
|
18148
18883
|
"link_campaign_to_project",
|
|
18149
|
-
|
|
18884
|
+
linkCampaignToProjectGuidance.summary + " Es la \xFAnica acci\xF3n de este grupo que escribe algo, pero solo vincula un identificador \u2014 nunca crea, pausa ni activa ninguna campa\xF1a real en Meta o TikTok. El servidor verifica con el token del usuario que la campa\xF1a vive en una de sus cuentas antes de vincularla; si no la ve, responde 404. Si la campa\xF1a ya est\xE1 vinculada a otro proyecto, responde 409 y no reasigna nada. Para Meta, el servidor deriva la cuenta publicitaria de la campa\xF1a e ignora el `accountId` recibido.",
|
|
18150
18885
|
LinkCampaignInput.shape,
|
|
18151
18886
|
// Creates one internal link row; never creates/pauses/activates a real
|
|
18152
18887
|
// campaign, but the server verifies the campaign against the provider.
|
|
@@ -18162,7 +18897,7 @@ function registerDailyControlTools(server, api) {
|
|
|
18162
18897
|
);
|
|
18163
18898
|
server.tool(
|
|
18164
18899
|
"report_daily_returns",
|
|
18165
|
-
|
|
18900
|
+
reportDailyReturnsGuidance.summary + ' Es el \xFAnico dato del control diario que ProductMaker no puede ver por s\xED solo: quien maneja la log\xEDstica de contra-entrega es la transportadora, no la tienda. Sin este reporte, get_daily_control usa la tasa de devoluci\xF3n estimada del costeo (marcada `returnedSource: "estimated"`) en vez de un n\xFAmero medido. P\xEDdele el n\xFAmero exacto al usuario \u2014 nunca lo inventes ni lo deduzcas de otras m\xE9tricas.',
|
|
18166
18901
|
ReportReturnsInput.shape,
|
|
18167
18902
|
// PUT: replaces whatever number was reported for that product-day.
|
|
18168
18903
|
OVERWRITES_INTERNAL,
|