@productmaker/mcp 11.3.3 → 11.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/dist/http.js +935 -894
- package/dist/stdio.js +924 -883
- package/package.json +1 -1
package/dist/http.js
CHANGED
|
@@ -9676,13 +9676,23 @@ var FacebookCreateCampaignFromTasksBodySchema = z51.object({
|
|
|
9676
9676
|
portfolioId: z51.string().min(1),
|
|
9677
9677
|
pageId: z51.string().min(1),
|
|
9678
9678
|
pixelId: z51.string().optional(),
|
|
9679
|
+
/**
|
|
9680
|
+
* Omitted: a campaign with task creatives lands on the published service
|
|
9681
|
+
* landing of its service tasks (resolved server side, META_NO_LANDING_URL
|
|
9682
|
+
* when there is none); a media-only campaign must name it.
|
|
9683
|
+
*/
|
|
9679
9684
|
landingUrl: HttpUrl2.optional(),
|
|
9680
|
-
|
|
9685
|
+
/**
|
|
9686
|
+
* Omitted: the brand country of its service tasks; a product-only campaign
|
|
9687
|
+
* keeps "US". Never a hardcoded country for a service (META_NO_TARGET_COUNTRY).
|
|
9688
|
+
*/
|
|
9689
|
+
targetCountry: CountryIso2Schema.optional(),
|
|
9681
9690
|
campaignName: z51.string().min(1).max(100),
|
|
9682
9691
|
campaignConfig: MetaCampaignConfig.optional()
|
|
9683
9692
|
}).superRefine((value, ctx) => {
|
|
9684
9693
|
const isWhatsapp = value.campaignConfig?.destination?.type === "whatsapp";
|
|
9685
|
-
|
|
9694
|
+
const hasTaskCreative = value.creatives.some((creative) => creative.source.type === "task");
|
|
9695
|
+
if (!isWhatsapp && !value.landingUrl && !hasTaskCreative) {
|
|
9686
9696
|
ctx.addIssue({
|
|
9687
9697
|
code: z51.ZodIssueCode.custom,
|
|
9688
9698
|
path: [
|
|
@@ -18759,7 +18769,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
18759
18769
|
], [
|
|
18760
18770
|
"tiktok_advertiser"
|
|
18761
18771
|
]),
|
|
18762
|
-
defineCapability("publish_creatives_to_meta", "
|
|
18772
|
+
defineCapability("publish_creatives_to_meta", "dff962c84ed7d0393444dcbe86cb6f4016b5928c1d0005f78ce9a365f1923ac3", "external_mutation", "publishing", [
|
|
18763
18773
|
"external_mutation",
|
|
18764
18774
|
"state_change"
|
|
18765
18775
|
], [
|
|
@@ -22109,19 +22119,37 @@ var ServiceImageContextSchema = z106.object({
|
|
|
22109
22119
|
referenceKeys: z106.array(z106.string()).max(10)
|
|
22110
22120
|
}).strict();
|
|
22111
22121
|
|
|
22112
|
-
// ../../packages/types/src/
|
|
22122
|
+
// ../../packages/types/src/task-ad-defaults.ts
|
|
22113
22123
|
import { z as z107 } from "zod";
|
|
22124
|
+
var AD_HEADLINE_MAX_CHARS = 255;
|
|
22125
|
+
var TaskAdDefaultsSchema = z107.object({
|
|
22126
|
+
subjectKind: z107.enum([
|
|
22127
|
+
"product",
|
|
22128
|
+
"service"
|
|
22129
|
+
]),
|
|
22130
|
+
landingUrl: z107.string().url().nullable(),
|
|
22131
|
+
landingSource: z107.enum([
|
|
22132
|
+
"shopify",
|
|
22133
|
+
"service_page"
|
|
22134
|
+
]).nullable(),
|
|
22135
|
+
headline: z107.string().min(1).max(AD_HEADLINE_MAX_CHARS).nullable(),
|
|
22136
|
+
/** ISO 3166-1 alpha-2 when known. */
|
|
22137
|
+
country: z107.string().min(2).nullable()
|
|
22138
|
+
});
|
|
22139
|
+
|
|
22140
|
+
// ../../packages/types/src/service-website-capture.ts
|
|
22141
|
+
import { z as z108 } from "zod";
|
|
22114
22142
|
var WEBSITE_CAPTURE_MAX_RESEARCH_BYTES = 1024 * 1024;
|
|
22115
22143
|
var WEBSITE_CAPTURE_MAX_FILES = 100;
|
|
22116
22144
|
var WEBSITE_CAPTURE_MAX_FILE_BYTES = 8 * 1024 * 1024;
|
|
22117
22145
|
var WEBSITE_CAPTURE_MAX_BUNDLE_BYTES = 30 * 1024 * 1024;
|
|
22118
|
-
var WebsiteCaptureCauseSchema =
|
|
22146
|
+
var WebsiteCaptureCauseSchema = z108.enum([
|
|
22119
22147
|
"site_blocked",
|
|
22120
22148
|
"site_unreachable",
|
|
22121
22149
|
"not_enough_content",
|
|
22122
22150
|
"internal"
|
|
22123
22151
|
]);
|
|
22124
|
-
var WebsiteCaptureStatusSchema =
|
|
22152
|
+
var WebsiteCaptureStatusSchema = z108.enum([
|
|
22125
22153
|
"queued",
|
|
22126
22154
|
"capturing",
|
|
22127
22155
|
"ready",
|
|
@@ -22143,143 +22171,143 @@ function normalizeWebsiteCaptureUrl(value) {
|
|
|
22143
22171
|
}
|
|
22144
22172
|
}
|
|
22145
22173
|
__name(normalizeWebsiteCaptureUrl, "normalizeWebsiteCaptureUrl");
|
|
22146
|
-
var WebsiteCaptureRequestSchema =
|
|
22147
|
-
url:
|
|
22174
|
+
var WebsiteCaptureRequestSchema = z108.object({
|
|
22175
|
+
url: z108.string().trim().max(2048).url().refine((value) => normalizeWebsiteCaptureUrl(value) !== null, "Use an HTTP(S) URL without credentials").transform((value) => normalizeWebsiteCaptureUrl(value)),
|
|
22148
22176
|
language: MotionGraphicsLanguageSchema
|
|
22149
22177
|
}).strict();
|
|
22150
|
-
var WebsiteCaptureResponseSchema =
|
|
22151
|
-
captureId:
|
|
22178
|
+
var WebsiteCaptureResponseSchema = z108.object({
|
|
22179
|
+
captureId: z108.string().uuid(),
|
|
22152
22180
|
status: WebsiteCaptureStatusSchema,
|
|
22153
|
-
expiresAt:
|
|
22154
|
-
previewUrl:
|
|
22181
|
+
expiresAt: z108.string().datetime(),
|
|
22182
|
+
previewUrl: z108.string().url().optional(),
|
|
22155
22183
|
cause: WebsiteCaptureCauseSchema.optional()
|
|
22156
22184
|
});
|
|
22157
22185
|
var WebsiteCaptureJobSchema = WebsiteCaptureRequestSchema.extend({
|
|
22158
|
-
captureId:
|
|
22159
|
-
attempt:
|
|
22160
|
-
leaseUntil:
|
|
22186
|
+
captureId: z108.string().uuid(),
|
|
22187
|
+
attempt: z108.number().int().positive(),
|
|
22188
|
+
leaseUntil: z108.string().datetime()
|
|
22161
22189
|
});
|
|
22162
|
-
var WebsiteCaptureClaimResponseSchema =
|
|
22190
|
+
var WebsiteCaptureClaimResponseSchema = z108.object({
|
|
22163
22191
|
capture: WebsiteCaptureJobSchema.nullable()
|
|
22164
22192
|
});
|
|
22165
22193
|
var attempt = {
|
|
22166
|
-
attempt:
|
|
22194
|
+
attempt: z108.number().int().positive()
|
|
22167
22195
|
};
|
|
22168
|
-
var digest =
|
|
22169
|
-
var WebsiteCaptureUploadRequestSchema =
|
|
22196
|
+
var digest = z108.string().regex(/^[a-f0-9]{64}$/);
|
|
22197
|
+
var WebsiteCaptureUploadRequestSchema = z108.object({
|
|
22170
22198
|
...attempt,
|
|
22171
|
-
contentLength:
|
|
22199
|
+
contentLength: z108.number().int().positive().max(WEBSITE_CAPTURE_MAX_BUNDLE_BYTES),
|
|
22172
22200
|
sha256: digest
|
|
22173
22201
|
}).strict();
|
|
22174
|
-
var WebsiteCaptureDoneRequestSchema =
|
|
22202
|
+
var WebsiteCaptureDoneRequestSchema = z108.object({
|
|
22175
22203
|
...attempt,
|
|
22176
22204
|
sha256: digest
|
|
22177
22205
|
}).strict();
|
|
22178
|
-
var WebsiteCaptureFailedRequestSchema =
|
|
22206
|
+
var WebsiteCaptureFailedRequestSchema = z108.object({
|
|
22179
22207
|
...attempt,
|
|
22180
22208
|
cause: WebsiteCaptureCauseSchema
|
|
22181
22209
|
}).strict();
|
|
22182
|
-
var WebsiteCaptureBundleSchema =
|
|
22183
|
-
version:
|
|
22184
|
-
files:
|
|
22185
|
-
path:
|
|
22186
|
-
base64:
|
|
22210
|
+
var WebsiteCaptureBundleSchema = z108.object({
|
|
22211
|
+
version: z108.literal(1),
|
|
22212
|
+
files: z108.array(z108.object({
|
|
22213
|
+
path: z108.string().max(140).regex(/^research\/(?:page\.json|(?:desktop|mobile)-[1-9]\d*\.jpg|logo\.(?:png|svg)|image-[1-9]\d*\.(?:png|jpg|jpeg|webp|svg|avif)|font-[1-9]\d*\.(?:woff2?|ttf|otf))$/),
|
|
22214
|
+
base64: z108.string().max(Math.ceil(WEBSITE_CAPTURE_MAX_FILE_BYTES / 3) * 4).regex(/^[A-Za-z0-9+/]*={0,2}$/).refine((value) => value.length % 4 === 0),
|
|
22187
22215
|
sha256: digest
|
|
22188
22216
|
}).strict()).min(1).max(WEBSITE_CAPTURE_MAX_FILES)
|
|
22189
22217
|
}).strict().refine((bundle) => new Set(bundle.files.map((file) => file.path)).size === bundle.files.length, "Duplicate capture file");
|
|
22190
|
-
var WebsiteCaptureScreenshotSchema =
|
|
22191
|
-
file:
|
|
22192
|
-
scrollTop:
|
|
22193
|
-
});
|
|
22194
|
-
var WebsiteCaptureAccessSchema =
|
|
22195
|
-
publicContentText:
|
|
22196
|
-
passwordGate:
|
|
22197
|
-
challengeGate:
|
|
22198
|
-
blockingOverlay:
|
|
22218
|
+
var WebsiteCaptureScreenshotSchema = z108.object({
|
|
22219
|
+
file: z108.string(),
|
|
22220
|
+
scrollTop: z108.number()
|
|
22221
|
+
});
|
|
22222
|
+
var WebsiteCaptureAccessSchema = z108.object({
|
|
22223
|
+
publicContentText: z108.string().max(8e3),
|
|
22224
|
+
passwordGate: z108.boolean(),
|
|
22225
|
+
challengeGate: z108.boolean(),
|
|
22226
|
+
blockingOverlay: z108.boolean(),
|
|
22199
22227
|
// Decoded, substantial images visible outside access walls and page chrome.
|
|
22200
22228
|
// Optional for compatibility with already captured text-led research.
|
|
22201
|
-
publicImageUrls:
|
|
22202
|
-
});
|
|
22203
|
-
var WebsiteCaptureResearchSchema =
|
|
22204
|
-
requestedUrl:
|
|
22205
|
-
capturedAt:
|
|
22206
|
-
locale:
|
|
22207
|
-
bodyTextTruncated:
|
|
22208
|
-
finalUrl:
|
|
22209
|
-
lang:
|
|
22210
|
-
title:
|
|
22211
|
-
description:
|
|
22212
|
-
openGraph:
|
|
22213
|
-
title:
|
|
22214
|
-
description:
|
|
22215
|
-
image:
|
|
22216
|
-
siteName:
|
|
22229
|
+
publicImageUrls: z108.array(z108.string().url().max(8192)).max(20).optional()
|
|
22230
|
+
});
|
|
22231
|
+
var WebsiteCaptureResearchSchema = z108.object({
|
|
22232
|
+
requestedUrl: z108.string().url(),
|
|
22233
|
+
capturedAt: z108.string().datetime(),
|
|
22234
|
+
locale: z108.string(),
|
|
22235
|
+
bodyTextTruncated: z108.boolean(),
|
|
22236
|
+
finalUrl: z108.string().url(),
|
|
22237
|
+
lang: z108.string().nullable(),
|
|
22238
|
+
title: z108.string(),
|
|
22239
|
+
description: z108.string(),
|
|
22240
|
+
openGraph: z108.object({
|
|
22241
|
+
title: z108.string(),
|
|
22242
|
+
description: z108.string(),
|
|
22243
|
+
image: z108.string(),
|
|
22244
|
+
siteName: z108.string()
|
|
22217
22245
|
}),
|
|
22218
|
-
themeColor:
|
|
22219
|
-
headings:
|
|
22220
|
-
h1:
|
|
22221
|
-
h2:
|
|
22222
|
-
h3:
|
|
22246
|
+
themeColor: z108.string(),
|
|
22247
|
+
headings: z108.object({
|
|
22248
|
+
h1: z108.array(z108.string()),
|
|
22249
|
+
h2: z108.array(z108.string()),
|
|
22250
|
+
h3: z108.array(z108.string())
|
|
22223
22251
|
}),
|
|
22224
|
-
callsToAction:
|
|
22225
|
-
listItems:
|
|
22226
|
-
bodyText:
|
|
22252
|
+
callsToAction: z108.array(z108.string()),
|
|
22253
|
+
listItems: z108.array(z108.string()),
|
|
22254
|
+
bodyText: z108.string(),
|
|
22227
22255
|
access: WebsiteCaptureAccessSchema.optional(),
|
|
22228
|
-
consent:
|
|
22229
|
-
pressed:
|
|
22230
|
-
removed:
|
|
22256
|
+
consent: z108.object({
|
|
22257
|
+
pressed: z108.string().nullable(),
|
|
22258
|
+
removed: z108.number().nonnegative()
|
|
22231
22259
|
}).optional(),
|
|
22232
|
-
overlaysDismissed:
|
|
22233
|
-
style:
|
|
22234
|
-
bodyBackground:
|
|
22235
|
-
bodyColor:
|
|
22236
|
-
bodyFont:
|
|
22237
|
-
headingFont:
|
|
22238
|
-
headingColor:
|
|
22239
|
-
actionColors:
|
|
22240
|
-
color:
|
|
22241
|
-
uses:
|
|
22260
|
+
overlaysDismissed: z108.number().int().nonnegative().optional(),
|
|
22261
|
+
style: z108.object({
|
|
22262
|
+
bodyBackground: z108.string(),
|
|
22263
|
+
bodyColor: z108.string(),
|
|
22264
|
+
bodyFont: z108.string(),
|
|
22265
|
+
headingFont: z108.string().nullable(),
|
|
22266
|
+
headingColor: z108.string().nullable(),
|
|
22267
|
+
actionColors: z108.array(z108.object({
|
|
22268
|
+
color: z108.string(),
|
|
22269
|
+
uses: z108.number()
|
|
22242
22270
|
}))
|
|
22243
22271
|
}),
|
|
22244
|
-
images:
|
|
22245
|
-
file:
|
|
22246
|
-
src:
|
|
22247
|
-
alt:
|
|
22248
|
-
width:
|
|
22249
|
-
height:
|
|
22250
|
-
isOpenGraph:
|
|
22272
|
+
images: z108.array(z108.object({
|
|
22273
|
+
file: z108.string(),
|
|
22274
|
+
src: z108.string(),
|
|
22275
|
+
alt: z108.string(),
|
|
22276
|
+
width: z108.number().nullable(),
|
|
22277
|
+
height: z108.number().nullable(),
|
|
22278
|
+
isOpenGraph: z108.boolean()
|
|
22251
22279
|
})),
|
|
22252
|
-
logo:
|
|
22253
|
-
file:
|
|
22254
|
-
svg:
|
|
22255
|
-
width:
|
|
22256
|
-
height:
|
|
22280
|
+
logo: z108.object({
|
|
22281
|
+
file: z108.literal("logo.png"),
|
|
22282
|
+
svg: z108.literal("logo.svg").optional(),
|
|
22283
|
+
width: z108.number(),
|
|
22284
|
+
height: z108.number()
|
|
22257
22285
|
}).nullable(),
|
|
22258
|
-
fonts:
|
|
22259
|
-
family:
|
|
22260
|
-
weight:
|
|
22261
|
-
style:
|
|
22262
|
-
unicodeRange:
|
|
22263
|
-
file:
|
|
22286
|
+
fonts: z108.array(z108.object({
|
|
22287
|
+
family: z108.string(),
|
|
22288
|
+
weight: z108.string(),
|
|
22289
|
+
style: z108.string(),
|
|
22290
|
+
unicodeRange: z108.string().nullable(),
|
|
22291
|
+
file: z108.string().optional()
|
|
22264
22292
|
}).transform((font) => ({
|
|
22265
22293
|
...font,
|
|
22266
22294
|
file: font.file
|
|
22267
22295
|
}))),
|
|
22268
|
-
screenshots:
|
|
22269
|
-
desktop:
|
|
22270
|
-
mobile:
|
|
22296
|
+
screenshots: z108.object({
|
|
22297
|
+
desktop: z108.array(WebsiteCaptureScreenshotSchema),
|
|
22298
|
+
mobile: z108.array(WebsiteCaptureScreenshotSchema)
|
|
22271
22299
|
})
|
|
22272
22300
|
});
|
|
22273
22301
|
|
|
22274
22302
|
// ../../packages/types/src/demo-mode.ts
|
|
22275
|
-
import { z as
|
|
22303
|
+
import { z as z109 } from "zod";
|
|
22276
22304
|
var DEMO_MODE_FLOWS = [
|
|
22277
22305
|
"brand",
|
|
22278
22306
|
"servicePage",
|
|
22279
22307
|
"motion",
|
|
22280
22308
|
"image"
|
|
22281
22309
|
];
|
|
22282
|
-
var DemoModeFlowSchema =
|
|
22310
|
+
var DemoModeFlowSchema = z109.enum(DEMO_MODE_FLOWS);
|
|
22283
22311
|
var DEMO_MODE_STEPS = [
|
|
22284
22312
|
"running",
|
|
22285
22313
|
"research",
|
|
@@ -22292,27 +22320,27 @@ var DEMO_MODE_STEPS = [
|
|
|
22292
22320
|
"final",
|
|
22293
22321
|
"watchdog"
|
|
22294
22322
|
];
|
|
22295
|
-
var DemoModeStepSchema =
|
|
22323
|
+
var DemoModeStepSchema = z109.enum(DEMO_MODE_STEPS);
|
|
22296
22324
|
var DEMO_MODE_WAIT_SECONDS = {
|
|
22297
22325
|
min: 30,
|
|
22298
22326
|
max: 450,
|
|
22299
22327
|
default: 150
|
|
22300
22328
|
};
|
|
22301
|
-
var centsSchema =
|
|
22302
|
-
var emailSchema =
|
|
22303
|
-
var DemoModeTemplatesSchema =
|
|
22304
|
-
brandId:
|
|
22305
|
-
servicePageId:
|
|
22306
|
-
motionTaskId:
|
|
22307
|
-
imageTaskId:
|
|
22308
|
-
});
|
|
22309
|
-
var DemoModeEditableSchema =
|
|
22310
|
-
enabled:
|
|
22311
|
-
emails:
|
|
22329
|
+
var centsSchema = z109.number().int().min(0).max(1e5);
|
|
22330
|
+
var emailSchema = z109.string().trim().toLowerCase().email();
|
|
22331
|
+
var DemoModeTemplatesSchema = z109.object({
|
|
22332
|
+
brandId: z109.string().uuid(),
|
|
22333
|
+
servicePageId: z109.string().uuid(),
|
|
22334
|
+
motionTaskId: z109.string().uuid(),
|
|
22335
|
+
imageTaskId: z109.string().uuid()
|
|
22336
|
+
});
|
|
22337
|
+
var DemoModeEditableSchema = z109.object({
|
|
22338
|
+
enabled: z109.boolean(),
|
|
22339
|
+
emails: z109.array(emailSchema).max(50).transform((list) => [
|
|
22312
22340
|
...new Set(list)
|
|
22313
22341
|
]),
|
|
22314
|
-
waitSeconds:
|
|
22315
|
-
chargeCents:
|
|
22342
|
+
waitSeconds: z109.number().int().min(DEMO_MODE_WAIT_SECONDS.min).max(DEMO_MODE_WAIT_SECONDS.max),
|
|
22343
|
+
chargeCents: z109.object({
|
|
22316
22344
|
brand: centsSchema,
|
|
22317
22345
|
servicePage: centsSchema,
|
|
22318
22346
|
motion: centsSchema,
|
|
@@ -22320,73 +22348,73 @@ var DemoModeEditableSchema = z108.object({
|
|
|
22320
22348
|
}),
|
|
22321
22349
|
templates: DemoModeTemplatesSchema
|
|
22322
22350
|
});
|
|
22323
|
-
var nullableString =
|
|
22324
|
-
var DemoModeSnapshotSchema =
|
|
22325
|
-
brand:
|
|
22351
|
+
var nullableString = z109.string().nullable();
|
|
22352
|
+
var DemoModeSnapshotSchema = z109.object({
|
|
22353
|
+
brand: z109.object({
|
|
22326
22354
|
/** Columnas de identidad de `Brand` listas para un `update` (sin id/userId/slug/estado/fechas). */
|
|
22327
|
-
identity:
|
|
22328
|
-
productSamples:
|
|
22329
|
-
name:
|
|
22330
|
-
priceCents:
|
|
22355
|
+
identity: z109.record(z109.unknown()),
|
|
22356
|
+
productSamples: z109.array(z109.object({
|
|
22357
|
+
name: z109.string(),
|
|
22358
|
+
priceCents: z109.number().int().nullable(),
|
|
22331
22359
|
currency: nullableString,
|
|
22332
|
-
imageKey:
|
|
22360
|
+
imageKey: z109.string(),
|
|
22333
22361
|
productUrl: nullableString,
|
|
22334
|
-
position:
|
|
22362
|
+
position: z109.number().int()
|
|
22335
22363
|
})),
|
|
22336
|
-
personas:
|
|
22337
|
-
name:
|
|
22364
|
+
personas: z109.array(z109.object({
|
|
22365
|
+
name: z109.string(),
|
|
22338
22366
|
demographics: nullableString,
|
|
22339
22367
|
painPoints: nullableString,
|
|
22340
22368
|
motivations: nullableString,
|
|
22341
22369
|
objections: nullableString,
|
|
22342
22370
|
gender: nullableString,
|
|
22343
|
-
isDefault:
|
|
22371
|
+
isDefault: z109.boolean()
|
|
22344
22372
|
}))
|
|
22345
22373
|
}),
|
|
22346
|
-
servicePage:
|
|
22347
|
-
facts:
|
|
22348
|
-
review:
|
|
22349
|
-
artifact:
|
|
22374
|
+
servicePage: z109.object({
|
|
22375
|
+
facts: z109.unknown(),
|
|
22376
|
+
review: z109.unknown(),
|
|
22377
|
+
artifact: z109.unknown()
|
|
22350
22378
|
}),
|
|
22351
|
-
motion:
|
|
22379
|
+
motion: z109.object({
|
|
22352
22380
|
outputs: MotionGraphicsOutputsSchema,
|
|
22353
22381
|
/**
|
|
22354
22382
|
* La captura REAL de la web de la plantilla (nunca una fabricada por la
|
|
22355
22383
|
* demo). Null cuando la plantilla no tiene ninguna: la captura demo nunca
|
|
22356
22384
|
* va live, así que el servicio usa `DEMO_MODE_PLACEHOLDER_CAPTURE`.
|
|
22357
22385
|
*/
|
|
22358
|
-
capture:
|
|
22359
|
-
bundleKey:
|
|
22360
|
-
sha256:
|
|
22361
|
-
uploadBytes:
|
|
22386
|
+
capture: z109.object({
|
|
22387
|
+
bundleKey: z109.string(),
|
|
22388
|
+
sha256: z109.string(),
|
|
22389
|
+
uploadBytes: z109.number().int().nullable(),
|
|
22362
22390
|
previewKey: nullableString
|
|
22363
22391
|
}).nullable()
|
|
22364
22392
|
}),
|
|
22365
|
-
image:
|
|
22366
|
-
provider:
|
|
22367
|
-
model:
|
|
22368
|
-
prompt:
|
|
22369
|
-
imageUrl:
|
|
22370
|
-
width:
|
|
22371
|
-
height:
|
|
22393
|
+
image: z109.object({
|
|
22394
|
+
provider: z109.string(),
|
|
22395
|
+
model: z109.string(),
|
|
22396
|
+
prompt: z109.string(),
|
|
22397
|
+
imageUrl: z109.string(),
|
|
22398
|
+
width: z109.number().int(),
|
|
22399
|
+
height: z109.number().int(),
|
|
22372
22400
|
adCopy: nullableString,
|
|
22373
|
-
rawResponse:
|
|
22401
|
+
rawResponse: z109.unknown()
|
|
22374
22402
|
})
|
|
22375
22403
|
});
|
|
22376
22404
|
var DemoModeConfigSchema = DemoModeEditableSchema.extend({
|
|
22377
22405
|
snapshot: DemoModeSnapshotSchema.nullable(),
|
|
22378
|
-
snapshotAt:
|
|
22406
|
+
snapshotAt: z109.string().datetime().nullable()
|
|
22379
22407
|
});
|
|
22380
22408
|
var DemoModeAdminViewSchema = DemoModeEditableSchema.extend({
|
|
22381
22409
|
// Sin configurar, la API devuelve ids vacíos ("" no es uuid): la vista los
|
|
22382
22410
|
// admite; el PUT sí exige uuid (`DemoModeEditableSchema`).
|
|
22383
|
-
templates:
|
|
22384
|
-
brandId:
|
|
22385
|
-
servicePageId:
|
|
22386
|
-
motionTaskId:
|
|
22387
|
-
imageTaskId:
|
|
22411
|
+
templates: z109.object({
|
|
22412
|
+
brandId: z109.string(),
|
|
22413
|
+
servicePageId: z109.string(),
|
|
22414
|
+
motionTaskId: z109.string(),
|
|
22415
|
+
imageTaskId: z109.string()
|
|
22388
22416
|
}),
|
|
22389
|
-
snapshotAt:
|
|
22417
|
+
snapshotAt: z109.string().nullable()
|
|
22390
22418
|
});
|
|
22391
22419
|
var DEMO_MODE_TEMPLATE_PROBLEMS = [
|
|
22392
22420
|
"not_found",
|
|
@@ -22397,31 +22425,31 @@ var DEMO_MODE_TEMPLATE_PROBLEMS = [
|
|
|
22397
22425
|
"no_video",
|
|
22398
22426
|
"no_creative"
|
|
22399
22427
|
];
|
|
22400
|
-
var DemoModeTemplateVerdictSchema =
|
|
22401
|
-
|
|
22402
|
-
ok:
|
|
22428
|
+
var DemoModeTemplateVerdictSchema = z109.discriminatedUnion("ok", [
|
|
22429
|
+
z109.object({
|
|
22430
|
+
ok: z109.literal(true)
|
|
22403
22431
|
}),
|
|
22404
|
-
|
|
22405
|
-
ok:
|
|
22406
|
-
problem:
|
|
22432
|
+
z109.object({
|
|
22433
|
+
ok: z109.literal(false),
|
|
22434
|
+
problem: z109.enum(DEMO_MODE_TEMPLATE_PROBLEMS)
|
|
22407
22435
|
})
|
|
22408
22436
|
]);
|
|
22409
|
-
var DemoModeValidationSchema =
|
|
22437
|
+
var DemoModeValidationSchema = z109.object({
|
|
22410
22438
|
brandId: DemoModeTemplateVerdictSchema,
|
|
22411
22439
|
servicePageId: DemoModeTemplateVerdictSchema,
|
|
22412
22440
|
motionTaskId: DemoModeTemplateVerdictSchema,
|
|
22413
22441
|
imageTaskId: DemoModeTemplateVerdictSchema
|
|
22414
22442
|
});
|
|
22415
|
-
var DemoModeJobSchema =
|
|
22443
|
+
var DemoModeJobSchema = z109.object({
|
|
22416
22444
|
flow: DemoModeFlowSchema,
|
|
22417
22445
|
step: DemoModeStepSchema,
|
|
22418
22446
|
/** brandId | servicePageOperationId | taskId según el flujo. */
|
|
22419
|
-
targetId:
|
|
22420
|
-
userId:
|
|
22447
|
+
targetId: z109.string().uuid(),
|
|
22448
|
+
userId: z109.string().min(1),
|
|
22421
22449
|
/** Solo marca: la generación de extracción que el guion completa. */
|
|
22422
|
-
generation:
|
|
22450
|
+
generation: z109.number().int().positive().optional(),
|
|
22423
22451
|
/** Solo `final`/`watchdog`: la parte del snapshot de ESTE flujo, congelada al empezar. */
|
|
22424
|
-
result:
|
|
22452
|
+
result: z109.unknown().optional()
|
|
22425
22453
|
});
|
|
22426
22454
|
|
|
22427
22455
|
// src/http.ts
|
|
@@ -22933,23 +22961,23 @@ import { InsufficientScopeError, InvalidTokenError } from "@modelcontextprotocol
|
|
|
22933
22961
|
import { createRemoteJWKSet as createRemoteJWKSet2, jwtVerify as jwtVerify2 } from "jose";
|
|
22934
22962
|
|
|
22935
22963
|
// src/auth/oauth-config.ts
|
|
22936
|
-
import { z as
|
|
22964
|
+
import { z as z110 } from "zod";
|
|
22937
22965
|
var MCP_RESOURCE = new URL("https://mcp.productmaker.app/mcp");
|
|
22938
22966
|
var MCP_SCOPE = "mcp:access";
|
|
22939
22967
|
var REFRESH_SCOPE = "offline_access";
|
|
22940
22968
|
var STATIC_CLIENT_ISSUER = new URL(MCP_RESOURCE.origin);
|
|
22941
|
-
var oauthEnvSchema =
|
|
22942
|
-
MCP_REMOTE_AUTH_MODE:
|
|
22943
|
-
MCP_AUTH0_ISSUER:
|
|
22944
|
-
MCP_AUTH0_AUDIENCE:
|
|
22969
|
+
var oauthEnvSchema = z110.object({
|
|
22970
|
+
MCP_REMOTE_AUTH_MODE: z110.literal("oauth"),
|
|
22971
|
+
MCP_AUTH0_ISSUER: z110.string().trim().min(1),
|
|
22972
|
+
MCP_AUTH0_AUDIENCE: z110.string().trim().refine((value) => value === MCP_RESOURCE.href, {
|
|
22945
22973
|
message: `must equal ${MCP_RESOURCE.href}`
|
|
22946
22974
|
}),
|
|
22947
|
-
MCP_AUTH0_CLIENT_ID:
|
|
22948
|
-
MCP_AUTH0_CLIENT_SECRET:
|
|
22949
|
-
PM_API_AUDIENCE:
|
|
22950
|
-
AUTH0_AUDIENCE:
|
|
22951
|
-
MCP_STATIC_CLIENT_ID:
|
|
22952
|
-
MCP_STATIC_CLIENT_SECRET:
|
|
22975
|
+
MCP_AUTH0_CLIENT_ID: z110.string().trim().min(1),
|
|
22976
|
+
MCP_AUTH0_CLIENT_SECRET: z110.string().trim().min(1),
|
|
22977
|
+
PM_API_AUDIENCE: z110.string().trim().min(1),
|
|
22978
|
+
AUTH0_AUDIENCE: z110.string().trim().min(1),
|
|
22979
|
+
MCP_STATIC_CLIENT_ID: z110.string().trim().min(1).optional(),
|
|
22980
|
+
MCP_STATIC_CLIENT_SECRET: z110.string().trim().min(1).optional()
|
|
22953
22981
|
});
|
|
22954
22982
|
function formatZodIssues(error) {
|
|
22955
22983
|
return error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
|
|
@@ -24105,7 +24133,7 @@ var ApiClient = class {
|
|
|
24105
24133
|
};
|
|
24106
24134
|
|
|
24107
24135
|
// src/index.ts
|
|
24108
|
-
var MCP_VERSION = "11.
|
|
24136
|
+
var MCP_VERSION = "11.4.0";
|
|
24109
24137
|
|
|
24110
24138
|
// src/meta-upload-app.ts
|
|
24111
24139
|
import { readFileSync } from "fs";
|
|
@@ -24177,7 +24205,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
|
|
|
24177
24205
|
__name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
|
|
24178
24206
|
|
|
24179
24207
|
// src/tools/tasks.ts
|
|
24180
|
-
import { z as
|
|
24208
|
+
import { z as z115 } from "zod";
|
|
24181
24209
|
|
|
24182
24210
|
// src/resolve-image.ts
|
|
24183
24211
|
import { lookup as dnsLookup } from "dns/promises";
|
|
@@ -24738,9 +24766,9 @@ async function resolveMediaRef(ref, opts) {
|
|
|
24738
24766
|
__name(resolveMediaRef, "resolveMediaRef");
|
|
24739
24767
|
|
|
24740
24768
|
// src/tools/shared.ts
|
|
24741
|
-
import { z as
|
|
24742
|
-
var Lang =
|
|
24743
|
-
var Country =
|
|
24769
|
+
import { z as z111 } from "zod";
|
|
24770
|
+
var Lang = z111.string().regex(/^[a-z]{2}(?:[-_][a-zA-Z]{2})?$/, "Usa un c\xF3digo de idioma BCP-47, por ejemplo es, en-US o pt-BR").max(10);
|
|
24771
|
+
var Country = z111.string().min(2).max(3);
|
|
24744
24772
|
var LandingStrategyEnum = LandingStrategySchema;
|
|
24745
24773
|
var LandingImageFormatEnum = LandingImageFormatSchema;
|
|
24746
24774
|
var VideoPresetEnum = VideoPreset.extract([
|
|
@@ -24844,7 +24872,7 @@ function animationStyleApplies(videoPreset, angleNarratives) {
|
|
|
24844
24872
|
return ANIMATED_VIDEO_PRESETS.has(videoPreset ?? "") || (angleNarratives ?? []).some((n) => ANIMATED_NARRATIVE_STYLES.has(n));
|
|
24845
24873
|
}
|
|
24846
24874
|
__name(animationStyleApplies, "animationStyleApplies");
|
|
24847
|
-
var VideoTierEnum =
|
|
24875
|
+
var VideoTierEnum = z111.enum([
|
|
24848
24876
|
"basic"
|
|
24849
24877
|
]);
|
|
24850
24878
|
function resolveVideoTier(_tier) {
|
|
@@ -24902,10 +24930,10 @@ var ImageCreativeStyleEnum = ImageCreativeStyle;
|
|
|
24902
24930
|
var ImageCreativeArchetypeEnum = ImageCreativeArchetype;
|
|
24903
24931
|
var ImageCreativeVisualTreatmentEnum = ImageCreativeVisualTreatment;
|
|
24904
24932
|
var ImageCreativeAspectRatioEnum = ImageCreativeAspectRatio;
|
|
24905
|
-
var ImageRefSchema =
|
|
24906
|
-
url:
|
|
24907
|
-
path:
|
|
24908
|
-
assetId:
|
|
24933
|
+
var ImageRefSchema = z111.object({
|
|
24934
|
+
url: z111.string().url().optional().describe('URL p\xFAblica HTTPS de la foto. Ej: una URL de Shopify CDN, Cloudinary, Imgur. \xDAsala cuando el usuario te diga "est\xE1 en X.com/foto.jpg" o cuando la foto ya est\xE9 hospedada.'),
|
|
24935
|
+
path: z111.string().min(1).optional().describe('Ruta del archivo en el computador del usuario. Ej: "/Users/maria/Desktop/foto.jpg", "~/Pictures/camiseta.png", "C:\\Users\\Maria\\Desktop\\foto.jpg". El MCP local la lee del disco y la sube. SOLO funciona cuando el MCP corre local (stdio). NO funciona en mcp.productmaker.app (HTTP) \u2014 ah\xED usa `url`.'),
|
|
24936
|
+
assetId: z111.string().uuid().optional().describe("ID opaco devuelto por check_media_upload. \xDAsalo para una imagen subida desde el MCP App; ProductMaker adopta el archivo directamente y el MCP nunca descarga sus bytes.")
|
|
24909
24937
|
}).refine((v) => [
|
|
24910
24938
|
v.url,
|
|
24911
24939
|
v.path,
|
|
@@ -24913,11 +24941,11 @@ var ImageRefSchema = z110.object({
|
|
|
24913
24941
|
].filter(Boolean).length === 1, {
|
|
24914
24942
|
message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
|
|
24915
24943
|
});
|
|
24916
|
-
var ImagesInput =
|
|
24944
|
+
var ImagesInput = z111.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
|
|
24917
24945
|
const assetCount = images.filter((image) => Boolean(image.assetId)).length;
|
|
24918
24946
|
if (assetCount > 0 && assetCount !== images.length) {
|
|
24919
24947
|
ctx.addIssue({
|
|
24920
|
-
code:
|
|
24948
|
+
code: z111.ZodIssueCode.custom,
|
|
24921
24949
|
message: "all image entries must use assetId, or all must use URL/path sources"
|
|
24922
24950
|
});
|
|
24923
24951
|
}
|
|
@@ -24998,14 +25026,14 @@ async function submitCreative(api, opts) {
|
|
|
24998
25026
|
});
|
|
24999
25027
|
}
|
|
25000
25028
|
__name(submitCreative, "submitCreative");
|
|
25001
|
-
var ResearchTargetCountryEnum =
|
|
25029
|
+
var ResearchTargetCountryEnum = z111.enum([
|
|
25002
25030
|
"CO",
|
|
25003
25031
|
"MX",
|
|
25004
25032
|
"PE",
|
|
25005
25033
|
"EC",
|
|
25006
25034
|
"CL"
|
|
25007
25035
|
]);
|
|
25008
|
-
var ResearchCategoryEnum =
|
|
25036
|
+
var ResearchCategoryEnum = z111.enum([
|
|
25009
25037
|
"auto",
|
|
25010
25038
|
"automotive",
|
|
25011
25039
|
"kitchen",
|
|
@@ -25135,6 +25163,7 @@ var McpErrorCode = {
|
|
|
25135
25163
|
CAMPAIGN_NOT_FOUND: "CAMPAIGN_NOT_FOUND",
|
|
25136
25164
|
CAMPAIGN_TASK_NOT_FOUND: "CAMPAIGN_TASK_NOT_FOUND",
|
|
25137
25165
|
CAMPAIGN_MISSING_LANDING_URL: "CAMPAIGN_MISSING_LANDING_URL",
|
|
25166
|
+
CAMPAIGN_MISSING_TARGET_COUNTRY: "CAMPAIGN_MISSING_TARGET_COUNTRY",
|
|
25138
25167
|
CAMPAIGN_NO_CREATIVES: "CAMPAIGN_NO_CREATIVES",
|
|
25139
25168
|
CAMPAIGN_MISSING_THUMBNAILS: "CAMPAIGN_MISSING_THUMBNAILS",
|
|
25140
25169
|
CAMPAIGN_RECONCILIATION_REQUIRED: "CAMPAIGN_RECONCILIATION_REQUIRED",
|
|
@@ -25174,6 +25203,7 @@ var McpErrorCode = {
|
|
|
25174
25203
|
META_NO_ASSETS_READY: "META_NO_ASSETS_READY",
|
|
25175
25204
|
META_NO_THUMBNAIL_SOURCE: "META_NO_THUMBNAIL_SOURCE",
|
|
25176
25205
|
META_NO_LANDING_URL: "META_NO_LANDING_URL",
|
|
25206
|
+
META_NO_TARGET_COUNTRY: "META_NO_TARGET_COUNTRY",
|
|
25177
25207
|
META_TASK_NOT_FOUND: "META_TASK_NOT_FOUND",
|
|
25178
25208
|
META_INVALID_DATA: "META_INVALID_DATA",
|
|
25179
25209
|
META_INVALID_AD_ACCOUNT: "META_INVALID_AD_ACCOUNT",
|
|
@@ -25261,7 +25291,8 @@ var CODE_MESSAGES = {
|
|
|
25261
25291
|
META_NO_ADS_CREATED: "No ads could be created. Most likely: the Meta Ads account has no payment method, no Facebook Page is linked, or the Facebook app lost permissions. Verify all three at https://business.facebook.com.",
|
|
25262
25292
|
META_NO_ASSETS_READY: "The task has no videos or ad creative ready to publish yet. Wait for generation to finish or regenerate the assets.",
|
|
25263
25293
|
META_NO_THUMBNAIL_SOURCE: "No image is available to use as the video thumbnail. Upload a product image or generate the ad creative before publishing.",
|
|
25264
|
-
META_NO_LANDING_URL: "Missing landing URL. Pass it in `landingUrl
|
|
25294
|
+
META_NO_LANDING_URL: "Missing landing URL. Pass it in `landingUrl`, or publish first: a product to Shopify with `publish_to_shopify`, a service to its service landing.",
|
|
25295
|
+
META_NO_TARGET_COUNTRY: "This service ad has no target country (its brand sets none). Ask the user which country and pass it in `campaignConfig.targetCountries`; never assume one.",
|
|
25265
25296
|
META_TASK_NOT_FOUND: "Task not found or does not belong to this user. Verify the `taskId`.",
|
|
25266
25297
|
META_INVALID_DATA: "Meta rejected the request due to invalid data. Verify that `adAccountId` and `pixelId` are correct.",
|
|
25267
25298
|
META_INVALID_AD_ACCOUNT: "Ad account not found or no access. Confirm the `adAccountId` with `list_meta_ad_accounts`.",
|
|
@@ -25300,7 +25331,8 @@ var CODE_MESSAGES = {
|
|
|
25300
25331
|
// Campaign (shared)
|
|
25301
25332
|
CAMPAIGN_NOT_FOUND: "Campaign not found or does not belong to this user. Verify the `campaignId`.",
|
|
25302
25333
|
CAMPAIGN_TASK_NOT_FOUND: "Campaign task not found. Verify the `taskId`.",
|
|
25303
|
-
CAMPAIGN_MISSING_LANDING_URL: "Missing landing URL for the campaign. Publish to Shopify
|
|
25334
|
+
CAMPAIGN_MISSING_LANDING_URL: "Missing landing URL for the campaign. Publish first (a product to Shopify, a service to its service landing) or pass `landingUrl` explicitly.",
|
|
25335
|
+
CAMPAIGN_MISSING_TARGET_COUNTRY: "This service ad has no target country (its brand sets none). Ask the user which country and pass it in `campaignConfig.targetCountries`; never assume one.",
|
|
25304
25336
|
CAMPAIGN_NO_CREATIVES: "The task has no creatives (video/image) ready for the campaign. Wait for generation to finish.",
|
|
25305
25337
|
CAMPAIGN_MISSING_THUMBNAILS: "Missing thumbnails for the videos. Verify that image/video generation has finished.",
|
|
25306
25338
|
CAMPAIGN_RECONCILIATION_REQUIRED: "A campaign may already have been created. Do not retry creation; reopen the project and reconcile it or contact support.",
|
|
@@ -25392,8 +25424,10 @@ var INVALID_PARAM_CODES = /* @__PURE__ */ new Set([
|
|
|
25392
25424
|
McpErrorCode.TIKTOK_ADVERTISER_REQUIRED,
|
|
25393
25425
|
McpErrorCode.TIKTOK_PIXEL_NOT_FOUND,
|
|
25394
25426
|
McpErrorCode.CAMPAIGN_MISSING_LANDING_URL,
|
|
25427
|
+
McpErrorCode.CAMPAIGN_MISSING_TARGET_COUNTRY,
|
|
25395
25428
|
McpErrorCode.CAMPAIGN_RECONCILIATION_REQUIRED,
|
|
25396
25429
|
McpErrorCode.META_NO_LANDING_URL,
|
|
25430
|
+
McpErrorCode.META_NO_TARGET_COUNTRY,
|
|
25397
25431
|
McpErrorCode.META_PORTFOLIO_MISMATCH,
|
|
25398
25432
|
McpErrorCode.META_PAGE_SELECTION_REQUIRED,
|
|
25399
25433
|
McpErrorCode.META_INVALID_PAGE,
|
|
@@ -25504,6 +25538,7 @@ var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
|
|
|
25504
25538
|
McpErrorCode.META_NO_ASSETS_READY,
|
|
25505
25539
|
McpErrorCode.META_NO_THUMBNAIL_SOURCE,
|
|
25506
25540
|
McpErrorCode.META_NO_LANDING_URL,
|
|
25541
|
+
McpErrorCode.META_NO_TARGET_COUNTRY,
|
|
25507
25542
|
McpErrorCode.META_TASK_NOT_FOUND,
|
|
25508
25543
|
McpErrorCode.META_INVALID_DATA,
|
|
25509
25544
|
McpErrorCode.META_INVALID_AD_ACCOUNT,
|
|
@@ -25551,6 +25586,7 @@ var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
|
|
|
25551
25586
|
McpErrorCode.CAMPAIGN_NOT_FOUND,
|
|
25552
25587
|
McpErrorCode.CAMPAIGN_TASK_NOT_FOUND,
|
|
25553
25588
|
McpErrorCode.CAMPAIGN_MISSING_LANDING_URL,
|
|
25589
|
+
McpErrorCode.CAMPAIGN_MISSING_TARGET_COUNTRY,
|
|
25554
25590
|
McpErrorCode.CAMPAIGN_NO_CREATIVES,
|
|
25555
25591
|
McpErrorCode.CAMPAIGN_MISSING_THUMBNAILS,
|
|
25556
25592
|
McpErrorCode.CAMPAIGN_RECONCILIATION_REQUIRED,
|
|
@@ -26317,29 +26353,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
|
|
|
26317
26353
|
__name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
|
|
26318
26354
|
|
|
26319
26355
|
// src/tools/media-presentation.ts
|
|
26320
|
-
import { z as
|
|
26321
|
-
var HttpsPresentationUrlSchema =
|
|
26356
|
+
import { z as z112 } from "zod";
|
|
26357
|
+
var HttpsPresentationUrlSchema = z112.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
|
|
26322
26358
|
var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
|
|
26323
26359
|
const hostname = new URL(value).hostname.toLowerCase();
|
|
26324
26360
|
return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
|
|
26325
26361
|
}, "preview URL must be owned by ProductMaker");
|
|
26326
|
-
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) =>
|
|
26327
|
-
var PresentationImageSchema =
|
|
26328
|
-
kind:
|
|
26362
|
+
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z112.number().int().positive().max(maximum), "positiveIntAtMost");
|
|
26363
|
+
var PresentationImageSchema = z112.object({
|
|
26364
|
+
kind: z112.literal("image"),
|
|
26329
26365
|
url: HttpsPresentationUrlSchema,
|
|
26330
|
-
mimeType:
|
|
26366
|
+
mimeType: z112.enum([
|
|
26331
26367
|
"image/jpeg",
|
|
26332
26368
|
"image/png"
|
|
26333
26369
|
]),
|
|
26334
26370
|
byteSize: positiveIntAtMost(5 * 1024 * 1024),
|
|
26335
26371
|
width: positiveIntAtMost(16384),
|
|
26336
26372
|
height: positiveIntAtMost(16384),
|
|
26337
|
-
alt:
|
|
26373
|
+
alt: z112.string().trim().min(1).max(240)
|
|
26338
26374
|
}).strict();
|
|
26339
26375
|
var McpMediaPresentationSchema = PresentationImageSchema;
|
|
26340
|
-
var GalleryImageSchema =
|
|
26376
|
+
var GalleryImageSchema = z112.object({
|
|
26341
26377
|
url: ProductMakerPreviewUrlSchema,
|
|
26342
|
-
alt:
|
|
26378
|
+
alt: z112.string().trim().min(1).max(240)
|
|
26343
26379
|
});
|
|
26344
26380
|
var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
|
|
26345
26381
|
async function imageBlocks(image, transport) {
|
|
@@ -26396,12 +26432,12 @@ async function buildMcpMediaPresentationContent(rawPresentation, transport = "ht
|
|
|
26396
26432
|
];
|
|
26397
26433
|
}
|
|
26398
26434
|
__name(buildMcpMediaPresentationContent, "buildMcpMediaPresentationContent");
|
|
26399
|
-
var OwnedImagePreviewSchema =
|
|
26435
|
+
var OwnedImagePreviewSchema = z112.object({
|
|
26400
26436
|
url: HttpsPresentationUrlSchema.refine((value) => {
|
|
26401
26437
|
const url = new URL(value);
|
|
26402
26438
|
return !url.username && !url.password && !isPrivateHost(url.hostname);
|
|
26403
26439
|
}, "Preview URL must be public HTTPS without credentials"),
|
|
26404
|
-
alt:
|
|
26440
|
+
alt: z112.string().trim().min(1).max(240)
|
|
26405
26441
|
});
|
|
26406
26442
|
async function buildMcpImagePreviewContent(rawPreview, transport = "http") {
|
|
26407
26443
|
const preview2 = OwnedImagePreviewSchema.safeParse(rawPreview);
|
|
@@ -26484,7 +26520,7 @@ async function buildMcpImageGalleryContent(rawItems, transport = "http") {
|
|
|
26484
26520
|
__name(buildMcpImageGalleryContent, "buildMcpImageGalleryContent");
|
|
26485
26521
|
|
|
26486
26522
|
// src/tools/animated-video.ts
|
|
26487
|
-
import { z as
|
|
26523
|
+
import { z as z113 } from "zod";
|
|
26488
26524
|
|
|
26489
26525
|
// src/tools/paid-confirmation.ts
|
|
26490
26526
|
function describeMarketStudyChoice(enabled) {
|
|
@@ -26734,27 +26770,27 @@ function hookVariantsLabel(count) {
|
|
|
26734
26770
|
return count === 1 ? "1 versi\xF3n del gancho" : `${count} versiones del gancho`;
|
|
26735
26771
|
}
|
|
26736
26772
|
__name(hookVariantsLabel, "hookVariantsLabel");
|
|
26737
|
-
var DurationInput =
|
|
26738
|
-
var CreateAnimatedVideoInput =
|
|
26739
|
-
action:
|
|
26773
|
+
var DurationInput = z113.union(MOTION_GRAPHICS_DURATIONS.map((d) => z113.literal(d)));
|
|
26774
|
+
var CreateAnimatedVideoInput = z113.object({
|
|
26775
|
+
action: z113.enum([
|
|
26740
26776
|
"prepare",
|
|
26741
26777
|
"status",
|
|
26742
26778
|
"cancel",
|
|
26743
26779
|
"generate"
|
|
26744
26780
|
]).default("prepare").describe("prepare inicia una captura gratuita; status consulta websiteCaptureId; cancel la cancela; generate requiere captura ready y confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrar vista previa y precio."),
|
|
26745
|
-
websiteCaptureId:
|
|
26746
|
-
generationRequestId:
|
|
26747
|
-
confirmed:
|
|
26781
|
+
websiteCaptureId: z113.string().uuid().optional().describe("ID de la captura preparada. Obligatorio para status/cancel/generate; no inventarlo."),
|
|
26782
|
+
generationRequestId: z113.string().uuid().optional().describe("Identidad opcional de una generaci\xF3n confirmada. Repite el mismo UUID al recuperar una respuesta perdida; usa otro \xFAnicamente cuando el usuario pida y confirme otro video, nunca por un error de transporte."),
|
|
26783
|
+
confirmed: z113.boolean().optional().describe("Solo true despu\xE9s de que el usuario confirme esta captura, formato, duraci\xF3n, idioma y precio. Obligatorio para generate; preparar no genera ni cobra."),
|
|
26748
26784
|
// Plain text, not `.url()`: users type «cal.com», and the web accepts it.
|
|
26749
26785
|
// normalizeWebAddress (shared with the web) adds https:// and refuses
|
|
26750
26786
|
// anything that is not a public http(s) address.
|
|
26751
|
-
landingUrl:
|
|
26787
|
+
landingUrl: z113.string().trim().min(1).optional().describe("Enlace p\xFAblico de la p\xE1gina del servicio, como lo dio el usuario (\xABcal.com\xBB o \xABhttps://cal.com\xBB). El video sale de lo que muestra esa p\xE1gina: su marca, colores y mensajes."),
|
|
26752
26788
|
format: MotionGraphicsFormatSchema.optional().describe('Formato: "vertical" (9:16, Reels/TikTok), "square" (1:1, feed) u "horizontal" (16:9, YouTube/web). Si el usuario no lo dijo, PREG\xDANTALE.'),
|
|
26753
26789
|
durationSec: DurationInput.optional().describe(`Duraci\xF3n en segundos: ${MOTION_GRAPHICS_DURATIONS.join(", ")}. Fija el precio (ver la descripci\xF3n de la herramienta). Si el usuario no la dijo, PREG\xDANTALE.`),
|
|
26754
26790
|
language: MotionGraphicsLanguageSchema.optional().describe('Idioma de los textos del video: "es", "en" o "pt".'),
|
|
26755
|
-
notes:
|
|
26791
|
+
notes: z113.string().trim().max(MOTION_GRAPHICS_NOTES_MAX_CHARS).optional().describe("Opcional. Indicaciones para el video en lenguaje natural (ej. enf\xF3cate en los precios, tono m\xE1s formal, menciona la prueba gratis)."),
|
|
26756
26792
|
hookVariants: MotionGraphicsHookVariantsSchema.optional().describe(`Opcional. Versiones del gancho: el mismo video con distintas aperturas para probar cu\xE1l funciona mejor, de 1 a ${MOTION_GRAPHICS_HOOK_VARIANTS_MAX} (por defecto 1). Cada versi\xF3n extra tiene precio (ver la descripci\xF3n de la herramienta); \xFAsalo solo si el usuario lo pide.`),
|
|
26757
|
-
music:
|
|
26793
|
+
music: z113.boolean().optional().describe("Opcional. M\xFAsica de fondo (por defecto true). false hace el video sin m\xFAsica, m\xE1s crudo, estilo UGC: quedan la voz y los efectos de sonido. Mismo precio. \xDAsalo solo si el usuario lo pide.")
|
|
26758
26794
|
}).strict();
|
|
26759
26795
|
function captureNextAction(capture) {
|
|
26760
26796
|
if (capture.status === "ready") return "Muestra la vista previa al usuario y confirma formato, duraci\xF3n, idioma y precio. Solo despu\xE9s llama create_animated_video con action=generate, este websiteCaptureId y confirmed=true.";
|
|
@@ -26787,43 +26823,43 @@ var FORMAT_LABELS = {
|
|
|
26787
26823
|
square: "cuadrado 1:1",
|
|
26788
26824
|
horizontal: "horizontal 16:9"
|
|
26789
26825
|
};
|
|
26790
|
-
var AnimatedVideoResultSchema =
|
|
26791
|
-
status:
|
|
26826
|
+
var AnimatedVideoResultSchema = z113.object({
|
|
26827
|
+
status: z113.enum([
|
|
26792
26828
|
"pending",
|
|
26793
26829
|
"done",
|
|
26794
26830
|
"error"
|
|
26795
26831
|
]),
|
|
26796
|
-
serviceMode:
|
|
26797
|
-
finalMp4Url:
|
|
26798
|
-
error:
|
|
26799
|
-
motionGraphics:
|
|
26832
|
+
serviceMode: z113.literal("motion_graphics"),
|
|
26833
|
+
finalMp4Url: z113.string().optional(),
|
|
26834
|
+
error: z113.string().optional(),
|
|
26835
|
+
motionGraphics: z113.object({
|
|
26800
26836
|
stage: MotionGraphicsStageSchema,
|
|
26801
26837
|
format: MotionGraphicsFormatSchema,
|
|
26802
|
-
durationSec:
|
|
26803
|
-
width:
|
|
26804
|
-
height:
|
|
26838
|
+
durationSec: z113.number(),
|
|
26839
|
+
width: z113.number().optional(),
|
|
26840
|
+
height: z113.number().optional(),
|
|
26805
26841
|
language: MotionGraphicsLanguageSchema.optional(),
|
|
26806
|
-
queuedAt:
|
|
26807
|
-
jobsAhead:
|
|
26808
|
-
stageStartedAt:
|
|
26809
|
-
renderProgress:
|
|
26842
|
+
queuedAt: z113.string().optional(),
|
|
26843
|
+
jobsAhead: z113.number().int().nonnegative().optional(),
|
|
26844
|
+
stageStartedAt: z113.string().optional(),
|
|
26845
|
+
renderProgress: z113.number().optional(),
|
|
26810
26846
|
// AI clip fields (absent on a video paid before clips, or from an API
|
|
26811
26847
|
// that predates them). Lenient: an unreadable value is dropped
|
|
26812
26848
|
// instead of hiding the status.
|
|
26813
|
-
clipCount:
|
|
26814
|
-
clipsUsed:
|
|
26815
|
-
clipPriceCents:
|
|
26816
|
-
clipsRefunded:
|
|
26849
|
+
clipCount: z113.number().int().nonnegative().optional().catch(void 0),
|
|
26850
|
+
clipsUsed: z113.number().int().nonnegative().optional().catch(void 0),
|
|
26851
|
+
clipPriceCents: z113.number().finite().nonnegative().optional().catch(void 0),
|
|
26852
|
+
clipsRefunded: z113.number().int().nonnegative().optional().catch(void 0),
|
|
26817
26853
|
// Hook versions (absent from an API or a video before them): the
|
|
26818
26854
|
// count ordered and, once done, the signed URLs of the EXTRA versions
|
|
26819
26855
|
// (hook 2, hook 3); `finalMp4Url` is hook 1.
|
|
26820
|
-
hookVariants:
|
|
26821
|
-
variantUrls:
|
|
26856
|
+
hookVariants: z113.number().int().min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).optional().catch(void 0),
|
|
26857
|
+
variantUrls: z113.array(z113.string().min(1)).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
|
|
26822
26858
|
// Extra hook versions given back, as the task recorded it once the
|
|
26823
26859
|
// refunds landed (absent until then, and from an API before it).
|
|
26824
|
-
variantsRefunded:
|
|
26825
|
-
activity:
|
|
26826
|
-
previewUrl:
|
|
26860
|
+
variantsRefunded: z113.number().int().nonnegative().optional().catch(void 0),
|
|
26861
|
+
activity: z113.array(MotionGraphicsActivitySchema).optional().catch(void 0),
|
|
26862
|
+
previewUrl: z113.string().optional()
|
|
26827
26863
|
}).passthrough()
|
|
26828
26864
|
}).passthrough();
|
|
26829
26865
|
function parseAnimatedVideoResult(value) {
|
|
@@ -27079,10 +27115,10 @@ function registerAnimatedVideoTools(server, api) {
|
|
|
27079
27115
|
__name(registerAnimatedVideoTools, "registerAnimatedVideoTools");
|
|
27080
27116
|
|
|
27081
27117
|
// src/tools/winning-product-image.ts
|
|
27082
|
-
import { z as
|
|
27083
|
-
var WinnerReferenceInput =
|
|
27084
|
-
runId:
|
|
27085
|
-
candidateSourceId:
|
|
27118
|
+
import { z as z114 } from "zod";
|
|
27119
|
+
var WinnerReferenceInput = z114.object({
|
|
27120
|
+
runId: z114.string().uuid(),
|
|
27121
|
+
candidateSourceId: z114.string().trim().min(1).max(160)
|
|
27086
27122
|
}).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
|
|
27087
27123
|
async function resolveWinnerImages(api, winnerReference, images) {
|
|
27088
27124
|
if (!winnerReference) return images;
|
|
@@ -27119,62 +27155,62 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
|
|
|
27119
27155
|
var CREATE_SERVICE_VIDEO_ON_MCP = PRODUCTMAKER_MCP_CAPABILITY_NAMES.includes("create_service_video");
|
|
27120
27156
|
var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
|
|
27121
27157
|
var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
|
|
27122
|
-
var CreateProductTaskInput =
|
|
27158
|
+
var CreateProductTaskInput = z115.object({
|
|
27123
27159
|
images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
|
|
27124
27160
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
27125
|
-
projectId:
|
|
27126
|
-
productUrl:
|
|
27161
|
+
projectId: z115.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
|
|
27162
|
+
productUrl: z115.string().url().optional().describe("Opcional. URL de la p\xE1gina del producto (Shopify, AliExpress, Amazon, etc.) para enriquecer el contexto. Si se omite, la IA infiere todo desde la imagen."),
|
|
27127
27163
|
language: Lang.describe('C\xF3digo de idioma para el contenido generado. Ejemplos: "es", "en", "pt". REQUERIDO \u2014 si el usuario no lo especific\xF3, PREG\xDANTALE antes de invocar. NUNCA infieras desde el contexto del chat ni asumas "es" por default.'),
|
|
27128
27164
|
country: Country.describe('C\xF3digo ISO del pa\xEDs objetivo. Ejemplos: "CO", "MX", "US", "AR". Define moneda, m\xE9todos de pago locales y tono. REQUERIDO \u2014 si el usuario no lo especific\xF3, PREG\xDANTALE antes de invocar. NUNCA infieras desde el contexto del chat.'),
|
|
27129
|
-
price:
|
|
27130
|
-
compareAtPrice:
|
|
27131
|
-
offer:
|
|
27132
|
-
paymentMethods:
|
|
27133
|
-
productContext:
|
|
27134
|
-
productLabel:
|
|
27165
|
+
price: z115.string().min(1).max(120).optional().describe('Precio que se mostrar\xE1 en la landing y video. Formato libre \u2014 ej. "$89.900", "USD 29.99", "MXN 599". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar. Si te dice "t\xFA elige", om\xEDtelo y el backend sugiere uno.'),
|
|
27166
|
+
compareAtPrice: z115.string().min(1).max(120).optional().describe('Opcional. Precio anterior para comunicar un descuento real en landing e im\xE1genes. Ej. "$129.000" cuando price="$89.900".'),
|
|
27167
|
+
offer: z115.string().min(1).max(240).optional().describe('Oferta o promoci\xF3n a destacar. Ej. "2x1", "Env\xEDo gratis hoy", "50% OFF". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar (es v\xE1lido que diga "sin oferta"). Si te dice "t\xFA elige", om\xEDtelo.'),
|
|
27168
|
+
paymentMethods: z115.string().min(1).max(240).optional().describe('Opcional. M\xE9todos de pago que puede mostrar la landing. Ej. "Tarjeta, PSE, Nequi, Contraentrega". Si se omite, la landing no muestra m\xE9todos de pago.'),
|
|
27169
|
+
productContext: z115.string().max(PRODUCT_CONTEXT_MAX_CHARS).optional().describe("Opcional. Informacion adicional del producto que la IA debe usar como contexto prioritario: uso real, comprador, restricciones, diferenciadores o direccion creativa. No reemplaza la investigacion de competencia; si hay competencia, guia el primer angulo y los outputs no deben contradecirlo."),
|
|
27170
|
+
productLabel: z115.string().trim().max(80).optional().describe('Opcional. Qu\xE9 es el producto, en pocas palabras (ej. "quita pelusas para ropa"). Es AUTORITATIVO: si lo env\xEDas, la IA usa esta identidad y no la reemplaza por otra categor\xEDa. Si lo omites, la IA detecta el producto desde la imagen.'),
|
|
27135
27171
|
videoPreset: VideoPresetEnum.default("auto").describe('Opcional. Tipo/narrativa del video \u2014 \xFAnico campo de "estilo" que el usuario controla. Default "auto" (la IA escoge tras analizar el producto). Todos los presets funcionan a 15s (single_call) y 30s (Multiescena); "problem_solution" en single_call abre sin el producto y el producto entra por referencia en su beat de soluci\xF3n. Opciones: "auto", "ugc_dynamic" (review con experiencia y prueba), "ugc_how_to" (tutorial con pasos y resultado visible), "ugc_unboxing_chaos" (apertura y primera prueba), "problem_solution" (problema concreto, producto como soluci\xF3n y CTA), "product_showcase" (producto ejecutando una funci\xF3n real), "wearable_showcase" (prenda o accesorio modelado), "cinematic" (TV spot con receta cinematogr\xE1fica), "wild_card" (idea imposible: un truco visual que en la vida real no podr\xEDa pasar, y al cierre la invitaci\xF3n a comprar), "pixar_problem" (problema animado 3D), "pixar_sassy" (producto que habla). Si el usuario pide algo fuera de esta lista, p\xEDdele una opci\xF3n v\xE1lida.'),
|
|
27136
27172
|
animationStyle: AnimationStyleEnum.optional().describe('Opcional. Estilo visual SOLO para presets animados ("pixar_problem" o "pixar_sassy") \u2014 la API lo rechaza con cualquier otro preset. Opciones: "pixar_3d" (default, look 3D de pel\xEDcula animada), "claymation" (plastilina stop-motion artesanal), "wes_anderson" (tableau sim\xE9trico pastel), "sci_fi" (futurista con HUDs y ne\xF3n), "realista" (fotorrealista, fiel al producto). Si el usuario pide un look animado sin nombrar el estilo, omite el campo.'),
|
|
27137
|
-
durationSeconds:
|
|
27138
|
-
|
|
27139
|
-
|
|
27173
|
+
durationSeconds: z115.union([
|
|
27174
|
+
z115.literal(15),
|
|
27175
|
+
z115.literal(30)
|
|
27140
27176
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
27141
|
-
pauseForAngleReview:
|
|
27142
|
-
aiDecidesAll:
|
|
27177
|
+
pauseForAngleReview: z115.boolean().optional().describe("Compatibilidad heredada. MCP deriva esta pausa de aiDecidesAll: manual siempre pausa y autom\xE1tico siempre la omite. No uses este campo para saltar reviews."),
|
|
27178
|
+
aiDecidesAll: z115.boolean().optional().describe("Mapea el toggle web \u201CDejar que la IA decida todo\u201D. Si true, ProductMaker omite reviews. Act\xEDvalo \xFAnicamente cuando el usuario lo pida expl\xEDcitamente. Omitido/false = reviews conversacionales."),
|
|
27143
27179
|
videoTier: VideoTierEnum.optional().describe('Opcional. Estilo del video. "basic" = "Realista" para 15s; al pedir durationSeconds=30 el sistema selecciona internamente Multiescena. No se expone el tier interno directamente.'),
|
|
27144
27180
|
videoStructure: VideoStructureEnum.default("single_take").describe('Opcional. Formato: "single_take" = Un solo clip (generado completo; puede incluir cambios de plano) o "multi_scene" = Multiescena. Default: single_take.'),
|
|
27145
27181
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
27146
27182
|
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render. En la web se pregunta "\xBFResoluci\xF3n del video?". "480p" = excelente calidad y m\xE1s econ\xF3mico (RECOMENDADO, default si se omite); "720p" = m\xE1xima nitidez, entre 3% y 15% m\xE1s caro seg\xFAn formato y tier. Si el usuario no menciona resoluci\xF3n, OMITE este campo (el backend usa 480p).'),
|
|
27147
|
-
videoAngleCount:
|
|
27183
|
+
videoAngleCount: z115.number().int().min(1).max(3).optional().describe("Cantidad de videos a renderizar: 1, 2 o 3. REQUERIDO cuando outputs incluye video (o se omite outputs, cuyo default incluye video); om\xEDtelo s\xF3lo cuando no se generar\xE1 video. Preg\xFAntalo incluso con aiDecidesAll=true porque cambia el costo."),
|
|
27148
27184
|
angleNarratives: PublicNarrativeStyleEnum.array().max(3).optional().describe('Opcional. Narrativa POR \xC1NGULO (posicional). Valores actuales: "review", "ugc_how_to", "ugc_unboxing_chaos", "problem_product_cta" (problema concreto, producto como soluci\xF3n y CTA), "product_showcase", "wearable_showcase", "cinematic", "wild_card", "animated_problem_pixar", "sassy_product_pixar", "market" (narrativa an\xE1lisis de mercado: adapta el video a los patrones ganadores estudiados de la competencia; requiere competitorScanEnabled: true). angleNarratives[i] fuerza la narrativa del \xE1ngulo i; las posiciones restantes las elige la IA. La lista no puede superar videoAngleCount.'),
|
|
27149
|
-
outputs:
|
|
27185
|
+
outputs: z115.array(z115.enum([
|
|
27150
27186
|
"landing",
|
|
27151
27187
|
"video",
|
|
27152
27188
|
"image"
|
|
27153
27189
|
])).min(1).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}`),
|
|
27154
|
-
includeInitialLandingGif:
|
|
27155
|
-
competitorScanEnabled:
|
|
27190
|
+
includeInitialLandingGif: z115.boolean().optional().describe("Opcional. En nuevas landings cl\xE1sicas habilitadas, omitirlo incluye el primer GIF del producto y su coste en el total. Env\xEDa false si el usuario lo excluye: no se genera ni se reserva su coste. Conserva la elecci\xF3n al confirmar y al reintentar."),
|
|
27191
|
+
competitorScanEnabled: z115.boolean().optional().describe("Opcional. Default false: omitirlo significa SIN estudio de mercado. Antes de crear, llama estimate_market_study_cost con kind=product_task, muestra al usuario el costo con y sin estudio y preg\xFAntale si lo quiere; env\xEDa true solo si lo acepta (o si solicita la narrativa an\xE1lisis de mercado). Si la tarea incluye video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico."),
|
|
27156
27192
|
generateAiEdit: AiEditRequestSchema.optional().describe('Opcional. Pide la Edici\xF3n con IA: una pasada que a\xF1ade texto, efectos y m\xFAsica sobre cada video entregado (variante with_ai_edit; se cobra al entregar, por video). Nivel: "economy" (Econ\xF3mica, Sonnet 5.5, m\xE1s barata) o "pro" (Opus 5.5, mejor calidad, ~10 min). true equivale a "pro"; false/omitido = sin edici\xF3n.'),
|
|
27157
|
-
replicateWinnerWhenFound:
|
|
27158
|
-
brandId:
|
|
27159
|
-
actorId:
|
|
27193
|
+
replicateWinnerWhenFound: z115.boolean().optional().describe("Conserva la preferencia de copiar un ganador si existe. false estudia el mercado sin reemplazar un \xE1ngulo por el anuncio ganador. No a\xF1ade una pregunta obligatoria."),
|
|
27194
|
+
brandId: z115.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."),
|
|
27195
|
+
actorId: z115.string().trim().min(1).max(120).optional().describe("Opcional. ID de un personaje guardado (usa list_actors para verlos). Si lo env\xEDas, su foto y su voz mandan sobre la descripci\xF3n de texto."),
|
|
27160
27196
|
creativeGender: CreativeGenderEnum.optional().describe('Opcional. QUI\xC9N APARECE EN PANTALLA en todos los creativos de la task: el presentador del video, las personas fotografiadas en la landing y la persona del anuncio. NO es la voz. M\xE1ndalo en cuanto el usuario lo diga en cualquier momento de la conversaci\xF3n y con cualquier redacci\xF3n ("quiero una mujer", "que salga un hombre", "esto es para hombres"): si no lo mandas, el g\xE9nero lo inventa la IA y el usuario recibe lo contrario de lo que pidi\xF3 sin ning\xFAn aviso. "mixed" solo cuando pida expl\xEDcitamente ambos. Si adem\xE1s mandas actorId, el personaje guardado manda sobre este campo.'),
|
|
27161
|
-
creativeDirection:
|
|
27162
|
-
headline:
|
|
27163
|
-
subheadline:
|
|
27197
|
+
creativeDirection: z115.string().max(500).optional().describe('Opcional. Direcci\xF3n creativa en texto libre (colores, mood, estilo) que aplica a los outputs de IMAGEN y LANDING (no al video \u2014 el estilo/ambiente del video se dirige con scriptNotes). M\xC1XIMA PRIORIDAD: anula marca, colores y estilo por defecto. Ej. "amarillo y azul, minimalista". M\xE1x 500 caracteres.'),
|
|
27198
|
+
headline: z115.string().max(120).optional().describe("Opcional. Titular EXACTO a renderizar. Se imprime tal cual: la IA no lo reescribe, no lo acorta y no lo traduce. Se aplica a las IM\xC1GENES y a la portada de la landing de esta task (el video no lo usa; para el video usa scriptNotes). \xDAsalo cuando el copy es de marca y no es negociable. M\xE1x 120 caracteres. Si lo omites, la IA escribe el titular."),
|
|
27199
|
+
subheadline: z115.string().max(160).optional().describe("Opcional. Subt\xEDtulo EXACTO a renderizar, misma regla que headline. Independiente: puedes fijar solo el subt\xEDtulo. M\xE1x 160 caracteres."),
|
|
27164
27200
|
landingStrategy: LandingStrategyEnum.optional().describe('Opcional. Estructura de la landing cl\xE1sica cuando landing est\xE1 entre outputs: "classic" (estructura original probada y recomendada; default del primer rollout), "auto" (la IA decide; experimental), "pain_solution", "social_proof" (Landing Viral: UGC, WhatsApp, Instagram y evidencia social), "benefits_clarity", "offer_value" o "lifestyle_identity". Default "classic".'),
|
|
27165
27201
|
landingImageFormat: LandingImageFormatEnum.default("9:16").describe('Opcional. Formato/relaci\xF3n de aspecto de las im\xE1genes de la landing cl\xE1sica cuando landing est\xE1 entre outputs: "9:16" (vertical, por defecto), "4:5" (vertical compacto para feed) o "1:1" (cuadrado). Default "9:16".')
|
|
27166
27202
|
}).strict();
|
|
27167
|
-
var CreateServiceVideoInput =
|
|
27168
|
-
landingUrl:
|
|
27169
|
-
additionalContext:
|
|
27203
|
+
var CreateServiceVideoInput = z115.object({
|
|
27204
|
+
landingUrl: z115.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
|
|
27205
|
+
additionalContext: z115.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
|
|
27170
27206
|
language: Lang.describe("Idioma del video: es, en o pt."),
|
|
27171
|
-
voiceId:
|
|
27172
|
-
brandId:
|
|
27173
|
-
reviewMode:
|
|
27207
|
+
voiceId: z115.string().trim().min(1).pipe(VoiceId).optional().describe('Opcional. Voz para toda la narraci\xF3n. Usa "auto" para que la IA la alinee con el presentador. Las voces del banco compartido fueron retiradas.'),
|
|
27208
|
+
brandId: z115.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
|
|
27209
|
+
reviewMode: z115.enum([
|
|
27174
27210
|
"automatic",
|
|
27175
27211
|
"guided"
|
|
27176
27212
|
]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
|
|
27177
|
-
videoPreset:
|
|
27213
|
+
videoPreset: z115.enum([
|
|
27178
27214
|
"auto",
|
|
27179
27215
|
"ugc_dynamic",
|
|
27180
27216
|
"ugc_how_to",
|
|
@@ -27184,128 +27220,128 @@ var CreateServiceVideoInput = z114.object({
|
|
|
27184
27220
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
27185
27221
|
videoResolution: VideoResolutionEnum.default("480p").describe('Opcional. Resoluci\xF3n: "480p" o "720p". 720p cuesta m\xE1s por segundo y solo est\xE1 disponible en "economy" y "pro" (Medio = 768P). Default: 480p.')
|
|
27186
27222
|
}).strict();
|
|
27187
|
-
var GetTaskStatusInput =
|
|
27188
|
-
taskId:
|
|
27189
|
-
waitSeconds:
|
|
27223
|
+
var GetTaskStatusInput = z115.object({
|
|
27224
|
+
taskId: z115.string().min(1),
|
|
27225
|
+
waitSeconds: z115.number().int().min(0).max(120).optional()
|
|
27190
27226
|
});
|
|
27191
|
-
var ListTasksInput =
|
|
27192
|
-
limit:
|
|
27193
|
-
offset:
|
|
27194
|
-
search:
|
|
27227
|
+
var ListTasksInput = z115.object({
|
|
27228
|
+
limit: z115.number().int().min(1).max(50).optional(),
|
|
27229
|
+
offset: z115.number().int().min(0).optional(),
|
|
27230
|
+
search: z115.string().optional()
|
|
27195
27231
|
});
|
|
27196
27232
|
var MCP_REVIEW_LIST_FIELD_MAX = IMAGE_WIZARD_LIST_FIELD_MAX;
|
|
27197
27233
|
var MCP_REVIEW_FEATURE_ITEM_MAX = IMAGE_FEATURE_ITEM_MAX;
|
|
27198
|
-
var EditTaskDraftInput =
|
|
27199
|
-
taskId:
|
|
27200
|
-
angleIndex:
|
|
27201
|
-
angle:
|
|
27202
|
-
angle:
|
|
27203
|
-
buyerPersona:
|
|
27204
|
-
actor:
|
|
27205
|
-
actorId:
|
|
27206
|
-
gender:
|
|
27234
|
+
var EditTaskDraftInput = z115.object({
|
|
27235
|
+
taskId: z115.string().min(1),
|
|
27236
|
+
angleIndex: z115.number().int().min(0),
|
|
27237
|
+
angle: z115.object({
|
|
27238
|
+
angle: z115.string().min(1).max(480),
|
|
27239
|
+
buyerPersona: z115.string().min(1).max(360),
|
|
27240
|
+
actor: z115.string().min(1).max(360).optional(),
|
|
27241
|
+
actorId: z115.string().trim().min(1).optional().describe("Opcional. ID de un personaje guardado (usa list_actors para verlos). Si lo env\xEDas, su foto y su voz mandan sobre la descripci\xF3n de texto."),
|
|
27242
|
+
gender: z115.enum([
|
|
27207
27243
|
"female",
|
|
27208
27244
|
"male"
|
|
27209
27245
|
]).optional(),
|
|
27210
|
-
scriptNotes:
|
|
27246
|
+
scriptNotes: z115.string().max(2e3).optional()
|
|
27211
27247
|
})
|
|
27212
27248
|
});
|
|
27213
|
-
var PendingActionPayload =
|
|
27214
|
-
|
|
27215
|
-
kind:
|
|
27249
|
+
var PendingActionPayload = z115.discriminatedUnion("kind", [
|
|
27250
|
+
z115.object({
|
|
27251
|
+
kind: z115.literal("product_reference_set_approval"),
|
|
27216
27252
|
scope: ProductReferenceScopeEnum.optional(),
|
|
27217
|
-
scopeKey:
|
|
27218
|
-
scopeSnapshotId:
|
|
27219
|
-
expectedScopeHash:
|
|
27253
|
+
scopeKey: z115.string().min(1).max(120).optional(),
|
|
27254
|
+
scopeSnapshotId: z115.string().uuid().optional(),
|
|
27255
|
+
expectedScopeHash: z115.string().min(1).max(128).optional(),
|
|
27220
27256
|
decision: ProductReferenceResolutionDecisionEnum,
|
|
27221
27257
|
reason: ProductReferenceRejectionReasonEnum.optional(),
|
|
27222
|
-
affectedRefKeys:
|
|
27223
|
-
affectedPhotoNumbers:
|
|
27224
|
-
recoveryAction:
|
|
27258
|
+
affectedRefKeys: z115.array(z115.string().min(1).max(200)).min(1).optional(),
|
|
27259
|
+
affectedPhotoNumbers: z115.array(z115.number().int().positive()).min(1).optional(),
|
|
27260
|
+
recoveryAction: z115.enum([
|
|
27225
27261
|
"remove",
|
|
27226
27262
|
"replace",
|
|
27227
27263
|
"upload",
|
|
27228
27264
|
"return_to_selection"
|
|
27229
27265
|
]).optional()
|
|
27230
27266
|
}),
|
|
27231
|
-
|
|
27232
|
-
kind:
|
|
27233
|
-
selectedPhotoNumbers:
|
|
27267
|
+
z115.object({
|
|
27268
|
+
kind: z115.literal("product_reference_confirmation"),
|
|
27269
|
+
selectedPhotoNumbers: z115.array(z115.number().int().positive().max(5)).min(1).max(5).optional().describe("Opcional. N\xFAmeros visibles de las fotos que el usuario quiere conservar; las dem\xE1s se deseleccionan. Debe quedar al menos una."),
|
|
27234
27270
|
userChoice: ProductReferenceUserChoiceEnum.optional(),
|
|
27235
|
-
confirmedProductNames:
|
|
27271
|
+
confirmedProductNames: z115.array(z115.string().min(1).max(120)).min(2).max(8).optional(),
|
|
27236
27272
|
videoStructure: VideoStructureEnum.optional().describe("Opcional. Formato para reanudar el video: single_take (Un solo clip, generado completo; puede incluir cambios de plano) o multi_scene (Multiescena). El backend vuelve a validar que sea compatible con el agrupamiento confirmado."),
|
|
27237
27273
|
videoQuality: VideoQualityEnum.optional().describe("Opcional. Calidad para reanudar el video: economy (Econ\xF3mico), medium (Medio) o pro. El proveedor se elige internamente y el backend vuelve a cotizar la ruta."),
|
|
27238
|
-
useMultiSceneShowcase:
|
|
27274
|
+
useMultiSceneShowcase: z115.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
|
|
27239
27275
|
}),
|
|
27240
|
-
|
|
27241
|
-
kind:
|
|
27276
|
+
z115.object({
|
|
27277
|
+
kind: z115.literal("angle_review_approval"),
|
|
27242
27278
|
// All edits are optional — empty action body just approves the
|
|
27243
27279
|
// backend-generated draft as-is. Field shapes mirror the angle-review
|
|
27244
27280
|
// request contracts in @packages/types/wizard.ts; the handler routes to
|
|
27245
27281
|
// the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
|
|
27246
|
-
customAngle:
|
|
27282
|
+
customAngle: z115.string().min(1).max(480).optional(),
|
|
27247
27283
|
// Keep the shared MCP action within the strictest downstream contract:
|
|
27248
27284
|
// autopilot/image resume endpoints cap these fields at 1500 characters.
|
|
27249
|
-
painPoints:
|
|
27250
|
-
benefits:
|
|
27285
|
+
painPoints: z115.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
27286
|
+
benefits: z115.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
27251
27287
|
// Same policy as the two fields above: the strictest downstream contract
|
|
27252
27288
|
// wins. The image endpoint caps each feature at 240 while landing/video
|
|
27253
27289
|
// accept 300, and this single action routes to whichever the task is — so
|
|
27254
27290
|
// accepting 300 here turns a 250-character feature on an image task into
|
|
27255
27291
|
// an opaque HTTP 400 after the model already believed it had been saved.
|
|
27256
|
-
features:
|
|
27257
|
-
buyerPersona:
|
|
27292
|
+
features: z115.array(z115.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
|
|
27293
|
+
buyerPersona: z115.string().min(1).max(360).optional(),
|
|
27258
27294
|
narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n) funciona en ambos formatos \u2014 en Un solo clip abre sin producto y el producto entra por referencia en su beat. La familia storyteller ("animated_storyteller", "animated_inner_journey", "animated_object_soul", "animated_timeline") no est\xE1 disponible por ahora.'),
|
|
27259
|
-
actor:
|
|
27260
|
-
actorId:
|
|
27261
|
-
creativeDirection:
|
|
27262
|
-
selectedAngleNumbers:
|
|
27263
|
-
angleEdits:
|
|
27264
|
-
angleNumber:
|
|
27265
|
-
narrativeSelection:
|
|
27295
|
+
actor: z115.string().min(1).max(360).optional().describe("Nueva descripci\xF3n del presentador. Al enviarla sin actorId, se elimina autom\xE1ticamente cualquier actor guardado previo de esos \xE1ngulos."),
|
|
27296
|
+
actorId: z115.string().max(120).nullable().optional(),
|
|
27297
|
+
creativeDirection: z115.string().max(2e3).optional(),
|
|
27298
|
+
selectedAngleNumbers: z115.array(z115.number().int().positive()).min(1).max(3).optional().describe("N\xFAmeros visibles (1-based) de los \xE1ngulos que el usuario quiere renderizar. Deben ser \xFAnicos, existir en la review y no superar el videoAngleCount autorizado."),
|
|
27299
|
+
angleEdits: z115.array(z115.object({
|
|
27300
|
+
angleNumber: z115.number().int().positive(),
|
|
27301
|
+
narrativeSelection: z115.enum([
|
|
27266
27302
|
"market",
|
|
27267
27303
|
"guided"
|
|
27268
27304
|
]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
|
|
27269
|
-
angle:
|
|
27270
|
-
buyerPersona:
|
|
27305
|
+
angle: z115.string().min(1).max(480).optional(),
|
|
27306
|
+
buyerPersona: z115.string().min(1).max(360).optional(),
|
|
27271
27307
|
narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n) funciona en ambos formatos \u2014 en Un solo clip abre sin producto y el producto entra por referencia en su beat. La familia storyteller ("animated_storyteller", "animated_inner_journey", "animated_object_soul", "animated_timeline") no est\xE1 disponible por ahora.'),
|
|
27272
|
-
actor:
|
|
27273
|
-
actorId:
|
|
27274
|
-
creativeDirection:
|
|
27308
|
+
actor: z115.string().min(1).max(360).optional(),
|
|
27309
|
+
actorId: z115.string().max(120).nullable().optional(),
|
|
27310
|
+
creativeDirection: z115.string().max(2e3).optional()
|
|
27275
27311
|
}).strict()).max(3).optional().describe("Ediciones independientes por n\xFAmero visible de \xE1ngulo. S\xF3lo se aceptan para \xE1ngulos incluidos en selectedAngleNumbers (o en la selecci\xF3n por defecto)."),
|
|
27276
|
-
gapDurationSeconds:
|
|
27277
|
-
|
|
27278
|
-
|
|
27312
|
+
gapDurationSeconds: z115.union([
|
|
27313
|
+
z115.literal(15),
|
|
27314
|
+
z115.literal(30)
|
|
27279
27315
|
]).optional().describe("Opcional. Solo para aceptar expl\xEDcitamente la recomendaci\xF3n gapDurationChoice del status. 30 env\xEDa el override double_30s para el \xE1ngulo recomendado; 15 u omitido conserva la duraci\xF3n cotizada.")
|
|
27280
27316
|
}),
|
|
27281
|
-
|
|
27282
|
-
kind:
|
|
27283
|
-
angleId:
|
|
27284
|
-
angleNumber:
|
|
27285
|
-
content:
|
|
27286
|
-
creativeDirection:
|
|
27287
|
-
actor:
|
|
27317
|
+
z115.object({
|
|
27318
|
+
kind: z115.literal("service_angle_approval"),
|
|
27319
|
+
angleId: z115.string().uuid().optional(),
|
|
27320
|
+
angleNumber: z115.number().int().positive().optional(),
|
|
27321
|
+
content: z115.string().min(1).max(480).optional(),
|
|
27322
|
+
creativeDirection: z115.string().min(1).max(1500).optional(),
|
|
27323
|
+
actor: z115.string().min(1).max(360).optional()
|
|
27288
27324
|
}),
|
|
27289
|
-
|
|
27290
|
-
kind:
|
|
27291
|
-
voiceovers:
|
|
27292
|
-
visualDirections:
|
|
27293
|
-
voiceoversByScene:
|
|
27294
|
-
visualDirectionsByScene:
|
|
27325
|
+
z115.object({
|
|
27326
|
+
kind: z115.literal("service_script_approval"),
|
|
27327
|
+
voiceovers: z115.record(z115.string(), z115.string().min(1).max(600)).optional(),
|
|
27328
|
+
visualDirections: z115.record(z115.string(), z115.string().min(1).max(1200)).optional(),
|
|
27329
|
+
voiceoversByScene: z115.record(z115.string(), z115.string().min(1).max(600)).optional(),
|
|
27330
|
+
visualDirectionsByScene: z115.record(z115.string(), z115.string().min(1).max(1200)).optional()
|
|
27295
27331
|
})
|
|
27296
27332
|
]);
|
|
27297
|
-
var ResolvePendingActionInput =
|
|
27298
|
-
taskId:
|
|
27333
|
+
var ResolvePendingActionInput = z115.object({
|
|
27334
|
+
taskId: z115.string().min(1),
|
|
27299
27335
|
action: PendingActionPayload
|
|
27300
27336
|
}).strict();
|
|
27301
27337
|
function resolveVariantConfirmVideoTier(action) {
|
|
27302
27338
|
return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
|
|
27303
27339
|
}
|
|
27304
27340
|
__name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
|
|
27305
|
-
var StatusForResolveSchema =
|
|
27341
|
+
var StatusForResolveSchema = z115.object({
|
|
27306
27342
|
// Metadata used to select the backend resume contract. Older API responses
|
|
27307
27343
|
// may omit these fields, so the resolver keeps the generic fallback.
|
|
27308
|
-
kind:
|
|
27344
|
+
kind: z115.enum([
|
|
27309
27345
|
"autopilot",
|
|
27310
27346
|
"video",
|
|
27311
27347
|
"image",
|
|
@@ -27313,18 +27349,18 @@ var StatusForResolveSchema = z114.object({
|
|
|
27313
27349
|
"mix",
|
|
27314
27350
|
"service"
|
|
27315
27351
|
]).optional(),
|
|
27316
|
-
selectedOutputs:
|
|
27352
|
+
selectedOutputs: z115.array(z115.enum([
|
|
27317
27353
|
"landing",
|
|
27318
27354
|
"video",
|
|
27319
27355
|
"image"
|
|
27320
27356
|
])).optional(),
|
|
27321
|
-
videoAngleCount:
|
|
27322
|
-
ugcFormat:
|
|
27357
|
+
videoAngleCount: z115.number().int().min(1).max(3).optional(),
|
|
27358
|
+
ugcFormat: z115.enum([
|
|
27323
27359
|
"single_8s",
|
|
27324
27360
|
"single_15s",
|
|
27325
27361
|
"double_30s"
|
|
27326
27362
|
]).optional(),
|
|
27327
|
-
videoStyle:
|
|
27363
|
+
videoStyle: z115.enum([
|
|
27328
27364
|
"ugc",
|
|
27329
27365
|
"cartoon_3d",
|
|
27330
27366
|
"product_only",
|
|
@@ -27334,13 +27370,13 @@ var StatusForResolveSchema = z114.object({
|
|
|
27334
27370
|
videoQuality: VideoQualityEnum.optional(),
|
|
27335
27371
|
videoRouteId: VideoRouteIdEnum.optional(),
|
|
27336
27372
|
videoModel: TaskVideoModelEnum.optional(),
|
|
27337
|
-
videoTier:
|
|
27373
|
+
videoTier: z115.enum([
|
|
27338
27374
|
"legacy",
|
|
27339
27375
|
"standard",
|
|
27340
27376
|
"pro",
|
|
27341
27377
|
"single_call"
|
|
27342
27378
|
]).optional(),
|
|
27343
|
-
videoResolution:
|
|
27379
|
+
videoResolution: z115.enum([
|
|
27344
27380
|
"480p",
|
|
27345
27381
|
"720p"
|
|
27346
27382
|
]).optional(),
|
|
@@ -27348,60 +27384,60 @@ var StatusForResolveSchema = z114.object({
|
|
|
27348
27384
|
// A task created before a narrative was blocked/hidden must still parse,
|
|
27349
27385
|
// or resolve_pending_action could never approve it.
|
|
27350
27386
|
narrativeStyle: NarrativeStyle.optional(),
|
|
27351
|
-
pauseForVideoScriptReview:
|
|
27352
|
-
pendingUserAction:
|
|
27353
|
-
kind:
|
|
27354
|
-
candidateGrouping:
|
|
27355
|
-
selectedImageUrls:
|
|
27356
|
-
proposedProductNames:
|
|
27387
|
+
pauseForVideoScriptReview: z115.boolean().optional(),
|
|
27388
|
+
pendingUserAction: z115.object({
|
|
27389
|
+
kind: z115.string(),
|
|
27390
|
+
candidateGrouping: z115.string().optional(),
|
|
27391
|
+
selectedImageUrls: z115.array(z115.string()).optional(),
|
|
27392
|
+
proposedProductNames: z115.array(z115.string()).optional(),
|
|
27357
27393
|
// Adaptive reference questions are server-owned. Echo only the evidence
|
|
27358
27394
|
// identity and the choices shown by the current snapshot; never accept a
|
|
27359
27395
|
// client-supplied reference set as authorization.
|
|
27360
|
-
options:
|
|
27361
|
-
mode:
|
|
27396
|
+
options: z115.array(ProductReferenceUserChoiceEnum).max(4).optional(),
|
|
27397
|
+
mode: z115.enum([
|
|
27362
27398
|
"question",
|
|
27363
27399
|
"visual_recovery"
|
|
27364
27400
|
]).optional(),
|
|
27365
27401
|
/** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
|
|
27366
|
-
canKeepSelection:
|
|
27367
|
-
decisionKey:
|
|
27368
|
-
questionOrdinal:
|
|
27369
|
-
questionCeiling:
|
|
27370
|
-
|
|
27371
|
-
|
|
27402
|
+
canKeepSelection: z115.boolean().optional(),
|
|
27403
|
+
decisionKey: z115.string().optional(),
|
|
27404
|
+
questionOrdinal: z115.number().int().min(1).max(5).optional(),
|
|
27405
|
+
questionCeiling: z115.union([
|
|
27406
|
+
z115.literal(3),
|
|
27407
|
+
z115.literal(5)
|
|
27372
27408
|
]).optional(),
|
|
27373
|
-
referenceEvidenceVersion:
|
|
27374
|
-
expectedEvidenceHash:
|
|
27375
|
-
question:
|
|
27376
|
-
prompt:
|
|
27377
|
-
helpText:
|
|
27378
|
-
options:
|
|
27409
|
+
referenceEvidenceVersion: z115.number().int().positive().optional(),
|
|
27410
|
+
expectedEvidenceHash: z115.string().optional(),
|
|
27411
|
+
question: z115.object({
|
|
27412
|
+
prompt: z115.string().min(1).max(240),
|
|
27413
|
+
helpText: z115.string().min(1).max(300).optional(),
|
|
27414
|
+
options: z115.array(z115.object({
|
|
27379
27415
|
value: ProductReferenceUserChoiceEnum,
|
|
27380
|
-
label:
|
|
27381
|
-
description:
|
|
27416
|
+
label: z115.string().min(1).max(120),
|
|
27417
|
+
description: z115.string().min(1).max(240).optional()
|
|
27382
27418
|
})).min(2).max(4)
|
|
27383
27419
|
}).optional(),
|
|
27384
27420
|
scope: ProductReferenceScopeEnum.optional(),
|
|
27385
|
-
scopeKey:
|
|
27386
|
-
scopeSnapshotId:
|
|
27387
|
-
scopeHash:
|
|
27388
|
-
baseReferenceSetHash:
|
|
27389
|
-
phase:
|
|
27421
|
+
scopeKey: z115.string().optional(),
|
|
27422
|
+
scopeSnapshotId: z115.string().uuid().optional(),
|
|
27423
|
+
scopeHash: z115.string().optional(),
|
|
27424
|
+
baseReferenceSetHash: z115.string().optional(),
|
|
27425
|
+
phase: z115.enum([
|
|
27390
27426
|
"preparation",
|
|
27391
27427
|
"final"
|
|
27392
27428
|
]).optional(),
|
|
27393
|
-
selectedRefKeys:
|
|
27394
|
-
allowedDecisions:
|
|
27395
|
-
previews:
|
|
27396
|
-
refKey:
|
|
27429
|
+
selectedRefKeys: z115.array(z115.string().min(1).max(200)).optional(),
|
|
27430
|
+
allowedDecisions: z115.array(ProductReferenceResolutionDecisionEnum).optional(),
|
|
27431
|
+
previews: z115.array(z115.object({
|
|
27432
|
+
refKey: z115.string().min(1).max(200)
|
|
27397
27433
|
}).passthrough()).optional(),
|
|
27398
|
-
customAngleDraft:
|
|
27399
|
-
painPointsDraft:
|
|
27400
|
-
benefitsDraft:
|
|
27401
|
-
featuresDraft:
|
|
27402
|
-
angleOptions:
|
|
27403
|
-
index:
|
|
27404
|
-
angle:
|
|
27434
|
+
customAngleDraft: z115.string().optional(),
|
|
27435
|
+
painPointsDraft: z115.string().optional(),
|
|
27436
|
+
benefitsDraft: z115.string().optional(),
|
|
27437
|
+
featuresDraft: z115.array(z115.string()).optional(),
|
|
27438
|
+
angleOptions: z115.array(z115.object({
|
|
27439
|
+
index: z115.number().int().nonnegative(),
|
|
27440
|
+
angle: z115.string().min(1)
|
|
27405
27441
|
}).passthrough()).min(1).max(5).optional(),
|
|
27406
27442
|
// Recommendation consumed only when the caller explicitly sends
|
|
27407
27443
|
// gapDurationSeconds: 30 in the angle approval action.
|
|
@@ -27411,17 +27447,17 @@ var StatusForResolveSchema = z114.object({
|
|
|
27411
27447
|
// keys. `actorId` (the saved custom actor the picker stored) was silently
|
|
27412
27448
|
// dropped here, so the approval handler below could not echo it back on the
|
|
27413
27449
|
// PATCH — the selection looked accepted and reached no render.
|
|
27414
|
-
angles:
|
|
27415
|
-
id:
|
|
27416
|
-
content:
|
|
27417
|
-
creativeDirection:
|
|
27418
|
-
actor:
|
|
27419
|
-
actorId:
|
|
27450
|
+
angles: z115.array(z115.object({
|
|
27451
|
+
id: z115.string().uuid(),
|
|
27452
|
+
content: z115.string(),
|
|
27453
|
+
creativeDirection: z115.string(),
|
|
27454
|
+
actor: z115.string(),
|
|
27455
|
+
actorId: z115.string().nullable().optional()
|
|
27420
27456
|
}).passthrough()).optional(),
|
|
27421
|
-
panels:
|
|
27422
|
-
beatId:
|
|
27423
|
-
voiceover:
|
|
27424
|
-
visualDirection:
|
|
27457
|
+
panels: z115.array(z115.object({
|
|
27458
|
+
beatId: z115.string(),
|
|
27459
|
+
voiceover: z115.string(),
|
|
27460
|
+
visualDirection: z115.string()
|
|
27425
27461
|
}).passthrough()).optional()
|
|
27426
27462
|
}).optional()
|
|
27427
27463
|
}).passthrough();
|
|
@@ -27773,8 +27809,8 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
27773
27809
|
server.registerTool("verify_landing_commerce", {
|
|
27774
27810
|
description: getProductMakerCapabilityModelGuidance("verify_landing_commerce").summary + " Verifica una correcci\xF3n manual de precios, tachados o packs de una landing editable existente. Solo relee Shopify y los recibos externos; no cambia precios, inventario, SKU ni compra una edici\xF3n. Pasa taskId y editId de la edici\xF3n ya conocida; nunca inventes IDs ni pidas repetir el cambio. Devuelve el estado can\xF3nico por proveedor: conserva el aviso pendiente hasta confirmar los valores reales. Solo despu\xE9s de confirmar todos los valores, el servidor puede volver a habilitar la compra. Web guardada no demuestra publicaci\xF3n p\xFAblica ni checkout; muestra las correcciones y enlaces pendientes sin c\xF3digos t\xE9cnicos. La disponibilidad del editor conserva sus permisos actuales.",
|
|
27775
27811
|
inputSchema: {
|
|
27776
|
-
taskId:
|
|
27777
|
-
editId:
|
|
27812
|
+
taskId: z115.string().uuid(),
|
|
27813
|
+
editId: z115.string().uuid()
|
|
27778
27814
|
},
|
|
27779
27815
|
annotations: OVERWRITES_EXTERNAL
|
|
27780
27816
|
}, async (input) => {
|
|
@@ -28420,25 +28456,25 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
28420
28456
|
__name(registerTaskTools, "registerTaskTools");
|
|
28421
28457
|
|
|
28422
28458
|
// src/tools/brands.ts
|
|
28423
|
-
import { z as
|
|
28459
|
+
import { z as z116 } from "zod";
|
|
28424
28460
|
var guidance2 = getProductMakerCapabilityModelGuidance("create_brand");
|
|
28425
28461
|
var BRAND_START_REPLAY_WINDOW_MS = 15 * 60 * 1e3;
|
|
28426
28462
|
var BRAND_NOTES_MAX_CHARS = 2e4;
|
|
28427
|
-
var CreateBrandInput =
|
|
28428
|
-
action:
|
|
28463
|
+
var CreateBrandInput = z116.object({
|
|
28464
|
+
action: z116.enum([
|
|
28429
28465
|
"start",
|
|
28430
28466
|
"status",
|
|
28431
28467
|
"list"
|
|
28432
28468
|
]).default("start").describe("start cotiza (sin confirmed) o inicia (confirmed=true) el an\xE1lisis; status consulta brandId hasta ready o failed; list muestra las marcas que el usuario ya tiene."),
|
|
28433
|
-
sourceUrl:
|
|
28434
|
-
businessNotes:
|
|
28435
|
-
language:
|
|
28469
|
+
sourceUrl: z116.string().trim().min(1).max(500).optional().describe("Instagram, Facebook, TikTok o web p\xFAblica del negocio, como la dio el usuario (\xAB@sanlucasbarberia\xBB, \xABinstagram.com/sanlucasbarberia\xBB, \xABmibarberia.com\xBB). Obligatorio para start."),
|
|
28470
|
+
businessNotes: z116.string().trim().max(BRAND_NOTES_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cuente de su negocio en el chat (servicios y precios, WhatsApp, ciudad o zona, horarios). Se guarda como documento del negocio y llega tal cual a la marca y a su landing. Copia sus palabras; no inventes datos."),
|
|
28471
|
+
language: z116.enum([
|
|
28436
28472
|
"es",
|
|
28437
28473
|
"en",
|
|
28438
28474
|
"pt"
|
|
28439
28475
|
]).optional().describe("Idioma de la conversaci\xF3n. Solo se usa si la p\xE1gina del negocio no deja claro su idioma."),
|
|
28440
|
-
confirmed:
|
|
28441
|
-
brandId:
|
|
28476
|
+
confirmed: z116.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, start solo cotiza y no cobra."),
|
|
28477
|
+
brandId: z116.string().uuid().optional().describe("ID de la marca. Obligatorio para status; no lo inventes.")
|
|
28442
28478
|
}).strict();
|
|
28443
28479
|
function normalizeBrandSourceUrl(raw) {
|
|
28444
28480
|
const value = raw.trim();
|
|
@@ -28678,24 +28714,24 @@ __name(registerBrandTools, "registerBrandTools");
|
|
|
28678
28714
|
|
|
28679
28715
|
// src/tools/service-landing.ts
|
|
28680
28716
|
import { createHash as createHash4 } from "crypto";
|
|
28681
|
-
import { z as
|
|
28717
|
+
import { z as z117 } from "zod";
|
|
28682
28718
|
var guidance3 = getProductMakerCapabilityModelGuidance("create_service_landing");
|
|
28683
28719
|
var SERVICE_LANDING_KEY_NAMESPACE = "6f1d8c2a-3b4e-5f60-8a7b-9c0d1e2f3a4b";
|
|
28684
28720
|
var SERVICE_LANDING_INFO_MAX_CHARS = 2e4;
|
|
28685
|
-
var CreateServiceLandingInput =
|
|
28686
|
-
action:
|
|
28721
|
+
var CreateServiceLandingInput = z117.object({
|
|
28722
|
+
action: z117.enum([
|
|
28687
28723
|
"prepare",
|
|
28688
28724
|
"build",
|
|
28689
28725
|
"status",
|
|
28690
28726
|
"publish"
|
|
28691
28727
|
]).default("prepare").describe("prepare (gratis) crea o retoma la landing de la marca y da el precio; build (pagado, confirmed=true) lee los datos del negocio y luego crea la p\xE1gina; status sigue el avance; publish la publica y devuelve su enlace."),
|
|
28692
|
-
brandId:
|
|
28693
|
-
servicePageId:
|
|
28694
|
-
businessInfo:
|
|
28695
|
-
confirmed:
|
|
28696
|
-
maxCredits:
|
|
28697
|
-
operationId:
|
|
28698
|
-
slug:
|
|
28728
|
+
brandId: z117.string().uuid().optional().describe("ID de la marca (de create_brand). Obligatorio para prepare. Nunca un taskId de producto."),
|
|
28729
|
+
servicePageId: z117.string().uuid().optional().describe("ID de la landing que devolvi\xF3 prepare. Obligatorio para build, status y publish."),
|
|
28730
|
+
businessInfo: z117.string().trim().max(SERVICE_LANDING_INFO_MAX_CHARS).optional().describe("Opcional. Lo que el usuario cont\xF3 del negocio y no estaba en su marca: servicios y precios, WhatsApp o tel\xE9fono, ciudad o zona, horarios. Copia sus palabras; no inventes datos."),
|
|
28731
|
+
confirmed: z117.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio total y que el usuario acepte. Obligatorio para build."),
|
|
28732
|
+
maxCredits: z117.number().int().positive().optional().describe("El total en cr\xE9ditos que el usuario acept\xF3 (el que devolvi\xF3 prepare). Obligatorio para build: ninguna etapa se inicia si su precio supera este total."),
|
|
28733
|
+
operationId: z117.string().uuid().optional().describe("Opcional en status: la operaci\xF3n que devolvi\xF3 build."),
|
|
28734
|
+
slug: z117.string().trim().toLowerCase().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).max(64).optional().describe("Opcional en publish: la direcci\xF3n corta de la p\xE1gina (ej. sanlucas-barberia). Si falta se usa la sugerida desde el nombre del negocio.")
|
|
28699
28735
|
}).strict();
|
|
28700
28736
|
var SERVICE_LANDING_MAX_BUILD_ATTEMPTS = 10;
|
|
28701
28737
|
function serviceKey(...parts) {
|
|
@@ -29028,7 +29064,7 @@ function registerServiceLandingTools(server, api) {
|
|
|
29028
29064
|
__name(registerServiceLandingTools, "registerServiceLandingTools");
|
|
29029
29065
|
|
|
29030
29066
|
// src/tools/service-images.ts
|
|
29031
|
-
import { z as
|
|
29067
|
+
import { z as z118 } from "zod";
|
|
29032
29068
|
var guidance4 = getProductMakerCapabilityModelGuidance("create_service_images");
|
|
29033
29069
|
var SERVICE_IMAGE_FORMATS = [
|
|
29034
29070
|
"4:5",
|
|
@@ -29041,23 +29077,23 @@ var LANGUAGE_TAGS = {
|
|
|
29041
29077
|
en: "en-US",
|
|
29042
29078
|
pt: "pt-BR"
|
|
29043
29079
|
};
|
|
29044
|
-
var CreateServiceImagesInput =
|
|
29045
|
-
brandId:
|
|
29046
|
-
instruction:
|
|
29047
|
-
delegateToAi:
|
|
29048
|
-
format:
|
|
29049
|
-
count:
|
|
29050
|
-
quality:
|
|
29080
|
+
var CreateServiceImagesInput = z118.object({
|
|
29081
|
+
brandId: z118.string().uuid().optional().describe("ID de la marca (de create_brand). Recomendado: da nombre, colores, tono y servicios. Nunca un taskId de producto."),
|
|
29082
|
+
instruction: z118.string().trim().max(4e3).optional().describe("Qu\xE9 servicio o promoci\xF3n mostrar, con las palabras del usuario (ej. \xABcorte + barba a $35.000 los martes\xBB). Si el usuario deja que la IA decida, om\xEDtelo y usa delegateToAi=true."),
|
|
29083
|
+
delegateToAi: z118.boolean().optional().describe("true si el usuario prefiere que la IA elija qu\xE9 mostrar a partir de su marca."),
|
|
29084
|
+
format: z118.enum(SERVICE_IMAGE_FORMATS).optional().describe('Formato: "4:5" (feed, por defecto), "9:16" (historias/reels) o "1:1" (cuadrado).'),
|
|
29085
|
+
count: z118.number().int().min(1).max(SERVICE_IMAGE_MAX_COUNT).optional().describe("Cu\xE1ntas im\xE1genes, de 1 a 3 (por defecto 1)."),
|
|
29086
|
+
quality: z118.enum([
|
|
29051
29087
|
"standard",
|
|
29052
29088
|
"high"
|
|
29053
29089
|
]).optional().describe('Calidad: "standard" (por defecto) o "high" (m\xE1s cara; no disponible en 4:5).'),
|
|
29054
|
-
language:
|
|
29090
|
+
language: z118.enum([
|
|
29055
29091
|
"es",
|
|
29056
29092
|
"en",
|
|
29057
29093
|
"pt"
|
|
29058
29094
|
]).optional().describe("Idioma de los textos de la imagen (por defecto es)."),
|
|
29059
|
-
adCopy:
|
|
29060
|
-
confirmed:
|
|
29095
|
+
adCopy: z118.boolean().optional().describe("Opcional. true agrega textos para el anuncio (titular y descripci\xF3n). Por defecto false."),
|
|
29096
|
+
confirmed: z118.boolean().optional().describe("Solo true despu\xE9s de mostrar el precio y que el usuario acepte. Sin confirmed, solo cotiza y no cobra.")
|
|
29061
29097
|
}).strict();
|
|
29062
29098
|
function serviceImageModel(quality) {
|
|
29063
29099
|
return quality === "high" ? AD_CREATIVE_MODELS.PREMIUM : AD_CREATIVE_MODELS.STANDARD;
|
|
@@ -29168,7 +29204,7 @@ function registerServiceImageTools(server, api, options = {}) {
|
|
|
29168
29204
|
nextAction: "Dile al usuario que est\xE1s creando sus im\xE1genes. Llama get_task_status con este taskId (waitSeconds=45) hasta done (trae las im\xE1genes) o error."
|
|
29169
29205
|
});
|
|
29170
29206
|
} catch (error) {
|
|
29171
|
-
if (error instanceof
|
|
29207
|
+
if (error instanceof z118.ZodError) throw invalidInputFromZod(error);
|
|
29172
29208
|
throw translateError(error);
|
|
29173
29209
|
}
|
|
29174
29210
|
});
|
|
@@ -29176,7 +29212,7 @@ function registerServiceImageTools(server, api, options = {}) {
|
|
|
29176
29212
|
__name(registerServiceImageTools, "registerServiceImageTools");
|
|
29177
29213
|
|
|
29178
29214
|
// src/tools/creatives.ts
|
|
29179
|
-
import { z as
|
|
29215
|
+
import { z as z119 } from "zod";
|
|
29180
29216
|
var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
|
|
29181
29217
|
var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
|
|
29182
29218
|
var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
|
|
@@ -29187,72 +29223,72 @@ var CreativeRefs = {
|
|
|
29187
29223
|
images: ImagesInput,
|
|
29188
29224
|
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.'),
|
|
29189
29225
|
country: Country.describe('Pa\xEDs objetivo ISO. Ej. "CO", "MX", "US", "AR". Define moneda, m\xE9todos de pago y tono. REQUERIDO \u2014 si el usuario no lo dijo, PREG\xDANTALE antes de invocar. NUNCA infieras desde el contexto del chat ni asumas un default.'),
|
|
29190
|
-
price:
|
|
29191
|
-
offer:
|
|
29192
|
-
compareAtPrice:
|
|
29193
|
-
productContext:
|
|
29194
|
-
productLabel:
|
|
29195
|
-
buyerPersona:
|
|
29196
|
-
isCombo:
|
|
29197
|
-
competitorScanEnabled:
|
|
29198
|
-
brandId:
|
|
29226
|
+
price: z119.string().min(1).max(120).optional().describe('Precio en formato libre \u2014 ej. "$89.900", "USD 29.99". Opcional pero MUY IMPACTANTE para conversi\xF3n: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar. Si el usuario te dice "t\xFA elige", omite el campo y la IA del backend sugiere uno.'),
|
|
29227
|
+
offer: z119.string().min(1).max(240).optional().describe('Oferta a destacar \u2014 ej. "2x1", "Env\xEDo gratis", "50% OFF". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar (es v\xE1lido que diga "sin oferta"). Si el usuario te dice "t\xFA elige", omite el campo.'),
|
|
29228
|
+
compareAtPrice: z119.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
|
|
29229
|
+
productContext: z119.string().max(3e3).optional().describe("Opcional. Informacion adicional del producto que la IA debe usar como contexto prioritario: uso real, comprador, restricciones, diferenciadores o direccion creativa. No reemplaza la investigacion de competencia; si hay competencia, guia el primer angulo y los outputs no deben contradecirlo."),
|
|
29230
|
+
productLabel: z119.string().trim().max(80).optional().describe('Opcional. Nombre o tipo del producto en pocas palabras (ej. "collar de oro", "quita pelusas para ropa"). Es AUTORITATIVO: la IA usa esta identidad y no la reemplaza por otra categor\xEDa. Si lo omites, la IA lo detecta desde la imagen. NO salta la extracci\xF3n.'),
|
|
29231
|
+
buyerPersona: z119.string().optional().describe('Opcional. Descripci\xF3n del comprador objetivo. Ej. "Mujeres 35-50, profesionales urbanas". Si se omite, la IA infiere desde el \xE1ngulo y producto.'),
|
|
29232
|
+
isCombo: z119.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
|
|
29233
|
+
competitorScanEnabled: z119.boolean().optional().describe("Opcional. Default false: omitirlo significa SIN estudio de mercado. Antes de crear, llama estimate_market_study_cost, muestra al usuario el costo con y sin estudio y preg\xFAntale si lo quiere; env\xEDa true solo si lo acepta (o si solicita la narrativa an\xE1lisis de mercado). En video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico."),
|
|
29234
|
+
brandId: z119.string().uuid().optional().describe("Opcional. ID de una marca del usuario; si se env\xEDa, el sistema usa su voz, colores y persona para enriquecer el creativo.")
|
|
29199
29235
|
};
|
|
29200
|
-
var VideoPresenter =
|
|
29201
|
-
|
|
29202
|
-
mode:
|
|
29236
|
+
var VideoPresenter = z119.discriminatedUnion("mode", [
|
|
29237
|
+
z119.object({
|
|
29238
|
+
mode: z119.literal("none")
|
|
29203
29239
|
}).strict(),
|
|
29204
|
-
|
|
29205
|
-
mode:
|
|
29206
|
-
actorId:
|
|
29240
|
+
z119.object({
|
|
29241
|
+
mode: z119.literal("saved_actor"),
|
|
29242
|
+
actorId: z119.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
|
|
29207
29243
|
}).strict(),
|
|
29208
|
-
|
|
29209
|
-
mode:
|
|
29210
|
-
description:
|
|
29244
|
+
z119.object({
|
|
29245
|
+
mode: z119.literal("described"),
|
|
29246
|
+
description: z119.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
|
|
29211
29247
|
}).strict()
|
|
29212
29248
|
]);
|
|
29213
|
-
var VideoCreativeSetup =
|
|
29214
|
-
|
|
29215
|
-
mode:
|
|
29249
|
+
var VideoCreativeSetup = z119.discriminatedUnion("mode", [
|
|
29250
|
+
z119.object({
|
|
29251
|
+
mode: z119.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
|
|
29216
29252
|
}).strict(),
|
|
29217
|
-
|
|
29218
|
-
mode:
|
|
29253
|
+
z119.object({
|
|
29254
|
+
mode: z119.literal("guided"),
|
|
29219
29255
|
videoPreset: VideoPresetEnum.default("auto").describe('Narrativa opcional. Con estudio de mercado no la preguntes: se usa "auto" y el estudio define la estructura. Sin estudio conserva la elecci\xF3n del usuario. Todas las narrativas funcionan en Un solo clip y Multiescena.'),
|
|
29220
|
-
buyerPersona:
|
|
29256
|
+
buyerPersona: z119.string().trim().min(1).max(360),
|
|
29221
29257
|
animationStyle: AnimationStyleEnum.optional().describe('Opcional. Estilo visual SOLO para presets animados ("pixar_problem" o "pixar_sassy") \u2014 la API lo rechaza con cualquier otro preset. Opciones: "pixar_3d" (default, look 3D de pel\xEDcula animada), "claymation" (plastilina stop-motion artesanal), "wes_anderson" (tableau sim\xE9trico pastel), "sci_fi" (futurista con HUDs y ne\xF3n), "realista" (fotorrealista, fiel al producto). Si el usuario pide un look animado sin nombrar el estilo, omite el campo.'),
|
|
29222
29258
|
presenter: VideoPresenter,
|
|
29223
|
-
creativeDirection:
|
|
29259
|
+
creativeDirection: z119.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
|
|
29224
29260
|
}).strict()
|
|
29225
29261
|
]);
|
|
29226
|
-
var VideoInput =
|
|
29262
|
+
var VideoInput = z119.object({
|
|
29227
29263
|
images: CreativeRefs.images.optional(),
|
|
29228
29264
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
29229
|
-
title:
|
|
29230
|
-
primaryAngle:
|
|
29265
|
+
title: z119.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
|
|
29266
|
+
primaryAngle: z119.string().min(1).describe('\xC1ngulo de venta principal (frase del beneficio). Ej. "Reduce arrugas en 14 d\xEDas" o "Para quienes odian las cremas grasosas".'),
|
|
29231
29267
|
language: CreativeRefs.language,
|
|
29232
29268
|
country: CreativeRefs.country,
|
|
29233
|
-
aspectRatio:
|
|
29269
|
+
aspectRatio: z119.enum([
|
|
29234
29270
|
"9:16",
|
|
29235
29271
|
"16:9",
|
|
29236
29272
|
"Auto"
|
|
29237
29273
|
]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
|
|
29238
29274
|
generateAiEdit: AiEditRequestSchema.optional().describe('Opcional. Pide la Edici\xF3n con IA: una pasada que a\xF1ade texto, efectos y m\xFAsica sobre cada video entregado (variante with_ai_edit; se cobra al entregar, por video). Nivel: "economy" (Econ\xF3mica, Sonnet 5.5, m\xE1s barata) o "pro" (Opus 5.5, mejor calidad, ~10 min). true equivale a "pro"; false/omitido = sin edici\xF3n.'),
|
|
29239
|
-
durationSeconds:
|
|
29240
|
-
videoAngleCount:
|
|
29275
|
+
durationSeconds: z119.number().int().min(4).max(30).default(15).describe("Opcional. Duraci\xF3n objetivo: Un solo clip Econ\xF3mico o Medio usa 15s; Un solo clip Pro usa 15s o 30s; Multiescena usa 15s o 30s totales. La combinaci\xF3n de formato y calidad determina la ruta y el costo."),
|
|
29276
|
+
videoAngleCount: z119.number().int().min(1).max(3).describe("Cantidad de videos a renderizar: 1, 2 o 3. Es una decisi\xF3n de costo obligatoria: preg\xFAntala incluso cuando creativeSetup.mode=automatic."),
|
|
29241
29277
|
angleNarratives: PublicNarrativeStyleEnum.array().max(3).optional().describe('Opcional. Narrativa POR \xC1NGULO (posicional). Valores actuales: "review", "ugc_how_to", "ugc_unboxing_chaos", "problem_product_cta" (problema concreto, producto como soluci\xF3n y CTA), "product_showcase", "wearable_showcase", "cinematic", "wild_card", "animated_problem_pixar", "sassy_product_pixar", "market" (narrativa an\xE1lisis de mercado: adapta el video a los patrones ganadores estudiados de la competencia; requiere competitorScanEnabled: true). angleNarratives[i] fuerza la narrativa del \xE1ngulo i; las posiciones restantes las elige la IA. La lista no puede superar videoAngleCount.'),
|
|
29242
29278
|
creativeSetup: VideoCreativeSetup.describe("Configuraci\xF3n creativa obligatoria. En guided pregunta narrativa, p\xFAblico, presentador y direcci\xF3n antes de confirmar. Usa automatic s\xF3lo si el usuario deleg\xF3 todo expl\xEDcitamente."),
|
|
29243
29279
|
videoStructure: VideoStructureEnum.default("single_take").describe('Opcional. Formato: "single_take" = Un solo clip (generado completo; puede incluir cambios de plano) o "multi_scene" = Multiescena (varias tomas concatenadas). Default: single_take.'),
|
|
29244
29280
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
|
|
29245
29281
|
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render: "480p" o "720p". Si se omite, se usa 480p; elige 720p expl\xEDcitamente si necesitas m\xE1s nitidez.'),
|
|
29246
|
-
features:
|
|
29282
|
+
features: z119.array(z119.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
|
|
29247
29283
|
price: CreativeRefs.price,
|
|
29248
29284
|
offer: CreativeRefs.offer,
|
|
29249
29285
|
productContext: CreativeRefs.productContext,
|
|
29250
29286
|
productLabel: CreativeRefs.productLabel,
|
|
29251
|
-
cta:
|
|
29252
|
-
scriptNotes:
|
|
29287
|
+
cta: z119.string().optional().describe('Opcional. Call-to-action final del video. Ej. "Compra ahora", "Pide el tuyo hoy", "Link en bio". Si se omite, la IA escribe uno.'),
|
|
29288
|
+
scriptNotes: z119.string().optional().describe('Opcional. Notas/restricciones para el guion (la IA las usa al redactar). Ej. "No mencionar la marca X", "Tono divertido, no cl\xEDnico", "Mencionar 2x1". NO es el guion literal: creativeSetup.mode=guided activa siempre la revisi\xF3n palabra-por-palabra con get_video_script / approve_video_script.'),
|
|
29253
29289
|
creativeGender: CreativeGenderEnum.optional().describe('Opcional. QUI\xC9N APARECE EN PANTALLA en el video: mujer ("female"), hombre ("male") o ambos ("mixed"). NO es la voz; cuando se fija, la voz se alinea sola con el personaje. M\xE1ndalo en cuanto el usuario diga qui\xE9n debe SALIR en el video, con cualquier redacci\xF3n ("quiero una mujer", "que salga un hombre", "protagonista femenina"): si no lo mandas, el g\xE9nero lo inventa la IA y el usuario puede recibir lo contrario de lo que pidi\xF3 sin ning\xFAn aviso. NO lo mandes cuando hable del P\xDABLICO COMPRADOR ("esto es para hombres", "mi p\xFAblico son mujeres", "va dirigido a mam\xE1s"): eso es a qui\xE9n se le vende, no qui\xE9n act\xFAa, y fijarlo ah\xED pinea un protagonista que nadie pidi\xF3. "mixed" solo cuando pida expl\xEDcitamente ambos, y ten en cuenta que no garantiza una mezcla: no fija ning\xFAn g\xE9nero y cada creativo elige su protagonista. No lo preguntes como paso obligatorio. Si creativeSetup.presenter.mode="saved_actor", el personaje guardado manda sobre este campo.'),
|
|
29254
29290
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
29255
|
-
replicateWinnerWhenFound:
|
|
29291
|
+
replicateWinnerWhenFound: z119.boolean().optional().describe("Conserva la preferencia de copiar un ganador si existe. false permite estudiar el mercado sin reemplazar un \xE1ngulo por el anuncio ganador. No a\xF1adas una pregunta obligatoria para este campo."),
|
|
29256
29292
|
brandId: CreativeRefs.brandId
|
|
29257
29293
|
}).strict();
|
|
29258
29294
|
var FreeVideoQualityEnum = VideoQualityEnum;
|
|
@@ -29270,7 +29306,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
|
|
|
29270
29306
|
length: 29
|
|
29271
29307
|
}, (_, index) => index + 2)
|
|
29272
29308
|
};
|
|
29273
|
-
var FreeVideoModelIdEnum =
|
|
29309
|
+
var FreeVideoModelIdEnum = z119.enum([
|
|
29274
29310
|
"grok-imagine-video-1-5-preview",
|
|
29275
29311
|
"minimax-h3/reference-to-video",
|
|
29276
29312
|
"wan/3-0-video",
|
|
@@ -29281,66 +29317,66 @@ var FREE_SELECTABLE_MODEL_IDS = [
|
|
|
29281
29317
|
"minimax-h3/reference-to-video",
|
|
29282
29318
|
"wan/3-0-video"
|
|
29283
29319
|
];
|
|
29284
|
-
var FreeVideoInput =
|
|
29320
|
+
var FreeVideoInput = z119.object({
|
|
29285
29321
|
images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
|
|
29286
|
-
rawPrompt:
|
|
29322
|
+
rawPrompt: z119.string().trim().min(1).max(2e3).describe("Prompt o guion exacto del video. Si activas subt\xEDtulos, este mismo texto se usa como guion de subt\xEDtulos."),
|
|
29287
29323
|
language: CreativeRefs.language,
|
|
29288
29324
|
quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
|
|
29289
29325
|
// Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
|
|
29290
29326
|
// parsed ONLY so the handler can reject it with a message naming its
|
|
29291
29327
|
// replacement — dropping it silently would turn a caller's explicit
|
|
29292
29328
|
// Pro++ pick into a quiet fallback to Wan.
|
|
29293
|
-
freeProModel:
|
|
29329
|
+
freeProModel: z119.enum([
|
|
29294
29330
|
"wan",
|
|
29295
29331
|
"seedance"
|
|
29296
29332
|
]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
|
|
29297
29333
|
modelId: FreeVideoModelIdEnum.optional().describe('Opcional. Elige expl\xEDcitamente el modelo del registro en vez del default de la calidad: "grok-imagine-video-1-5-preview" (Grok 1.5), "minimax-h3/reference-to-video" (H3 Max) o "wan/3-0-video" (Wan 3.0). Om\xEDtelo para usar el modelo por defecto de la calidad elegida. El modelo determina la duraci\xF3n permitida (Grok 6/8/10/15s, H3 Max 4-15s, Wan 2-30s) y el precio. "bytedance/seedance-2-5" est\xE1 inactivo y se rechaza con un error claro, nunca un 500.'),
|
|
29298
|
-
durationSeconds:
|
|
29334
|
+
durationSeconds: z119.number().int().min(2).max(30).describe("Duraci\xF3n exacta. Econ\xF3mico: 6, 8, 10 o 15s; Medio: enteros de 4 a 15s; Pro Wan: 2 a 30s; Pro++ Seedance: 4 a 30s."),
|
|
29299
29335
|
videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
|
|
29300
|
-
generateAiMusic:
|
|
29336
|
+
generateAiMusic: z119.boolean().default(false).describe('Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false. Equivale a generateAiEdit (nivel "pro"): la Edici\xF3n con IA trae su propia m\xFAsica.'),
|
|
29301
29337
|
generateAiEdit: AiEditRequestSchema.optional().describe('Opcional. Pide la Edici\xF3n con IA: una pasada que a\xF1ade texto, gr\xE1ficos y m\xFAsica sobre el video ya entregado (variante with_ai_edit; se cobra al entregar). Nivel: "economy" (Econ\xF3mica, Sonnet 5.5, m\xE1s barata) o "pro" (Opus 5.5, mejor calidad, ~10 min). true equivale a "pro". Default sin edici\xF3n.'),
|
|
29302
|
-
addSubtitles:
|
|
29303
|
-
idempotencyKey:
|
|
29338
|
+
addSubtitles: z119.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
|
|
29339
|
+
idempotencyKey: z119.string().uuid().optional().describe("Opcional. Se acepta por compatibilidad pero se ignora: la identidad del reintento se deriva autom\xE1ticamente de los argumentos sem\xE1nticos, as\xED que un retry con los mismos argumentos ya es idempotente sin este campo.")
|
|
29304
29340
|
}).strict();
|
|
29305
29341
|
var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
|
|
29306
|
-
var ImageCreativeSetup =
|
|
29307
|
-
|
|
29308
|
-
mode:
|
|
29342
|
+
var ImageCreativeSetup = z119.discriminatedUnion("mode", [
|
|
29343
|
+
z119.object({
|
|
29344
|
+
mode: z119.literal("automatic")
|
|
29309
29345
|
}).strict(),
|
|
29310
|
-
|
|
29311
|
-
mode:
|
|
29312
|
-
creativeArchetype:
|
|
29346
|
+
z119.object({
|
|
29347
|
+
mode: z119.literal("guided"),
|
|
29348
|
+
creativeArchetype: z119.union([
|
|
29313
29349
|
ImageCreativeArchetypeEnum,
|
|
29314
|
-
|
|
29350
|
+
z119.literal("ai_decides")
|
|
29315
29351
|
]),
|
|
29316
|
-
visualTreatment:
|
|
29352
|
+
visualTreatment: z119.union([
|
|
29317
29353
|
ImageCreativeVisualTreatmentEnum,
|
|
29318
|
-
|
|
29354
|
+
z119.literal("ai_decides")
|
|
29319
29355
|
]),
|
|
29320
29356
|
aspectRatio: ImageCreativeAspectRatioEnum,
|
|
29321
|
-
nVariants:
|
|
29322
|
-
|
|
29323
|
-
|
|
29324
|
-
|
|
29325
|
-
|
|
29326
|
-
|
|
29357
|
+
nVariants: z119.union([
|
|
29358
|
+
z119.literal(1),
|
|
29359
|
+
z119.literal(2),
|
|
29360
|
+
z119.literal(3),
|
|
29361
|
+
z119.literal(4),
|
|
29362
|
+
z119.literal(6)
|
|
29327
29363
|
]),
|
|
29328
|
-
imageModel:
|
|
29329
|
-
styleMix:
|
|
29330
|
-
generateAdCopy:
|
|
29331
|
-
competitorScanEnabled:
|
|
29332
|
-
productContext:
|
|
29333
|
-
creativeDirection:
|
|
29334
|
-
brandColors:
|
|
29335
|
-
headline:
|
|
29336
|
-
subheadline:
|
|
29364
|
+
imageModel: z119.enum(PUBLIC_IMAGE_QUALITY_INPUTS).describe('Calidad: "image:1k" (Est\xE1ndar) o "image:2k" (Premium). Los tokens gpt-image-2-5:{1k,2k} y gpt-image-2:{1k,2k} se siguen aceptando.'),
|
|
29365
|
+
styleMix: z119.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
|
|
29366
|
+
generateAdCopy: z119.boolean(),
|
|
29367
|
+
competitorScanEnabled: z119.boolean(),
|
|
29368
|
+
productContext: z119.string().trim().min(1).max(3e3).nullable(),
|
|
29369
|
+
creativeDirection: z119.string().trim().min(1).max(500).nullable(),
|
|
29370
|
+
brandColors: z119.string().trim().min(1).max(240).nullable().describe('Colores en lenguaje natural, igual que en el chat web. Ej. "Azul y Dorado". null significa sin colores espec\xEDficos.'),
|
|
29371
|
+
headline: z119.string().trim().min(1).max(120).nullable(),
|
|
29372
|
+
subheadline: z119.string().trim().min(1).max(160).nullable()
|
|
29337
29373
|
}).strict()
|
|
29338
29374
|
]).superRefine((setup, context) => {
|
|
29339
29375
|
if (setup.mode !== "guided") return;
|
|
29340
29376
|
const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
|
|
29341
29377
|
if (needsStyleMix && setup.styleMix === null) {
|
|
29342
29378
|
context.addIssue({
|
|
29343
|
-
code:
|
|
29379
|
+
code: z119.ZodIssueCode.custom,
|
|
29344
29380
|
path: [
|
|
29345
29381
|
"styleMix"
|
|
29346
29382
|
],
|
|
@@ -29349,7 +29385,7 @@ var ImageCreativeSetup = z118.discriminatedUnion("mode", [
|
|
|
29349
29385
|
}
|
|
29350
29386
|
if (!needsStyleMix && setup.styleMix !== null) {
|
|
29351
29387
|
context.addIssue({
|
|
29352
|
-
code:
|
|
29388
|
+
code: z119.ZodIssueCode.custom,
|
|
29353
29389
|
path: [
|
|
29354
29390
|
"styleMix"
|
|
29355
29391
|
],
|
|
@@ -29358,7 +29394,7 @@ var ImageCreativeSetup = z118.discriminatedUnion("mode", [
|
|
|
29358
29394
|
}
|
|
29359
29395
|
if (imageResolutionOf(setup.imageModel) === "2k" && setup.aspectRatio === "4:5") {
|
|
29360
29396
|
context.addIssue({
|
|
29361
|
-
code:
|
|
29397
|
+
code: z119.ZodIssueCode.custom,
|
|
29362
29398
|
path: [
|
|
29363
29399
|
"aspectRatio"
|
|
29364
29400
|
],
|
|
@@ -29366,55 +29402,55 @@ var ImageCreativeSetup = z118.discriminatedUnion("mode", [
|
|
|
29366
29402
|
});
|
|
29367
29403
|
}
|
|
29368
29404
|
});
|
|
29369
|
-
var LandingCreativeSetup =
|
|
29370
|
-
|
|
29371
|
-
mode:
|
|
29405
|
+
var LandingCreativeSetup = z119.discriminatedUnion("mode", [
|
|
29406
|
+
z119.object({
|
|
29407
|
+
mode: z119.literal("automatic")
|
|
29372
29408
|
}).strict(),
|
|
29373
|
-
|
|
29374
|
-
mode:
|
|
29409
|
+
z119.object({
|
|
29410
|
+
mode: z119.literal("guided"),
|
|
29375
29411
|
landingStrategy: LandingStrategyEnum,
|
|
29376
29412
|
landingImageFormat: LandingImageFormatEnum,
|
|
29377
|
-
competitorScanEnabled:
|
|
29378
|
-
paymentMethods:
|
|
29379
|
-
productContext:
|
|
29380
|
-
creativeDirection:
|
|
29381
|
-
headline:
|
|
29382
|
-
subheadline:
|
|
29413
|
+
competitorScanEnabled: z119.boolean(),
|
|
29414
|
+
paymentMethods: z119.string().trim().min(1).max(240).nullable(),
|
|
29415
|
+
productContext: z119.string().trim().min(1).max(3e3).nullable(),
|
|
29416
|
+
creativeDirection: z119.string().trim().min(1).max(500).nullable(),
|
|
29417
|
+
headline: z119.string().trim().min(1).max(120).nullable(),
|
|
29418
|
+
subheadline: z119.string().trim().min(1).max(160).nullable()
|
|
29383
29419
|
}).strict()
|
|
29384
29420
|
]);
|
|
29385
|
-
var ImageInput =
|
|
29421
|
+
var ImageInput = z119.object({
|
|
29386
29422
|
images: CreativeRefs.images.optional(),
|
|
29387
29423
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
29388
|
-
productTitle:
|
|
29389
|
-
primaryAngle:
|
|
29424
|
+
productTitle: z119.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
|
|
29425
|
+
primaryAngle: z119.string().min(1).optional().describe('Opcional. \xC1ngulo de venta principal. Si se omite, ProductMaker lo genera y creativeSetup.mode="guided" lo muestra para revisi\xF3n antes de crear las im\xE1genes.'),
|
|
29390
29426
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
29391
29427
|
language: CreativeRefs.language,
|
|
29392
29428
|
country: CreativeRefs.country,
|
|
29393
29429
|
creativeSetup: ImageCreativeSetup.describe("Configuraci\xF3n obligatoria equivalente al wizard web. Usa guided salvo que el usuario delegue expl\xEDcitamente todo; presenta las decisiones guiadas en un \xFAnico checklist compacto."),
|
|
29394
29430
|
imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
|
|
29395
|
-
features:
|
|
29431
|
+
features: z119.array(z119.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
|
|
29396
29432
|
price: CreativeRefs.price,
|
|
29397
|
-
omitPrice:
|
|
29433
|
+
omitPrice: z119.boolean().optional().describe("Pon true \xFAnicamente cuando el usuario pida expl\xEDcitamente una imagen sin precio. Evita que el backend reutilice un precio extra\xEDdo del producto. No lo combines con price ni compareAtPrice."),
|
|
29398
29434
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
29399
29435
|
offer: CreativeRefs.offer,
|
|
29400
29436
|
productLabel: CreativeRefs.productLabel,
|
|
29401
29437
|
isCombo: CreativeRefs.isCombo,
|
|
29402
29438
|
brandId: CreativeRefs.brandId
|
|
29403
29439
|
});
|
|
29404
|
-
var EditImageCreativeInput =
|
|
29405
|
-
taskId:
|
|
29406
|
-
variantIndex:
|
|
29407
|
-
clientRequestId:
|
|
29408
|
-
instruction:
|
|
29440
|
+
var EditImageCreativeInput = z119.object({
|
|
29441
|
+
taskId: z119.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
|
|
29442
|
+
variantIndex: z119.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
|
|
29443
|
+
clientRequestId: z119.string().min(1).max(160).optional().describe("Identidad estable de esta correcci\xF3n; reutil\xEDzala al reconciliar una respuesta perdida, no para otra instrucci\xF3n."),
|
|
29444
|
+
instruction: z119.string().min(1).max(1e3).describe('Qu\xE9 cambiar en esa imagen. Ej. "quita el badge de env\xEDo gratis", "cambia el fondo a blanco".')
|
|
29409
29445
|
});
|
|
29410
|
-
var LandingInput =
|
|
29411
|
-
includeInitialLandingGif:
|
|
29446
|
+
var LandingInput = z119.object({
|
|
29447
|
+
includeInitialLandingGif: z119.boolean().optional().describe("Opcional. En nuevas landings cl\xE1sicas habilitadas, omitirlo incluye el primer GIF del producto y su coste en el total. Env\xEDa false si el usuario lo excluye: no se genera ni se reserva su coste. Conserva la elecci\xF3n al confirmar y al reintentar."),
|
|
29412
29448
|
images: CreativeRefs.images.optional(),
|
|
29413
29449
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
29414
29450
|
language: CreativeRefs.language,
|
|
29415
29451
|
country: CreativeRefs.country,
|
|
29416
29452
|
creativeSetup: LandingCreativeSetup.describe("Configuraci\xF3n obligatoria de landing cl\xE1sica equivalente al wizard web. No expone landing editable/code mientras siga siendo admin-only."),
|
|
29417
|
-
salesAngle:
|
|
29453
|
+
salesAngle: z119.string().optional().describe('Opcional. \xC1ngulo de venta principal. Ej. "Reduce arrugas en 14 d\xEDas". Si se omite, la IA lo deduce de la imagen.'),
|
|
29418
29454
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
29419
29455
|
price: CreativeRefs.price,
|
|
29420
29456
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
@@ -29696,8 +29732,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
29696
29732
|
server.registerTool("get_image_edit_status", {
|
|
29697
29733
|
description: imageEditStatusGuidance.summary,
|
|
29698
29734
|
inputSchema: {
|
|
29699
|
-
taskId:
|
|
29700
|
-
operationId:
|
|
29735
|
+
taskId: z119.string().uuid(),
|
|
29736
|
+
operationId: z119.string().uuid()
|
|
29701
29737
|
},
|
|
29702
29738
|
annotations: READS_INTERNAL
|
|
29703
29739
|
}, async (input) => {
|
|
@@ -29754,10 +29790,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
29754
29790
|
__name(registerCreativeTools, "registerCreativeTools");
|
|
29755
29791
|
|
|
29756
29792
|
// src/tools/creative-variants.ts
|
|
29757
|
-
import { z as
|
|
29793
|
+
import { z as z120 } from "zod";
|
|
29758
29794
|
var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
|
|
29759
29795
|
var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
|
|
29760
|
-
var LandingSectionKeyEnum =
|
|
29796
|
+
var LandingSectionKeyEnum = z120.enum([
|
|
29761
29797
|
"problem_hook",
|
|
29762
29798
|
"problem_cost",
|
|
29763
29799
|
"solution_mechanism",
|
|
@@ -29797,24 +29833,24 @@ var LandingSectionKeyEnum = z119.enum([
|
|
|
29797
29833
|
"lifestyle_fit",
|
|
29798
29834
|
"join_lifestyle"
|
|
29799
29835
|
]);
|
|
29800
|
-
var CreativeVariantKindEnum =
|
|
29836
|
+
var CreativeVariantKindEnum = z120.enum([
|
|
29801
29837
|
"video",
|
|
29802
29838
|
"image",
|
|
29803
29839
|
"landing"
|
|
29804
29840
|
]);
|
|
29805
|
-
var EstimateCreativeVariantInputBase =
|
|
29806
|
-
sourceTaskId:
|
|
29841
|
+
var EstimateCreativeVariantInputBase = z120.object({
|
|
29842
|
+
sourceTaskId: z120.string().uuid().describe("ID de la tarea original completada."),
|
|
29807
29843
|
kind: CreativeVariantKindEnum,
|
|
29808
29844
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
|
|
29809
29845
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
|
|
29810
|
-
nVariants:
|
|
29846
|
+
nVariants: z120.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
29811
29847
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
|
|
29812
|
-
instructions:
|
|
29848
|
+
instructions: z120.string().trim().min(1).max(2e3).optional().describe("Opcional para landing. Si se env\xEDa sin sectionKey, el estimado suma la clasificaci\xF3n pagada con IA.")
|
|
29813
29849
|
}).strict();
|
|
29814
29850
|
var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
29815
29851
|
if (input.kind === "video" && input.nVariants !== void 0) {
|
|
29816
29852
|
ctx.addIssue({
|
|
29817
|
-
code:
|
|
29853
|
+
code: z120.ZodIssueCode.custom,
|
|
29818
29854
|
path: [
|
|
29819
29855
|
"nVariants"
|
|
29820
29856
|
],
|
|
@@ -29824,7 +29860,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
29824
29860
|
if (input.kind !== "video") {
|
|
29825
29861
|
if (input.videoPreset !== void 0) {
|
|
29826
29862
|
ctx.addIssue({
|
|
29827
|
-
code:
|
|
29863
|
+
code: z120.ZodIssueCode.custom,
|
|
29828
29864
|
path: [
|
|
29829
29865
|
"videoPreset"
|
|
29830
29866
|
],
|
|
@@ -29833,7 +29869,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
29833
29869
|
}
|
|
29834
29870
|
if (input.videoResolution !== void 0) {
|
|
29835
29871
|
ctx.addIssue({
|
|
29836
|
-
code:
|
|
29872
|
+
code: z120.ZodIssueCode.custom,
|
|
29837
29873
|
path: [
|
|
29838
29874
|
"videoResolution"
|
|
29839
29875
|
],
|
|
@@ -29843,7 +29879,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
29843
29879
|
}
|
|
29844
29880
|
if (input.kind !== "image" && input.nVariants !== void 0) {
|
|
29845
29881
|
ctx.addIssue({
|
|
29846
|
-
code:
|
|
29882
|
+
code: z120.ZodIssueCode.custom,
|
|
29847
29883
|
path: [
|
|
29848
29884
|
"nVariants"
|
|
29849
29885
|
],
|
|
@@ -29853,7 +29889,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
29853
29889
|
if (input.kind !== "landing") {
|
|
29854
29890
|
if (input.sectionKey !== void 0) {
|
|
29855
29891
|
ctx.addIssue({
|
|
29856
|
-
code:
|
|
29892
|
+
code: z120.ZodIssueCode.custom,
|
|
29857
29893
|
path: [
|
|
29858
29894
|
"sectionKey"
|
|
29859
29895
|
],
|
|
@@ -29862,7 +29898,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
29862
29898
|
}
|
|
29863
29899
|
if (input.instructions !== void 0) {
|
|
29864
29900
|
ctx.addIssue({
|
|
29865
|
-
code:
|
|
29901
|
+
code: z120.ZodIssueCode.custom,
|
|
29866
29902
|
path: [
|
|
29867
29903
|
"instructions"
|
|
29868
29904
|
],
|
|
@@ -29871,31 +29907,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
29871
29907
|
}
|
|
29872
29908
|
}
|
|
29873
29909
|
});
|
|
29874
|
-
var CreateCreativeVariantInputBase =
|
|
29875
|
-
sourceTaskId:
|
|
29910
|
+
var CreateCreativeVariantInputBase = z120.object({
|
|
29911
|
+
sourceTaskId: z120.string().uuid().describe("ID de la tarea original completada."),
|
|
29876
29912
|
kind: CreativeVariantKindEnum,
|
|
29877
|
-
confirm:
|
|
29878
|
-
clientRequestId:
|
|
29879
|
-
angle:
|
|
29880
|
-
buyerPersona:
|
|
29881
|
-
scriptNotes:
|
|
29882
|
-
creativeDirection:
|
|
29913
|
+
confirm: z120.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
|
|
29914
|
+
clientRequestId: z120.string().uuid().describe("UUID estable para esta intenci\xF3n (obligatorio por compatibilidad de contrato; el servidor deriva la identidad real del request desde los argumentos sem\xE1nticos, as\xED que un UUID nuevo en un retry NO crea una variante duplicada). Si la API devuelve status=error, una nueva generaci\xF3n exige otra confirmaci\xF3n."),
|
|
29915
|
+
angle: z120.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
|
|
29916
|
+
buyerPersona: z120.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
|
|
29917
|
+
scriptNotes: z120.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
|
|
29918
|
+
creativeDirection: z120.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
|
|
29883
29919
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
|
|
29884
29920
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
|
|
29885
|
-
generateAiMusic:
|
|
29886
|
-
nVariants:
|
|
29921
|
+
generateAiMusic: z120.boolean().optional().describe("Opcional para video."),
|
|
29922
|
+
nVariants: z120.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
29887
29923
|
imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
|
|
29888
29924
|
creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
|
|
29889
29925
|
visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
|
|
29890
29926
|
aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
|
|
29891
|
-
styleMix:
|
|
29927
|
+
styleMix: z120.boolean().optional().describe("Opcional para imagen."),
|
|
29892
29928
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
|
|
29893
|
-
instructions:
|
|
29929
|
+
instructions: z120.string().trim().min(1).max(2e3).optional().describe("Solicitud libre para una nueva secci\xF3n de landing. La IA la clasifica si no env\xEDas sectionKey.")
|
|
29894
29930
|
}).strict();
|
|
29895
29931
|
var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
29896
29932
|
if ((input.kind === "video" || input.kind === "image") && !input.angle) {
|
|
29897
29933
|
ctx.addIssue({
|
|
29898
|
-
code:
|
|
29934
|
+
code: z120.ZodIssueCode.custom,
|
|
29899
29935
|
path: [
|
|
29900
29936
|
"angle"
|
|
29901
29937
|
],
|
|
@@ -29904,7 +29940,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
29904
29940
|
}
|
|
29905
29941
|
if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
|
|
29906
29942
|
ctx.addIssue({
|
|
29907
|
-
code:
|
|
29943
|
+
code: z120.ZodIssueCode.custom,
|
|
29908
29944
|
path: [
|
|
29909
29945
|
"instructions"
|
|
29910
29946
|
],
|
|
@@ -29950,7 +29986,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
29950
29986
|
for (const field of fieldsByKind[input.kind]) {
|
|
29951
29987
|
if (input[field] !== void 0) {
|
|
29952
29988
|
ctx.addIssue({
|
|
29953
|
-
code:
|
|
29989
|
+
code: z120.ZodIssueCode.custom,
|
|
29954
29990
|
path: [
|
|
29955
29991
|
field
|
|
29956
29992
|
],
|
|
@@ -30083,13 +30119,13 @@ function registerCreativeVariantTools(server, api) {
|
|
|
30083
30119
|
__name(registerCreativeVariantTools, "registerCreativeVariantTools");
|
|
30084
30120
|
|
|
30085
30121
|
// src/tools/script-review.ts
|
|
30086
|
-
import { z as
|
|
30122
|
+
import { z as z121 } from "zod";
|
|
30087
30123
|
var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
|
|
30088
30124
|
var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
|
|
30089
30125
|
var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
|
|
30090
|
-
var GetVideoScriptInput =
|
|
30091
|
-
taskId:
|
|
30092
|
-
angleKey:
|
|
30126
|
+
var GetVideoScriptInput = z121.object({
|
|
30127
|
+
taskId: z121.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
|
|
30128
|
+
angleKey: z121.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.')
|
|
30093
30129
|
}).strict();
|
|
30094
30130
|
var ApproveVideoScriptInput = ApproveVideoScriptCapabilityRequest;
|
|
30095
30131
|
var RegenerateVideoScriptInput = RegenerateVideoScriptCapabilityRequest.extend({
|
|
@@ -30172,7 +30208,7 @@ function registerScriptReviewTools(server, api) {
|
|
|
30172
30208
|
__name(registerScriptReviewTools, "registerScriptReviewTools");
|
|
30173
30209
|
|
|
30174
30210
|
// src/tools/connections.ts
|
|
30175
|
-
import { z as
|
|
30211
|
+
import { z as z122 } from "zod";
|
|
30176
30212
|
var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
|
|
30177
30213
|
var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
|
|
30178
30214
|
var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
|
|
@@ -30181,7 +30217,7 @@ var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list
|
|
|
30181
30217
|
function registerConnectionTools(server, api) {
|
|
30182
30218
|
server.registerTool("list_shopify_shops", {
|
|
30183
30219
|
description: listShopifyShopsGuidance.summary + " Si la lista est\xE1 vac\xEDa, dile al usuario que conecte una tienda en productmaker.app/integrations antes de intentar publicar.",
|
|
30184
|
-
inputSchema:
|
|
30220
|
+
inputSchema: z122.object({}).shape,
|
|
30185
30221
|
annotations: READS_INTERNAL
|
|
30186
30222
|
}, async () => {
|
|
30187
30223
|
try {
|
|
@@ -30193,10 +30229,10 @@ function registerConnectionTools(server, api) {
|
|
|
30193
30229
|
});
|
|
30194
30230
|
server.registerTool("list_shopify_products", {
|
|
30195
30231
|
description: 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.',
|
|
30196
|
-
inputSchema:
|
|
30197
|
-
shopDomain:
|
|
30198
|
-
query:
|
|
30199
|
-
taskId:
|
|
30232
|
+
inputSchema: z122.object({
|
|
30233
|
+
shopDomain: z122.string().min(3).max(120),
|
|
30234
|
+
query: z122.string().trim().max(120).optional(),
|
|
30235
|
+
taskId: z122.string().uuid().optional()
|
|
30200
30236
|
}).shape,
|
|
30201
30237
|
annotations: READS_EXTERNAL
|
|
30202
30238
|
}, async ({ shopDomain, query, taskId }) => {
|
|
@@ -30214,7 +30250,7 @@ function registerConnectionTools(server, api) {
|
|
|
30214
30250
|
});
|
|
30215
30251
|
server.registerTool("list_meta_ad_accounts", {
|
|
30216
30252
|
description: 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.",
|
|
30217
|
-
inputSchema:
|
|
30253
|
+
inputSchema: z122.object({}).shape,
|
|
30218
30254
|
annotations: READS_EXTERNAL
|
|
30219
30255
|
}, async () => {
|
|
30220
30256
|
try {
|
|
@@ -30226,7 +30262,7 @@ function registerConnectionTools(server, api) {
|
|
|
30226
30262
|
});
|
|
30227
30263
|
server.registerTool("list_meta_destinations", {
|
|
30228
30264
|
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.",
|
|
30229
|
-
inputSchema:
|
|
30265
|
+
inputSchema: z122.object({}).shape,
|
|
30230
30266
|
annotations: READS_EXTERNAL,
|
|
30231
30267
|
_meta: {
|
|
30232
30268
|
"openai/widgetAccessible": true
|
|
@@ -30241,7 +30277,7 @@ function registerConnectionTools(server, api) {
|
|
|
30241
30277
|
});
|
|
30242
30278
|
server.registerTool("list_tiktok_advertisers", {
|
|
30243
30279
|
description: listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.",
|
|
30244
|
-
inputSchema:
|
|
30280
|
+
inputSchema: z122.object({}).shape,
|
|
30245
30281
|
annotations: READS_EXTERNAL
|
|
30246
30282
|
}, async () => {
|
|
30247
30283
|
try {
|
|
@@ -30255,7 +30291,7 @@ function registerConnectionTools(server, api) {
|
|
|
30255
30291
|
__name(registerConnectionTools, "registerConnectionTools");
|
|
30256
30292
|
|
|
30257
30293
|
// src/tools/actors.ts
|
|
30258
|
-
import { z as
|
|
30294
|
+
import { z as z123 } from "zod";
|
|
30259
30295
|
var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
|
|
30260
30296
|
var actorVoiceGuidance = {
|
|
30261
30297
|
capabilities: getProductMakerCapabilityModelGuidance("get_actor_voice_capabilities"),
|
|
@@ -30295,7 +30331,7 @@ function sanitizeVoiceResult(value) {
|
|
|
30295
30331
|
__name(sanitizeVoiceResult, "sanitizeVoiceResult");
|
|
30296
30332
|
function registerActorTools(server, api) {
|
|
30297
30333
|
const actor = {
|
|
30298
|
-
actorId:
|
|
30334
|
+
actorId: z123.string().min(1).max(64)
|
|
30299
30335
|
};
|
|
30300
30336
|
const safe = /* @__PURE__ */ __name(async (request) => {
|
|
30301
30337
|
try {
|
|
@@ -30324,8 +30360,8 @@ function registerActorTools(server, api) {
|
|
|
30324
30360
|
inputSchema: {
|
|
30325
30361
|
...actor,
|
|
30326
30362
|
draft: ActorVoiceDraftSchema,
|
|
30327
|
-
requestKey:
|
|
30328
|
-
acceptedQuoteId:
|
|
30363
|
+
requestKey: z123.string().trim().min(1).max(128),
|
|
30364
|
+
acceptedQuoteId: z123.string().trim().min(1).max(128)
|
|
30329
30365
|
},
|
|
30330
30366
|
annotations: CREATES_PAID
|
|
30331
30367
|
}, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/previews`, body)));
|
|
@@ -30333,7 +30369,7 @@ function registerActorTools(server, api) {
|
|
|
30333
30369
|
description: actorVoiceGuidance.get.summary,
|
|
30334
30370
|
inputSchema: {
|
|
30335
30371
|
...actor,
|
|
30336
|
-
candidateId:
|
|
30372
|
+
candidateId: z123.string().min(1).max(64)
|
|
30337
30373
|
},
|
|
30338
30374
|
// Polling can resume the first paid submission of an accepted quote.
|
|
30339
30375
|
// The immutable candidate/operation key keeps recovery idempotent.
|
|
@@ -30346,16 +30382,16 @@ function registerActorTools(server, api) {
|
|
|
30346
30382
|
description: actorVoiceGuidance.approve.summary,
|
|
30347
30383
|
inputSchema: {
|
|
30348
30384
|
...actor,
|
|
30349
|
-
candidateId:
|
|
30350
|
-
expectedRevision:
|
|
30351
|
-
expectedApprovedRevision:
|
|
30385
|
+
candidateId: z123.string().min(1).max(64),
|
|
30386
|
+
expectedRevision: z123.number().int().positive(),
|
|
30387
|
+
expectedApprovedRevision: z123.number().int().positive().nullable().optional()
|
|
30352
30388
|
},
|
|
30353
30389
|
// Replaces the selected voice and withdraws the old catalog grants.
|
|
30354
30390
|
annotations: OVERWRITES_INTERNAL
|
|
30355
30391
|
}, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/approve`, body)));
|
|
30356
30392
|
server.registerTool("list_actors", {
|
|
30357
30393
|
description: listActorsGuidance.summary + " Devuelve id, nombre, descripci\xF3n, g\xE9nero y voz privada del personaje. Cuando el personaje tiene una voz personalizada, `voice.identityId` y `voice.revision` identifican la versi\xF3n aprobada \u2014 conserva la revisi\xF3n al llamar `approve_actor_voice` (expectedApprovedRevision) para reemplazarla. Los IDs de proveedor nunca se exponen por MCP. 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.",
|
|
30358
|
-
inputSchema:
|
|
30394
|
+
inputSchema: z123.object({}).shape,
|
|
30359
30395
|
annotations: READS_INTERNAL
|
|
30360
30396
|
}, async () => {
|
|
30361
30397
|
try {
|
|
@@ -30388,7 +30424,7 @@ function registerActorTools(server, api) {
|
|
|
30388
30424
|
__name(registerActorTools, "registerActorTools");
|
|
30389
30425
|
|
|
30390
30426
|
// src/tools/publish.ts
|
|
30391
|
-
import { z as
|
|
30427
|
+
import { z as z124 } from "zod";
|
|
30392
30428
|
|
|
30393
30429
|
// src/tools/meta-publish-attempt-id.ts
|
|
30394
30430
|
var META_PUBLISH_NAMESPACE = "7b19c9ac-b4eb-4db1-970e-c2f24ce30b98";
|
|
@@ -30427,40 +30463,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
|
|
|
30427
30463
|
var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
|
|
30428
30464
|
var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
|
|
30429
30465
|
var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
|
|
30430
|
-
var ShopifyInput =
|
|
30431
|
-
taskId:
|
|
30432
|
-
shopDomain:
|
|
30466
|
+
var ShopifyInput = z124.object({
|
|
30467
|
+
taskId: z124.string().min(1),
|
|
30468
|
+
shopDomain: z124.string().min(1),
|
|
30433
30469
|
/** Override: number of landing images to include. Default = ALL images the
|
|
30434
30470
|
* task generated (the MCP fetches /v1/results first to count). Bounded
|
|
30435
30471
|
* generously here; the backend validates each index against
|
|
30436
30472
|
* landing.images.length and rejects out-of-range. */
|
|
30437
|
-
numLandingImages:
|
|
30438
|
-
variantIndex:
|
|
30473
|
+
numLandingImages: z124.number().int().min(1).max(20).optional(),
|
|
30474
|
+
variantIndex: z124.number().int().min(0).optional(),
|
|
30439
30475
|
/** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
|
|
30440
30476
|
* When true, the landing renders variant-picker pills; when false, it ships
|
|
30441
30477
|
* a single-option product page. Defaults to false. */
|
|
30442
|
-
showVariantPicker:
|
|
30478
|
+
showVariantPicker: z124.boolean().optional(),
|
|
30443
30479
|
/** Default `auto` updates the product previously published for this task and
|
|
30444
30480
|
* shop. Use `existing` with targetProductId to choose another product, or
|
|
30445
30481
|
* `new` only when the user explicitly wants a duplicate/new listing. */
|
|
30446
|
-
publicationMode:
|
|
30482
|
+
publicationMode: z124.enum([
|
|
30447
30483
|
"auto",
|
|
30448
30484
|
"existing",
|
|
30449
30485
|
"new"
|
|
30450
30486
|
]).optional(),
|
|
30451
30487
|
/** Shopify product GID, numeric id, or admin product URL. Required when
|
|
30452
30488
|
* publicationMode is `existing`. */
|
|
30453
|
-
targetProductId:
|
|
30489
|
+
targetProductId: z124.string().trim().min(1).max(300).optional(),
|
|
30454
30490
|
/** Add an announcement bar text above add-to-cart (optional). */
|
|
30455
|
-
announcementBarEnabled:
|
|
30456
|
-
announcementBarText:
|
|
30491
|
+
announcementBarEnabled: z124.boolean().optional(),
|
|
30492
|
+
announcementBarText: z124.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
|
|
30457
30493
|
commerceCorrection: PublishCommerceCorrectionSchema.optional().describe("Complete seller-confirmed commerce values, with the revision and fingerprint returned in recovery. Never invent missing prices or convert currency."),
|
|
30458
|
-
confirmed:
|
|
30494
|
+
confirmed: z124.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
|
|
30459
30495
|
});
|
|
30460
30496
|
var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
|
|
30461
30497
|
if (value.commerceCorrection && value.confirmed !== true) {
|
|
30462
30498
|
ctx.addIssue({
|
|
30463
|
-
code:
|
|
30499
|
+
code: z124.ZodIssueCode.custom,
|
|
30464
30500
|
path: [
|
|
30465
30501
|
"confirmed"
|
|
30466
30502
|
],
|
|
@@ -30469,7 +30505,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
30469
30505
|
}
|
|
30470
30506
|
if (value.announcementBarEnabled && !value.announcementBarText) {
|
|
30471
30507
|
ctx.addIssue({
|
|
30472
|
-
code:
|
|
30508
|
+
code: z124.ZodIssueCode.custom,
|
|
30473
30509
|
path: [
|
|
30474
30510
|
"announcementBarText"
|
|
30475
30511
|
],
|
|
@@ -30478,7 +30514,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
30478
30514
|
}
|
|
30479
30515
|
if (!value.announcementBarEnabled && value.announcementBarText) {
|
|
30480
30516
|
ctx.addIssue({
|
|
30481
|
-
code:
|
|
30517
|
+
code: z124.ZodIssueCode.custom,
|
|
30482
30518
|
path: [
|
|
30483
30519
|
"announcementBarText"
|
|
30484
30520
|
],
|
|
@@ -30492,91 +30528,91 @@ function parseShopifyInput(rawInput) {
|
|
|
30492
30528
|
return parsed.data;
|
|
30493
30529
|
}
|
|
30494
30530
|
__name(parseShopifyInput, "parseShopifyInput");
|
|
30495
|
-
var McpCampaignConfig =
|
|
30531
|
+
var McpCampaignConfig = z124.object({
|
|
30496
30532
|
/** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
|
|
30497
30533
|
* converts to the account currency server-side. Do NOT pre-convert: on a COP
|
|
30498
30534
|
* account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
|
|
30499
|
-
dailyBudgetUsd:
|
|
30535
|
+
dailyBudgetUsd: z124.number().positive().optional(),
|
|
30500
30536
|
/** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
|
|
30501
30537
|
* normalizes at validation). Meta accepts max 1 (single-country ad set).
|
|
30502
30538
|
* TikTok takes only the first entry. */
|
|
30503
|
-
targetCountries:
|
|
30504
|
-
campaignName:
|
|
30539
|
+
targetCountries: z124.array(CountryIso2Schema).max(1).optional(),
|
|
30540
|
+
campaignName: z124.string().trim().min(1).max(100).optional()
|
|
30505
30541
|
});
|
|
30506
30542
|
var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
|
|
30507
|
-
var MetaInput =
|
|
30508
|
-
taskId:
|
|
30543
|
+
var MetaInput = z124.object({
|
|
30544
|
+
taskId: z124.string().min(1),
|
|
30509
30545
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
30510
|
-
portfolioId:
|
|
30546
|
+
portfolioId: z124.string().trim().min(1),
|
|
30511
30547
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
30512
|
-
pageId:
|
|
30548
|
+
pageId: z124.string().trim().min(1),
|
|
30513
30549
|
adAccountId: McpAdAccountId,
|
|
30514
|
-
pixelId:
|
|
30515
|
-
landingUrl:
|
|
30550
|
+
pixelId: z124.string().min(1).optional(),
|
|
30551
|
+
landingUrl: z124.string().url().optional(),
|
|
30516
30552
|
/** Select which angles to publish by 0-based index. Omit to publish all
|
|
30517
30553
|
* successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
|
|
30518
|
-
angleIndexes:
|
|
30554
|
+
angleIndexes: z124.array(z124.number().int().nonnegative()).optional(),
|
|
30519
30555
|
campaignConfig: McpCampaignConfig.optional(),
|
|
30520
30556
|
/** Override the ad's primary text (body copy). If omitted, ProductMaker
|
|
30521
30557
|
* uses the auto-generated copy attached to the task. Capped at 500 chars
|
|
30522
30558
|
* (Meta's primary-text limit). */
|
|
30523
|
-
primaryText:
|
|
30559
|
+
primaryText: z124.string().trim().min(1).max(500).optional(),
|
|
30524
30560
|
/** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
|
|
30525
30561
|
* (wa.me) instead of a landing page. */
|
|
30526
|
-
phoneNumber:
|
|
30562
|
+
phoneNumber: z124.string().min(8).max(32).optional()
|
|
30527
30563
|
});
|
|
30528
|
-
var GroupedTaskSource =
|
|
30529
|
-
type:
|
|
30530
|
-
taskId:
|
|
30531
|
-
angleIndex:
|
|
30532
|
-
videoVariant:
|
|
30564
|
+
var GroupedTaskSource = z124.object({
|
|
30565
|
+
type: z124.literal("task"),
|
|
30566
|
+
taskId: z124.string().min(1),
|
|
30567
|
+
angleIndex: z124.number().int().min(0).optional(),
|
|
30568
|
+
videoVariant: z124.enum([
|
|
30533
30569
|
"with_subtitles",
|
|
30534
30570
|
"without_subtitles"
|
|
30535
30571
|
]).optional(),
|
|
30536
|
-
imageVariantIndex:
|
|
30537
|
-
});
|
|
30538
|
-
var GroupedMediaSource =
|
|
30539
|
-
type:
|
|
30540
|
-
url:
|
|
30541
|
-
path:
|
|
30542
|
-
thumbnailUrl:
|
|
30543
|
-
thumbnailPath:
|
|
30572
|
+
imageVariantIndex: z124.number().int().min(0).optional()
|
|
30573
|
+
});
|
|
30574
|
+
var GroupedMediaSource = z124.object({
|
|
30575
|
+
type: z124.literal("media"),
|
|
30576
|
+
url: z124.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
|
|
30577
|
+
path: z124.string().min(1).optional().describe('Local file path only when this MCP runs over stdio. On the hosted MCP, call request_media_upload and then use source.type="asset".'),
|
|
30578
|
+
thumbnailUrl: z124.string().url().optional(),
|
|
30579
|
+
thumbnailPath: z124.string().min(1).optional()
|
|
30544
30580
|
}).refine((value) => Boolean(value.url) !== Boolean(value.path), {
|
|
30545
30581
|
message: "media source needs exactly one of `url` or `path`"
|
|
30546
30582
|
}).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
|
|
30547
30583
|
message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
|
|
30548
30584
|
});
|
|
30549
|
-
var GroupedUploadedAssetSource =
|
|
30550
|
-
type:
|
|
30585
|
+
var GroupedUploadedAssetSource = z124.object({
|
|
30586
|
+
type: z124.literal("asset"),
|
|
30551
30587
|
/** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
|
|
30552
|
-
assetId:
|
|
30553
|
-
thumbnailAssetId:
|
|
30588
|
+
assetId: z124.string().uuid(),
|
|
30589
|
+
thumbnailAssetId: z124.string().uuid().optional()
|
|
30554
30590
|
});
|
|
30555
|
-
var GroupedCreative =
|
|
30556
|
-
type:
|
|
30591
|
+
var GroupedCreative = z124.object({
|
|
30592
|
+
type: z124.enum([
|
|
30557
30593
|
"image",
|
|
30558
30594
|
"video"
|
|
30559
30595
|
]),
|
|
30560
|
-
source:
|
|
30596
|
+
source: z124.union([
|
|
30561
30597
|
GroupedTaskSource,
|
|
30562
30598
|
GroupedMediaSource,
|
|
30563
30599
|
GroupedUploadedAssetSource
|
|
30564
30600
|
]),
|
|
30565
|
-
title:
|
|
30566
|
-
description:
|
|
30601
|
+
title: z124.string().max(120).optional(),
|
|
30602
|
+
description: z124.string().max(500).optional(),
|
|
30567
30603
|
cta: MetaCtaType.optional(),
|
|
30568
|
-
creativeId:
|
|
30604
|
+
creativeId: z124.string().min(1).optional()
|
|
30569
30605
|
});
|
|
30570
|
-
var GroupedCampaignConfigBase =
|
|
30606
|
+
var GroupedCampaignConfigBase = z124.object({
|
|
30571
30607
|
campaignType: MetaCampaignType.default("sales"),
|
|
30572
30608
|
optimizationMode: MetaOptimizationMode.default("advantage_plus"),
|
|
30573
30609
|
budgetMode: MetaBudgetMode.optional(),
|
|
30574
|
-
campaignDailyBudget:
|
|
30575
|
-
adSets:
|
|
30576
|
-
tempId:
|
|
30577
|
-
name:
|
|
30578
|
-
dailyBudget:
|
|
30579
|
-
creativeIds:
|
|
30610
|
+
campaignDailyBudget: z124.number().int().positive().optional(),
|
|
30611
|
+
adSets: z124.array(z124.object({
|
|
30612
|
+
tempId: z124.string().min(1).max(80),
|
|
30613
|
+
name: z124.string().min(1).max(100),
|
|
30614
|
+
dailyBudget: z124.number().int().positive().optional(),
|
|
30615
|
+
creativeIds: z124.array(z124.string().min(1)).min(1)
|
|
30580
30616
|
})).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
|
|
30581
30617
|
/**
|
|
30582
30618
|
* Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
|
|
@@ -30584,17 +30620,17 @@ var GroupedCampaignConfigBase = z123.object({
|
|
|
30584
30620
|
* opaque `invalid_literal` and made the WhatsApp destination — supported by
|
|
30585
30621
|
* the API since #849 — unreachable from this tool.
|
|
30586
30622
|
*/
|
|
30587
|
-
destination:
|
|
30588
|
-
|
|
30589
|
-
type:
|
|
30590
|
-
landingUrl:
|
|
30623
|
+
destination: z124.discriminatedUnion("type", [
|
|
30624
|
+
z124.object({
|
|
30625
|
+
type: z124.literal("landing"),
|
|
30626
|
+
landingUrl: z124.string().url()
|
|
30591
30627
|
}),
|
|
30592
|
-
|
|
30593
|
-
type:
|
|
30594
|
-
phoneNumber:
|
|
30628
|
+
z124.object({
|
|
30629
|
+
type: z124.literal("whatsapp"),
|
|
30630
|
+
phoneNumber: z124.string().min(8).max(32)
|
|
30595
30631
|
})
|
|
30596
30632
|
]),
|
|
30597
|
-
saveAsDefault:
|
|
30633
|
+
saveAsDefault: z124.boolean().default(false),
|
|
30598
30634
|
budgetPolicy: MetaBudgetPolicy.optional()
|
|
30599
30635
|
});
|
|
30600
30636
|
function resolveBudgetMode(value) {
|
|
@@ -30608,7 +30644,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
30608
30644
|
const budgetMode = resolveBudgetMode(value);
|
|
30609
30645
|
if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
|
|
30610
30646
|
ctx.addIssue({
|
|
30611
|
-
code:
|
|
30647
|
+
code: z124.ZodIssueCode.custom,
|
|
30612
30648
|
path: [
|
|
30613
30649
|
"campaignDailyBudget"
|
|
30614
30650
|
],
|
|
@@ -30619,7 +30655,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
30619
30655
|
value.adSets.forEach((adSet, index) => {
|
|
30620
30656
|
if (adSet.dailyBudget === void 0) {
|
|
30621
30657
|
ctx.addIssue({
|
|
30622
|
-
code:
|
|
30658
|
+
code: z124.ZodIssueCode.custom,
|
|
30623
30659
|
path: [
|
|
30624
30660
|
"adSets",
|
|
30625
30661
|
index,
|
|
@@ -30634,28 +30670,33 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
30634
30670
|
...value,
|
|
30635
30671
|
budgetMode: resolveBudgetMode(value)
|
|
30636
30672
|
}));
|
|
30637
|
-
var PublishCreativesToMetaInputBase =
|
|
30638
|
-
creatives:
|
|
30673
|
+
var PublishCreativesToMetaInputBase = z124.object({
|
|
30674
|
+
creatives: z124.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
|
|
30639
30675
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
30640
|
-
portfolioId:
|
|
30676
|
+
portfolioId: z124.string().trim().min(1),
|
|
30641
30677
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
30642
|
-
pageId:
|
|
30678
|
+
pageId: z124.string().trim().min(1),
|
|
30643
30679
|
adAccountId: McpAdAccountId,
|
|
30644
|
-
pixelId:
|
|
30645
|
-
/** Required unless `campaignConfig.destination` is whatsapp
|
|
30646
|
-
*
|
|
30647
|
-
|
|
30680
|
+
pixelId: z124.string().min(1).optional(),
|
|
30681
|
+
/** Required unless `campaignConfig.destination` is whatsapp or a creative
|
|
30682
|
+
* comes from a task (the API then lands on the published service landing
|
|
30683
|
+
* of its service tasks) — see the superRefine below. Mirrors the API's
|
|
30684
|
+
* `FacebookCreateCampaignFromTasksBodySchema`. */
|
|
30685
|
+
landingUrl: z124.string().url().optional(),
|
|
30648
30686
|
/** ISO-2 code or resolvable country name — mirrors the API contract
|
|
30649
|
-
* (CountryIso2Schema), which normalizes names to alpha-2 at validation.
|
|
30650
|
-
|
|
30651
|
-
|
|
30687
|
+
* (CountryIso2Schema), which normalizes names to alpha-2 at validation.
|
|
30688
|
+
* Omitted: the brand country of its service tasks (the API answers
|
|
30689
|
+
* META_NO_TARGET_COUNTRY when it has none); "US" for products. */
|
|
30690
|
+
targetCountry: CountryIso2Schema.optional(),
|
|
30691
|
+
campaignName: z124.string().trim().min(1).max(100),
|
|
30652
30692
|
campaignConfig: GroupedCampaignConfig.optional()
|
|
30653
30693
|
});
|
|
30654
30694
|
var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
|
|
30655
30695
|
const destination = value.campaignConfig?.destination;
|
|
30656
|
-
|
|
30696
|
+
const hasTaskCreative = value.creatives.some((creative) => creative.source.type === "task");
|
|
30697
|
+
if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl && !hasTaskCreative) {
|
|
30657
30698
|
ctx.addIssue({
|
|
30658
|
-
code:
|
|
30699
|
+
code: z124.ZodIssueCode.custom,
|
|
30659
30700
|
path: [
|
|
30660
30701
|
"landingUrl"
|
|
30661
30702
|
],
|
|
@@ -30664,7 +30705,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
30664
30705
|
}
|
|
30665
30706
|
if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
|
|
30666
30707
|
ctx.addIssue({
|
|
30667
|
-
code:
|
|
30708
|
+
code: z124.ZodIssueCode.custom,
|
|
30668
30709
|
path: [
|
|
30669
30710
|
"campaignConfig",
|
|
30670
30711
|
"destination",
|
|
@@ -30683,16 +30724,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
30683
30724
|
}
|
|
30684
30725
|
return value;
|
|
30685
30726
|
});
|
|
30686
|
-
var PresignUploadResponseSchema =
|
|
30687
|
-
uploadUrl:
|
|
30727
|
+
var PresignUploadResponseSchema = z124.object({
|
|
30728
|
+
uploadUrl: z124.string().url().refine((value) => {
|
|
30688
30729
|
const url = new URL(value);
|
|
30689
30730
|
return !url.username && !url.password && url.protocol === "https:";
|
|
30690
30731
|
}, "presigned upload URL must be HTTPS without embedded credentials"),
|
|
30691
|
-
publicUrl:
|
|
30732
|
+
publicUrl: z124.string().url().refine((value) => {
|
|
30692
30733
|
const url = new URL(value);
|
|
30693
30734
|
return !url.username && !url.password;
|
|
30694
30735
|
}, "public media URL must not contain embedded credentials"),
|
|
30695
|
-
stagingAssetId:
|
|
30736
|
+
stagingAssetId: z124.string().uuid()
|
|
30696
30737
|
});
|
|
30697
30738
|
async function uploadResolvedMedia(api, media, assetRole) {
|
|
30698
30739
|
if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
|
|
@@ -30717,16 +30758,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
|
|
|
30717
30758
|
return uploadResolvedMedia(api, media, assetRole);
|
|
30718
30759
|
}
|
|
30719
30760
|
__name(resolveAndUploadMedia, "resolveAndUploadMedia");
|
|
30720
|
-
var TikTokInput =
|
|
30721
|
-
taskId:
|
|
30722
|
-
advertiserId:
|
|
30723
|
-
pixelId:
|
|
30724
|
-
landingUrl:
|
|
30725
|
-
angleIndexes:
|
|
30761
|
+
var TikTokInput = z124.object({
|
|
30762
|
+
taskId: z124.string().min(1),
|
|
30763
|
+
advertiserId: z124.string().min(1),
|
|
30764
|
+
pixelId: z124.string().min(1).optional(),
|
|
30765
|
+
landingUrl: z124.string().url().optional(),
|
|
30766
|
+
angleIndexes: z124.array(z124.number().int().nonnegative()).optional(),
|
|
30726
30767
|
campaignConfig: McpCampaignConfig.optional(),
|
|
30727
30768
|
/** Override the ad's description (TikTok's body copy). If omitted,
|
|
30728
30769
|
* ProductMaker uses the auto-generated copy attached to the task. */
|
|
30729
|
-
primaryText:
|
|
30770
|
+
primaryText: z124.string().trim().min(1).max(500).optional()
|
|
30730
30771
|
});
|
|
30731
30772
|
function registerPublishTools(server, api, opts = {}) {
|
|
30732
30773
|
const transport = opts.transport ?? "http";
|
|
@@ -30848,7 +30889,7 @@ function registerPublishTools(server, api, opts = {}) {
|
|
|
30848
30889
|
}
|
|
30849
30890
|
});
|
|
30850
30891
|
server.registerTool("publish_creatives_to_meta", {
|
|
30851
|
-
description: 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.',
|
|
30892
|
+
description: 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. Con creativos de tarea de servicio puedes omitir `landingUrl` y `targetCountry`: se usan su landing de servicio publicada y el pa\xEDs de su marca; si falta alguno, pregunta al usuario (nunca asumas un pa\xEDs). 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.',
|
|
30852
30893
|
inputSchema: PublishCreativesToMetaInputBase.shape,
|
|
30853
30894
|
annotations: CREATES_EXTERNAL
|
|
30854
30895
|
}, async (rawInput, extra) => {
|
|
@@ -31078,39 +31119,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
|
|
|
31078
31119
|
|
|
31079
31120
|
// src/tools/meta-upload.ts
|
|
31080
31121
|
import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
|
|
31081
|
-
import { z as
|
|
31122
|
+
import { z as z125 } from "zod";
|
|
31082
31123
|
var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
|
|
31083
|
-
var UploadSessionInputBase =
|
|
31084
|
-
mediaKind:
|
|
31124
|
+
var UploadSessionInputBase = z125.object({
|
|
31125
|
+
mediaKind: z125.enum([
|
|
31085
31126
|
"image",
|
|
31086
31127
|
"video",
|
|
31087
31128
|
"mixed"
|
|
31088
31129
|
]).default("mixed").describe("The kind of file the user will select. Use image for product references and landing pages, video for a single video, and mixed only when the consumer supports both."),
|
|
31089
|
-
assetRole:
|
|
31130
|
+
assetRole: z125.enum([
|
|
31090
31131
|
"media",
|
|
31091
31132
|
"thumbnail"
|
|
31092
31133
|
]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
|
|
31093
|
-
uploadPurpose:
|
|
31134
|
+
uploadPurpose: z125.enum([
|
|
31094
31135
|
"product_reference",
|
|
31095
31136
|
"creative",
|
|
31096
31137
|
"generic"
|
|
31097
31138
|
]).default("generic").describe("The user's purpose for these files. Use product_reference for a product photo used by tasks or landings, creative for media that will become an ad or creative, and generic only when neither applies."),
|
|
31098
|
-
maxFiles:
|
|
31139
|
+
maxFiles: z125.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
|
|
31099
31140
|
});
|
|
31100
|
-
var OpenAiFileReference =
|
|
31101
|
-
download_url:
|
|
31102
|
-
file_id:
|
|
31103
|
-
mime_type:
|
|
31104
|
-
file_name:
|
|
31141
|
+
var OpenAiFileReference = z125.object({
|
|
31142
|
+
download_url: z125.string().url().describe("Required by ChatGPT's openai/fileParams schema. The App prefers getFileDownloadUrl(file_id) for a fresh URL, and the server never fetches this value."),
|
|
31143
|
+
file_id: z125.string().min(1),
|
|
31144
|
+
mime_type: z125.string().min(1).optional(),
|
|
31145
|
+
file_name: z125.string().min(1).optional()
|
|
31105
31146
|
});
|
|
31106
31147
|
var UploadSessionToolInputShape = {
|
|
31107
31148
|
...UploadSessionInputBase.shape,
|
|
31108
|
-
files:
|
|
31149
|
+
files: z125.array(OpenAiFileReference).max(10).optional().describe("Optional OpenAI-hosted file references provided by ChatGPT. They are only metadata for the UI bridge and are never forwarded to ProductMaker.")
|
|
31109
31150
|
};
|
|
31110
|
-
var UploadSessionToolInput =
|
|
31151
|
+
var UploadSessionToolInput = z125.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
|
|
31111
31152
|
if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
|
|
31112
31153
|
ctx.addIssue({
|
|
31113
|
-
code:
|
|
31154
|
+
code: z125.ZodIssueCode.custom,
|
|
31114
31155
|
path: [
|
|
31115
31156
|
"mediaKind"
|
|
31116
31157
|
],
|
|
@@ -31119,7 +31160,7 @@ var UploadSessionToolInput = z124.object(UploadSessionToolInputShape).superRefin
|
|
|
31119
31160
|
}
|
|
31120
31161
|
if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
|
|
31121
31162
|
ctx.addIssue({
|
|
31122
|
-
code:
|
|
31163
|
+
code: z125.ZodIssueCode.custom,
|
|
31123
31164
|
path: [
|
|
31124
31165
|
"maxFiles"
|
|
31125
31166
|
],
|
|
@@ -31128,7 +31169,7 @@ var UploadSessionToolInput = z124.object(UploadSessionToolInputShape).superRefin
|
|
|
31128
31169
|
}
|
|
31129
31170
|
if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
|
|
31130
31171
|
ctx.addIssue({
|
|
31131
|
-
code:
|
|
31172
|
+
code: z125.ZodIssueCode.custom,
|
|
31132
31173
|
path: [
|
|
31133
31174
|
"maxFiles"
|
|
31134
31175
|
],
|
|
@@ -31136,38 +31177,38 @@ var UploadSessionToolInput = z124.object(UploadSessionToolInputShape).superRefin
|
|
|
31136
31177
|
});
|
|
31137
31178
|
}
|
|
31138
31179
|
});
|
|
31139
|
-
var UploadSessionResponse =
|
|
31140
|
-
sessionId:
|
|
31141
|
-
uploadPageUrl:
|
|
31142
|
-
mediaKind:
|
|
31180
|
+
var UploadSessionResponse = z125.object({
|
|
31181
|
+
sessionId: z125.string().uuid(),
|
|
31182
|
+
uploadPageUrl: z125.string().url(),
|
|
31183
|
+
mediaKind: z125.enum([
|
|
31143
31184
|
"image",
|
|
31144
31185
|
"video",
|
|
31145
31186
|
"mixed"
|
|
31146
31187
|
]),
|
|
31147
|
-
assetRole:
|
|
31188
|
+
assetRole: z125.enum([
|
|
31148
31189
|
"media",
|
|
31149
31190
|
"thumbnail"
|
|
31150
31191
|
]),
|
|
31151
|
-
maxFiles:
|
|
31152
|
-
expiresAt:
|
|
31192
|
+
maxFiles: z125.number().int().positive(),
|
|
31193
|
+
expiresAt: z125.string().datetime()
|
|
31153
31194
|
});
|
|
31154
|
-
var UploadStatusInput =
|
|
31155
|
-
sessionId:
|
|
31195
|
+
var UploadStatusInput = z125.object({
|
|
31196
|
+
sessionId: z125.string().uuid().describe("The sessionId returned by request_media_upload.")
|
|
31156
31197
|
});
|
|
31157
|
-
var UniversalUploadStatusResponse =
|
|
31158
|
-
|
|
31159
|
-
status:
|
|
31160
|
-
assets:
|
|
31198
|
+
var UniversalUploadStatusResponse = z125.discriminatedUnion("status", [
|
|
31199
|
+
z125.object({
|
|
31200
|
+
status: z125.literal("pending"),
|
|
31201
|
+
assets: z125.array(z125.never()).length(0)
|
|
31161
31202
|
}),
|
|
31162
|
-
|
|
31163
|
-
status:
|
|
31164
|
-
assets:
|
|
31165
|
-
assetId:
|
|
31166
|
-
mediaKind:
|
|
31203
|
+
z125.object({
|
|
31204
|
+
status: z125.literal("uploaded"),
|
|
31205
|
+
assets: z125.array(z125.object({
|
|
31206
|
+
assetId: z125.string().uuid(),
|
|
31207
|
+
mediaKind: z125.enum([
|
|
31167
31208
|
"image",
|
|
31168
31209
|
"video"
|
|
31169
31210
|
]),
|
|
31170
|
-
assetRole:
|
|
31211
|
+
assetRole: z125.enum([
|
|
31171
31212
|
"media",
|
|
31172
31213
|
"thumbnail"
|
|
31173
31214
|
])
|
|
@@ -31175,13 +31216,13 @@ var UniversalUploadStatusResponse = z124.discriminatedUnion("status", [
|
|
|
31175
31216
|
})
|
|
31176
31217
|
]);
|
|
31177
31218
|
var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
|
|
31178
|
-
uploadPurpose:
|
|
31219
|
+
uploadPurpose: z125.enum([
|
|
31179
31220
|
"product_reference",
|
|
31180
31221
|
"creative",
|
|
31181
31222
|
"generic"
|
|
31182
31223
|
]),
|
|
31183
|
-
checkToolName:
|
|
31184
|
-
resolveEndpoint:
|
|
31224
|
+
checkToolName: z125.literal("check_media_upload"),
|
|
31225
|
+
resolveEndpoint: z125.string().url()
|
|
31185
31226
|
});
|
|
31186
31227
|
function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
|
|
31187
31228
|
const url = new URL(uploadPageUrl);
|
|
@@ -31272,15 +31313,15 @@ function registerMediaUploadTools(server, api) {
|
|
|
31272
31313
|
__name(registerMediaUploadTools, "registerMediaUploadTools");
|
|
31273
31314
|
|
|
31274
31315
|
// src/tools/campaigns.ts
|
|
31275
|
-
import { z as
|
|
31316
|
+
import { z as z126 } from "zod";
|
|
31276
31317
|
var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
|
|
31277
31318
|
var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
|
|
31278
|
-
var MetaStatusInput =
|
|
31279
|
-
campaignId:
|
|
31319
|
+
var MetaStatusInput = z126.object({
|
|
31320
|
+
campaignId: z126.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
|
|
31280
31321
|
});
|
|
31281
|
-
var TikTokStatusInput =
|
|
31282
|
-
campaignId:
|
|
31283
|
-
advertiserId:
|
|
31322
|
+
var TikTokStatusInput = z126.object({
|
|
31323
|
+
campaignId: z126.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
|
|
31324
|
+
advertiserId: z126.string().min(1).describe("The same advertiserId used to publish the campaign.")
|
|
31284
31325
|
});
|
|
31285
31326
|
function registerCampaignTools(server, api) {
|
|
31286
31327
|
server.registerTool("get_meta_campaign_status", {
|
|
@@ -31385,10 +31426,10 @@ function renderTikTokStatusMarkdown(r) {
|
|
|
31385
31426
|
__name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
|
|
31386
31427
|
|
|
31387
31428
|
// ../../packages/product-economics/src/product-costing.ts
|
|
31388
|
-
import { z as
|
|
31429
|
+
import { z as z128 } from "zod";
|
|
31389
31430
|
|
|
31390
31431
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
31391
|
-
import { z as
|
|
31432
|
+
import { z as z127 } from "zod";
|
|
31392
31433
|
|
|
31393
31434
|
// ../../packages/product-economics/src/product-costing-shipping-references.json
|
|
31394
31435
|
var product_costing_shipping_references_default = {
|
|
@@ -31452,21 +31493,21 @@ var product_costing_shipping_references_default = {
|
|
|
31452
31493
|
};
|
|
31453
31494
|
|
|
31454
31495
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
31455
|
-
var ShippingReferenceSchema =
|
|
31456
|
-
reference:
|
|
31457
|
-
min:
|
|
31458
|
-
max:
|
|
31459
|
-
updatedAt:
|
|
31460
|
-
confidence:
|
|
31496
|
+
var ShippingReferenceSchema = z127.object({
|
|
31497
|
+
reference: z127.number().positive(),
|
|
31498
|
+
min: z127.number().nonnegative(),
|
|
31499
|
+
max: z127.number().positive(),
|
|
31500
|
+
updatedAt: z127.string().date(),
|
|
31501
|
+
confidence: z127.enum([
|
|
31461
31502
|
"high",
|
|
31462
31503
|
"medium",
|
|
31463
31504
|
"medium-low"
|
|
31464
31505
|
]),
|
|
31465
|
-
sources:
|
|
31506
|
+
sources: z127.array(z127.string().url().startsWith("https://")).min(1).max(3)
|
|
31466
31507
|
}).superRefine(({ reference, min, max }, context) => {
|
|
31467
31508
|
if (min > reference || reference > max) {
|
|
31468
31509
|
context.addIssue({
|
|
31469
|
-
code:
|
|
31510
|
+
code: z127.ZodIssueCode.custom,
|
|
31470
31511
|
message: "shipping_reference_outside_range",
|
|
31471
31512
|
path: [
|
|
31472
31513
|
"reference"
|
|
@@ -31474,7 +31515,7 @@ var ShippingReferenceSchema = z126.object({
|
|
|
31474
31515
|
});
|
|
31475
31516
|
}
|
|
31476
31517
|
});
|
|
31477
|
-
var SHIPPING_REFERENCES =
|
|
31518
|
+
var SHIPPING_REFERENCES = z127.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
|
|
31478
31519
|
var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
|
|
31479
31520
|
var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
|
|
31480
31521
|
"MX",
|
|
@@ -31656,18 +31697,18 @@ function getProductCostingCountryName(country) {
|
|
|
31656
31697
|
__name(getProductCostingCountryName, "getProductCostingCountryName");
|
|
31657
31698
|
|
|
31658
31699
|
// ../../packages/product-economics/src/product-costing.ts
|
|
31659
|
-
var ProductCostingInputSchema =
|
|
31660
|
-
country:
|
|
31661
|
-
supplierCost:
|
|
31662
|
-
shippingCost:
|
|
31663
|
-
returnRate:
|
|
31664
|
-
cancellationRate:
|
|
31665
|
-
adsManagerCpa:
|
|
31666
|
-
desiredMargin:
|
|
31700
|
+
var ProductCostingInputSchema = z128.object({
|
|
31701
|
+
country: z128.string().refine(isProductCostingCountryCode, "unsupported_country"),
|
|
31702
|
+
supplierCost: z128.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
|
|
31703
|
+
shippingCost: z128.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
|
|
31704
|
+
returnRate: z128.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
31705
|
+
cancellationRate: z128.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
31706
|
+
adsManagerCpa: z128.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
|
|
31707
|
+
desiredMargin: z128.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
|
|
31667
31708
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
31668
31709
|
if (returnRate + cancellationRate >= 1) {
|
|
31669
31710
|
context.addIssue({
|
|
31670
|
-
code:
|
|
31711
|
+
code: z128.ZodIssueCode.custom,
|
|
31671
31712
|
message: "delivery_rate_positive",
|
|
31672
31713
|
path: [
|
|
31673
31714
|
"cancellationRate"
|
|
@@ -31764,15 +31805,15 @@ function calculateProductCosting(rawInput) {
|
|
|
31764
31805
|
__name(calculateProductCosting, "calculateProductCosting");
|
|
31765
31806
|
|
|
31766
31807
|
// src/tools/product-costing.ts
|
|
31767
|
-
import { z as
|
|
31808
|
+
import { z as z129 } from "zod";
|
|
31768
31809
|
var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
|
|
31769
|
-
var optionalAmount = /* @__PURE__ */ __name((description) =>
|
|
31770
|
-
var optionalPercent = /* @__PURE__ */ __name((description) =>
|
|
31771
|
-
var ProductCostingToolInput =
|
|
31772
|
-
country:
|
|
31810
|
+
var optionalAmount = /* @__PURE__ */ __name((description) => z129.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
|
|
31811
|
+
var optionalPercent = /* @__PURE__ */ __name((description) => z129.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
|
|
31812
|
+
var ProductCostingToolInput = z129.object({
|
|
31813
|
+
country: z129.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
|
|
31773
31814
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
31774
31815
|
}).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
|
|
31775
|
-
supplierCost:
|
|
31816
|
+
supplierCost: z129.number().finite().max(Number.MAX_SAFE_INTEGER).positive().optional().describe("Costo real de una unidad con el proveedor, en la moneda del pa\xEDs. Requerido salvo que uses supplierCostCop para Colombia."),
|
|
31776
31817
|
supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
|
|
31777
31818
|
shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
|
|
31778
31819
|
shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
|
|
@@ -31935,7 +31976,7 @@ function formatPercent(value) {
|
|
|
31935
31976
|
__name(formatPercent, "formatPercent");
|
|
31936
31977
|
|
|
31937
31978
|
// src/tools/product-research.ts
|
|
31938
|
-
import { z as
|
|
31979
|
+
import { z as z130 } from "zod";
|
|
31939
31980
|
|
|
31940
31981
|
// src/tools/product-research-idempotency.ts
|
|
31941
31982
|
var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
|
|
@@ -32306,17 +32347,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
|
|
|
32306
32347
|
]);
|
|
32307
32348
|
var POLL_INTERVAL_MS = 5e3;
|
|
32308
32349
|
var MAX_WAIT_SECONDS = 120;
|
|
32309
|
-
var FindInput =
|
|
32350
|
+
var FindInput = z130.object({
|
|
32310
32351
|
targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
|
|
32311
32352
|
categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
|
|
32312
|
-
confirmed:
|
|
32313
|
-
waitSeconds:
|
|
32353
|
+
confirmed: z130.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
|
|
32354
|
+
waitSeconds: z130.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
|
|
32314
32355
|
});
|
|
32315
|
-
var GetInput =
|
|
32316
|
-
runId:
|
|
32356
|
+
var GetInput = z130.object({
|
|
32357
|
+
runId: z130.string().uuid().describe("ID del run devuelto por find_winning_products.")
|
|
32317
32358
|
});
|
|
32318
|
-
var ListInput =
|
|
32319
|
-
limit:
|
|
32359
|
+
var ListInput = z130.object({
|
|
32360
|
+
limit: z130.number().int().min(1).max(20).default(10)
|
|
32320
32361
|
});
|
|
32321
32362
|
function textResult(text2) {
|
|
32322
32363
|
return {
|
|
@@ -32455,17 +32496,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
|
|
|
32455
32496
|
__name(registerProductResearchTools, "registerProductResearchTools");
|
|
32456
32497
|
|
|
32457
32498
|
// src/tools/dropshipping-projects.ts
|
|
32458
|
-
import { z as
|
|
32499
|
+
import { z as z131 } from "zod";
|
|
32459
32500
|
var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
|
|
32460
32501
|
var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
|
|
32461
32502
|
var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
|
|
32462
|
-
var ProjectId =
|
|
32463
|
-
var DropshippingProjectStatus =
|
|
32503
|
+
var ProjectId = z131.string().uuid();
|
|
32504
|
+
var DropshippingProjectStatus = z131.enum([
|
|
32464
32505
|
"active",
|
|
32465
32506
|
"completed",
|
|
32466
32507
|
"archived"
|
|
32467
32508
|
]);
|
|
32468
|
-
var DropshippingProjectPhase =
|
|
32509
|
+
var DropshippingProjectPhase = z131.enum([
|
|
32469
32510
|
"research",
|
|
32470
32511
|
"costing",
|
|
32471
32512
|
"media",
|
|
@@ -32474,21 +32515,21 @@ var DropshippingProjectPhase = z130.enum([
|
|
|
32474
32515
|
"advertising",
|
|
32475
32516
|
"complete"
|
|
32476
32517
|
]);
|
|
32477
|
-
var DropshippingRewardMilestone =
|
|
32518
|
+
var DropshippingRewardMilestone = z131.enum([
|
|
32478
32519
|
"product_selected",
|
|
32479
32520
|
"costing_saved",
|
|
32480
32521
|
"product_media_ready",
|
|
32481
32522
|
"creatives_completed",
|
|
32482
32523
|
"campaign_created"
|
|
32483
32524
|
]);
|
|
32484
|
-
var TargetCountry =
|
|
32525
|
+
var TargetCountry = z131.enum([
|
|
32485
32526
|
"CO",
|
|
32486
32527
|
"MX",
|
|
32487
32528
|
"PE",
|
|
32488
32529
|
"EC",
|
|
32489
32530
|
"CL"
|
|
32490
32531
|
]);
|
|
32491
|
-
var ResearchCategory =
|
|
32532
|
+
var ResearchCategory = z131.enum([
|
|
32492
32533
|
"auto",
|
|
32493
32534
|
"automotive",
|
|
32494
32535
|
"kitchen",
|
|
@@ -32503,7 +32544,7 @@ var ResearchCategory = z130.enum([
|
|
|
32503
32544
|
"garden",
|
|
32504
32545
|
"cleaning"
|
|
32505
32546
|
]);
|
|
32506
|
-
var HttpUrl3 =
|
|
32547
|
+
var HttpUrl3 = z131.string().url().max(2e3).refine((value) => {
|
|
32507
32548
|
try {
|
|
32508
32549
|
return [
|
|
32509
32550
|
"http:",
|
|
@@ -32513,45 +32554,45 @@ var HttpUrl3 = z130.string().url().max(2e3).refine((value) => {
|
|
|
32513
32554
|
return false;
|
|
32514
32555
|
}
|
|
32515
32556
|
}, "URL must use HTTP(S)");
|
|
32516
|
-
var ResearchCandidateOrigin =
|
|
32517
|
-
type:
|
|
32557
|
+
var ResearchCandidateOrigin = z131.object({
|
|
32558
|
+
type: z131.literal("research_candidate"),
|
|
32518
32559
|
runId: ProjectId,
|
|
32519
|
-
candidateSourceId:
|
|
32560
|
+
candidateSourceId: z131.string().min(1).max(160)
|
|
32520
32561
|
});
|
|
32521
|
-
var TaskOrigin =
|
|
32522
|
-
type:
|
|
32562
|
+
var TaskOrigin = z131.object({
|
|
32563
|
+
type: z131.literal("task"),
|
|
32523
32564
|
taskId: ProjectId
|
|
32524
32565
|
});
|
|
32525
|
-
var ManualOrigin =
|
|
32526
|
-
type:
|
|
32566
|
+
var ManualOrigin = z131.object({
|
|
32567
|
+
type: z131.literal("manual"),
|
|
32527
32568
|
clientRequestId: ProjectId,
|
|
32528
|
-
country:
|
|
32569
|
+
country: z131.string().min(2).max(3).optional()
|
|
32529
32570
|
});
|
|
32530
|
-
var StartProjectInput =
|
|
32531
|
-
origin:
|
|
32571
|
+
var StartProjectInput = z131.object({
|
|
32572
|
+
origin: z131.discriminatedUnion("type", [
|
|
32532
32573
|
ResearchCandidateOrigin,
|
|
32533
32574
|
TaskOrigin,
|
|
32534
32575
|
ManualOrigin
|
|
32535
32576
|
]),
|
|
32536
|
-
productName:
|
|
32577
|
+
productName: z131.string().trim().min(1).max(240).optional(),
|
|
32537
32578
|
productUrl: HttpUrl3.optional(),
|
|
32538
|
-
country:
|
|
32539
|
-
languageCode:
|
|
32579
|
+
country: z131.string().min(2).max(3).optional(),
|
|
32580
|
+
languageCode: z131.string().min(2).max(16).optional()
|
|
32540
32581
|
}).strict();
|
|
32541
|
-
var CostProjectInput =
|
|
32582
|
+
var CostProjectInput = z131.object({
|
|
32542
32583
|
projectId: ProjectId,
|
|
32543
|
-
version:
|
|
32544
|
-
country:
|
|
32584
|
+
version: z131.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
|
|
32585
|
+
country: z131.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
|
|
32545
32586
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
32546
32587
|
}).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
|
|
32547
|
-
supplierCost:
|
|
32548
|
-
shippingCost:
|
|
32549
|
-
returnRate:
|
|
32550
|
-
cancellationRate:
|
|
32551
|
-
adsManagerCpa:
|
|
32552
|
-
desiredMargin:
|
|
32553
|
-
});
|
|
32554
|
-
var GuideInput =
|
|
32588
|
+
supplierCost: z131.number().finite().positive().describe("Costo real de una unidad con el proveedor, en la moneda del pa\xEDs. \xDANICO dato que debes pedirle al usuario: nunca lo inventes."),
|
|
32589
|
+
shippingCost: z131.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
|
|
32590
|
+
returnRate: z131.number().finite().min(0).lt(1).optional().describe("Fracci\xF3n de pedidos devueltos (0.25 = 25%). Omite para usar el valor gu\xEDa del pa\xEDs."),
|
|
32591
|
+
cancellationRate: z131.number().finite().min(0).lt(1).optional().describe("Fracci\xF3n de pedidos cancelados (0.15 = 15%). Omite para usar el valor gu\xEDa del pa\xEDs."),
|
|
32592
|
+
adsManagerCpa: z131.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
|
|
32593
|
+
desiredMargin: z131.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
|
|
32594
|
+
});
|
|
32595
|
+
var GuideInput = z131.object({
|
|
32555
32596
|
projectId: ProjectId.optional()
|
|
32556
32597
|
}).strict();
|
|
32557
32598
|
var NEXT_ACTION_KINDS = [
|
|
@@ -32569,29 +32610,29 @@ var NEXT_ACTION_KINDS = [
|
|
|
32569
32610
|
"repair_meta_campaign",
|
|
32570
32611
|
"review_paused_campaign"
|
|
32571
32612
|
];
|
|
32572
|
-
var DropshippingProjectNextAction =
|
|
32573
|
-
kind:
|
|
32574
|
-
href:
|
|
32613
|
+
var DropshippingProjectNextAction = z131.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z131.object({
|
|
32614
|
+
kind: z131.literal(kind),
|
|
32615
|
+
href: z131.string().min(1)
|
|
32575
32616
|
})));
|
|
32576
|
-
var CostingInputSchema =
|
|
32577
|
-
country:
|
|
32578
|
-
supplierCost:
|
|
32579
|
-
shippingCost:
|
|
32580
|
-
returnRate:
|
|
32581
|
-
cancellationRate:
|
|
32582
|
-
adsManagerCpa:
|
|
32583
|
-
desiredMargin:
|
|
32617
|
+
var CostingInputSchema = z131.object({
|
|
32618
|
+
country: z131.string().min(2).max(3),
|
|
32619
|
+
supplierCost: z131.number().finite().positive(),
|
|
32620
|
+
shippingCost: z131.number().finite().nonnegative(),
|
|
32621
|
+
returnRate: z131.number().finite().min(0).lt(1),
|
|
32622
|
+
cancellationRate: z131.number().finite().min(0).lt(1),
|
|
32623
|
+
adsManagerCpa: z131.number().finite().nonnegative(),
|
|
32624
|
+
desiredMargin: z131.number().finite().min(0).lt(1)
|
|
32584
32625
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
32585
32626
|
if (returnRate + cancellationRate >= 1) context.addIssue({
|
|
32586
|
-
code:
|
|
32627
|
+
code: z131.ZodIssueCode.custom,
|
|
32587
32628
|
path: [
|
|
32588
32629
|
"cancellationRate"
|
|
32589
32630
|
]
|
|
32590
32631
|
});
|
|
32591
32632
|
});
|
|
32592
|
-
var FiniteCostingNumber =
|
|
32593
|
-
var CostingResultSchema =
|
|
32594
|
-
country:
|
|
32633
|
+
var FiniteCostingNumber = z131.number().finite();
|
|
32634
|
+
var CostingResultSchema = z131.object({
|
|
32635
|
+
country: z131.string().min(2).max(3),
|
|
32595
32636
|
deliveryRate: FiniteCostingNumber,
|
|
32596
32637
|
adjustedShippingCost: FiniteCostingNumber,
|
|
32597
32638
|
adjustedCpa: FiniteCostingNumber,
|
|
@@ -32604,45 +32645,45 @@ var CostingResultSchema = z130.object({
|
|
|
32604
32645
|
estimatedProfit: FiniteCostingNumber,
|
|
32605
32646
|
actualMargin: FiniteCostingNumber,
|
|
32606
32647
|
breakEvenAdsManagerCpa: FiniteCostingNumber,
|
|
32607
|
-
wasPriceAutoAdjusted:
|
|
32608
|
-
profitabilityStatus:
|
|
32609
|
-
});
|
|
32610
|
-
var RewardProgressSchema =
|
|
32611
|
-
campaignKey:
|
|
32612
|
-
totalCredits:
|
|
32613
|
-
earnedCredits:
|
|
32614
|
-
milestones:
|
|
32648
|
+
wasPriceAutoAdjusted: z131.boolean(),
|
|
32649
|
+
profitabilityStatus: z131.literal("healthy")
|
|
32650
|
+
});
|
|
32651
|
+
var RewardProgressSchema = z131.object({
|
|
32652
|
+
campaignKey: z131.literal("dropshipping-launch-v1"),
|
|
32653
|
+
totalCredits: z131.number().int().positive(),
|
|
32654
|
+
earnedCredits: z131.number().int().nonnegative(),
|
|
32655
|
+
milestones: z131.array(z131.object({
|
|
32615
32656
|
milestone: DropshippingRewardMilestone,
|
|
32616
|
-
credits:
|
|
32617
|
-
available:
|
|
32618
|
-
earned:
|
|
32657
|
+
credits: z131.number().int().positive(),
|
|
32658
|
+
available: z131.boolean().optional(),
|
|
32659
|
+
earned: z131.boolean(),
|
|
32619
32660
|
grantId: ProjectId.nullable(),
|
|
32620
|
-
grantedAt:
|
|
32661
|
+
grantedAt: z131.string().datetime().nullable()
|
|
32621
32662
|
})).length(DropshippingRewardMilestone.options.length)
|
|
32622
32663
|
});
|
|
32623
|
-
var ProjectResponseSchema =
|
|
32664
|
+
var ProjectResponseSchema = z131.object({
|
|
32624
32665
|
id: ProjectId,
|
|
32625
32666
|
taskId: ProjectId.nullable(),
|
|
32626
32667
|
status: DropshippingProjectStatus,
|
|
32627
|
-
originKey:
|
|
32668
|
+
originKey: z131.string().min(1),
|
|
32628
32669
|
researchRunId: ProjectId.nullable(),
|
|
32629
|
-
candidateSourceId:
|
|
32630
|
-
productName:
|
|
32670
|
+
candidateSourceId: z131.string().nullable(),
|
|
32671
|
+
productName: z131.string().nullable(),
|
|
32631
32672
|
productUrl: HttpUrl3.nullable(),
|
|
32632
32673
|
referenceImageUrl: HttpUrl3.nullable(),
|
|
32633
|
-
targetCountry:
|
|
32634
|
-
languageCode:
|
|
32635
|
-
hasReferenceImage:
|
|
32636
|
-
hasWinnerReferenceImage:
|
|
32674
|
+
targetCountry: z131.string().nullable(),
|
|
32675
|
+
languageCode: z131.string().nullable(),
|
|
32676
|
+
hasReferenceImage: z131.boolean(),
|
|
32677
|
+
hasWinnerReferenceImage: z131.boolean(),
|
|
32637
32678
|
costingInput: CostingInputSchema.nullable(),
|
|
32638
32679
|
costingResult: CostingResultSchema.nullable(),
|
|
32639
|
-
costingVersion:
|
|
32640
|
-
version:
|
|
32680
|
+
costingVersion: z131.number().int().positive().nullable(),
|
|
32681
|
+
version: z131.number().int().positive(),
|
|
32641
32682
|
phase: DropshippingProjectPhase,
|
|
32642
32683
|
nextAction: DropshippingProjectNextAction.nullable(),
|
|
32643
32684
|
rewards: RewardProgressSchema,
|
|
32644
|
-
createdAt:
|
|
32645
|
-
updatedAt:
|
|
32685
|
+
createdAt: z131.string().datetime(),
|
|
32686
|
+
updatedAt: z131.string().datetime()
|
|
32646
32687
|
}).passthrough();
|
|
32647
32688
|
var NEXT_ACTION_GUIDANCE = {
|
|
32648
32689
|
cost_product: "Llama `cost_dropshipping_project` con el costo real del proveedor. Nunca lo inventes: p\xEDdeselo al usuario. Es el \xDANICO dato que debes pedirle: omite env\xEDo, devoluciones, cancelaciones, CPA y margen para que ProductMaker use los valores gu\xEDa del pa\xEDs, y luego dile al usuario cu\xE1les us\xF3 por si quiere corregirlos.",
|
|
@@ -32762,58 +32803,58 @@ function registerDropshippingProjectTools(server, api) {
|
|
|
32762
32803
|
__name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
|
|
32763
32804
|
|
|
32764
32805
|
// src/tools/daily-control.ts
|
|
32765
|
-
import { z as
|
|
32806
|
+
import { z as z132 } from "zod";
|
|
32766
32807
|
var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
|
|
32767
32808
|
var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
|
|
32768
32809
|
var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
|
|
32769
|
-
var ProviderCampaignIdentifier =
|
|
32770
|
-
var DateOnly =
|
|
32771
|
-
var DailyControlInput =
|
|
32810
|
+
var ProviderCampaignIdentifier = z132.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
|
|
32811
|
+
var DateOnly = z132.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
32812
|
+
var DailyControlInput = z132.object({
|
|
32772
32813
|
date: DateOnly.optional().describe("D\xEDa final de la ventana (YYYY-MM-DD). Si se omite, la ventana termina AYER en UTC \u2014 nunca hoy, porque el d\xEDa en curso est\xE1 incompleto \u2014 y el servidor puede correrla un d\xEDa m\xE1s atr\xE1s si en la zona horaria de la tienda ese d\xEDa todav\xEDa no ha cerrado."),
|
|
32773
|
-
days:
|
|
32774
|
-
projectId:
|
|
32814
|
+
days: z132.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
|
|
32815
|
+
projectId: z132.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
|
|
32775
32816
|
}).strict();
|
|
32776
|
-
var LinkCampaignInput =
|
|
32777
|
-
projectId:
|
|
32778
|
-
provider:
|
|
32817
|
+
var LinkCampaignInput = z132.object({
|
|
32818
|
+
projectId: z132.string().uuid(),
|
|
32819
|
+
provider: z132.enum([
|
|
32779
32820
|
"meta",
|
|
32780
32821
|
"tiktok"
|
|
32781
32822
|
]),
|
|
32782
32823
|
accountId: ProviderCampaignIdentifier.describe("Cuenta publicitaria del proveedor. Para Meta el servidor la IGNORA y deriva la cuenta real de la campa\xF1a \u2014 se sigue pidiendo aqu\xED solo porque TikTok s\xED la necesita para resolver la campa\xF1a."),
|
|
32783
32824
|
campaignId: ProviderCampaignIdentifier
|
|
32784
32825
|
}).strict();
|
|
32785
|
-
var ReportReturnsInput =
|
|
32786
|
-
projectId:
|
|
32826
|
+
var ReportReturnsInput = z132.object({
|
|
32827
|
+
projectId: z132.string().uuid(),
|
|
32787
32828
|
date: DateOnly,
|
|
32788
|
-
returnedOrders:
|
|
32789
|
-
note:
|
|
32829
|
+
returnedOrders: z132.number().int().min(0).max(1e5),
|
|
32830
|
+
note: z132.string().trim().max(280).optional()
|
|
32790
32831
|
}).strict();
|
|
32791
|
-
var DailyControlStatusMirror = DailyControlStatusEnum.or(
|
|
32792
|
-
var DailyControlLightMirror = DailyControlLightEnum.or(
|
|
32793
|
-
var DailyControlSourceMirror = DailyControlSourceEnum.or(
|
|
32794
|
-
var DailyControlVerdictMirror = DailyControlVerdictEnum.or(
|
|
32795
|
-
var DailyControlDayMirror =
|
|
32796
|
-
date:
|
|
32797
|
-
returnedOrders:
|
|
32832
|
+
var DailyControlStatusMirror = DailyControlStatusEnum.or(z132.string());
|
|
32833
|
+
var DailyControlLightMirror = DailyControlLightEnum.or(z132.string());
|
|
32834
|
+
var DailyControlSourceMirror = DailyControlSourceEnum.or(z132.string());
|
|
32835
|
+
var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z132.string());
|
|
32836
|
+
var DailyControlDayMirror = z132.object({
|
|
32837
|
+
date: z132.string(),
|
|
32838
|
+
returnedOrders: z132.number(),
|
|
32798
32839
|
returnedSource: DailyControlSourceMirror,
|
|
32799
32840
|
cancelledSource: DailyControlSourceMirror,
|
|
32800
|
-
hasEstimates:
|
|
32841
|
+
hasEstimates: z132.boolean(),
|
|
32801
32842
|
light: DailyControlLightMirror
|
|
32802
32843
|
}).passthrough();
|
|
32803
|
-
var DailyControlProductMirror =
|
|
32804
|
-
projectId:
|
|
32805
|
-
productName:
|
|
32844
|
+
var DailyControlProductMirror = z132.object({
|
|
32845
|
+
projectId: z132.string().uuid(),
|
|
32846
|
+
productName: z132.string().nullable(),
|
|
32806
32847
|
status: DailyControlStatusMirror,
|
|
32807
|
-
statusMessage:
|
|
32808
|
-
days:
|
|
32848
|
+
statusMessage: z132.string().nullable(),
|
|
32849
|
+
days: z132.array(DailyControlDayMirror),
|
|
32809
32850
|
verdict: DailyControlVerdictMirror.nullable(),
|
|
32810
|
-
rationale:
|
|
32851
|
+
rationale: z132.string().nullable()
|
|
32811
32852
|
}).passthrough();
|
|
32812
|
-
var DailyControlResponseMirror =
|
|
32813
|
-
since:
|
|
32814
|
-
until:
|
|
32815
|
-
products:
|
|
32816
|
-
archivedProjectSpend:
|
|
32853
|
+
var DailyControlResponseMirror = z132.object({
|
|
32854
|
+
since: z132.string(),
|
|
32855
|
+
until: z132.string(),
|
|
32856
|
+
products: z132.array(DailyControlProductMirror),
|
|
32857
|
+
archivedProjectSpend: z132.array(z132.unknown())
|
|
32817
32858
|
}).passthrough();
|
|
32818
32859
|
var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
|
|
32819
32860
|
function withWarnings(response) {
|
|
@@ -32888,7 +32929,7 @@ __name(registerDailyControlTools, "registerDailyControlTools");
|
|
|
32888
32929
|
// src/tools/product-control.ts
|
|
32889
32930
|
import { readFile, stat } from "fs/promises";
|
|
32890
32931
|
import { basename as basename2, isAbsolute, resolve as resolve3 } from "path";
|
|
32891
|
-
import { z as
|
|
32932
|
+
import { z as z133 } from "zod";
|
|
32892
32933
|
var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
|
|
32893
32934
|
var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
|
|
32894
32935
|
var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
|
|
@@ -32901,36 +32942,36 @@ var createOperationGuidance = getProductMakerCapabilityModelGuidance("create_ope
|
|
|
32901
32942
|
var mergeProductsGuidance = getProductMakerCapabilityModelGuidance("merge_products");
|
|
32902
32943
|
var syncShopifyOrdersGuidance = getProductMakerCapabilityModelGuidance("sync_shopify_orders");
|
|
32903
32944
|
var importOrdersFileGuidance = getProductMakerCapabilityModelGuidance("import_orders_file");
|
|
32904
|
-
var DateOnly2 =
|
|
32945
|
+
var DateOnly2 = z133.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
32905
32946
|
var IMPORT_BATCH_MAX2 = 50;
|
|
32906
|
-
var ProductControlListInput =
|
|
32907
|
-
days:
|
|
32947
|
+
var ProductControlListInput = z133.object({
|
|
32948
|
+
days: z133.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
|
|
32908
32949
|
date: DateOnly2.optional().describe("D\xEDa final de la ventana (YYYY-MM-DD). Si se omite, termina en el \xFAltimo d\xEDa cerrado \u2014 nunca hoy, que est\xE1 incompleto."),
|
|
32909
|
-
shopDomain:
|
|
32950
|
+
shopDomain: z133.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
|
|
32910
32951
|
}).strict();
|
|
32911
|
-
var ImportableProductsInput =
|
|
32912
|
-
q:
|
|
32913
|
-
after:
|
|
32914
|
-
shopDomain:
|
|
32952
|
+
var ImportableProductsInput = z133.object({
|
|
32953
|
+
q: z133.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
|
|
32954
|
+
after: z133.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
|
|
32955
|
+
shopDomain: z133.string().min(1).optional()
|
|
32915
32956
|
}).strict();
|
|
32916
|
-
var ImportProductControlsInput =
|
|
32917
|
-
shopifyProductIds:
|
|
32957
|
+
var ImportProductControlsInput = z133.object({
|
|
32958
|
+
shopifyProductIds: z133.array(z133.string().min(1).max(64)).min(1).max(IMPORT_BATCH_MAX2).describe("Identificadores tal como vinieron de list_importable_products. NO los inventes ni los deduzcas del t\xEDtulo."),
|
|
32918
32959
|
// Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
|
|
32919
32960
|
// sin decir a cuál archivaría el producto bajo la tienda equivocada.
|
|
32920
|
-
shopDomain:
|
|
32961
|
+
shopDomain: z133.string().min(1)
|
|
32921
32962
|
}).strict();
|
|
32922
|
-
var SetProductCostingInput =
|
|
32923
|
-
shopDomain:
|
|
32924
|
-
shopifyProductId:
|
|
32925
|
-
targetCountry:
|
|
32926
|
-
supplierCost:
|
|
32927
|
-
shippingCost:
|
|
32928
|
-
returnRate:
|
|
32929
|
-
cancellationRate:
|
|
32963
|
+
var SetProductCostingInput = z133.object({
|
|
32964
|
+
shopDomain: z133.string().min(1),
|
|
32965
|
+
shopifyProductId: z133.string().min(1).max(64),
|
|
32966
|
+
targetCountry: z133.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
|
|
32967
|
+
supplierCost: z133.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
|
|
32968
|
+
shippingCost: z133.number().finite().nonnegative(),
|
|
32969
|
+
returnRate: z133.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
|
|
32970
|
+
cancellationRate: z133.number().finite().min(0).lt(1)
|
|
32930
32971
|
}).strict();
|
|
32931
|
-
var Count =
|
|
32932
|
-
var ReportProductCountsInput =
|
|
32933
|
-
productControlId:
|
|
32972
|
+
var Count = z133.number().int().min(0).max(1e5).nullable().optional();
|
|
32973
|
+
var ReportProductCountsInput = z133.object({
|
|
32974
|
+
productControlId: z133.string().uuid().describe("El identificador que devuelve get_product_control."),
|
|
32934
32975
|
date: DateOnly2,
|
|
32935
32976
|
orders: Count.describe("Pedidos que entraron ese d\xEDa."),
|
|
32936
32977
|
cancelledOrders: Count,
|
|
@@ -32940,36 +32981,36 @@ var ReportProductCountsInput = z132.object({
|
|
|
32940
32981
|
}).strict();
|
|
32941
32982
|
var MAX_ORDERS_FILE_BYTES = 8 * 1024 * 1024;
|
|
32942
32983
|
var SyncShopifyOrdersInput = SyncShopifyOrdersSchema;
|
|
32943
|
-
var ImportOrdersFileInput =
|
|
32984
|
+
var ImportOrdersFileInput = z133.object({
|
|
32944
32985
|
/** Ruta ABSOLUTA en la máquina de quien usa el MCP. */
|
|
32945
|
-
path:
|
|
32946
|
-
operationId:
|
|
32986
|
+
path: z133.string().min(1),
|
|
32987
|
+
operationId: z133.string().uuid().optional(),
|
|
32947
32988
|
/** Solo mirar: devuelve el resumen y no escribe nada. */
|
|
32948
|
-
dryRun:
|
|
32989
|
+
dryRun: z133.boolean().optional()
|
|
32949
32990
|
}).strict();
|
|
32950
|
-
var CreateOperationInput =
|
|
32951
|
-
countryCode:
|
|
32952
|
-
label:
|
|
32991
|
+
var CreateOperationInput = z133.object({
|
|
32992
|
+
countryCode: z133.string().length(2),
|
|
32993
|
+
label: z133.string().trim().min(1).max(60).optional()
|
|
32953
32994
|
}).strict();
|
|
32954
|
-
var MergeProductsInput =
|
|
32955
|
-
sourceId:
|
|
32956
|
-
targetId:
|
|
32995
|
+
var MergeProductsInput = z133.object({
|
|
32996
|
+
sourceId: z133.string().uuid(),
|
|
32997
|
+
targetId: z133.string().uuid()
|
|
32957
32998
|
}).strict();
|
|
32958
|
-
var SetMonthlyExpenseInput =
|
|
32959
|
-
month:
|
|
32999
|
+
var SetMonthlyExpenseInput = z133.object({
|
|
33000
|
+
month: z133.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
|
|
32960
33001
|
label: SaveMonthlyExpenseSchema.shape.label,
|
|
32961
|
-
amount:
|
|
32962
|
-
operationId:
|
|
33002
|
+
amount: z133.number().finite().min(0),
|
|
33003
|
+
operationId: z133.string().uuid().optional()
|
|
32963
33004
|
}).strict();
|
|
32964
|
-
var SetAdSpendInput =
|
|
32965
|
-
month:
|
|
32966
|
-
operationId:
|
|
33005
|
+
var SetAdSpendInput = z133.object({
|
|
33006
|
+
month: z133.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
|
|
33007
|
+
operationId: z133.string().uuid().optional(),
|
|
32967
33008
|
/** null RETIRA la corrección; cero afirma que no pautó. */
|
|
32968
|
-
amount:
|
|
33009
|
+
amount: z133.number().finite().min(0).nullable()
|
|
32969
33010
|
}).strict();
|
|
32970
|
-
var GetFinancesInput =
|
|
32971
|
-
month:
|
|
32972
|
-
operationId:
|
|
33011
|
+
var GetFinancesInput = z133.object({
|
|
33012
|
+
month: z133.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional().describe("Mes en YYYY-MM. Si se omite, el mes en curso. Solo mes calendario."),
|
|
33013
|
+
operationId: z133.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
|
|
32973
33014
|
}).strict();
|
|
32974
33015
|
function registerProductControlTools(server, api, { transport = "http" } = {}) {
|
|
32975
33016
|
server.registerTool("get_product_control", {
|
|
@@ -33161,28 +33202,28 @@ function registerProductControlTools(server, api, { transport = "http" } = {}) {
|
|
|
33161
33202
|
__name(registerProductControlTools, "registerProductControlTools");
|
|
33162
33203
|
|
|
33163
33204
|
// src/tools/market-study-estimate.ts
|
|
33164
|
-
import { z as
|
|
33205
|
+
import { z as z134 } from "zod";
|
|
33165
33206
|
var estimateMarketStudyGuidance = getProductMakerCapabilityModelGuidance("estimate_market_study_cost");
|
|
33166
|
-
var ProductTaskOutputEnum =
|
|
33207
|
+
var ProductTaskOutputEnum = z134.enum([
|
|
33167
33208
|
"landing",
|
|
33168
33209
|
"video",
|
|
33169
33210
|
"image"
|
|
33170
33211
|
]);
|
|
33171
|
-
var EstimateMarketStudyInput =
|
|
33172
|
-
kind:
|
|
33212
|
+
var EstimateMarketStudyInput = z134.object({
|
|
33213
|
+
kind: z134.enum([
|
|
33173
33214
|
"video",
|
|
33174
33215
|
"product_task"
|
|
33175
33216
|
]).describe('"video" para generate_video_creative; "product_task" para create_product_task.'),
|
|
33176
|
-
videoAngleCount:
|
|
33177
|
-
durationSeconds:
|
|
33217
|
+
videoAngleCount: z134.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
|
|
33218
|
+
durationSeconds: z134.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
|
|
33178
33219
|
videoStructure: VideoStructureEnum.default("single_take"),
|
|
33179
33220
|
videoQuality: VideoQualityEnum.default("economy"),
|
|
33180
33221
|
videoResolution: VideoResolutionEnum.default("480p"),
|
|
33181
|
-
productImageCount:
|
|
33222
|
+
productImageCount: z134.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
|
|
33182
33223
|
outputs: ProductTaskOutputEnum.array().min(1).max(3).optional().describe('Solo para kind="product_task": los mismos outputs de create_product_task. Default: todos.'),
|
|
33183
|
-
generateAiMusic:
|
|
33224
|
+
generateAiMusic: z134.boolean().optional(),
|
|
33184
33225
|
generateAiEdit: AiEditRequestSchema.optional(),
|
|
33185
|
-
replicateWinnerWhenFound:
|
|
33226
|
+
replicateWinnerWhenFound: z134.boolean().optional().describe("La misma preferencia que enviar\xE1s al crear. false excluye la reserva de r\xE9plica del ganador de la cotizaci\xF3n con estudio.")
|
|
33186
33227
|
}).strict();
|
|
33187
33228
|
function buildMarketStudyEstimateRequests(input) {
|
|
33188
33229
|
const quotesVideo = input.kind === "video" || (input.outputs ?? [
|