@productmaker/mcp 11.3.2 → 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 +11 -0
- package/dist/http.js +1068 -844
- package/dist/stdio.js +1057 -833
- 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
|
], [
|
|
@@ -21600,8 +21610,33 @@ var ServicePageGenerateRequestSchema = z100.object({
|
|
|
21600
21610
|
instruction: ServicePageEditInstructionSchema.optional(),
|
|
21601
21611
|
attachmentRefs: ServicePageAttachmentRefsSchema.optional()
|
|
21602
21612
|
}).strict();
|
|
21613
|
+
var SERVICE_PAGE_CREATION_MAX_ATTEMPTS = 3;
|
|
21614
|
+
var ServicePageCreationMarkerSchema = z100.object({
|
|
21615
|
+
rootOperationId: z100.string().uuid().optional(),
|
|
21616
|
+
attempt: z100.number().int().min(1).max(SERVICE_PAGE_CREATION_MAX_ATTEMPTS)
|
|
21617
|
+
}).strict();
|
|
21618
|
+
var ServicePageCreationEstimateRequestSchema = z100.object({
|
|
21619
|
+
textCharacters: z100.number().int().min(0).max(1e6),
|
|
21620
|
+
documentBytes: z100.number().int().min(0).max(1e8),
|
|
21621
|
+
imageCount: z100.number().int().min(0).max(50),
|
|
21622
|
+
instagram: z100.boolean()
|
|
21623
|
+
}).strict();
|
|
21624
|
+
var ServicePageCreationEstimateResponseSchema = z100.object({
|
|
21625
|
+
estimatedMinCostCredits: z100.number().int().nonnegative(),
|
|
21626
|
+
estimatedMaxCostCredits: z100.number().int().nonnegative()
|
|
21627
|
+
}).strict();
|
|
21628
|
+
var ServicePageCreationStatusSchema = z100.object({
|
|
21629
|
+
status: z100.enum([
|
|
21630
|
+
"idle",
|
|
21631
|
+
"running",
|
|
21632
|
+
"failed"
|
|
21633
|
+
]),
|
|
21634
|
+
errorCode: z100.string().max(64).optional()
|
|
21635
|
+
}).strict();
|
|
21603
21636
|
var ServicePageFactExtractionRequestSchema = ServicePageGenerateRequestSchema.omit({
|
|
21604
21637
|
instruction: true
|
|
21638
|
+
}).extend({
|
|
21639
|
+
continueWith: z100.literal("generation").optional()
|
|
21605
21640
|
});
|
|
21606
21641
|
var ServicePageOperationStatusSchema = z100.enum([
|
|
21607
21642
|
"queued",
|
|
@@ -22084,19 +22119,37 @@ var ServiceImageContextSchema = z106.object({
|
|
|
22084
22119
|
referenceKeys: z106.array(z106.string()).max(10)
|
|
22085
22120
|
}).strict();
|
|
22086
22121
|
|
|
22087
|
-
// ../../packages/types/src/
|
|
22122
|
+
// ../../packages/types/src/task-ad-defaults.ts
|
|
22088
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";
|
|
22089
22142
|
var WEBSITE_CAPTURE_MAX_RESEARCH_BYTES = 1024 * 1024;
|
|
22090
22143
|
var WEBSITE_CAPTURE_MAX_FILES = 100;
|
|
22091
22144
|
var WEBSITE_CAPTURE_MAX_FILE_BYTES = 8 * 1024 * 1024;
|
|
22092
22145
|
var WEBSITE_CAPTURE_MAX_BUNDLE_BYTES = 30 * 1024 * 1024;
|
|
22093
|
-
var WebsiteCaptureCauseSchema =
|
|
22146
|
+
var WebsiteCaptureCauseSchema = z108.enum([
|
|
22094
22147
|
"site_blocked",
|
|
22095
22148
|
"site_unreachable",
|
|
22096
22149
|
"not_enough_content",
|
|
22097
22150
|
"internal"
|
|
22098
22151
|
]);
|
|
22099
|
-
var WebsiteCaptureStatusSchema =
|
|
22152
|
+
var WebsiteCaptureStatusSchema = z108.enum([
|
|
22100
22153
|
"queued",
|
|
22101
22154
|
"capturing",
|
|
22102
22155
|
"ready",
|
|
@@ -22118,133 +22171,286 @@ function normalizeWebsiteCaptureUrl(value) {
|
|
|
22118
22171
|
}
|
|
22119
22172
|
}
|
|
22120
22173
|
__name(normalizeWebsiteCaptureUrl, "normalizeWebsiteCaptureUrl");
|
|
22121
|
-
var WebsiteCaptureRequestSchema =
|
|
22122
|
-
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)),
|
|
22123
22176
|
language: MotionGraphicsLanguageSchema
|
|
22124
22177
|
}).strict();
|
|
22125
|
-
var WebsiteCaptureResponseSchema =
|
|
22126
|
-
captureId:
|
|
22178
|
+
var WebsiteCaptureResponseSchema = z108.object({
|
|
22179
|
+
captureId: z108.string().uuid(),
|
|
22127
22180
|
status: WebsiteCaptureStatusSchema,
|
|
22128
|
-
expiresAt:
|
|
22129
|
-
previewUrl:
|
|
22181
|
+
expiresAt: z108.string().datetime(),
|
|
22182
|
+
previewUrl: z108.string().url().optional(),
|
|
22130
22183
|
cause: WebsiteCaptureCauseSchema.optional()
|
|
22131
22184
|
});
|
|
22132
22185
|
var WebsiteCaptureJobSchema = WebsiteCaptureRequestSchema.extend({
|
|
22133
|
-
captureId:
|
|
22134
|
-
attempt:
|
|
22135
|
-
leaseUntil:
|
|
22186
|
+
captureId: z108.string().uuid(),
|
|
22187
|
+
attempt: z108.number().int().positive(),
|
|
22188
|
+
leaseUntil: z108.string().datetime()
|
|
22136
22189
|
});
|
|
22137
|
-
var WebsiteCaptureClaimResponseSchema =
|
|
22190
|
+
var WebsiteCaptureClaimResponseSchema = z108.object({
|
|
22138
22191
|
capture: WebsiteCaptureJobSchema.nullable()
|
|
22139
22192
|
});
|
|
22140
22193
|
var attempt = {
|
|
22141
|
-
attempt:
|
|
22194
|
+
attempt: z108.number().int().positive()
|
|
22142
22195
|
};
|
|
22143
|
-
var digest =
|
|
22144
|
-
var WebsiteCaptureUploadRequestSchema =
|
|
22196
|
+
var digest = z108.string().regex(/^[a-f0-9]{64}$/);
|
|
22197
|
+
var WebsiteCaptureUploadRequestSchema = z108.object({
|
|
22145
22198
|
...attempt,
|
|
22146
|
-
contentLength:
|
|
22199
|
+
contentLength: z108.number().int().positive().max(WEBSITE_CAPTURE_MAX_BUNDLE_BYTES),
|
|
22147
22200
|
sha256: digest
|
|
22148
22201
|
}).strict();
|
|
22149
|
-
var WebsiteCaptureDoneRequestSchema =
|
|
22202
|
+
var WebsiteCaptureDoneRequestSchema = z108.object({
|
|
22150
22203
|
...attempt,
|
|
22151
22204
|
sha256: digest
|
|
22152
22205
|
}).strict();
|
|
22153
|
-
var WebsiteCaptureFailedRequestSchema =
|
|
22206
|
+
var WebsiteCaptureFailedRequestSchema = z108.object({
|
|
22154
22207
|
...attempt,
|
|
22155
22208
|
cause: WebsiteCaptureCauseSchema
|
|
22156
22209
|
}).strict();
|
|
22157
|
-
var WebsiteCaptureBundleSchema =
|
|
22158
|
-
version:
|
|
22159
|
-
files:
|
|
22160
|
-
path:
|
|
22161
|
-
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),
|
|
22162
22215
|
sha256: digest
|
|
22163
22216
|
}).strict()).min(1).max(WEBSITE_CAPTURE_MAX_FILES)
|
|
22164
22217
|
}).strict().refine((bundle) => new Set(bundle.files.map((file) => file.path)).size === bundle.files.length, "Duplicate capture file");
|
|
22165
|
-
var WebsiteCaptureScreenshotSchema =
|
|
22166
|
-
file:
|
|
22167
|
-
scrollTop:
|
|
22168
|
-
});
|
|
22169
|
-
var WebsiteCaptureAccessSchema =
|
|
22170
|
-
publicContentText:
|
|
22171
|
-
passwordGate:
|
|
22172
|
-
challengeGate:
|
|
22173
|
-
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(),
|
|
22174
22227
|
// Decoded, substantial images visible outside access walls and page chrome.
|
|
22175
22228
|
// Optional for compatibility with already captured text-led research.
|
|
22176
|
-
publicImageUrls:
|
|
22177
|
-
});
|
|
22178
|
-
var WebsiteCaptureResearchSchema =
|
|
22179
|
-
requestedUrl:
|
|
22180
|
-
capturedAt:
|
|
22181
|
-
locale:
|
|
22182
|
-
bodyTextTruncated:
|
|
22183
|
-
finalUrl:
|
|
22184
|
-
lang:
|
|
22185
|
-
title:
|
|
22186
|
-
description:
|
|
22187
|
-
openGraph:
|
|
22188
|
-
title:
|
|
22189
|
-
description:
|
|
22190
|
-
image:
|
|
22191
|
-
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()
|
|
22192
22245
|
}),
|
|
22193
|
-
themeColor:
|
|
22194
|
-
headings:
|
|
22195
|
-
h1:
|
|
22196
|
-
h2:
|
|
22197
|
-
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())
|
|
22198
22251
|
}),
|
|
22199
|
-
callsToAction:
|
|
22200
|
-
listItems:
|
|
22201
|
-
bodyText:
|
|
22252
|
+
callsToAction: z108.array(z108.string()),
|
|
22253
|
+
listItems: z108.array(z108.string()),
|
|
22254
|
+
bodyText: z108.string(),
|
|
22202
22255
|
access: WebsiteCaptureAccessSchema.optional(),
|
|
22203
|
-
consent:
|
|
22204
|
-
pressed:
|
|
22205
|
-
removed:
|
|
22256
|
+
consent: z108.object({
|
|
22257
|
+
pressed: z108.string().nullable(),
|
|
22258
|
+
removed: z108.number().nonnegative()
|
|
22206
22259
|
}).optional(),
|
|
22207
|
-
overlaysDismissed:
|
|
22208
|
-
style:
|
|
22209
|
-
bodyBackground:
|
|
22210
|
-
bodyColor:
|
|
22211
|
-
bodyFont:
|
|
22212
|
-
headingFont:
|
|
22213
|
-
headingColor:
|
|
22214
|
-
actionColors:
|
|
22215
|
-
color:
|
|
22216
|
-
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()
|
|
22217
22270
|
}))
|
|
22218
22271
|
}),
|
|
22219
|
-
images:
|
|
22220
|
-
file:
|
|
22221
|
-
src:
|
|
22222
|
-
alt:
|
|
22223
|
-
width:
|
|
22224
|
-
height:
|
|
22225
|
-
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()
|
|
22226
22279
|
})),
|
|
22227
|
-
logo:
|
|
22228
|
-
file:
|
|
22229
|
-
svg:
|
|
22230
|
-
width:
|
|
22231
|
-
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()
|
|
22232
22285
|
}).nullable(),
|
|
22233
|
-
fonts:
|
|
22234
|
-
family:
|
|
22235
|
-
weight:
|
|
22236
|
-
style:
|
|
22237
|
-
unicodeRange:
|
|
22238
|
-
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()
|
|
22239
22292
|
}).transform((font) => ({
|
|
22240
22293
|
...font,
|
|
22241
22294
|
file: font.file
|
|
22242
22295
|
}))),
|
|
22243
|
-
screenshots:
|
|
22244
|
-
desktop:
|
|
22245
|
-
mobile:
|
|
22296
|
+
screenshots: z108.object({
|
|
22297
|
+
desktop: z108.array(WebsiteCaptureScreenshotSchema),
|
|
22298
|
+
mobile: z108.array(WebsiteCaptureScreenshotSchema)
|
|
22299
|
+
})
|
|
22300
|
+
});
|
|
22301
|
+
|
|
22302
|
+
// ../../packages/types/src/demo-mode.ts
|
|
22303
|
+
import { z as z109 } from "zod";
|
|
22304
|
+
var DEMO_MODE_FLOWS = [
|
|
22305
|
+
"brand",
|
|
22306
|
+
"servicePage",
|
|
22307
|
+
"motion",
|
|
22308
|
+
"image"
|
|
22309
|
+
];
|
|
22310
|
+
var DemoModeFlowSchema = z109.enum(DEMO_MODE_FLOWS);
|
|
22311
|
+
var DEMO_MODE_STEPS = [
|
|
22312
|
+
"running",
|
|
22313
|
+
"research",
|
|
22314
|
+
"design",
|
|
22315
|
+
"render_0",
|
|
22316
|
+
"render_33",
|
|
22317
|
+
"render_66",
|
|
22318
|
+
"render_100",
|
|
22319
|
+
"review",
|
|
22320
|
+
"final",
|
|
22321
|
+
"watchdog"
|
|
22322
|
+
];
|
|
22323
|
+
var DemoModeStepSchema = z109.enum(DEMO_MODE_STEPS);
|
|
22324
|
+
var DEMO_MODE_WAIT_SECONDS = {
|
|
22325
|
+
min: 30,
|
|
22326
|
+
max: 450,
|
|
22327
|
+
default: 150
|
|
22328
|
+
};
|
|
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) => [
|
|
22340
|
+
...new Set(list)
|
|
22341
|
+
]),
|
|
22342
|
+
waitSeconds: z109.number().int().min(DEMO_MODE_WAIT_SECONDS.min).max(DEMO_MODE_WAIT_SECONDS.max),
|
|
22343
|
+
chargeCents: z109.object({
|
|
22344
|
+
brand: centsSchema,
|
|
22345
|
+
servicePage: centsSchema,
|
|
22346
|
+
motion: centsSchema,
|
|
22347
|
+
image: centsSchema
|
|
22348
|
+
}),
|
|
22349
|
+
templates: DemoModeTemplatesSchema
|
|
22350
|
+
});
|
|
22351
|
+
var nullableString = z109.string().nullable();
|
|
22352
|
+
var DemoModeSnapshotSchema = z109.object({
|
|
22353
|
+
brand: z109.object({
|
|
22354
|
+
/** Columnas de identidad de `Brand` listas para un `update` (sin id/userId/slug/estado/fechas). */
|
|
22355
|
+
identity: z109.record(z109.unknown()),
|
|
22356
|
+
productSamples: z109.array(z109.object({
|
|
22357
|
+
name: z109.string(),
|
|
22358
|
+
priceCents: z109.number().int().nullable(),
|
|
22359
|
+
currency: nullableString,
|
|
22360
|
+
imageKey: z109.string(),
|
|
22361
|
+
productUrl: nullableString,
|
|
22362
|
+
position: z109.number().int()
|
|
22363
|
+
})),
|
|
22364
|
+
personas: z109.array(z109.object({
|
|
22365
|
+
name: z109.string(),
|
|
22366
|
+
demographics: nullableString,
|
|
22367
|
+
painPoints: nullableString,
|
|
22368
|
+
motivations: nullableString,
|
|
22369
|
+
objections: nullableString,
|
|
22370
|
+
gender: nullableString,
|
|
22371
|
+
isDefault: z109.boolean()
|
|
22372
|
+
}))
|
|
22373
|
+
}),
|
|
22374
|
+
servicePage: z109.object({
|
|
22375
|
+
facts: z109.unknown(),
|
|
22376
|
+
review: z109.unknown(),
|
|
22377
|
+
artifact: z109.unknown()
|
|
22378
|
+
}),
|
|
22379
|
+
motion: z109.object({
|
|
22380
|
+
outputs: MotionGraphicsOutputsSchema,
|
|
22381
|
+
/**
|
|
22382
|
+
* La captura REAL de la web de la plantilla (nunca una fabricada por la
|
|
22383
|
+
* demo). Null cuando la plantilla no tiene ninguna: la captura demo nunca
|
|
22384
|
+
* va live, así que el servicio usa `DEMO_MODE_PLACEHOLDER_CAPTURE`.
|
|
22385
|
+
*/
|
|
22386
|
+
capture: z109.object({
|
|
22387
|
+
bundleKey: z109.string(),
|
|
22388
|
+
sha256: z109.string(),
|
|
22389
|
+
uploadBytes: z109.number().int().nullable(),
|
|
22390
|
+
previewKey: nullableString
|
|
22391
|
+
}).nullable()
|
|
22392
|
+
}),
|
|
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(),
|
|
22400
|
+
adCopy: nullableString,
|
|
22401
|
+
rawResponse: z109.unknown()
|
|
22246
22402
|
})
|
|
22247
22403
|
});
|
|
22404
|
+
var DemoModeConfigSchema = DemoModeEditableSchema.extend({
|
|
22405
|
+
snapshot: DemoModeSnapshotSchema.nullable(),
|
|
22406
|
+
snapshotAt: z109.string().datetime().nullable()
|
|
22407
|
+
});
|
|
22408
|
+
var DemoModeAdminViewSchema = DemoModeEditableSchema.extend({
|
|
22409
|
+
// Sin configurar, la API devuelve ids vacíos ("" no es uuid): la vista los
|
|
22410
|
+
// admite; el PUT sí exige uuid (`DemoModeEditableSchema`).
|
|
22411
|
+
templates: z109.object({
|
|
22412
|
+
brandId: z109.string(),
|
|
22413
|
+
servicePageId: z109.string(),
|
|
22414
|
+
motionTaskId: z109.string(),
|
|
22415
|
+
imageTaskId: z109.string()
|
|
22416
|
+
}),
|
|
22417
|
+
snapshotAt: z109.string().nullable()
|
|
22418
|
+
});
|
|
22419
|
+
var DEMO_MODE_TEMPLATE_PROBLEMS = [
|
|
22420
|
+
"not_found",
|
|
22421
|
+
"brand_not_ready",
|
|
22422
|
+
"no_artifact",
|
|
22423
|
+
"artifact_invalid",
|
|
22424
|
+
"task_not_done",
|
|
22425
|
+
"no_video",
|
|
22426
|
+
"no_creative"
|
|
22427
|
+
];
|
|
22428
|
+
var DemoModeTemplateVerdictSchema = z109.discriminatedUnion("ok", [
|
|
22429
|
+
z109.object({
|
|
22430
|
+
ok: z109.literal(true)
|
|
22431
|
+
}),
|
|
22432
|
+
z109.object({
|
|
22433
|
+
ok: z109.literal(false),
|
|
22434
|
+
problem: z109.enum(DEMO_MODE_TEMPLATE_PROBLEMS)
|
|
22435
|
+
})
|
|
22436
|
+
]);
|
|
22437
|
+
var DemoModeValidationSchema = z109.object({
|
|
22438
|
+
brandId: DemoModeTemplateVerdictSchema,
|
|
22439
|
+
servicePageId: DemoModeTemplateVerdictSchema,
|
|
22440
|
+
motionTaskId: DemoModeTemplateVerdictSchema,
|
|
22441
|
+
imageTaskId: DemoModeTemplateVerdictSchema
|
|
22442
|
+
});
|
|
22443
|
+
var DemoModeJobSchema = z109.object({
|
|
22444
|
+
flow: DemoModeFlowSchema,
|
|
22445
|
+
step: DemoModeStepSchema,
|
|
22446
|
+
/** brandId | servicePageOperationId | taskId según el flujo. */
|
|
22447
|
+
targetId: z109.string().uuid(),
|
|
22448
|
+
userId: z109.string().min(1),
|
|
22449
|
+
/** Solo marca: la generación de extracción que el guion completa. */
|
|
22450
|
+
generation: z109.number().int().positive().optional(),
|
|
22451
|
+
/** Solo `final`/`watchdog`: la parte del snapshot de ESTE flujo, congelada al empezar. */
|
|
22452
|
+
result: z109.unknown().optional()
|
|
22453
|
+
});
|
|
22248
22454
|
|
|
22249
22455
|
// src/http.ts
|
|
22250
22456
|
import express4 from "express";
|
|
@@ -22755,23 +22961,23 @@ import { InsufficientScopeError, InvalidTokenError } from "@modelcontextprotocol
|
|
|
22755
22961
|
import { createRemoteJWKSet as createRemoteJWKSet2, jwtVerify as jwtVerify2 } from "jose";
|
|
22756
22962
|
|
|
22757
22963
|
// src/auth/oauth-config.ts
|
|
22758
|
-
import { z as
|
|
22964
|
+
import { z as z110 } from "zod";
|
|
22759
22965
|
var MCP_RESOURCE = new URL("https://mcp.productmaker.app/mcp");
|
|
22760
22966
|
var MCP_SCOPE = "mcp:access";
|
|
22761
22967
|
var REFRESH_SCOPE = "offline_access";
|
|
22762
22968
|
var STATIC_CLIENT_ISSUER = new URL(MCP_RESOURCE.origin);
|
|
22763
|
-
var oauthEnvSchema =
|
|
22764
|
-
MCP_REMOTE_AUTH_MODE:
|
|
22765
|
-
MCP_AUTH0_ISSUER:
|
|
22766
|
-
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, {
|
|
22767
22973
|
message: `must equal ${MCP_RESOURCE.href}`
|
|
22768
22974
|
}),
|
|
22769
|
-
MCP_AUTH0_CLIENT_ID:
|
|
22770
|
-
MCP_AUTH0_CLIENT_SECRET:
|
|
22771
|
-
PM_API_AUDIENCE:
|
|
22772
|
-
AUTH0_AUDIENCE:
|
|
22773
|
-
MCP_STATIC_CLIENT_ID:
|
|
22774
|
-
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()
|
|
22775
22981
|
});
|
|
22776
22982
|
function formatZodIssues(error) {
|
|
22777
22983
|
return error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
|
|
@@ -23927,7 +24133,7 @@ var ApiClient = class {
|
|
|
23927
24133
|
};
|
|
23928
24134
|
|
|
23929
24135
|
// src/index.ts
|
|
23930
|
-
var MCP_VERSION = "11.
|
|
24136
|
+
var MCP_VERSION = "11.4.0";
|
|
23931
24137
|
|
|
23932
24138
|
// src/meta-upload-app.ts
|
|
23933
24139
|
import { readFileSync } from "fs";
|
|
@@ -23999,7 +24205,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
|
|
|
23999
24205
|
__name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
|
|
24000
24206
|
|
|
24001
24207
|
// src/tools/tasks.ts
|
|
24002
|
-
import { z as
|
|
24208
|
+
import { z as z115 } from "zod";
|
|
24003
24209
|
|
|
24004
24210
|
// src/resolve-image.ts
|
|
24005
24211
|
import { lookup as dnsLookup } from "dns/promises";
|
|
@@ -24560,9 +24766,9 @@ async function resolveMediaRef(ref, opts) {
|
|
|
24560
24766
|
__name(resolveMediaRef, "resolveMediaRef");
|
|
24561
24767
|
|
|
24562
24768
|
// src/tools/shared.ts
|
|
24563
|
-
import { z as
|
|
24564
|
-
var Lang =
|
|
24565
|
-
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);
|
|
24566
24772
|
var LandingStrategyEnum = LandingStrategySchema;
|
|
24567
24773
|
var LandingImageFormatEnum = LandingImageFormatSchema;
|
|
24568
24774
|
var VideoPresetEnum = VideoPreset.extract([
|
|
@@ -24666,7 +24872,7 @@ function animationStyleApplies(videoPreset, angleNarratives) {
|
|
|
24666
24872
|
return ANIMATED_VIDEO_PRESETS.has(videoPreset ?? "") || (angleNarratives ?? []).some((n) => ANIMATED_NARRATIVE_STYLES.has(n));
|
|
24667
24873
|
}
|
|
24668
24874
|
__name(animationStyleApplies, "animationStyleApplies");
|
|
24669
|
-
var VideoTierEnum =
|
|
24875
|
+
var VideoTierEnum = z111.enum([
|
|
24670
24876
|
"basic"
|
|
24671
24877
|
]);
|
|
24672
24878
|
function resolveVideoTier(_tier) {
|
|
@@ -24724,10 +24930,10 @@ var ImageCreativeStyleEnum = ImageCreativeStyle;
|
|
|
24724
24930
|
var ImageCreativeArchetypeEnum = ImageCreativeArchetype;
|
|
24725
24931
|
var ImageCreativeVisualTreatmentEnum = ImageCreativeVisualTreatment;
|
|
24726
24932
|
var ImageCreativeAspectRatioEnum = ImageCreativeAspectRatio;
|
|
24727
|
-
var ImageRefSchema =
|
|
24728
|
-
url:
|
|
24729
|
-
path:
|
|
24730
|
-
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.")
|
|
24731
24937
|
}).refine((v) => [
|
|
24732
24938
|
v.url,
|
|
24733
24939
|
v.path,
|
|
@@ -24735,11 +24941,11 @@ var ImageRefSchema = z109.object({
|
|
|
24735
24941
|
].filter(Boolean).length === 1, {
|
|
24736
24942
|
message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
|
|
24737
24943
|
});
|
|
24738
|
-
var ImagesInput =
|
|
24944
|
+
var ImagesInput = z111.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
|
|
24739
24945
|
const assetCount = images.filter((image) => Boolean(image.assetId)).length;
|
|
24740
24946
|
if (assetCount > 0 && assetCount !== images.length) {
|
|
24741
24947
|
ctx.addIssue({
|
|
24742
|
-
code:
|
|
24948
|
+
code: z111.ZodIssueCode.custom,
|
|
24743
24949
|
message: "all image entries must use assetId, or all must use URL/path sources"
|
|
24744
24950
|
});
|
|
24745
24951
|
}
|
|
@@ -24789,16 +24995,24 @@ async function submitCreative(api, opts) {
|
|
|
24789
24995
|
...img,
|
|
24790
24996
|
filename: `image-${i}.png`
|
|
24791
24997
|
}));
|
|
24792
|
-
const r = await api.postMultipart(
|
|
24793
|
-
|
|
24794
|
-
|
|
24795
|
-
|
|
24796
|
-
|
|
24797
|
-
|
|
24798
|
-
|
|
24799
|
-
|
|
24800
|
-
|
|
24801
|
-
|
|
24998
|
+
const r = await api.postMultipart(
|
|
24999
|
+
opts.path,
|
|
25000
|
+
{
|
|
25001
|
+
images: parts
|
|
25002
|
+
},
|
|
25003
|
+
// assetIds stays an array so postMultipart appends one `assetIds` field per
|
|
25004
|
+
// id: `flatten` would comma-join them into a single non-UUID value and the
|
|
25005
|
+
// API rejects every multi-photo upload with "assetId must be a valid UUID".
|
|
25006
|
+
{
|
|
25007
|
+
...flatten(rest),
|
|
25008
|
+
...assetIds ? {
|
|
25009
|
+
assetIds
|
|
25010
|
+
} : {}
|
|
25011
|
+
},
|
|
25012
|
+
opts.idempotencyKey ? {
|
|
25013
|
+
idempotencyKey: opts.idempotencyKey
|
|
25014
|
+
} : void 0
|
|
25015
|
+
);
|
|
24802
25016
|
const taskId = r.taskId ?? r.jobId;
|
|
24803
25017
|
return asText({
|
|
24804
25018
|
taskId,
|
|
@@ -24812,14 +25026,14 @@ async function submitCreative(api, opts) {
|
|
|
24812
25026
|
});
|
|
24813
25027
|
}
|
|
24814
25028
|
__name(submitCreative, "submitCreative");
|
|
24815
|
-
var ResearchTargetCountryEnum =
|
|
25029
|
+
var ResearchTargetCountryEnum = z111.enum([
|
|
24816
25030
|
"CO",
|
|
24817
25031
|
"MX",
|
|
24818
25032
|
"PE",
|
|
24819
25033
|
"EC",
|
|
24820
25034
|
"CL"
|
|
24821
25035
|
]);
|
|
24822
|
-
var ResearchCategoryEnum =
|
|
25036
|
+
var ResearchCategoryEnum = z111.enum([
|
|
24823
25037
|
"auto",
|
|
24824
25038
|
"automotive",
|
|
24825
25039
|
"kitchen",
|
|
@@ -24949,6 +25163,7 @@ var McpErrorCode = {
|
|
|
24949
25163
|
CAMPAIGN_NOT_FOUND: "CAMPAIGN_NOT_FOUND",
|
|
24950
25164
|
CAMPAIGN_TASK_NOT_FOUND: "CAMPAIGN_TASK_NOT_FOUND",
|
|
24951
25165
|
CAMPAIGN_MISSING_LANDING_URL: "CAMPAIGN_MISSING_LANDING_URL",
|
|
25166
|
+
CAMPAIGN_MISSING_TARGET_COUNTRY: "CAMPAIGN_MISSING_TARGET_COUNTRY",
|
|
24952
25167
|
CAMPAIGN_NO_CREATIVES: "CAMPAIGN_NO_CREATIVES",
|
|
24953
25168
|
CAMPAIGN_MISSING_THUMBNAILS: "CAMPAIGN_MISSING_THUMBNAILS",
|
|
24954
25169
|
CAMPAIGN_RECONCILIATION_REQUIRED: "CAMPAIGN_RECONCILIATION_REQUIRED",
|
|
@@ -24988,6 +25203,7 @@ var McpErrorCode = {
|
|
|
24988
25203
|
META_NO_ASSETS_READY: "META_NO_ASSETS_READY",
|
|
24989
25204
|
META_NO_THUMBNAIL_SOURCE: "META_NO_THUMBNAIL_SOURCE",
|
|
24990
25205
|
META_NO_LANDING_URL: "META_NO_LANDING_URL",
|
|
25206
|
+
META_NO_TARGET_COUNTRY: "META_NO_TARGET_COUNTRY",
|
|
24991
25207
|
META_TASK_NOT_FOUND: "META_TASK_NOT_FOUND",
|
|
24992
25208
|
META_INVALID_DATA: "META_INVALID_DATA",
|
|
24993
25209
|
META_INVALID_AD_ACCOUNT: "META_INVALID_AD_ACCOUNT",
|
|
@@ -25075,7 +25291,8 @@ var CODE_MESSAGES = {
|
|
|
25075
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.",
|
|
25076
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.",
|
|
25077
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.",
|
|
25078
|
-
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.",
|
|
25079
25296
|
META_TASK_NOT_FOUND: "Task not found or does not belong to this user. Verify the `taskId`.",
|
|
25080
25297
|
META_INVALID_DATA: "Meta rejected the request due to invalid data. Verify that `adAccountId` and `pixelId` are correct.",
|
|
25081
25298
|
META_INVALID_AD_ACCOUNT: "Ad account not found or no access. Confirm the `adAccountId` with `list_meta_ad_accounts`.",
|
|
@@ -25114,7 +25331,8 @@ var CODE_MESSAGES = {
|
|
|
25114
25331
|
// Campaign (shared)
|
|
25115
25332
|
CAMPAIGN_NOT_FOUND: "Campaign not found or does not belong to this user. Verify the `campaignId`.",
|
|
25116
25333
|
CAMPAIGN_TASK_NOT_FOUND: "Campaign task not found. Verify the `taskId`.",
|
|
25117
|
-
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.",
|
|
25118
25336
|
CAMPAIGN_NO_CREATIVES: "The task has no creatives (video/image) ready for the campaign. Wait for generation to finish.",
|
|
25119
25337
|
CAMPAIGN_MISSING_THUMBNAILS: "Missing thumbnails for the videos. Verify that image/video generation has finished.",
|
|
25120
25338
|
CAMPAIGN_RECONCILIATION_REQUIRED: "A campaign may already have been created. Do not retry creation; reopen the project and reconcile it or contact support.",
|
|
@@ -25206,8 +25424,10 @@ var INVALID_PARAM_CODES = /* @__PURE__ */ new Set([
|
|
|
25206
25424
|
McpErrorCode.TIKTOK_ADVERTISER_REQUIRED,
|
|
25207
25425
|
McpErrorCode.TIKTOK_PIXEL_NOT_FOUND,
|
|
25208
25426
|
McpErrorCode.CAMPAIGN_MISSING_LANDING_URL,
|
|
25427
|
+
McpErrorCode.CAMPAIGN_MISSING_TARGET_COUNTRY,
|
|
25209
25428
|
McpErrorCode.CAMPAIGN_RECONCILIATION_REQUIRED,
|
|
25210
25429
|
McpErrorCode.META_NO_LANDING_URL,
|
|
25430
|
+
McpErrorCode.META_NO_TARGET_COUNTRY,
|
|
25211
25431
|
McpErrorCode.META_PORTFOLIO_MISMATCH,
|
|
25212
25432
|
McpErrorCode.META_PAGE_SELECTION_REQUIRED,
|
|
25213
25433
|
McpErrorCode.META_INVALID_PAGE,
|
|
@@ -25318,6 +25538,7 @@ var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
|
|
|
25318
25538
|
McpErrorCode.META_NO_ASSETS_READY,
|
|
25319
25539
|
McpErrorCode.META_NO_THUMBNAIL_SOURCE,
|
|
25320
25540
|
McpErrorCode.META_NO_LANDING_URL,
|
|
25541
|
+
McpErrorCode.META_NO_TARGET_COUNTRY,
|
|
25321
25542
|
McpErrorCode.META_TASK_NOT_FOUND,
|
|
25322
25543
|
McpErrorCode.META_INVALID_DATA,
|
|
25323
25544
|
McpErrorCode.META_INVALID_AD_ACCOUNT,
|
|
@@ -25365,6 +25586,7 @@ var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
|
|
|
25365
25586
|
McpErrorCode.CAMPAIGN_NOT_FOUND,
|
|
25366
25587
|
McpErrorCode.CAMPAIGN_TASK_NOT_FOUND,
|
|
25367
25588
|
McpErrorCode.CAMPAIGN_MISSING_LANDING_URL,
|
|
25589
|
+
McpErrorCode.CAMPAIGN_MISSING_TARGET_COUNTRY,
|
|
25368
25590
|
McpErrorCode.CAMPAIGN_NO_CREATIVES,
|
|
25369
25591
|
McpErrorCode.CAMPAIGN_MISSING_THUMBNAILS,
|
|
25370
25592
|
McpErrorCode.CAMPAIGN_RECONCILIATION_REQUIRED,
|
|
@@ -26131,29 +26353,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
|
|
|
26131
26353
|
__name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
|
|
26132
26354
|
|
|
26133
26355
|
// src/tools/media-presentation.ts
|
|
26134
|
-
import { z as
|
|
26135
|
-
var HttpsPresentationUrlSchema =
|
|
26356
|
+
import { z as z112 } from "zod";
|
|
26357
|
+
var HttpsPresentationUrlSchema = z112.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
|
|
26136
26358
|
var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
|
|
26137
26359
|
const hostname = new URL(value).hostname.toLowerCase();
|
|
26138
26360
|
return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
|
|
26139
26361
|
}, "preview URL must be owned by ProductMaker");
|
|
26140
|
-
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) =>
|
|
26141
|
-
var PresentationImageSchema =
|
|
26142
|
-
kind:
|
|
26362
|
+
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z112.number().int().positive().max(maximum), "positiveIntAtMost");
|
|
26363
|
+
var PresentationImageSchema = z112.object({
|
|
26364
|
+
kind: z112.literal("image"),
|
|
26143
26365
|
url: HttpsPresentationUrlSchema,
|
|
26144
|
-
mimeType:
|
|
26366
|
+
mimeType: z112.enum([
|
|
26145
26367
|
"image/jpeg",
|
|
26146
26368
|
"image/png"
|
|
26147
26369
|
]),
|
|
26148
26370
|
byteSize: positiveIntAtMost(5 * 1024 * 1024),
|
|
26149
26371
|
width: positiveIntAtMost(16384),
|
|
26150
26372
|
height: positiveIntAtMost(16384),
|
|
26151
|
-
alt:
|
|
26373
|
+
alt: z112.string().trim().min(1).max(240)
|
|
26152
26374
|
}).strict();
|
|
26153
26375
|
var McpMediaPresentationSchema = PresentationImageSchema;
|
|
26154
|
-
var GalleryImageSchema =
|
|
26376
|
+
var GalleryImageSchema = z112.object({
|
|
26155
26377
|
url: ProductMakerPreviewUrlSchema,
|
|
26156
|
-
alt:
|
|
26378
|
+
alt: z112.string().trim().min(1).max(240)
|
|
26157
26379
|
});
|
|
26158
26380
|
var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
|
|
26159
26381
|
async function imageBlocks(image, transport) {
|
|
@@ -26210,12 +26432,12 @@ async function buildMcpMediaPresentationContent(rawPresentation, transport = "ht
|
|
|
26210
26432
|
];
|
|
26211
26433
|
}
|
|
26212
26434
|
__name(buildMcpMediaPresentationContent, "buildMcpMediaPresentationContent");
|
|
26213
|
-
var OwnedImagePreviewSchema =
|
|
26435
|
+
var OwnedImagePreviewSchema = z112.object({
|
|
26214
26436
|
url: HttpsPresentationUrlSchema.refine((value) => {
|
|
26215
26437
|
const url = new URL(value);
|
|
26216
26438
|
return !url.username && !url.password && !isPrivateHost(url.hostname);
|
|
26217
26439
|
}, "Preview URL must be public HTTPS without credentials"),
|
|
26218
|
-
alt:
|
|
26440
|
+
alt: z112.string().trim().min(1).max(240)
|
|
26219
26441
|
});
|
|
26220
26442
|
async function buildMcpImagePreviewContent(rawPreview, transport = "http") {
|
|
26221
26443
|
const preview2 = OwnedImagePreviewSchema.safeParse(rawPreview);
|
|
@@ -26298,7 +26520,7 @@ async function buildMcpImageGalleryContent(rawItems, transport = "http") {
|
|
|
26298
26520
|
__name(buildMcpImageGalleryContent, "buildMcpImageGalleryContent");
|
|
26299
26521
|
|
|
26300
26522
|
// src/tools/animated-video.ts
|
|
26301
|
-
import { z as
|
|
26523
|
+
import { z as z113 } from "zod";
|
|
26302
26524
|
|
|
26303
26525
|
// src/tools/paid-confirmation.ts
|
|
26304
26526
|
function describeMarketStudyChoice(enabled) {
|
|
@@ -26548,27 +26770,27 @@ function hookVariantsLabel(count) {
|
|
|
26548
26770
|
return count === 1 ? "1 versi\xF3n del gancho" : `${count} versiones del gancho`;
|
|
26549
26771
|
}
|
|
26550
26772
|
__name(hookVariantsLabel, "hookVariantsLabel");
|
|
26551
|
-
var DurationInput =
|
|
26552
|
-
var CreateAnimatedVideoInput =
|
|
26553
|
-
action:
|
|
26773
|
+
var DurationInput = z113.union(MOTION_GRAPHICS_DURATIONS.map((d) => z113.literal(d)));
|
|
26774
|
+
var CreateAnimatedVideoInput = z113.object({
|
|
26775
|
+
action: z113.enum([
|
|
26554
26776
|
"prepare",
|
|
26555
26777
|
"status",
|
|
26556
26778
|
"cancel",
|
|
26557
26779
|
"generate"
|
|
26558
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."),
|
|
26559
|
-
websiteCaptureId:
|
|
26560
|
-
generationRequestId:
|
|
26561
|
-
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."),
|
|
26562
26784
|
// Plain text, not `.url()`: users type «cal.com», and the web accepts it.
|
|
26563
26785
|
// normalizeWebAddress (shared with the web) adds https:// and refuses
|
|
26564
26786
|
// anything that is not a public http(s) address.
|
|
26565
|
-
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."),
|
|
26566
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.'),
|
|
26567
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.`),
|
|
26568
26790
|
language: MotionGraphicsLanguageSchema.optional().describe('Idioma de los textos del video: "es", "en" o "pt".'),
|
|
26569
|
-
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)."),
|
|
26570
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.`),
|
|
26571
|
-
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.")
|
|
26572
26794
|
}).strict();
|
|
26573
26795
|
function captureNextAction(capture) {
|
|
26574
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.";
|
|
@@ -26601,43 +26823,43 @@ var FORMAT_LABELS = {
|
|
|
26601
26823
|
square: "cuadrado 1:1",
|
|
26602
26824
|
horizontal: "horizontal 16:9"
|
|
26603
26825
|
};
|
|
26604
|
-
var AnimatedVideoResultSchema =
|
|
26605
|
-
status:
|
|
26826
|
+
var AnimatedVideoResultSchema = z113.object({
|
|
26827
|
+
status: z113.enum([
|
|
26606
26828
|
"pending",
|
|
26607
26829
|
"done",
|
|
26608
26830
|
"error"
|
|
26609
26831
|
]),
|
|
26610
|
-
serviceMode:
|
|
26611
|
-
finalMp4Url:
|
|
26612
|
-
error:
|
|
26613
|
-
motionGraphics:
|
|
26832
|
+
serviceMode: z113.literal("motion_graphics"),
|
|
26833
|
+
finalMp4Url: z113.string().optional(),
|
|
26834
|
+
error: z113.string().optional(),
|
|
26835
|
+
motionGraphics: z113.object({
|
|
26614
26836
|
stage: MotionGraphicsStageSchema,
|
|
26615
26837
|
format: MotionGraphicsFormatSchema,
|
|
26616
|
-
durationSec:
|
|
26617
|
-
width:
|
|
26618
|
-
height:
|
|
26838
|
+
durationSec: z113.number(),
|
|
26839
|
+
width: z113.number().optional(),
|
|
26840
|
+
height: z113.number().optional(),
|
|
26619
26841
|
language: MotionGraphicsLanguageSchema.optional(),
|
|
26620
|
-
queuedAt:
|
|
26621
|
-
jobsAhead:
|
|
26622
|
-
stageStartedAt:
|
|
26623
|
-
renderProgress:
|
|
26842
|
+
queuedAt: z113.string().optional(),
|
|
26843
|
+
jobsAhead: z113.number().int().nonnegative().optional(),
|
|
26844
|
+
stageStartedAt: z113.string().optional(),
|
|
26845
|
+
renderProgress: z113.number().optional(),
|
|
26624
26846
|
// AI clip fields (absent on a video paid before clips, or from an API
|
|
26625
26847
|
// that predates them). Lenient: an unreadable value is dropped
|
|
26626
26848
|
// instead of hiding the status.
|
|
26627
|
-
clipCount:
|
|
26628
|
-
clipsUsed:
|
|
26629
|
-
clipPriceCents:
|
|
26630
|
-
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),
|
|
26631
26853
|
// Hook versions (absent from an API or a video before them): the
|
|
26632
26854
|
// count ordered and, once done, the signed URLs of the EXTRA versions
|
|
26633
26855
|
// (hook 2, hook 3); `finalMp4Url` is hook 1.
|
|
26634
|
-
hookVariants:
|
|
26635
|
-
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),
|
|
26636
26858
|
// Extra hook versions given back, as the task recorded it once the
|
|
26637
26859
|
// refunds landed (absent until then, and from an API before it).
|
|
26638
|
-
variantsRefunded:
|
|
26639
|
-
activity:
|
|
26640
|
-
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()
|
|
26641
26863
|
}).passthrough()
|
|
26642
26864
|
}).passthrough();
|
|
26643
26865
|
function parseAnimatedVideoResult(value) {
|
|
@@ -26893,10 +27115,10 @@ function registerAnimatedVideoTools(server, api) {
|
|
|
26893
27115
|
__name(registerAnimatedVideoTools, "registerAnimatedVideoTools");
|
|
26894
27116
|
|
|
26895
27117
|
// src/tools/winning-product-image.ts
|
|
26896
|
-
import { z as
|
|
26897
|
-
var WinnerReferenceInput =
|
|
26898
|
-
runId:
|
|
26899
|
-
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)
|
|
26900
27122
|
}).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
|
|
26901
27123
|
async function resolveWinnerImages(api, winnerReference, images) {
|
|
26902
27124
|
if (!winnerReference) return images;
|
|
@@ -26933,62 +27155,62 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
|
|
|
26933
27155
|
var CREATE_SERVICE_VIDEO_ON_MCP = PRODUCTMAKER_MCP_CAPABILITY_NAMES.includes("create_service_video");
|
|
26934
27156
|
var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
|
|
26935
27157
|
var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
|
|
26936
|
-
var CreateProductTaskInput =
|
|
27158
|
+
var CreateProductTaskInput = z115.object({
|
|
26937
27159
|
images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
|
|
26938
27160
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
26939
|
-
projectId:
|
|
26940
|
-
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."),
|
|
26941
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.'),
|
|
26942
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.'),
|
|
26943
|
-
price:
|
|
26944
|
-
compareAtPrice:
|
|
26945
|
-
offer:
|
|
26946
|
-
paymentMethods:
|
|
26947
|
-
productContext:
|
|
26948
|
-
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.'),
|
|
26949
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.'),
|
|
26950
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.'),
|
|
26951
|
-
durationSeconds:
|
|
26952
|
-
|
|
26953
|
-
|
|
27173
|
+
durationSeconds: z115.union([
|
|
27174
|
+
z115.literal(15),
|
|
27175
|
+
z115.literal(30)
|
|
26954
27176
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
26955
|
-
pauseForAngleReview:
|
|
26956
|
-
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."),
|
|
26957
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.'),
|
|
26958
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.'),
|
|
26959
27181
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
26960
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).'),
|
|
26961
|
-
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."),
|
|
26962
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.'),
|
|
26963
|
-
outputs:
|
|
27185
|
+
outputs: z115.array(z115.enum([
|
|
26964
27186
|
"landing",
|
|
26965
27187
|
"video",
|
|
26966
27188
|
"image"
|
|
26967
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}`),
|
|
26968
|
-
includeInitialLandingGif:
|
|
26969
|
-
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."),
|
|
26970
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.'),
|
|
26971
|
-
replicateWinnerWhenFound:
|
|
26972
|
-
brandId:
|
|
26973
|
-
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."),
|
|
26974
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.'),
|
|
26975
|
-
creativeDirection:
|
|
26976
|
-
headline:
|
|
26977
|
-
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."),
|
|
26978
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".'),
|
|
26979
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".')
|
|
26980
27202
|
}).strict();
|
|
26981
|
-
var CreateServiceVideoInput =
|
|
26982
|
-
landingUrl:
|
|
26983
|
-
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.'),
|
|
26984
27206
|
language: Lang.describe("Idioma del video: es, en o pt."),
|
|
26985
|
-
voiceId:
|
|
26986
|
-
brandId:
|
|
26987
|
-
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([
|
|
26988
27210
|
"automatic",
|
|
26989
27211
|
"guided"
|
|
26990
27212
|
]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
|
|
26991
|
-
videoPreset:
|
|
27213
|
+
videoPreset: z115.enum([
|
|
26992
27214
|
"auto",
|
|
26993
27215
|
"ugc_dynamic",
|
|
26994
27216
|
"ugc_how_to",
|
|
@@ -26998,128 +27220,128 @@ var CreateServiceVideoInput = z113.object({
|
|
|
26998
27220
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
26999
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.')
|
|
27000
27222
|
}).strict();
|
|
27001
|
-
var GetTaskStatusInput =
|
|
27002
|
-
taskId:
|
|
27003
|
-
waitSeconds:
|
|
27223
|
+
var GetTaskStatusInput = z115.object({
|
|
27224
|
+
taskId: z115.string().min(1),
|
|
27225
|
+
waitSeconds: z115.number().int().min(0).max(120).optional()
|
|
27004
27226
|
});
|
|
27005
|
-
var ListTasksInput =
|
|
27006
|
-
limit:
|
|
27007
|
-
offset:
|
|
27008
|
-
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()
|
|
27009
27231
|
});
|
|
27010
27232
|
var MCP_REVIEW_LIST_FIELD_MAX = IMAGE_WIZARD_LIST_FIELD_MAX;
|
|
27011
27233
|
var MCP_REVIEW_FEATURE_ITEM_MAX = IMAGE_FEATURE_ITEM_MAX;
|
|
27012
|
-
var EditTaskDraftInput =
|
|
27013
|
-
taskId:
|
|
27014
|
-
angleIndex:
|
|
27015
|
-
angle:
|
|
27016
|
-
angle:
|
|
27017
|
-
buyerPersona:
|
|
27018
|
-
actor:
|
|
27019
|
-
actorId:
|
|
27020
|
-
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([
|
|
27021
27243
|
"female",
|
|
27022
27244
|
"male"
|
|
27023
27245
|
]).optional(),
|
|
27024
|
-
scriptNotes:
|
|
27246
|
+
scriptNotes: z115.string().max(2e3).optional()
|
|
27025
27247
|
})
|
|
27026
27248
|
});
|
|
27027
|
-
var PendingActionPayload =
|
|
27028
|
-
|
|
27029
|
-
kind:
|
|
27249
|
+
var PendingActionPayload = z115.discriminatedUnion("kind", [
|
|
27250
|
+
z115.object({
|
|
27251
|
+
kind: z115.literal("product_reference_set_approval"),
|
|
27030
27252
|
scope: ProductReferenceScopeEnum.optional(),
|
|
27031
|
-
scopeKey:
|
|
27032
|
-
scopeSnapshotId:
|
|
27033
|
-
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(),
|
|
27034
27256
|
decision: ProductReferenceResolutionDecisionEnum,
|
|
27035
27257
|
reason: ProductReferenceRejectionReasonEnum.optional(),
|
|
27036
|
-
affectedRefKeys:
|
|
27037
|
-
affectedPhotoNumbers:
|
|
27038
|
-
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([
|
|
27039
27261
|
"remove",
|
|
27040
27262
|
"replace",
|
|
27041
27263
|
"upload",
|
|
27042
27264
|
"return_to_selection"
|
|
27043
27265
|
]).optional()
|
|
27044
27266
|
}),
|
|
27045
|
-
|
|
27046
|
-
kind:
|
|
27047
|
-
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."),
|
|
27048
27270
|
userChoice: ProductReferenceUserChoiceEnum.optional(),
|
|
27049
|
-
confirmedProductNames:
|
|
27271
|
+
confirmedProductNames: z115.array(z115.string().min(1).max(120)).min(2).max(8).optional(),
|
|
27050
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."),
|
|
27051
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."),
|
|
27052
|
-
useMultiSceneShowcase:
|
|
27274
|
+
useMultiSceneShowcase: z115.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
|
|
27053
27275
|
}),
|
|
27054
|
-
|
|
27055
|
-
kind:
|
|
27276
|
+
z115.object({
|
|
27277
|
+
kind: z115.literal("angle_review_approval"),
|
|
27056
27278
|
// All edits are optional — empty action body just approves the
|
|
27057
27279
|
// backend-generated draft as-is. Field shapes mirror the angle-review
|
|
27058
27280
|
// request contracts in @packages/types/wizard.ts; the handler routes to
|
|
27059
27281
|
// the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
|
|
27060
|
-
customAngle:
|
|
27282
|
+
customAngle: z115.string().min(1).max(480).optional(),
|
|
27061
27283
|
// Keep the shared MCP action within the strictest downstream contract:
|
|
27062
27284
|
// autopilot/image resume endpoints cap these fields at 1500 characters.
|
|
27063
|
-
painPoints:
|
|
27064
|
-
benefits:
|
|
27285
|
+
painPoints: z115.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
27286
|
+
benefits: z115.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
27065
27287
|
// Same policy as the two fields above: the strictest downstream contract
|
|
27066
27288
|
// wins. The image endpoint caps each feature at 240 while landing/video
|
|
27067
27289
|
// accept 300, and this single action routes to whichever the task is — so
|
|
27068
27290
|
// accepting 300 here turns a 250-character feature on an image task into
|
|
27069
27291
|
// an opaque HTTP 400 after the model already believed it had been saved.
|
|
27070
|
-
features:
|
|
27071
|
-
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(),
|
|
27072
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.'),
|
|
27073
|
-
actor:
|
|
27074
|
-
actorId:
|
|
27075
|
-
creativeDirection:
|
|
27076
|
-
selectedAngleNumbers:
|
|
27077
|
-
angleEdits:
|
|
27078
|
-
angleNumber:
|
|
27079
|
-
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([
|
|
27080
27302
|
"market",
|
|
27081
27303
|
"guided"
|
|
27082
27304
|
]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
|
|
27083
|
-
angle:
|
|
27084
|
-
buyerPersona:
|
|
27305
|
+
angle: z115.string().min(1).max(480).optional(),
|
|
27306
|
+
buyerPersona: z115.string().min(1).max(360).optional(),
|
|
27085
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.'),
|
|
27086
|
-
actor:
|
|
27087
|
-
actorId:
|
|
27088
|
-
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()
|
|
27089
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)."),
|
|
27090
|
-
gapDurationSeconds:
|
|
27091
|
-
|
|
27092
|
-
|
|
27312
|
+
gapDurationSeconds: z115.union([
|
|
27313
|
+
z115.literal(15),
|
|
27314
|
+
z115.literal(30)
|
|
27093
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.")
|
|
27094
27316
|
}),
|
|
27095
|
-
|
|
27096
|
-
kind:
|
|
27097
|
-
angleId:
|
|
27098
|
-
angleNumber:
|
|
27099
|
-
content:
|
|
27100
|
-
creativeDirection:
|
|
27101
|
-
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()
|
|
27102
27324
|
}),
|
|
27103
|
-
|
|
27104
|
-
kind:
|
|
27105
|
-
voiceovers:
|
|
27106
|
-
visualDirections:
|
|
27107
|
-
voiceoversByScene:
|
|
27108
|
-
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()
|
|
27109
27331
|
})
|
|
27110
27332
|
]);
|
|
27111
|
-
var ResolvePendingActionInput =
|
|
27112
|
-
taskId:
|
|
27333
|
+
var ResolvePendingActionInput = z115.object({
|
|
27334
|
+
taskId: z115.string().min(1),
|
|
27113
27335
|
action: PendingActionPayload
|
|
27114
27336
|
}).strict();
|
|
27115
27337
|
function resolveVariantConfirmVideoTier(action) {
|
|
27116
27338
|
return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
|
|
27117
27339
|
}
|
|
27118
27340
|
__name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
|
|
27119
|
-
var StatusForResolveSchema =
|
|
27341
|
+
var StatusForResolveSchema = z115.object({
|
|
27120
27342
|
// Metadata used to select the backend resume contract. Older API responses
|
|
27121
27343
|
// may omit these fields, so the resolver keeps the generic fallback.
|
|
27122
|
-
kind:
|
|
27344
|
+
kind: z115.enum([
|
|
27123
27345
|
"autopilot",
|
|
27124
27346
|
"video",
|
|
27125
27347
|
"image",
|
|
@@ -27127,18 +27349,18 @@ var StatusForResolveSchema = z113.object({
|
|
|
27127
27349
|
"mix",
|
|
27128
27350
|
"service"
|
|
27129
27351
|
]).optional(),
|
|
27130
|
-
selectedOutputs:
|
|
27352
|
+
selectedOutputs: z115.array(z115.enum([
|
|
27131
27353
|
"landing",
|
|
27132
27354
|
"video",
|
|
27133
27355
|
"image"
|
|
27134
27356
|
])).optional(),
|
|
27135
|
-
videoAngleCount:
|
|
27136
|
-
ugcFormat:
|
|
27357
|
+
videoAngleCount: z115.number().int().min(1).max(3).optional(),
|
|
27358
|
+
ugcFormat: z115.enum([
|
|
27137
27359
|
"single_8s",
|
|
27138
27360
|
"single_15s",
|
|
27139
27361
|
"double_30s"
|
|
27140
27362
|
]).optional(),
|
|
27141
|
-
videoStyle:
|
|
27363
|
+
videoStyle: z115.enum([
|
|
27142
27364
|
"ugc",
|
|
27143
27365
|
"cartoon_3d",
|
|
27144
27366
|
"product_only",
|
|
@@ -27148,13 +27370,13 @@ var StatusForResolveSchema = z113.object({
|
|
|
27148
27370
|
videoQuality: VideoQualityEnum.optional(),
|
|
27149
27371
|
videoRouteId: VideoRouteIdEnum.optional(),
|
|
27150
27372
|
videoModel: TaskVideoModelEnum.optional(),
|
|
27151
|
-
videoTier:
|
|
27373
|
+
videoTier: z115.enum([
|
|
27152
27374
|
"legacy",
|
|
27153
27375
|
"standard",
|
|
27154
27376
|
"pro",
|
|
27155
27377
|
"single_call"
|
|
27156
27378
|
]).optional(),
|
|
27157
|
-
videoResolution:
|
|
27379
|
+
videoResolution: z115.enum([
|
|
27158
27380
|
"480p",
|
|
27159
27381
|
"720p"
|
|
27160
27382
|
]).optional(),
|
|
@@ -27162,60 +27384,60 @@ var StatusForResolveSchema = z113.object({
|
|
|
27162
27384
|
// A task created before a narrative was blocked/hidden must still parse,
|
|
27163
27385
|
// or resolve_pending_action could never approve it.
|
|
27164
27386
|
narrativeStyle: NarrativeStyle.optional(),
|
|
27165
|
-
pauseForVideoScriptReview:
|
|
27166
|
-
pendingUserAction:
|
|
27167
|
-
kind:
|
|
27168
|
-
candidateGrouping:
|
|
27169
|
-
selectedImageUrls:
|
|
27170
|
-
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(),
|
|
27171
27393
|
// Adaptive reference questions are server-owned. Echo only the evidence
|
|
27172
27394
|
// identity and the choices shown by the current snapshot; never accept a
|
|
27173
27395
|
// client-supplied reference set as authorization.
|
|
27174
|
-
options:
|
|
27175
|
-
mode:
|
|
27396
|
+
options: z115.array(ProductReferenceUserChoiceEnum).max(4).optional(),
|
|
27397
|
+
mode: z115.enum([
|
|
27176
27398
|
"question",
|
|
27177
27399
|
"visual_recovery"
|
|
27178
27400
|
]).optional(),
|
|
27179
27401
|
/** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
|
|
27180
|
-
canKeepSelection:
|
|
27181
|
-
decisionKey:
|
|
27182
|
-
questionOrdinal:
|
|
27183
|
-
questionCeiling:
|
|
27184
|
-
|
|
27185
|
-
|
|
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)
|
|
27186
27408
|
]).optional(),
|
|
27187
|
-
referenceEvidenceVersion:
|
|
27188
|
-
expectedEvidenceHash:
|
|
27189
|
-
question:
|
|
27190
|
-
prompt:
|
|
27191
|
-
helpText:
|
|
27192
|
-
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({
|
|
27193
27415
|
value: ProductReferenceUserChoiceEnum,
|
|
27194
|
-
label:
|
|
27195
|
-
description:
|
|
27416
|
+
label: z115.string().min(1).max(120),
|
|
27417
|
+
description: z115.string().min(1).max(240).optional()
|
|
27196
27418
|
})).min(2).max(4)
|
|
27197
27419
|
}).optional(),
|
|
27198
27420
|
scope: ProductReferenceScopeEnum.optional(),
|
|
27199
|
-
scopeKey:
|
|
27200
|
-
scopeSnapshotId:
|
|
27201
|
-
scopeHash:
|
|
27202
|
-
baseReferenceSetHash:
|
|
27203
|
-
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([
|
|
27204
27426
|
"preparation",
|
|
27205
27427
|
"final"
|
|
27206
27428
|
]).optional(),
|
|
27207
|
-
selectedRefKeys:
|
|
27208
|
-
allowedDecisions:
|
|
27209
|
-
previews:
|
|
27210
|
-
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)
|
|
27211
27433
|
}).passthrough()).optional(),
|
|
27212
|
-
customAngleDraft:
|
|
27213
|
-
painPointsDraft:
|
|
27214
|
-
benefitsDraft:
|
|
27215
|
-
featuresDraft:
|
|
27216
|
-
angleOptions:
|
|
27217
|
-
index:
|
|
27218
|
-
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)
|
|
27219
27441
|
}).passthrough()).min(1).max(5).optional(),
|
|
27220
27442
|
// Recommendation consumed only when the caller explicitly sends
|
|
27221
27443
|
// gapDurationSeconds: 30 in the angle approval action.
|
|
@@ -27225,17 +27447,17 @@ var StatusForResolveSchema = z113.object({
|
|
|
27225
27447
|
// keys. `actorId` (the saved custom actor the picker stored) was silently
|
|
27226
27448
|
// dropped here, so the approval handler below could not echo it back on the
|
|
27227
27449
|
// PATCH — the selection looked accepted and reached no render.
|
|
27228
|
-
angles:
|
|
27229
|
-
id:
|
|
27230
|
-
content:
|
|
27231
|
-
creativeDirection:
|
|
27232
|
-
actor:
|
|
27233
|
-
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()
|
|
27234
27456
|
}).passthrough()).optional(),
|
|
27235
|
-
panels:
|
|
27236
|
-
beatId:
|
|
27237
|
-
voiceover:
|
|
27238
|
-
visualDirection:
|
|
27457
|
+
panels: z115.array(z115.object({
|
|
27458
|
+
beatId: z115.string(),
|
|
27459
|
+
voiceover: z115.string(),
|
|
27460
|
+
visualDirection: z115.string()
|
|
27239
27461
|
}).passthrough()).optional()
|
|
27240
27462
|
}).optional()
|
|
27241
27463
|
}).passthrough();
|
|
@@ -27587,8 +27809,8 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
27587
27809
|
server.registerTool("verify_landing_commerce", {
|
|
27588
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.",
|
|
27589
27811
|
inputSchema: {
|
|
27590
|
-
taskId:
|
|
27591
|
-
editId:
|
|
27812
|
+
taskId: z115.string().uuid(),
|
|
27813
|
+
editId: z115.string().uuid()
|
|
27592
27814
|
},
|
|
27593
27815
|
annotations: OVERWRITES_EXTERNAL
|
|
27594
27816
|
}, async (input) => {
|
|
@@ -28234,25 +28456,25 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
28234
28456
|
__name(registerTaskTools, "registerTaskTools");
|
|
28235
28457
|
|
|
28236
28458
|
// src/tools/brands.ts
|
|
28237
|
-
import { z as
|
|
28459
|
+
import { z as z116 } from "zod";
|
|
28238
28460
|
var guidance2 = getProductMakerCapabilityModelGuidance("create_brand");
|
|
28239
28461
|
var BRAND_START_REPLAY_WINDOW_MS = 15 * 60 * 1e3;
|
|
28240
28462
|
var BRAND_NOTES_MAX_CHARS = 2e4;
|
|
28241
|
-
var CreateBrandInput =
|
|
28242
|
-
action:
|
|
28463
|
+
var CreateBrandInput = z116.object({
|
|
28464
|
+
action: z116.enum([
|
|
28243
28465
|
"start",
|
|
28244
28466
|
"status",
|
|
28245
28467
|
"list"
|
|
28246
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."),
|
|
28247
|
-
sourceUrl:
|
|
28248
|
-
businessNotes:
|
|
28249
|
-
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([
|
|
28250
28472
|
"es",
|
|
28251
28473
|
"en",
|
|
28252
28474
|
"pt"
|
|
28253
28475
|
]).optional().describe("Idioma de la conversaci\xF3n. Solo se usa si la p\xE1gina del negocio no deja claro su idioma."),
|
|
28254
|
-
confirmed:
|
|
28255
|
-
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.")
|
|
28256
28478
|
}).strict();
|
|
28257
28479
|
function normalizeBrandSourceUrl(raw) {
|
|
28258
28480
|
const value = raw.trim();
|
|
@@ -28492,24 +28714,24 @@ __name(registerBrandTools, "registerBrandTools");
|
|
|
28492
28714
|
|
|
28493
28715
|
// src/tools/service-landing.ts
|
|
28494
28716
|
import { createHash as createHash4 } from "crypto";
|
|
28495
|
-
import { z as
|
|
28717
|
+
import { z as z117 } from "zod";
|
|
28496
28718
|
var guidance3 = getProductMakerCapabilityModelGuidance("create_service_landing");
|
|
28497
28719
|
var SERVICE_LANDING_KEY_NAMESPACE = "6f1d8c2a-3b4e-5f60-8a7b-9c0d1e2f3a4b";
|
|
28498
28720
|
var SERVICE_LANDING_INFO_MAX_CHARS = 2e4;
|
|
28499
|
-
var CreateServiceLandingInput =
|
|
28500
|
-
action:
|
|
28721
|
+
var CreateServiceLandingInput = z117.object({
|
|
28722
|
+
action: z117.enum([
|
|
28501
28723
|
"prepare",
|
|
28502
28724
|
"build",
|
|
28503
28725
|
"status",
|
|
28504
28726
|
"publish"
|
|
28505
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."),
|
|
28506
|
-
brandId:
|
|
28507
|
-
servicePageId:
|
|
28508
|
-
businessInfo:
|
|
28509
|
-
confirmed:
|
|
28510
|
-
maxCredits:
|
|
28511
|
-
operationId:
|
|
28512
|
-
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.")
|
|
28513
28735
|
}).strict();
|
|
28514
28736
|
var SERVICE_LANDING_MAX_BUILD_ATTEMPTS = 10;
|
|
28515
28737
|
function serviceKey(...parts) {
|
|
@@ -28731,9 +28953,6 @@ function registerServiceLandingTools(server, api) {
|
|
|
28731
28953
|
let operation2 = null;
|
|
28732
28954
|
if (input.operationId) {
|
|
28733
28955
|
operation2 = await api.getJson(`/v1/service-pages/operations/${encodeURIComponent(input.operationId)}`);
|
|
28734
|
-
if (operation2.recoverable && (operation2.status === "failed" || operation2.status === "requires_reconciliation")) {
|
|
28735
|
-
operation2 = await api.postJson(`${pagePath(input.servicePageId)}/operations/${encodeURIComponent(operation2.opId)}/recover`, {});
|
|
28736
|
-
}
|
|
28737
28956
|
if (operation2.status === "queued" || operation2.status === "running") {
|
|
28738
28957
|
return asText({
|
|
28739
28958
|
servicePageId: input.servicePageId,
|
|
@@ -28750,7 +28969,7 @@ function registerServiceLandingTools(server, api) {
|
|
|
28750
28969
|
status: "in_review",
|
|
28751
28970
|
// Unknown on purpose: the charge is exactly what is being
|
|
28752
28971
|
// confirmed. Settlement only charges a completed step.
|
|
28753
|
-
nextAction: "Esta etapa qued\xF3 en revisi\xF3n por un problema temporal:
|
|
28972
|
+
nextAction: "Esta etapa qued\xF3 en revisi\xF3n por un problema temporal: el servidor est\xE1 confirmando si se complet\xF3 y la resuelve solo. Si no se completa, se devuelve lo cobrado. Dile al usuario que sus datos est\xE1n guardados; vuelve a llamar action=status con el mismo operationId en unos minutos (si no se complet\xF3, pasa a fallida y la reintentas con build). No inicies otra etapa mientras tanto."
|
|
28754
28973
|
});
|
|
28755
28974
|
}
|
|
28756
28975
|
if (operation2.status !== "succeeded") {
|
|
@@ -28845,7 +29064,7 @@ function registerServiceLandingTools(server, api) {
|
|
|
28845
29064
|
__name(registerServiceLandingTools, "registerServiceLandingTools");
|
|
28846
29065
|
|
|
28847
29066
|
// src/tools/service-images.ts
|
|
28848
|
-
import { z as
|
|
29067
|
+
import { z as z118 } from "zod";
|
|
28849
29068
|
var guidance4 = getProductMakerCapabilityModelGuidance("create_service_images");
|
|
28850
29069
|
var SERVICE_IMAGE_FORMATS = [
|
|
28851
29070
|
"4:5",
|
|
@@ -28858,23 +29077,23 @@ var LANGUAGE_TAGS = {
|
|
|
28858
29077
|
en: "en-US",
|
|
28859
29078
|
pt: "pt-BR"
|
|
28860
29079
|
};
|
|
28861
|
-
var CreateServiceImagesInput =
|
|
28862
|
-
brandId:
|
|
28863
|
-
instruction:
|
|
28864
|
-
delegateToAi:
|
|
28865
|
-
format:
|
|
28866
|
-
count:
|
|
28867
|
-
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([
|
|
28868
29087
|
"standard",
|
|
28869
29088
|
"high"
|
|
28870
29089
|
]).optional().describe('Calidad: "standard" (por defecto) o "high" (m\xE1s cara; no disponible en 4:5).'),
|
|
28871
|
-
language:
|
|
29090
|
+
language: z118.enum([
|
|
28872
29091
|
"es",
|
|
28873
29092
|
"en",
|
|
28874
29093
|
"pt"
|
|
28875
29094
|
]).optional().describe("Idioma de los textos de la imagen (por defecto es)."),
|
|
28876
|
-
adCopy:
|
|
28877
|
-
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.")
|
|
28878
29097
|
}).strict();
|
|
28879
29098
|
function serviceImageModel(quality) {
|
|
28880
29099
|
return quality === "high" ? AD_CREATIVE_MODELS.PREMIUM : AD_CREATIVE_MODELS.STANDARD;
|
|
@@ -28985,7 +29204,7 @@ function registerServiceImageTools(server, api, options = {}) {
|
|
|
28985
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."
|
|
28986
29205
|
});
|
|
28987
29206
|
} catch (error) {
|
|
28988
|
-
if (error instanceof
|
|
29207
|
+
if (error instanceof z118.ZodError) throw invalidInputFromZod(error);
|
|
28989
29208
|
throw translateError(error);
|
|
28990
29209
|
}
|
|
28991
29210
|
});
|
|
@@ -28993,7 +29212,7 @@ function registerServiceImageTools(server, api, options = {}) {
|
|
|
28993
29212
|
__name(registerServiceImageTools, "registerServiceImageTools");
|
|
28994
29213
|
|
|
28995
29214
|
// src/tools/creatives.ts
|
|
28996
|
-
import { z as
|
|
29215
|
+
import { z as z119 } from "zod";
|
|
28997
29216
|
var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
|
|
28998
29217
|
var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
|
|
28999
29218
|
var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
|
|
@@ -29004,72 +29223,72 @@ var CreativeRefs = {
|
|
|
29004
29223
|
images: ImagesInput,
|
|
29005
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.'),
|
|
29006
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.'),
|
|
29007
|
-
price:
|
|
29008
|
-
offer:
|
|
29009
|
-
compareAtPrice:
|
|
29010
|
-
productContext:
|
|
29011
|
-
productLabel:
|
|
29012
|
-
buyerPersona:
|
|
29013
|
-
isCombo:
|
|
29014
|
-
competitorScanEnabled:
|
|
29015
|
-
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.")
|
|
29016
29235
|
};
|
|
29017
|
-
var VideoPresenter =
|
|
29018
|
-
|
|
29019
|
-
mode:
|
|
29236
|
+
var VideoPresenter = z119.discriminatedUnion("mode", [
|
|
29237
|
+
z119.object({
|
|
29238
|
+
mode: z119.literal("none")
|
|
29020
29239
|
}).strict(),
|
|
29021
|
-
|
|
29022
|
-
mode:
|
|
29023
|
-
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.")
|
|
29024
29243
|
}).strict(),
|
|
29025
|
-
|
|
29026
|
-
mode:
|
|
29027
|
-
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.")
|
|
29028
29247
|
}).strict()
|
|
29029
29248
|
]);
|
|
29030
|
-
var VideoCreativeSetup =
|
|
29031
|
-
|
|
29032
|
-
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".')
|
|
29033
29252
|
}).strict(),
|
|
29034
|
-
|
|
29035
|
-
mode:
|
|
29253
|
+
z119.object({
|
|
29254
|
+
mode: z119.literal("guided"),
|
|
29036
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.'),
|
|
29037
|
-
buyerPersona:
|
|
29256
|
+
buyerPersona: z119.string().trim().min(1).max(360),
|
|
29038
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.'),
|
|
29039
29258
|
presenter: VideoPresenter,
|
|
29040
|
-
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.")
|
|
29041
29260
|
}).strict()
|
|
29042
29261
|
]);
|
|
29043
|
-
var VideoInput =
|
|
29262
|
+
var VideoInput = z119.object({
|
|
29044
29263
|
images: CreativeRefs.images.optional(),
|
|
29045
29264
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
29046
|
-
title:
|
|
29047
|
-
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".'),
|
|
29048
29267
|
language: CreativeRefs.language,
|
|
29049
29268
|
country: CreativeRefs.country,
|
|
29050
|
-
aspectRatio:
|
|
29269
|
+
aspectRatio: z119.enum([
|
|
29051
29270
|
"9:16",
|
|
29052
29271
|
"16:9",
|
|
29053
29272
|
"Auto"
|
|
29054
29273
|
]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
|
|
29055
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.'),
|
|
29056
|
-
durationSeconds:
|
|
29057
|
-
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."),
|
|
29058
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.'),
|
|
29059
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."),
|
|
29060
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.'),
|
|
29061
29280
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
|
|
29062
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.'),
|
|
29063
|
-
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"].'),
|
|
29064
29283
|
price: CreativeRefs.price,
|
|
29065
29284
|
offer: CreativeRefs.offer,
|
|
29066
29285
|
productContext: CreativeRefs.productContext,
|
|
29067
29286
|
productLabel: CreativeRefs.productLabel,
|
|
29068
|
-
cta:
|
|
29069
|
-
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.'),
|
|
29070
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.'),
|
|
29071
29290
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
29072
|
-
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."),
|
|
29073
29292
|
brandId: CreativeRefs.brandId
|
|
29074
29293
|
}).strict();
|
|
29075
29294
|
var FreeVideoQualityEnum = VideoQualityEnum;
|
|
@@ -29087,7 +29306,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
|
|
|
29087
29306
|
length: 29
|
|
29088
29307
|
}, (_, index) => index + 2)
|
|
29089
29308
|
};
|
|
29090
|
-
var FreeVideoModelIdEnum =
|
|
29309
|
+
var FreeVideoModelIdEnum = z119.enum([
|
|
29091
29310
|
"grok-imagine-video-1-5-preview",
|
|
29092
29311
|
"minimax-h3/reference-to-video",
|
|
29093
29312
|
"wan/3-0-video",
|
|
@@ -29098,66 +29317,66 @@ var FREE_SELECTABLE_MODEL_IDS = [
|
|
|
29098
29317
|
"minimax-h3/reference-to-video",
|
|
29099
29318
|
"wan/3-0-video"
|
|
29100
29319
|
];
|
|
29101
|
-
var FreeVideoInput =
|
|
29320
|
+
var FreeVideoInput = z119.object({
|
|
29102
29321
|
images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
|
|
29103
|
-
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."),
|
|
29104
29323
|
language: CreativeRefs.language,
|
|
29105
29324
|
quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
|
|
29106
29325
|
// Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
|
|
29107
29326
|
// parsed ONLY so the handler can reject it with a message naming its
|
|
29108
29327
|
// replacement — dropping it silently would turn a caller's explicit
|
|
29109
29328
|
// Pro++ pick into a quiet fallback to Wan.
|
|
29110
|
-
freeProModel:
|
|
29329
|
+
freeProModel: z119.enum([
|
|
29111
29330
|
"wan",
|
|
29112
29331
|
"seedance"
|
|
29113
29332
|
]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
|
|
29114
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.'),
|
|
29115
|
-
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."),
|
|
29116
29335
|
videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
|
|
29117
|
-
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.'),
|
|
29118
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.'),
|
|
29119
|
-
addSubtitles:
|
|
29120
|
-
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.")
|
|
29121
29340
|
}).strict();
|
|
29122
29341
|
var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
|
|
29123
|
-
var ImageCreativeSetup =
|
|
29124
|
-
|
|
29125
|
-
mode:
|
|
29342
|
+
var ImageCreativeSetup = z119.discriminatedUnion("mode", [
|
|
29343
|
+
z119.object({
|
|
29344
|
+
mode: z119.literal("automatic")
|
|
29126
29345
|
}).strict(),
|
|
29127
|
-
|
|
29128
|
-
mode:
|
|
29129
|
-
creativeArchetype:
|
|
29346
|
+
z119.object({
|
|
29347
|
+
mode: z119.literal("guided"),
|
|
29348
|
+
creativeArchetype: z119.union([
|
|
29130
29349
|
ImageCreativeArchetypeEnum,
|
|
29131
|
-
|
|
29350
|
+
z119.literal("ai_decides")
|
|
29132
29351
|
]),
|
|
29133
|
-
visualTreatment:
|
|
29352
|
+
visualTreatment: z119.union([
|
|
29134
29353
|
ImageCreativeVisualTreatmentEnum,
|
|
29135
|
-
|
|
29354
|
+
z119.literal("ai_decides")
|
|
29136
29355
|
]),
|
|
29137
29356
|
aspectRatio: ImageCreativeAspectRatioEnum,
|
|
29138
|
-
nVariants:
|
|
29139
|
-
|
|
29140
|
-
|
|
29141
|
-
|
|
29142
|
-
|
|
29143
|
-
|
|
29357
|
+
nVariants: z119.union([
|
|
29358
|
+
z119.literal(1),
|
|
29359
|
+
z119.literal(2),
|
|
29360
|
+
z119.literal(3),
|
|
29361
|
+
z119.literal(4),
|
|
29362
|
+
z119.literal(6)
|
|
29144
29363
|
]),
|
|
29145
|
-
imageModel:
|
|
29146
|
-
styleMix:
|
|
29147
|
-
generateAdCopy:
|
|
29148
|
-
competitorScanEnabled:
|
|
29149
|
-
productContext:
|
|
29150
|
-
creativeDirection:
|
|
29151
|
-
brandColors:
|
|
29152
|
-
headline:
|
|
29153
|
-
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()
|
|
29154
29373
|
}).strict()
|
|
29155
29374
|
]).superRefine((setup, context) => {
|
|
29156
29375
|
if (setup.mode !== "guided") return;
|
|
29157
29376
|
const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
|
|
29158
29377
|
if (needsStyleMix && setup.styleMix === null) {
|
|
29159
29378
|
context.addIssue({
|
|
29160
|
-
code:
|
|
29379
|
+
code: z119.ZodIssueCode.custom,
|
|
29161
29380
|
path: [
|
|
29162
29381
|
"styleMix"
|
|
29163
29382
|
],
|
|
@@ -29166,7 +29385,7 @@ var ImageCreativeSetup = z117.discriminatedUnion("mode", [
|
|
|
29166
29385
|
}
|
|
29167
29386
|
if (!needsStyleMix && setup.styleMix !== null) {
|
|
29168
29387
|
context.addIssue({
|
|
29169
|
-
code:
|
|
29388
|
+
code: z119.ZodIssueCode.custom,
|
|
29170
29389
|
path: [
|
|
29171
29390
|
"styleMix"
|
|
29172
29391
|
],
|
|
@@ -29175,7 +29394,7 @@ var ImageCreativeSetup = z117.discriminatedUnion("mode", [
|
|
|
29175
29394
|
}
|
|
29176
29395
|
if (imageResolutionOf(setup.imageModel) === "2k" && setup.aspectRatio === "4:5") {
|
|
29177
29396
|
context.addIssue({
|
|
29178
|
-
code:
|
|
29397
|
+
code: z119.ZodIssueCode.custom,
|
|
29179
29398
|
path: [
|
|
29180
29399
|
"aspectRatio"
|
|
29181
29400
|
],
|
|
@@ -29183,55 +29402,55 @@ var ImageCreativeSetup = z117.discriminatedUnion("mode", [
|
|
|
29183
29402
|
});
|
|
29184
29403
|
}
|
|
29185
29404
|
});
|
|
29186
|
-
var LandingCreativeSetup =
|
|
29187
|
-
|
|
29188
|
-
mode:
|
|
29405
|
+
var LandingCreativeSetup = z119.discriminatedUnion("mode", [
|
|
29406
|
+
z119.object({
|
|
29407
|
+
mode: z119.literal("automatic")
|
|
29189
29408
|
}).strict(),
|
|
29190
|
-
|
|
29191
|
-
mode:
|
|
29409
|
+
z119.object({
|
|
29410
|
+
mode: z119.literal("guided"),
|
|
29192
29411
|
landingStrategy: LandingStrategyEnum,
|
|
29193
29412
|
landingImageFormat: LandingImageFormatEnum,
|
|
29194
|
-
competitorScanEnabled:
|
|
29195
|
-
paymentMethods:
|
|
29196
|
-
productContext:
|
|
29197
|
-
creativeDirection:
|
|
29198
|
-
headline:
|
|
29199
|
-
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()
|
|
29200
29419
|
}).strict()
|
|
29201
29420
|
]);
|
|
29202
|
-
var ImageInput =
|
|
29421
|
+
var ImageInput = z119.object({
|
|
29203
29422
|
images: CreativeRefs.images.optional(),
|
|
29204
29423
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
29205
|
-
productTitle:
|
|
29206
|
-
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.'),
|
|
29207
29426
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
29208
29427
|
language: CreativeRefs.language,
|
|
29209
29428
|
country: CreativeRefs.country,
|
|
29210
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."),
|
|
29211
29430
|
imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
|
|
29212
|
-
features:
|
|
29431
|
+
features: z119.array(z119.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
|
|
29213
29432
|
price: CreativeRefs.price,
|
|
29214
|
-
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."),
|
|
29215
29434
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
29216
29435
|
offer: CreativeRefs.offer,
|
|
29217
29436
|
productLabel: CreativeRefs.productLabel,
|
|
29218
29437
|
isCombo: CreativeRefs.isCombo,
|
|
29219
29438
|
brandId: CreativeRefs.brandId
|
|
29220
29439
|
});
|
|
29221
|
-
var EditImageCreativeInput =
|
|
29222
|
-
taskId:
|
|
29223
|
-
variantIndex:
|
|
29224
|
-
clientRequestId:
|
|
29225
|
-
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".')
|
|
29226
29445
|
});
|
|
29227
|
-
var LandingInput =
|
|
29228
|
-
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."),
|
|
29229
29448
|
images: CreativeRefs.images.optional(),
|
|
29230
29449
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
29231
29450
|
language: CreativeRefs.language,
|
|
29232
29451
|
country: CreativeRefs.country,
|
|
29233
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."),
|
|
29234
|
-
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.'),
|
|
29235
29454
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
29236
29455
|
price: CreativeRefs.price,
|
|
29237
29456
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
@@ -29513,8 +29732,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
29513
29732
|
server.registerTool("get_image_edit_status", {
|
|
29514
29733
|
description: imageEditStatusGuidance.summary,
|
|
29515
29734
|
inputSchema: {
|
|
29516
|
-
taskId:
|
|
29517
|
-
operationId:
|
|
29735
|
+
taskId: z119.string().uuid(),
|
|
29736
|
+
operationId: z119.string().uuid()
|
|
29518
29737
|
},
|
|
29519
29738
|
annotations: READS_INTERNAL
|
|
29520
29739
|
}, async (input) => {
|
|
@@ -29571,10 +29790,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
29571
29790
|
__name(registerCreativeTools, "registerCreativeTools");
|
|
29572
29791
|
|
|
29573
29792
|
// src/tools/creative-variants.ts
|
|
29574
|
-
import { z as
|
|
29793
|
+
import { z as z120 } from "zod";
|
|
29575
29794
|
var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
|
|
29576
29795
|
var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
|
|
29577
|
-
var LandingSectionKeyEnum =
|
|
29796
|
+
var LandingSectionKeyEnum = z120.enum([
|
|
29578
29797
|
"problem_hook",
|
|
29579
29798
|
"problem_cost",
|
|
29580
29799
|
"solution_mechanism",
|
|
@@ -29614,24 +29833,24 @@ var LandingSectionKeyEnum = z118.enum([
|
|
|
29614
29833
|
"lifestyle_fit",
|
|
29615
29834
|
"join_lifestyle"
|
|
29616
29835
|
]);
|
|
29617
|
-
var CreativeVariantKindEnum =
|
|
29836
|
+
var CreativeVariantKindEnum = z120.enum([
|
|
29618
29837
|
"video",
|
|
29619
29838
|
"image",
|
|
29620
29839
|
"landing"
|
|
29621
29840
|
]);
|
|
29622
|
-
var EstimateCreativeVariantInputBase =
|
|
29623
|
-
sourceTaskId:
|
|
29841
|
+
var EstimateCreativeVariantInputBase = z120.object({
|
|
29842
|
+
sourceTaskId: z120.string().uuid().describe("ID de la tarea original completada."),
|
|
29624
29843
|
kind: CreativeVariantKindEnum,
|
|
29625
29844
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
|
|
29626
29845
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
|
|
29627
|
-
nVariants:
|
|
29846
|
+
nVariants: z120.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
29628
29847
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
|
|
29629
|
-
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.")
|
|
29630
29849
|
}).strict();
|
|
29631
29850
|
var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
29632
29851
|
if (input.kind === "video" && input.nVariants !== void 0) {
|
|
29633
29852
|
ctx.addIssue({
|
|
29634
|
-
code:
|
|
29853
|
+
code: z120.ZodIssueCode.custom,
|
|
29635
29854
|
path: [
|
|
29636
29855
|
"nVariants"
|
|
29637
29856
|
],
|
|
@@ -29641,7 +29860,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
29641
29860
|
if (input.kind !== "video") {
|
|
29642
29861
|
if (input.videoPreset !== void 0) {
|
|
29643
29862
|
ctx.addIssue({
|
|
29644
|
-
code:
|
|
29863
|
+
code: z120.ZodIssueCode.custom,
|
|
29645
29864
|
path: [
|
|
29646
29865
|
"videoPreset"
|
|
29647
29866
|
],
|
|
@@ -29650,7 +29869,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
29650
29869
|
}
|
|
29651
29870
|
if (input.videoResolution !== void 0) {
|
|
29652
29871
|
ctx.addIssue({
|
|
29653
|
-
code:
|
|
29872
|
+
code: z120.ZodIssueCode.custom,
|
|
29654
29873
|
path: [
|
|
29655
29874
|
"videoResolution"
|
|
29656
29875
|
],
|
|
@@ -29660,7 +29879,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
29660
29879
|
}
|
|
29661
29880
|
if (input.kind !== "image" && input.nVariants !== void 0) {
|
|
29662
29881
|
ctx.addIssue({
|
|
29663
|
-
code:
|
|
29882
|
+
code: z120.ZodIssueCode.custom,
|
|
29664
29883
|
path: [
|
|
29665
29884
|
"nVariants"
|
|
29666
29885
|
],
|
|
@@ -29670,7 +29889,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
29670
29889
|
if (input.kind !== "landing") {
|
|
29671
29890
|
if (input.sectionKey !== void 0) {
|
|
29672
29891
|
ctx.addIssue({
|
|
29673
|
-
code:
|
|
29892
|
+
code: z120.ZodIssueCode.custom,
|
|
29674
29893
|
path: [
|
|
29675
29894
|
"sectionKey"
|
|
29676
29895
|
],
|
|
@@ -29679,7 +29898,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
29679
29898
|
}
|
|
29680
29899
|
if (input.instructions !== void 0) {
|
|
29681
29900
|
ctx.addIssue({
|
|
29682
|
-
code:
|
|
29901
|
+
code: z120.ZodIssueCode.custom,
|
|
29683
29902
|
path: [
|
|
29684
29903
|
"instructions"
|
|
29685
29904
|
],
|
|
@@ -29688,31 +29907,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
29688
29907
|
}
|
|
29689
29908
|
}
|
|
29690
29909
|
});
|
|
29691
|
-
var CreateCreativeVariantInputBase =
|
|
29692
|
-
sourceTaskId:
|
|
29910
|
+
var CreateCreativeVariantInputBase = z120.object({
|
|
29911
|
+
sourceTaskId: z120.string().uuid().describe("ID de la tarea original completada."),
|
|
29693
29912
|
kind: CreativeVariantKindEnum,
|
|
29694
|
-
confirm:
|
|
29695
|
-
clientRequestId:
|
|
29696
|
-
angle:
|
|
29697
|
-
buyerPersona:
|
|
29698
|
-
scriptNotes:
|
|
29699
|
-
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."),
|
|
29700
29919
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
|
|
29701
29920
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
|
|
29702
|
-
generateAiMusic:
|
|
29703
|
-
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)."),
|
|
29704
29923
|
imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
|
|
29705
29924
|
creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
|
|
29706
29925
|
visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
|
|
29707
29926
|
aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
|
|
29708
|
-
styleMix:
|
|
29927
|
+
styleMix: z120.boolean().optional().describe("Opcional para imagen."),
|
|
29709
29928
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
|
|
29710
|
-
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.")
|
|
29711
29930
|
}).strict();
|
|
29712
29931
|
var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
29713
29932
|
if ((input.kind === "video" || input.kind === "image") && !input.angle) {
|
|
29714
29933
|
ctx.addIssue({
|
|
29715
|
-
code:
|
|
29934
|
+
code: z120.ZodIssueCode.custom,
|
|
29716
29935
|
path: [
|
|
29717
29936
|
"angle"
|
|
29718
29937
|
],
|
|
@@ -29721,7 +29940,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
29721
29940
|
}
|
|
29722
29941
|
if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
|
|
29723
29942
|
ctx.addIssue({
|
|
29724
|
-
code:
|
|
29943
|
+
code: z120.ZodIssueCode.custom,
|
|
29725
29944
|
path: [
|
|
29726
29945
|
"instructions"
|
|
29727
29946
|
],
|
|
@@ -29767,7 +29986,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
29767
29986
|
for (const field of fieldsByKind[input.kind]) {
|
|
29768
29987
|
if (input[field] !== void 0) {
|
|
29769
29988
|
ctx.addIssue({
|
|
29770
|
-
code:
|
|
29989
|
+
code: z120.ZodIssueCode.custom,
|
|
29771
29990
|
path: [
|
|
29772
29991
|
field
|
|
29773
29992
|
],
|
|
@@ -29900,13 +30119,13 @@ function registerCreativeVariantTools(server, api) {
|
|
|
29900
30119
|
__name(registerCreativeVariantTools, "registerCreativeVariantTools");
|
|
29901
30120
|
|
|
29902
30121
|
// src/tools/script-review.ts
|
|
29903
|
-
import { z as
|
|
30122
|
+
import { z as z121 } from "zod";
|
|
29904
30123
|
var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
|
|
29905
30124
|
var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
|
|
29906
30125
|
var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
|
|
29907
|
-
var GetVideoScriptInput =
|
|
29908
|
-
taskId:
|
|
29909
|
-
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.')
|
|
29910
30129
|
}).strict();
|
|
29911
30130
|
var ApproveVideoScriptInput = ApproveVideoScriptCapabilityRequest;
|
|
29912
30131
|
var RegenerateVideoScriptInput = RegenerateVideoScriptCapabilityRequest.extend({
|
|
@@ -29989,7 +30208,7 @@ function registerScriptReviewTools(server, api) {
|
|
|
29989
30208
|
__name(registerScriptReviewTools, "registerScriptReviewTools");
|
|
29990
30209
|
|
|
29991
30210
|
// src/tools/connections.ts
|
|
29992
|
-
import { z as
|
|
30211
|
+
import { z as z122 } from "zod";
|
|
29993
30212
|
var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
|
|
29994
30213
|
var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
|
|
29995
30214
|
var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
|
|
@@ -29998,7 +30217,7 @@ var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list
|
|
|
29998
30217
|
function registerConnectionTools(server, api) {
|
|
29999
30218
|
server.registerTool("list_shopify_shops", {
|
|
30000
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.",
|
|
30001
|
-
inputSchema:
|
|
30220
|
+
inputSchema: z122.object({}).shape,
|
|
30002
30221
|
annotations: READS_INTERNAL
|
|
30003
30222
|
}, async () => {
|
|
30004
30223
|
try {
|
|
@@ -30010,10 +30229,10 @@ function registerConnectionTools(server, api) {
|
|
|
30010
30229
|
});
|
|
30011
30230
|
server.registerTool("list_shopify_products", {
|
|
30012
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.',
|
|
30013
|
-
inputSchema:
|
|
30014
|
-
shopDomain:
|
|
30015
|
-
query:
|
|
30016
|
-
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()
|
|
30017
30236
|
}).shape,
|
|
30018
30237
|
annotations: READS_EXTERNAL
|
|
30019
30238
|
}, async ({ shopDomain, query, taskId }) => {
|
|
@@ -30031,7 +30250,7 @@ function registerConnectionTools(server, api) {
|
|
|
30031
30250
|
});
|
|
30032
30251
|
server.registerTool("list_meta_ad_accounts", {
|
|
30033
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.",
|
|
30034
|
-
inputSchema:
|
|
30253
|
+
inputSchema: z122.object({}).shape,
|
|
30035
30254
|
annotations: READS_EXTERNAL
|
|
30036
30255
|
}, async () => {
|
|
30037
30256
|
try {
|
|
@@ -30043,7 +30262,7 @@ function registerConnectionTools(server, api) {
|
|
|
30043
30262
|
});
|
|
30044
30263
|
server.registerTool("list_meta_destinations", {
|
|
30045
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.",
|
|
30046
|
-
inputSchema:
|
|
30265
|
+
inputSchema: z122.object({}).shape,
|
|
30047
30266
|
annotations: READS_EXTERNAL,
|
|
30048
30267
|
_meta: {
|
|
30049
30268
|
"openai/widgetAccessible": true
|
|
@@ -30058,7 +30277,7 @@ function registerConnectionTools(server, api) {
|
|
|
30058
30277
|
});
|
|
30059
30278
|
server.registerTool("list_tiktok_advertisers", {
|
|
30060
30279
|
description: listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.",
|
|
30061
|
-
inputSchema:
|
|
30280
|
+
inputSchema: z122.object({}).shape,
|
|
30062
30281
|
annotations: READS_EXTERNAL
|
|
30063
30282
|
}, async () => {
|
|
30064
30283
|
try {
|
|
@@ -30072,7 +30291,7 @@ function registerConnectionTools(server, api) {
|
|
|
30072
30291
|
__name(registerConnectionTools, "registerConnectionTools");
|
|
30073
30292
|
|
|
30074
30293
|
// src/tools/actors.ts
|
|
30075
|
-
import { z as
|
|
30294
|
+
import { z as z123 } from "zod";
|
|
30076
30295
|
var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
|
|
30077
30296
|
var actorVoiceGuidance = {
|
|
30078
30297
|
capabilities: getProductMakerCapabilityModelGuidance("get_actor_voice_capabilities"),
|
|
@@ -30112,7 +30331,7 @@ function sanitizeVoiceResult(value) {
|
|
|
30112
30331
|
__name(sanitizeVoiceResult, "sanitizeVoiceResult");
|
|
30113
30332
|
function registerActorTools(server, api) {
|
|
30114
30333
|
const actor = {
|
|
30115
|
-
actorId:
|
|
30334
|
+
actorId: z123.string().min(1).max(64)
|
|
30116
30335
|
};
|
|
30117
30336
|
const safe = /* @__PURE__ */ __name(async (request) => {
|
|
30118
30337
|
try {
|
|
@@ -30141,8 +30360,8 @@ function registerActorTools(server, api) {
|
|
|
30141
30360
|
inputSchema: {
|
|
30142
30361
|
...actor,
|
|
30143
30362
|
draft: ActorVoiceDraftSchema,
|
|
30144
|
-
requestKey:
|
|
30145
|
-
acceptedQuoteId:
|
|
30363
|
+
requestKey: z123.string().trim().min(1).max(128),
|
|
30364
|
+
acceptedQuoteId: z123.string().trim().min(1).max(128)
|
|
30146
30365
|
},
|
|
30147
30366
|
annotations: CREATES_PAID
|
|
30148
30367
|
}, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/previews`, body)));
|
|
@@ -30150,7 +30369,7 @@ function registerActorTools(server, api) {
|
|
|
30150
30369
|
description: actorVoiceGuidance.get.summary,
|
|
30151
30370
|
inputSchema: {
|
|
30152
30371
|
...actor,
|
|
30153
|
-
candidateId:
|
|
30372
|
+
candidateId: z123.string().min(1).max(64)
|
|
30154
30373
|
},
|
|
30155
30374
|
// Polling can resume the first paid submission of an accepted quote.
|
|
30156
30375
|
// The immutable candidate/operation key keeps recovery idempotent.
|
|
@@ -30163,16 +30382,16 @@ function registerActorTools(server, api) {
|
|
|
30163
30382
|
description: actorVoiceGuidance.approve.summary,
|
|
30164
30383
|
inputSchema: {
|
|
30165
30384
|
...actor,
|
|
30166
|
-
candidateId:
|
|
30167
|
-
expectedRevision:
|
|
30168
|
-
expectedApprovedRevision:
|
|
30385
|
+
candidateId: z123.string().min(1).max(64),
|
|
30386
|
+
expectedRevision: z123.number().int().positive(),
|
|
30387
|
+
expectedApprovedRevision: z123.number().int().positive().nullable().optional()
|
|
30169
30388
|
},
|
|
30170
30389
|
// Replaces the selected voice and withdraws the old catalog grants.
|
|
30171
30390
|
annotations: OVERWRITES_INTERNAL
|
|
30172
30391
|
}, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/approve`, body)));
|
|
30173
30392
|
server.registerTool("list_actors", {
|
|
30174
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.",
|
|
30175
|
-
inputSchema:
|
|
30394
|
+
inputSchema: z123.object({}).shape,
|
|
30176
30395
|
annotations: READS_INTERNAL
|
|
30177
30396
|
}, async () => {
|
|
30178
30397
|
try {
|
|
@@ -30205,7 +30424,7 @@ function registerActorTools(server, api) {
|
|
|
30205
30424
|
__name(registerActorTools, "registerActorTools");
|
|
30206
30425
|
|
|
30207
30426
|
// src/tools/publish.ts
|
|
30208
|
-
import { z as
|
|
30427
|
+
import { z as z124 } from "zod";
|
|
30209
30428
|
|
|
30210
30429
|
// src/tools/meta-publish-attempt-id.ts
|
|
30211
30430
|
var META_PUBLISH_NAMESPACE = "7b19c9ac-b4eb-4db1-970e-c2f24ce30b98";
|
|
@@ -30244,40 +30463,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
|
|
|
30244
30463
|
var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
|
|
30245
30464
|
var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
|
|
30246
30465
|
var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
|
|
30247
|
-
var ShopifyInput =
|
|
30248
|
-
taskId:
|
|
30249
|
-
shopDomain:
|
|
30466
|
+
var ShopifyInput = z124.object({
|
|
30467
|
+
taskId: z124.string().min(1),
|
|
30468
|
+
shopDomain: z124.string().min(1),
|
|
30250
30469
|
/** Override: number of landing images to include. Default = ALL images the
|
|
30251
30470
|
* task generated (the MCP fetches /v1/results first to count). Bounded
|
|
30252
30471
|
* generously here; the backend validates each index against
|
|
30253
30472
|
* landing.images.length and rejects out-of-range. */
|
|
30254
|
-
numLandingImages:
|
|
30255
|
-
variantIndex:
|
|
30473
|
+
numLandingImages: z124.number().int().min(1).max(20).optional(),
|
|
30474
|
+
variantIndex: z124.number().int().min(0).optional(),
|
|
30256
30475
|
/** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
|
|
30257
30476
|
* When true, the landing renders variant-picker pills; when false, it ships
|
|
30258
30477
|
* a single-option product page. Defaults to false. */
|
|
30259
|
-
showVariantPicker:
|
|
30478
|
+
showVariantPicker: z124.boolean().optional(),
|
|
30260
30479
|
/** Default `auto` updates the product previously published for this task and
|
|
30261
30480
|
* shop. Use `existing` with targetProductId to choose another product, or
|
|
30262
30481
|
* `new` only when the user explicitly wants a duplicate/new listing. */
|
|
30263
|
-
publicationMode:
|
|
30482
|
+
publicationMode: z124.enum([
|
|
30264
30483
|
"auto",
|
|
30265
30484
|
"existing",
|
|
30266
30485
|
"new"
|
|
30267
30486
|
]).optional(),
|
|
30268
30487
|
/** Shopify product GID, numeric id, or admin product URL. Required when
|
|
30269
30488
|
* publicationMode is `existing`. */
|
|
30270
|
-
targetProductId:
|
|
30489
|
+
targetProductId: z124.string().trim().min(1).max(300).optional(),
|
|
30271
30490
|
/** Add an announcement bar text above add-to-cart (optional). */
|
|
30272
|
-
announcementBarEnabled:
|
|
30273
|
-
announcementBarText:
|
|
30491
|
+
announcementBarEnabled: z124.boolean().optional(),
|
|
30492
|
+
announcementBarText: z124.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
|
|
30274
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."),
|
|
30275
|
-
confirmed:
|
|
30494
|
+
confirmed: z124.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
|
|
30276
30495
|
});
|
|
30277
30496
|
var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
|
|
30278
30497
|
if (value.commerceCorrection && value.confirmed !== true) {
|
|
30279
30498
|
ctx.addIssue({
|
|
30280
|
-
code:
|
|
30499
|
+
code: z124.ZodIssueCode.custom,
|
|
30281
30500
|
path: [
|
|
30282
30501
|
"confirmed"
|
|
30283
30502
|
],
|
|
@@ -30286,7 +30505,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
30286
30505
|
}
|
|
30287
30506
|
if (value.announcementBarEnabled && !value.announcementBarText) {
|
|
30288
30507
|
ctx.addIssue({
|
|
30289
|
-
code:
|
|
30508
|
+
code: z124.ZodIssueCode.custom,
|
|
30290
30509
|
path: [
|
|
30291
30510
|
"announcementBarText"
|
|
30292
30511
|
],
|
|
@@ -30295,7 +30514,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
30295
30514
|
}
|
|
30296
30515
|
if (!value.announcementBarEnabled && value.announcementBarText) {
|
|
30297
30516
|
ctx.addIssue({
|
|
30298
|
-
code:
|
|
30517
|
+
code: z124.ZodIssueCode.custom,
|
|
30299
30518
|
path: [
|
|
30300
30519
|
"announcementBarText"
|
|
30301
30520
|
],
|
|
@@ -30309,91 +30528,91 @@ function parseShopifyInput(rawInput) {
|
|
|
30309
30528
|
return parsed.data;
|
|
30310
30529
|
}
|
|
30311
30530
|
__name(parseShopifyInput, "parseShopifyInput");
|
|
30312
|
-
var McpCampaignConfig =
|
|
30531
|
+
var McpCampaignConfig = z124.object({
|
|
30313
30532
|
/** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
|
|
30314
30533
|
* converts to the account currency server-side. Do NOT pre-convert: on a COP
|
|
30315
30534
|
* account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
|
|
30316
|
-
dailyBudgetUsd:
|
|
30535
|
+
dailyBudgetUsd: z124.number().positive().optional(),
|
|
30317
30536
|
/** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
|
|
30318
30537
|
* normalizes at validation). Meta accepts max 1 (single-country ad set).
|
|
30319
30538
|
* TikTok takes only the first entry. */
|
|
30320
|
-
targetCountries:
|
|
30321
|
-
campaignName:
|
|
30539
|
+
targetCountries: z124.array(CountryIso2Schema).max(1).optional(),
|
|
30540
|
+
campaignName: z124.string().trim().min(1).max(100).optional()
|
|
30322
30541
|
});
|
|
30323
30542
|
var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
|
|
30324
|
-
var MetaInput =
|
|
30325
|
-
taskId:
|
|
30543
|
+
var MetaInput = z124.object({
|
|
30544
|
+
taskId: z124.string().min(1),
|
|
30326
30545
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
30327
|
-
portfolioId:
|
|
30546
|
+
portfolioId: z124.string().trim().min(1),
|
|
30328
30547
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
30329
|
-
pageId:
|
|
30548
|
+
pageId: z124.string().trim().min(1),
|
|
30330
30549
|
adAccountId: McpAdAccountId,
|
|
30331
|
-
pixelId:
|
|
30332
|
-
landingUrl:
|
|
30550
|
+
pixelId: z124.string().min(1).optional(),
|
|
30551
|
+
landingUrl: z124.string().url().optional(),
|
|
30333
30552
|
/** Select which angles to publish by 0-based index. Omit to publish all
|
|
30334
30553
|
* successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
|
|
30335
|
-
angleIndexes:
|
|
30554
|
+
angleIndexes: z124.array(z124.number().int().nonnegative()).optional(),
|
|
30336
30555
|
campaignConfig: McpCampaignConfig.optional(),
|
|
30337
30556
|
/** Override the ad's primary text (body copy). If omitted, ProductMaker
|
|
30338
30557
|
* uses the auto-generated copy attached to the task. Capped at 500 chars
|
|
30339
30558
|
* (Meta's primary-text limit). */
|
|
30340
|
-
primaryText:
|
|
30559
|
+
primaryText: z124.string().trim().min(1).max(500).optional(),
|
|
30341
30560
|
/** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
|
|
30342
30561
|
* (wa.me) instead of a landing page. */
|
|
30343
|
-
phoneNumber:
|
|
30562
|
+
phoneNumber: z124.string().min(8).max(32).optional()
|
|
30344
30563
|
});
|
|
30345
|
-
var GroupedTaskSource =
|
|
30346
|
-
type:
|
|
30347
|
-
taskId:
|
|
30348
|
-
angleIndex:
|
|
30349
|
-
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([
|
|
30350
30569
|
"with_subtitles",
|
|
30351
30570
|
"without_subtitles"
|
|
30352
30571
|
]).optional(),
|
|
30353
|
-
imageVariantIndex:
|
|
30354
|
-
});
|
|
30355
|
-
var GroupedMediaSource =
|
|
30356
|
-
type:
|
|
30357
|
-
url:
|
|
30358
|
-
path:
|
|
30359
|
-
thumbnailUrl:
|
|
30360
|
-
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()
|
|
30361
30580
|
}).refine((value) => Boolean(value.url) !== Boolean(value.path), {
|
|
30362
30581
|
message: "media source needs exactly one of `url` or `path`"
|
|
30363
30582
|
}).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
|
|
30364
30583
|
message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
|
|
30365
30584
|
});
|
|
30366
|
-
var GroupedUploadedAssetSource =
|
|
30367
|
-
type:
|
|
30585
|
+
var GroupedUploadedAssetSource = z124.object({
|
|
30586
|
+
type: z124.literal("asset"),
|
|
30368
30587
|
/** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
|
|
30369
|
-
assetId:
|
|
30370
|
-
thumbnailAssetId:
|
|
30588
|
+
assetId: z124.string().uuid(),
|
|
30589
|
+
thumbnailAssetId: z124.string().uuid().optional()
|
|
30371
30590
|
});
|
|
30372
|
-
var GroupedCreative =
|
|
30373
|
-
type:
|
|
30591
|
+
var GroupedCreative = z124.object({
|
|
30592
|
+
type: z124.enum([
|
|
30374
30593
|
"image",
|
|
30375
30594
|
"video"
|
|
30376
30595
|
]),
|
|
30377
|
-
source:
|
|
30596
|
+
source: z124.union([
|
|
30378
30597
|
GroupedTaskSource,
|
|
30379
30598
|
GroupedMediaSource,
|
|
30380
30599
|
GroupedUploadedAssetSource
|
|
30381
30600
|
]),
|
|
30382
|
-
title:
|
|
30383
|
-
description:
|
|
30601
|
+
title: z124.string().max(120).optional(),
|
|
30602
|
+
description: z124.string().max(500).optional(),
|
|
30384
30603
|
cta: MetaCtaType.optional(),
|
|
30385
|
-
creativeId:
|
|
30604
|
+
creativeId: z124.string().min(1).optional()
|
|
30386
30605
|
});
|
|
30387
|
-
var GroupedCampaignConfigBase =
|
|
30606
|
+
var GroupedCampaignConfigBase = z124.object({
|
|
30388
30607
|
campaignType: MetaCampaignType.default("sales"),
|
|
30389
30608
|
optimizationMode: MetaOptimizationMode.default("advantage_plus"),
|
|
30390
30609
|
budgetMode: MetaBudgetMode.optional(),
|
|
30391
|
-
campaignDailyBudget:
|
|
30392
|
-
adSets:
|
|
30393
|
-
tempId:
|
|
30394
|
-
name:
|
|
30395
|
-
dailyBudget:
|
|
30396
|
-
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)
|
|
30397
30616
|
})).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
|
|
30398
30617
|
/**
|
|
30399
30618
|
* Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
|
|
@@ -30401,17 +30620,17 @@ var GroupedCampaignConfigBase = z122.object({
|
|
|
30401
30620
|
* opaque `invalid_literal` and made the WhatsApp destination — supported by
|
|
30402
30621
|
* the API since #849 — unreachable from this tool.
|
|
30403
30622
|
*/
|
|
30404
|
-
destination:
|
|
30405
|
-
|
|
30406
|
-
type:
|
|
30407
|
-
landingUrl:
|
|
30623
|
+
destination: z124.discriminatedUnion("type", [
|
|
30624
|
+
z124.object({
|
|
30625
|
+
type: z124.literal("landing"),
|
|
30626
|
+
landingUrl: z124.string().url()
|
|
30408
30627
|
}),
|
|
30409
|
-
|
|
30410
|
-
type:
|
|
30411
|
-
phoneNumber:
|
|
30628
|
+
z124.object({
|
|
30629
|
+
type: z124.literal("whatsapp"),
|
|
30630
|
+
phoneNumber: z124.string().min(8).max(32)
|
|
30412
30631
|
})
|
|
30413
30632
|
]),
|
|
30414
|
-
saveAsDefault:
|
|
30633
|
+
saveAsDefault: z124.boolean().default(false),
|
|
30415
30634
|
budgetPolicy: MetaBudgetPolicy.optional()
|
|
30416
30635
|
});
|
|
30417
30636
|
function resolveBudgetMode(value) {
|
|
@@ -30425,7 +30644,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
30425
30644
|
const budgetMode = resolveBudgetMode(value);
|
|
30426
30645
|
if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
|
|
30427
30646
|
ctx.addIssue({
|
|
30428
|
-
code:
|
|
30647
|
+
code: z124.ZodIssueCode.custom,
|
|
30429
30648
|
path: [
|
|
30430
30649
|
"campaignDailyBudget"
|
|
30431
30650
|
],
|
|
@@ -30436,7 +30655,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
30436
30655
|
value.adSets.forEach((adSet, index) => {
|
|
30437
30656
|
if (adSet.dailyBudget === void 0) {
|
|
30438
30657
|
ctx.addIssue({
|
|
30439
|
-
code:
|
|
30658
|
+
code: z124.ZodIssueCode.custom,
|
|
30440
30659
|
path: [
|
|
30441
30660
|
"adSets",
|
|
30442
30661
|
index,
|
|
@@ -30451,28 +30670,33 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
30451
30670
|
...value,
|
|
30452
30671
|
budgetMode: resolveBudgetMode(value)
|
|
30453
30672
|
}));
|
|
30454
|
-
var PublishCreativesToMetaInputBase =
|
|
30455
|
-
creatives:
|
|
30673
|
+
var PublishCreativesToMetaInputBase = z124.object({
|
|
30674
|
+
creatives: z124.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
|
|
30456
30675
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
30457
|
-
portfolioId:
|
|
30676
|
+
portfolioId: z124.string().trim().min(1),
|
|
30458
30677
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
30459
|
-
pageId:
|
|
30678
|
+
pageId: z124.string().trim().min(1),
|
|
30460
30679
|
adAccountId: McpAdAccountId,
|
|
30461
|
-
pixelId:
|
|
30462
|
-
/** Required unless `campaignConfig.destination` is whatsapp
|
|
30463
|
-
*
|
|
30464
|
-
|
|
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(),
|
|
30465
30686
|
/** ISO-2 code or resolvable country name — mirrors the API contract
|
|
30466
|
-
* (CountryIso2Schema), which normalizes names to alpha-2 at validation.
|
|
30467
|
-
|
|
30468
|
-
|
|
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),
|
|
30469
30692
|
campaignConfig: GroupedCampaignConfig.optional()
|
|
30470
30693
|
});
|
|
30471
30694
|
var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
|
|
30472
30695
|
const destination = value.campaignConfig?.destination;
|
|
30473
|
-
|
|
30696
|
+
const hasTaskCreative = value.creatives.some((creative) => creative.source.type === "task");
|
|
30697
|
+
if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl && !hasTaskCreative) {
|
|
30474
30698
|
ctx.addIssue({
|
|
30475
|
-
code:
|
|
30699
|
+
code: z124.ZodIssueCode.custom,
|
|
30476
30700
|
path: [
|
|
30477
30701
|
"landingUrl"
|
|
30478
30702
|
],
|
|
@@ -30481,7 +30705,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
30481
30705
|
}
|
|
30482
30706
|
if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
|
|
30483
30707
|
ctx.addIssue({
|
|
30484
|
-
code:
|
|
30708
|
+
code: z124.ZodIssueCode.custom,
|
|
30485
30709
|
path: [
|
|
30486
30710
|
"campaignConfig",
|
|
30487
30711
|
"destination",
|
|
@@ -30500,16 +30724,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
30500
30724
|
}
|
|
30501
30725
|
return value;
|
|
30502
30726
|
});
|
|
30503
|
-
var PresignUploadResponseSchema =
|
|
30504
|
-
uploadUrl:
|
|
30727
|
+
var PresignUploadResponseSchema = z124.object({
|
|
30728
|
+
uploadUrl: z124.string().url().refine((value) => {
|
|
30505
30729
|
const url = new URL(value);
|
|
30506
30730
|
return !url.username && !url.password && url.protocol === "https:";
|
|
30507
30731
|
}, "presigned upload URL must be HTTPS without embedded credentials"),
|
|
30508
|
-
publicUrl:
|
|
30732
|
+
publicUrl: z124.string().url().refine((value) => {
|
|
30509
30733
|
const url = new URL(value);
|
|
30510
30734
|
return !url.username && !url.password;
|
|
30511
30735
|
}, "public media URL must not contain embedded credentials"),
|
|
30512
|
-
stagingAssetId:
|
|
30736
|
+
stagingAssetId: z124.string().uuid()
|
|
30513
30737
|
});
|
|
30514
30738
|
async function uploadResolvedMedia(api, media, assetRole) {
|
|
30515
30739
|
if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
|
|
@@ -30534,16 +30758,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
|
|
|
30534
30758
|
return uploadResolvedMedia(api, media, assetRole);
|
|
30535
30759
|
}
|
|
30536
30760
|
__name(resolveAndUploadMedia, "resolveAndUploadMedia");
|
|
30537
|
-
var TikTokInput =
|
|
30538
|
-
taskId:
|
|
30539
|
-
advertiserId:
|
|
30540
|
-
pixelId:
|
|
30541
|
-
landingUrl:
|
|
30542
|
-
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(),
|
|
30543
30767
|
campaignConfig: McpCampaignConfig.optional(),
|
|
30544
30768
|
/** Override the ad's description (TikTok's body copy). If omitted,
|
|
30545
30769
|
* ProductMaker uses the auto-generated copy attached to the task. */
|
|
30546
|
-
primaryText:
|
|
30770
|
+
primaryText: z124.string().trim().min(1).max(500).optional()
|
|
30547
30771
|
});
|
|
30548
30772
|
function registerPublishTools(server, api, opts = {}) {
|
|
30549
30773
|
const transport = opts.transport ?? "http";
|
|
@@ -30665,7 +30889,7 @@ function registerPublishTools(server, api, opts = {}) {
|
|
|
30665
30889
|
}
|
|
30666
30890
|
});
|
|
30667
30891
|
server.registerTool("publish_creatives_to_meta", {
|
|
30668
|
-
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.',
|
|
30669
30893
|
inputSchema: PublishCreativesToMetaInputBase.shape,
|
|
30670
30894
|
annotations: CREATES_EXTERNAL
|
|
30671
30895
|
}, async (rawInput, extra) => {
|
|
@@ -30895,39 +31119,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
|
|
|
30895
31119
|
|
|
30896
31120
|
// src/tools/meta-upload.ts
|
|
30897
31121
|
import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
|
|
30898
|
-
import { z as
|
|
31122
|
+
import { z as z125 } from "zod";
|
|
30899
31123
|
var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
|
|
30900
|
-
var UploadSessionInputBase =
|
|
30901
|
-
mediaKind:
|
|
31124
|
+
var UploadSessionInputBase = z125.object({
|
|
31125
|
+
mediaKind: z125.enum([
|
|
30902
31126
|
"image",
|
|
30903
31127
|
"video",
|
|
30904
31128
|
"mixed"
|
|
30905
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."),
|
|
30906
|
-
assetRole:
|
|
31130
|
+
assetRole: z125.enum([
|
|
30907
31131
|
"media",
|
|
30908
31132
|
"thumbnail"
|
|
30909
31133
|
]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
|
|
30910
|
-
uploadPurpose:
|
|
31134
|
+
uploadPurpose: z125.enum([
|
|
30911
31135
|
"product_reference",
|
|
30912
31136
|
"creative",
|
|
30913
31137
|
"generic"
|
|
30914
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."),
|
|
30915
|
-
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.")
|
|
30916
31140
|
});
|
|
30917
|
-
var OpenAiFileReference =
|
|
30918
|
-
download_url:
|
|
30919
|
-
file_id:
|
|
30920
|
-
mime_type:
|
|
30921
|
-
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()
|
|
30922
31146
|
});
|
|
30923
31147
|
var UploadSessionToolInputShape = {
|
|
30924
31148
|
...UploadSessionInputBase.shape,
|
|
30925
|
-
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.")
|
|
30926
31150
|
};
|
|
30927
|
-
var UploadSessionToolInput =
|
|
31151
|
+
var UploadSessionToolInput = z125.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
|
|
30928
31152
|
if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
|
|
30929
31153
|
ctx.addIssue({
|
|
30930
|
-
code:
|
|
31154
|
+
code: z125.ZodIssueCode.custom,
|
|
30931
31155
|
path: [
|
|
30932
31156
|
"mediaKind"
|
|
30933
31157
|
],
|
|
@@ -30936,7 +31160,7 @@ var UploadSessionToolInput = z123.object(UploadSessionToolInputShape).superRefin
|
|
|
30936
31160
|
}
|
|
30937
31161
|
if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
|
|
30938
31162
|
ctx.addIssue({
|
|
30939
|
-
code:
|
|
31163
|
+
code: z125.ZodIssueCode.custom,
|
|
30940
31164
|
path: [
|
|
30941
31165
|
"maxFiles"
|
|
30942
31166
|
],
|
|
@@ -30945,7 +31169,7 @@ var UploadSessionToolInput = z123.object(UploadSessionToolInputShape).superRefin
|
|
|
30945
31169
|
}
|
|
30946
31170
|
if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
|
|
30947
31171
|
ctx.addIssue({
|
|
30948
|
-
code:
|
|
31172
|
+
code: z125.ZodIssueCode.custom,
|
|
30949
31173
|
path: [
|
|
30950
31174
|
"maxFiles"
|
|
30951
31175
|
],
|
|
@@ -30953,38 +31177,38 @@ var UploadSessionToolInput = z123.object(UploadSessionToolInputShape).superRefin
|
|
|
30953
31177
|
});
|
|
30954
31178
|
}
|
|
30955
31179
|
});
|
|
30956
|
-
var UploadSessionResponse =
|
|
30957
|
-
sessionId:
|
|
30958
|
-
uploadPageUrl:
|
|
30959
|
-
mediaKind:
|
|
31180
|
+
var UploadSessionResponse = z125.object({
|
|
31181
|
+
sessionId: z125.string().uuid(),
|
|
31182
|
+
uploadPageUrl: z125.string().url(),
|
|
31183
|
+
mediaKind: z125.enum([
|
|
30960
31184
|
"image",
|
|
30961
31185
|
"video",
|
|
30962
31186
|
"mixed"
|
|
30963
31187
|
]),
|
|
30964
|
-
assetRole:
|
|
31188
|
+
assetRole: z125.enum([
|
|
30965
31189
|
"media",
|
|
30966
31190
|
"thumbnail"
|
|
30967
31191
|
]),
|
|
30968
|
-
maxFiles:
|
|
30969
|
-
expiresAt:
|
|
31192
|
+
maxFiles: z125.number().int().positive(),
|
|
31193
|
+
expiresAt: z125.string().datetime()
|
|
30970
31194
|
});
|
|
30971
|
-
var UploadStatusInput =
|
|
30972
|
-
sessionId:
|
|
31195
|
+
var UploadStatusInput = z125.object({
|
|
31196
|
+
sessionId: z125.string().uuid().describe("The sessionId returned by request_media_upload.")
|
|
30973
31197
|
});
|
|
30974
|
-
var UniversalUploadStatusResponse =
|
|
30975
|
-
|
|
30976
|
-
status:
|
|
30977
|
-
assets:
|
|
31198
|
+
var UniversalUploadStatusResponse = z125.discriminatedUnion("status", [
|
|
31199
|
+
z125.object({
|
|
31200
|
+
status: z125.literal("pending"),
|
|
31201
|
+
assets: z125.array(z125.never()).length(0)
|
|
30978
31202
|
}),
|
|
30979
|
-
|
|
30980
|
-
status:
|
|
30981
|
-
assets:
|
|
30982
|
-
assetId:
|
|
30983
|
-
mediaKind:
|
|
31203
|
+
z125.object({
|
|
31204
|
+
status: z125.literal("uploaded"),
|
|
31205
|
+
assets: z125.array(z125.object({
|
|
31206
|
+
assetId: z125.string().uuid(),
|
|
31207
|
+
mediaKind: z125.enum([
|
|
30984
31208
|
"image",
|
|
30985
31209
|
"video"
|
|
30986
31210
|
]),
|
|
30987
|
-
assetRole:
|
|
31211
|
+
assetRole: z125.enum([
|
|
30988
31212
|
"media",
|
|
30989
31213
|
"thumbnail"
|
|
30990
31214
|
])
|
|
@@ -30992,13 +31216,13 @@ var UniversalUploadStatusResponse = z123.discriminatedUnion("status", [
|
|
|
30992
31216
|
})
|
|
30993
31217
|
]);
|
|
30994
31218
|
var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
|
|
30995
|
-
uploadPurpose:
|
|
31219
|
+
uploadPurpose: z125.enum([
|
|
30996
31220
|
"product_reference",
|
|
30997
31221
|
"creative",
|
|
30998
31222
|
"generic"
|
|
30999
31223
|
]),
|
|
31000
|
-
checkToolName:
|
|
31001
|
-
resolveEndpoint:
|
|
31224
|
+
checkToolName: z125.literal("check_media_upload"),
|
|
31225
|
+
resolveEndpoint: z125.string().url()
|
|
31002
31226
|
});
|
|
31003
31227
|
function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
|
|
31004
31228
|
const url = new URL(uploadPageUrl);
|
|
@@ -31089,15 +31313,15 @@ function registerMediaUploadTools(server, api) {
|
|
|
31089
31313
|
__name(registerMediaUploadTools, "registerMediaUploadTools");
|
|
31090
31314
|
|
|
31091
31315
|
// src/tools/campaigns.ts
|
|
31092
|
-
import { z as
|
|
31316
|
+
import { z as z126 } from "zod";
|
|
31093
31317
|
var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
|
|
31094
31318
|
var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
|
|
31095
|
-
var MetaStatusInput =
|
|
31096
|
-
campaignId:
|
|
31319
|
+
var MetaStatusInput = z126.object({
|
|
31320
|
+
campaignId: z126.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
|
|
31097
31321
|
});
|
|
31098
|
-
var TikTokStatusInput =
|
|
31099
|
-
campaignId:
|
|
31100
|
-
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.")
|
|
31101
31325
|
});
|
|
31102
31326
|
function registerCampaignTools(server, api) {
|
|
31103
31327
|
server.registerTool("get_meta_campaign_status", {
|
|
@@ -31202,10 +31426,10 @@ function renderTikTokStatusMarkdown(r) {
|
|
|
31202
31426
|
__name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
|
|
31203
31427
|
|
|
31204
31428
|
// ../../packages/product-economics/src/product-costing.ts
|
|
31205
|
-
import { z as
|
|
31429
|
+
import { z as z128 } from "zod";
|
|
31206
31430
|
|
|
31207
31431
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
31208
|
-
import { z as
|
|
31432
|
+
import { z as z127 } from "zod";
|
|
31209
31433
|
|
|
31210
31434
|
// ../../packages/product-economics/src/product-costing-shipping-references.json
|
|
31211
31435
|
var product_costing_shipping_references_default = {
|
|
@@ -31269,21 +31493,21 @@ var product_costing_shipping_references_default = {
|
|
|
31269
31493
|
};
|
|
31270
31494
|
|
|
31271
31495
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
31272
|
-
var ShippingReferenceSchema =
|
|
31273
|
-
reference:
|
|
31274
|
-
min:
|
|
31275
|
-
max:
|
|
31276
|
-
updatedAt:
|
|
31277
|
-
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([
|
|
31278
31502
|
"high",
|
|
31279
31503
|
"medium",
|
|
31280
31504
|
"medium-low"
|
|
31281
31505
|
]),
|
|
31282
|
-
sources:
|
|
31506
|
+
sources: z127.array(z127.string().url().startsWith("https://")).min(1).max(3)
|
|
31283
31507
|
}).superRefine(({ reference, min, max }, context) => {
|
|
31284
31508
|
if (min > reference || reference > max) {
|
|
31285
31509
|
context.addIssue({
|
|
31286
|
-
code:
|
|
31510
|
+
code: z127.ZodIssueCode.custom,
|
|
31287
31511
|
message: "shipping_reference_outside_range",
|
|
31288
31512
|
path: [
|
|
31289
31513
|
"reference"
|
|
@@ -31291,7 +31515,7 @@ var ShippingReferenceSchema = z125.object({
|
|
|
31291
31515
|
});
|
|
31292
31516
|
}
|
|
31293
31517
|
});
|
|
31294
|
-
var SHIPPING_REFERENCES =
|
|
31518
|
+
var SHIPPING_REFERENCES = z127.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
|
|
31295
31519
|
var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
|
|
31296
31520
|
var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
|
|
31297
31521
|
"MX",
|
|
@@ -31473,18 +31697,18 @@ function getProductCostingCountryName(country) {
|
|
|
31473
31697
|
__name(getProductCostingCountryName, "getProductCostingCountryName");
|
|
31474
31698
|
|
|
31475
31699
|
// ../../packages/product-economics/src/product-costing.ts
|
|
31476
|
-
var ProductCostingInputSchema =
|
|
31477
|
-
country:
|
|
31478
|
-
supplierCost:
|
|
31479
|
-
shippingCost:
|
|
31480
|
-
returnRate:
|
|
31481
|
-
cancellationRate:
|
|
31482
|
-
adsManagerCpa:
|
|
31483
|
-
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")
|
|
31484
31708
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
31485
31709
|
if (returnRate + cancellationRate >= 1) {
|
|
31486
31710
|
context.addIssue({
|
|
31487
|
-
code:
|
|
31711
|
+
code: z128.ZodIssueCode.custom,
|
|
31488
31712
|
message: "delivery_rate_positive",
|
|
31489
31713
|
path: [
|
|
31490
31714
|
"cancellationRate"
|
|
@@ -31581,15 +31805,15 @@ function calculateProductCosting(rawInput) {
|
|
|
31581
31805
|
__name(calculateProductCosting, "calculateProductCosting");
|
|
31582
31806
|
|
|
31583
31807
|
// src/tools/product-costing.ts
|
|
31584
|
-
import { z as
|
|
31808
|
+
import { z as z129 } from "zod";
|
|
31585
31809
|
var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
|
|
31586
|
-
var optionalAmount = /* @__PURE__ */ __name((description) =>
|
|
31587
|
-
var optionalPercent = /* @__PURE__ */ __name((description) =>
|
|
31588
|
-
var ProductCostingToolInput =
|
|
31589
|
-
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, {
|
|
31590
31814
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
31591
31815
|
}).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
|
|
31592
|
-
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."),
|
|
31593
31817
|
supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
|
|
31594
31818
|
shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
|
|
31595
31819
|
shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
|
|
@@ -31752,7 +31976,7 @@ function formatPercent(value) {
|
|
|
31752
31976
|
__name(formatPercent, "formatPercent");
|
|
31753
31977
|
|
|
31754
31978
|
// src/tools/product-research.ts
|
|
31755
|
-
import { z as
|
|
31979
|
+
import { z as z130 } from "zod";
|
|
31756
31980
|
|
|
31757
31981
|
// src/tools/product-research-idempotency.ts
|
|
31758
31982
|
var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
|
|
@@ -32123,17 +32347,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
|
|
|
32123
32347
|
]);
|
|
32124
32348
|
var POLL_INTERVAL_MS = 5e3;
|
|
32125
32349
|
var MAX_WAIT_SECONDS = 120;
|
|
32126
|
-
var FindInput =
|
|
32350
|
+
var FindInput = z130.object({
|
|
32127
32351
|
targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
|
|
32128
32352
|
categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
|
|
32129
|
-
confirmed:
|
|
32130
|
-
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.")
|
|
32131
32355
|
});
|
|
32132
|
-
var GetInput =
|
|
32133
|
-
runId:
|
|
32356
|
+
var GetInput = z130.object({
|
|
32357
|
+
runId: z130.string().uuid().describe("ID del run devuelto por find_winning_products.")
|
|
32134
32358
|
});
|
|
32135
|
-
var ListInput =
|
|
32136
|
-
limit:
|
|
32359
|
+
var ListInput = z130.object({
|
|
32360
|
+
limit: z130.number().int().min(1).max(20).default(10)
|
|
32137
32361
|
});
|
|
32138
32362
|
function textResult(text2) {
|
|
32139
32363
|
return {
|
|
@@ -32272,17 +32496,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
|
|
|
32272
32496
|
__name(registerProductResearchTools, "registerProductResearchTools");
|
|
32273
32497
|
|
|
32274
32498
|
// src/tools/dropshipping-projects.ts
|
|
32275
|
-
import { z as
|
|
32499
|
+
import { z as z131 } from "zod";
|
|
32276
32500
|
var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
|
|
32277
32501
|
var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
|
|
32278
32502
|
var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
|
|
32279
|
-
var ProjectId =
|
|
32280
|
-
var DropshippingProjectStatus =
|
|
32503
|
+
var ProjectId = z131.string().uuid();
|
|
32504
|
+
var DropshippingProjectStatus = z131.enum([
|
|
32281
32505
|
"active",
|
|
32282
32506
|
"completed",
|
|
32283
32507
|
"archived"
|
|
32284
32508
|
]);
|
|
32285
|
-
var DropshippingProjectPhase =
|
|
32509
|
+
var DropshippingProjectPhase = z131.enum([
|
|
32286
32510
|
"research",
|
|
32287
32511
|
"costing",
|
|
32288
32512
|
"media",
|
|
@@ -32291,21 +32515,21 @@ var DropshippingProjectPhase = z129.enum([
|
|
|
32291
32515
|
"advertising",
|
|
32292
32516
|
"complete"
|
|
32293
32517
|
]);
|
|
32294
|
-
var DropshippingRewardMilestone =
|
|
32518
|
+
var DropshippingRewardMilestone = z131.enum([
|
|
32295
32519
|
"product_selected",
|
|
32296
32520
|
"costing_saved",
|
|
32297
32521
|
"product_media_ready",
|
|
32298
32522
|
"creatives_completed",
|
|
32299
32523
|
"campaign_created"
|
|
32300
32524
|
]);
|
|
32301
|
-
var TargetCountry =
|
|
32525
|
+
var TargetCountry = z131.enum([
|
|
32302
32526
|
"CO",
|
|
32303
32527
|
"MX",
|
|
32304
32528
|
"PE",
|
|
32305
32529
|
"EC",
|
|
32306
32530
|
"CL"
|
|
32307
32531
|
]);
|
|
32308
|
-
var ResearchCategory =
|
|
32532
|
+
var ResearchCategory = z131.enum([
|
|
32309
32533
|
"auto",
|
|
32310
32534
|
"automotive",
|
|
32311
32535
|
"kitchen",
|
|
@@ -32320,7 +32544,7 @@ var ResearchCategory = z129.enum([
|
|
|
32320
32544
|
"garden",
|
|
32321
32545
|
"cleaning"
|
|
32322
32546
|
]);
|
|
32323
|
-
var HttpUrl3 =
|
|
32547
|
+
var HttpUrl3 = z131.string().url().max(2e3).refine((value) => {
|
|
32324
32548
|
try {
|
|
32325
32549
|
return [
|
|
32326
32550
|
"http:",
|
|
@@ -32330,45 +32554,45 @@ var HttpUrl3 = z129.string().url().max(2e3).refine((value) => {
|
|
|
32330
32554
|
return false;
|
|
32331
32555
|
}
|
|
32332
32556
|
}, "URL must use HTTP(S)");
|
|
32333
|
-
var ResearchCandidateOrigin =
|
|
32334
|
-
type:
|
|
32557
|
+
var ResearchCandidateOrigin = z131.object({
|
|
32558
|
+
type: z131.literal("research_candidate"),
|
|
32335
32559
|
runId: ProjectId,
|
|
32336
|
-
candidateSourceId:
|
|
32560
|
+
candidateSourceId: z131.string().min(1).max(160)
|
|
32337
32561
|
});
|
|
32338
|
-
var TaskOrigin =
|
|
32339
|
-
type:
|
|
32562
|
+
var TaskOrigin = z131.object({
|
|
32563
|
+
type: z131.literal("task"),
|
|
32340
32564
|
taskId: ProjectId
|
|
32341
32565
|
});
|
|
32342
|
-
var ManualOrigin =
|
|
32343
|
-
type:
|
|
32566
|
+
var ManualOrigin = z131.object({
|
|
32567
|
+
type: z131.literal("manual"),
|
|
32344
32568
|
clientRequestId: ProjectId,
|
|
32345
|
-
country:
|
|
32569
|
+
country: z131.string().min(2).max(3).optional()
|
|
32346
32570
|
});
|
|
32347
|
-
var StartProjectInput =
|
|
32348
|
-
origin:
|
|
32571
|
+
var StartProjectInput = z131.object({
|
|
32572
|
+
origin: z131.discriminatedUnion("type", [
|
|
32349
32573
|
ResearchCandidateOrigin,
|
|
32350
32574
|
TaskOrigin,
|
|
32351
32575
|
ManualOrigin
|
|
32352
32576
|
]),
|
|
32353
|
-
productName:
|
|
32577
|
+
productName: z131.string().trim().min(1).max(240).optional(),
|
|
32354
32578
|
productUrl: HttpUrl3.optional(),
|
|
32355
|
-
country:
|
|
32356
|
-
languageCode:
|
|
32579
|
+
country: z131.string().min(2).max(3).optional(),
|
|
32580
|
+
languageCode: z131.string().min(2).max(16).optional()
|
|
32357
32581
|
}).strict();
|
|
32358
|
-
var CostProjectInput =
|
|
32582
|
+
var CostProjectInput = z131.object({
|
|
32359
32583
|
projectId: ProjectId,
|
|
32360
|
-
version:
|
|
32361
|
-
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, {
|
|
32362
32586
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
32363
32587
|
}).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
|
|
32364
|
-
supplierCost:
|
|
32365
|
-
shippingCost:
|
|
32366
|
-
returnRate:
|
|
32367
|
-
cancellationRate:
|
|
32368
|
-
adsManagerCpa:
|
|
32369
|
-
desiredMargin:
|
|
32370
|
-
});
|
|
32371
|
-
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({
|
|
32372
32596
|
projectId: ProjectId.optional()
|
|
32373
32597
|
}).strict();
|
|
32374
32598
|
var NEXT_ACTION_KINDS = [
|
|
@@ -32386,29 +32610,29 @@ var NEXT_ACTION_KINDS = [
|
|
|
32386
32610
|
"repair_meta_campaign",
|
|
32387
32611
|
"review_paused_campaign"
|
|
32388
32612
|
];
|
|
32389
|
-
var DropshippingProjectNextAction =
|
|
32390
|
-
kind:
|
|
32391
|
-
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)
|
|
32392
32616
|
})));
|
|
32393
|
-
var CostingInputSchema =
|
|
32394
|
-
country:
|
|
32395
|
-
supplierCost:
|
|
32396
|
-
shippingCost:
|
|
32397
|
-
returnRate:
|
|
32398
|
-
cancellationRate:
|
|
32399
|
-
adsManagerCpa:
|
|
32400
|
-
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)
|
|
32401
32625
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
32402
32626
|
if (returnRate + cancellationRate >= 1) context.addIssue({
|
|
32403
|
-
code:
|
|
32627
|
+
code: z131.ZodIssueCode.custom,
|
|
32404
32628
|
path: [
|
|
32405
32629
|
"cancellationRate"
|
|
32406
32630
|
]
|
|
32407
32631
|
});
|
|
32408
32632
|
});
|
|
32409
|
-
var FiniteCostingNumber =
|
|
32410
|
-
var CostingResultSchema =
|
|
32411
|
-
country:
|
|
32633
|
+
var FiniteCostingNumber = z131.number().finite();
|
|
32634
|
+
var CostingResultSchema = z131.object({
|
|
32635
|
+
country: z131.string().min(2).max(3),
|
|
32412
32636
|
deliveryRate: FiniteCostingNumber,
|
|
32413
32637
|
adjustedShippingCost: FiniteCostingNumber,
|
|
32414
32638
|
adjustedCpa: FiniteCostingNumber,
|
|
@@ -32421,45 +32645,45 @@ var CostingResultSchema = z129.object({
|
|
|
32421
32645
|
estimatedProfit: FiniteCostingNumber,
|
|
32422
32646
|
actualMargin: FiniteCostingNumber,
|
|
32423
32647
|
breakEvenAdsManagerCpa: FiniteCostingNumber,
|
|
32424
|
-
wasPriceAutoAdjusted:
|
|
32425
|
-
profitabilityStatus:
|
|
32426
|
-
});
|
|
32427
|
-
var RewardProgressSchema =
|
|
32428
|
-
campaignKey:
|
|
32429
|
-
totalCredits:
|
|
32430
|
-
earnedCredits:
|
|
32431
|
-
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({
|
|
32432
32656
|
milestone: DropshippingRewardMilestone,
|
|
32433
|
-
credits:
|
|
32434
|
-
available:
|
|
32435
|
-
earned:
|
|
32657
|
+
credits: z131.number().int().positive(),
|
|
32658
|
+
available: z131.boolean().optional(),
|
|
32659
|
+
earned: z131.boolean(),
|
|
32436
32660
|
grantId: ProjectId.nullable(),
|
|
32437
|
-
grantedAt:
|
|
32661
|
+
grantedAt: z131.string().datetime().nullable()
|
|
32438
32662
|
})).length(DropshippingRewardMilestone.options.length)
|
|
32439
32663
|
});
|
|
32440
|
-
var ProjectResponseSchema =
|
|
32664
|
+
var ProjectResponseSchema = z131.object({
|
|
32441
32665
|
id: ProjectId,
|
|
32442
32666
|
taskId: ProjectId.nullable(),
|
|
32443
32667
|
status: DropshippingProjectStatus,
|
|
32444
|
-
originKey:
|
|
32668
|
+
originKey: z131.string().min(1),
|
|
32445
32669
|
researchRunId: ProjectId.nullable(),
|
|
32446
|
-
candidateSourceId:
|
|
32447
|
-
productName:
|
|
32670
|
+
candidateSourceId: z131.string().nullable(),
|
|
32671
|
+
productName: z131.string().nullable(),
|
|
32448
32672
|
productUrl: HttpUrl3.nullable(),
|
|
32449
32673
|
referenceImageUrl: HttpUrl3.nullable(),
|
|
32450
|
-
targetCountry:
|
|
32451
|
-
languageCode:
|
|
32452
|
-
hasReferenceImage:
|
|
32453
|
-
hasWinnerReferenceImage:
|
|
32674
|
+
targetCountry: z131.string().nullable(),
|
|
32675
|
+
languageCode: z131.string().nullable(),
|
|
32676
|
+
hasReferenceImage: z131.boolean(),
|
|
32677
|
+
hasWinnerReferenceImage: z131.boolean(),
|
|
32454
32678
|
costingInput: CostingInputSchema.nullable(),
|
|
32455
32679
|
costingResult: CostingResultSchema.nullable(),
|
|
32456
|
-
costingVersion:
|
|
32457
|
-
version:
|
|
32680
|
+
costingVersion: z131.number().int().positive().nullable(),
|
|
32681
|
+
version: z131.number().int().positive(),
|
|
32458
32682
|
phase: DropshippingProjectPhase,
|
|
32459
32683
|
nextAction: DropshippingProjectNextAction.nullable(),
|
|
32460
32684
|
rewards: RewardProgressSchema,
|
|
32461
|
-
createdAt:
|
|
32462
|
-
updatedAt:
|
|
32685
|
+
createdAt: z131.string().datetime(),
|
|
32686
|
+
updatedAt: z131.string().datetime()
|
|
32463
32687
|
}).passthrough();
|
|
32464
32688
|
var NEXT_ACTION_GUIDANCE = {
|
|
32465
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.",
|
|
@@ -32579,58 +32803,58 @@ function registerDropshippingProjectTools(server, api) {
|
|
|
32579
32803
|
__name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
|
|
32580
32804
|
|
|
32581
32805
|
// src/tools/daily-control.ts
|
|
32582
|
-
import { z as
|
|
32806
|
+
import { z as z132 } from "zod";
|
|
32583
32807
|
var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
|
|
32584
32808
|
var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
|
|
32585
32809
|
var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
|
|
32586
|
-
var ProviderCampaignIdentifier =
|
|
32587
|
-
var DateOnly =
|
|
32588
|
-
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({
|
|
32589
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."),
|
|
32590
|
-
days:
|
|
32591
|
-
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.")
|
|
32592
32816
|
}).strict();
|
|
32593
|
-
var LinkCampaignInput =
|
|
32594
|
-
projectId:
|
|
32595
|
-
provider:
|
|
32817
|
+
var LinkCampaignInput = z132.object({
|
|
32818
|
+
projectId: z132.string().uuid(),
|
|
32819
|
+
provider: z132.enum([
|
|
32596
32820
|
"meta",
|
|
32597
32821
|
"tiktok"
|
|
32598
32822
|
]),
|
|
32599
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."),
|
|
32600
32824
|
campaignId: ProviderCampaignIdentifier
|
|
32601
32825
|
}).strict();
|
|
32602
|
-
var ReportReturnsInput =
|
|
32603
|
-
projectId:
|
|
32826
|
+
var ReportReturnsInput = z132.object({
|
|
32827
|
+
projectId: z132.string().uuid(),
|
|
32604
32828
|
date: DateOnly,
|
|
32605
|
-
returnedOrders:
|
|
32606
|
-
note:
|
|
32829
|
+
returnedOrders: z132.number().int().min(0).max(1e5),
|
|
32830
|
+
note: z132.string().trim().max(280).optional()
|
|
32607
32831
|
}).strict();
|
|
32608
|
-
var DailyControlStatusMirror = DailyControlStatusEnum.or(
|
|
32609
|
-
var DailyControlLightMirror = DailyControlLightEnum.or(
|
|
32610
|
-
var DailyControlSourceMirror = DailyControlSourceEnum.or(
|
|
32611
|
-
var DailyControlVerdictMirror = DailyControlVerdictEnum.or(
|
|
32612
|
-
var DailyControlDayMirror =
|
|
32613
|
-
date:
|
|
32614
|
-
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(),
|
|
32615
32839
|
returnedSource: DailyControlSourceMirror,
|
|
32616
32840
|
cancelledSource: DailyControlSourceMirror,
|
|
32617
|
-
hasEstimates:
|
|
32841
|
+
hasEstimates: z132.boolean(),
|
|
32618
32842
|
light: DailyControlLightMirror
|
|
32619
32843
|
}).passthrough();
|
|
32620
|
-
var DailyControlProductMirror =
|
|
32621
|
-
projectId:
|
|
32622
|
-
productName:
|
|
32844
|
+
var DailyControlProductMirror = z132.object({
|
|
32845
|
+
projectId: z132.string().uuid(),
|
|
32846
|
+
productName: z132.string().nullable(),
|
|
32623
32847
|
status: DailyControlStatusMirror,
|
|
32624
|
-
statusMessage:
|
|
32625
|
-
days:
|
|
32848
|
+
statusMessage: z132.string().nullable(),
|
|
32849
|
+
days: z132.array(DailyControlDayMirror),
|
|
32626
32850
|
verdict: DailyControlVerdictMirror.nullable(),
|
|
32627
|
-
rationale:
|
|
32851
|
+
rationale: z132.string().nullable()
|
|
32628
32852
|
}).passthrough();
|
|
32629
|
-
var DailyControlResponseMirror =
|
|
32630
|
-
since:
|
|
32631
|
-
until:
|
|
32632
|
-
products:
|
|
32633
|
-
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())
|
|
32634
32858
|
}).passthrough();
|
|
32635
32859
|
var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
|
|
32636
32860
|
function withWarnings(response) {
|
|
@@ -32705,7 +32929,7 @@ __name(registerDailyControlTools, "registerDailyControlTools");
|
|
|
32705
32929
|
// src/tools/product-control.ts
|
|
32706
32930
|
import { readFile, stat } from "fs/promises";
|
|
32707
32931
|
import { basename as basename2, isAbsolute, resolve as resolve3 } from "path";
|
|
32708
|
-
import { z as
|
|
32932
|
+
import { z as z133 } from "zod";
|
|
32709
32933
|
var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
|
|
32710
32934
|
var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
|
|
32711
32935
|
var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
|
|
@@ -32718,36 +32942,36 @@ var createOperationGuidance = getProductMakerCapabilityModelGuidance("create_ope
|
|
|
32718
32942
|
var mergeProductsGuidance = getProductMakerCapabilityModelGuidance("merge_products");
|
|
32719
32943
|
var syncShopifyOrdersGuidance = getProductMakerCapabilityModelGuidance("sync_shopify_orders");
|
|
32720
32944
|
var importOrdersFileGuidance = getProductMakerCapabilityModelGuidance("import_orders_file");
|
|
32721
|
-
var DateOnly2 =
|
|
32945
|
+
var DateOnly2 = z133.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
32722
32946
|
var IMPORT_BATCH_MAX2 = 50;
|
|
32723
|
-
var ProductControlListInput =
|
|
32724
|
-
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."),
|
|
32725
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."),
|
|
32726
|
-
shopDomain:
|
|
32950
|
+
shopDomain: z133.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
|
|
32727
32951
|
}).strict();
|
|
32728
|
-
var ImportableProductsInput =
|
|
32729
|
-
q:
|
|
32730
|
-
after:
|
|
32731
|
-
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()
|
|
32732
32956
|
}).strict();
|
|
32733
|
-
var ImportProductControlsInput =
|
|
32734
|
-
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."),
|
|
32735
32959
|
// Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
|
|
32736
32960
|
// sin decir a cuál archivaría el producto bajo la tienda equivocada.
|
|
32737
|
-
shopDomain:
|
|
32961
|
+
shopDomain: z133.string().min(1)
|
|
32738
32962
|
}).strict();
|
|
32739
|
-
var SetProductCostingInput =
|
|
32740
|
-
shopDomain:
|
|
32741
|
-
shopifyProductId:
|
|
32742
|
-
targetCountry:
|
|
32743
|
-
supplierCost:
|
|
32744
|
-
shippingCost:
|
|
32745
|
-
returnRate:
|
|
32746
|
-
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)
|
|
32747
32971
|
}).strict();
|
|
32748
|
-
var Count =
|
|
32749
|
-
var ReportProductCountsInput =
|
|
32750
|
-
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."),
|
|
32751
32975
|
date: DateOnly2,
|
|
32752
32976
|
orders: Count.describe("Pedidos que entraron ese d\xEDa."),
|
|
32753
32977
|
cancelledOrders: Count,
|
|
@@ -32757,36 +32981,36 @@ var ReportProductCountsInput = z131.object({
|
|
|
32757
32981
|
}).strict();
|
|
32758
32982
|
var MAX_ORDERS_FILE_BYTES = 8 * 1024 * 1024;
|
|
32759
32983
|
var SyncShopifyOrdersInput = SyncShopifyOrdersSchema;
|
|
32760
|
-
var ImportOrdersFileInput =
|
|
32984
|
+
var ImportOrdersFileInput = z133.object({
|
|
32761
32985
|
/** Ruta ABSOLUTA en la máquina de quien usa el MCP. */
|
|
32762
|
-
path:
|
|
32763
|
-
operationId:
|
|
32986
|
+
path: z133.string().min(1),
|
|
32987
|
+
operationId: z133.string().uuid().optional(),
|
|
32764
32988
|
/** Solo mirar: devuelve el resumen y no escribe nada. */
|
|
32765
|
-
dryRun:
|
|
32989
|
+
dryRun: z133.boolean().optional()
|
|
32766
32990
|
}).strict();
|
|
32767
|
-
var CreateOperationInput =
|
|
32768
|
-
countryCode:
|
|
32769
|
-
label:
|
|
32991
|
+
var CreateOperationInput = z133.object({
|
|
32992
|
+
countryCode: z133.string().length(2),
|
|
32993
|
+
label: z133.string().trim().min(1).max(60).optional()
|
|
32770
32994
|
}).strict();
|
|
32771
|
-
var MergeProductsInput =
|
|
32772
|
-
sourceId:
|
|
32773
|
-
targetId:
|
|
32995
|
+
var MergeProductsInput = z133.object({
|
|
32996
|
+
sourceId: z133.string().uuid(),
|
|
32997
|
+
targetId: z133.string().uuid()
|
|
32774
32998
|
}).strict();
|
|
32775
|
-
var SetMonthlyExpenseInput =
|
|
32776
|
-
month:
|
|
32999
|
+
var SetMonthlyExpenseInput = z133.object({
|
|
33000
|
+
month: z133.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
|
|
32777
33001
|
label: SaveMonthlyExpenseSchema.shape.label,
|
|
32778
|
-
amount:
|
|
32779
|
-
operationId:
|
|
33002
|
+
amount: z133.number().finite().min(0),
|
|
33003
|
+
operationId: z133.string().uuid().optional()
|
|
32780
33004
|
}).strict();
|
|
32781
|
-
var SetAdSpendInput =
|
|
32782
|
-
month:
|
|
32783
|
-
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(),
|
|
32784
33008
|
/** null RETIRA la corrección; cero afirma que no pautó. */
|
|
32785
|
-
amount:
|
|
33009
|
+
amount: z133.number().finite().min(0).nullable()
|
|
32786
33010
|
}).strict();
|
|
32787
|
-
var GetFinancesInput =
|
|
32788
|
-
month:
|
|
32789
|
-
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.")
|
|
32790
33014
|
}).strict();
|
|
32791
33015
|
function registerProductControlTools(server, api, { transport = "http" } = {}) {
|
|
32792
33016
|
server.registerTool("get_product_control", {
|
|
@@ -32978,28 +33202,28 @@ function registerProductControlTools(server, api, { transport = "http" } = {}) {
|
|
|
32978
33202
|
__name(registerProductControlTools, "registerProductControlTools");
|
|
32979
33203
|
|
|
32980
33204
|
// src/tools/market-study-estimate.ts
|
|
32981
|
-
import { z as
|
|
33205
|
+
import { z as z134 } from "zod";
|
|
32982
33206
|
var estimateMarketStudyGuidance = getProductMakerCapabilityModelGuidance("estimate_market_study_cost");
|
|
32983
|
-
var ProductTaskOutputEnum =
|
|
33207
|
+
var ProductTaskOutputEnum = z134.enum([
|
|
32984
33208
|
"landing",
|
|
32985
33209
|
"video",
|
|
32986
33210
|
"image"
|
|
32987
33211
|
]);
|
|
32988
|
-
var EstimateMarketStudyInput =
|
|
32989
|
-
kind:
|
|
33212
|
+
var EstimateMarketStudyInput = z134.object({
|
|
33213
|
+
kind: z134.enum([
|
|
32990
33214
|
"video",
|
|
32991
33215
|
"product_task"
|
|
32992
33216
|
]).describe('"video" para generate_video_creative; "product_task" para create_product_task.'),
|
|
32993
|
-
videoAngleCount:
|
|
32994
|
-
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."),
|
|
32995
33219
|
videoStructure: VideoStructureEnum.default("single_take"),
|
|
32996
33220
|
videoQuality: VideoQualityEnum.default("economy"),
|
|
32997
33221
|
videoResolution: VideoResolutionEnum.default("480p"),
|
|
32998
|
-
productImageCount:
|
|
33222
|
+
productImageCount: z134.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
|
|
32999
33223
|
outputs: ProductTaskOutputEnum.array().min(1).max(3).optional().describe('Solo para kind="product_task": los mismos outputs de create_product_task. Default: todos.'),
|
|
33000
|
-
generateAiMusic:
|
|
33224
|
+
generateAiMusic: z134.boolean().optional(),
|
|
33001
33225
|
generateAiEdit: AiEditRequestSchema.optional(),
|
|
33002
|
-
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.")
|
|
33003
33227
|
}).strict();
|
|
33004
33228
|
function buildMarketStudyEstimateRequests(input) {
|
|
33005
33229
|
const quotesVideo = input.kind === "video" || (input.outputs ?? [
|