@productmaker/mcp 11.2.0 → 11.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/http.js +830 -789
- package/dist/stdio.js +819 -778
- package/package.json +1 -1
package/dist/stdio.js
CHANGED
|
@@ -7536,6 +7536,12 @@ var ResultAngle = Angle.extend({
|
|
|
7536
7536
|
});
|
|
7537
7537
|
var MVPResult = z39.object({
|
|
7538
7538
|
taskId: z39.string().uuid(),
|
|
7539
|
+
/** Read-only identity derived from validated persisted request context.
|
|
7540
|
+
* Optional for older APIs and content-only tasks; absence never implies a service. */
|
|
7541
|
+
subjectKind: z39.enum([
|
|
7542
|
+
"product",
|
|
7543
|
+
"service"
|
|
7544
|
+
]).optional(),
|
|
7539
7545
|
product: Product,
|
|
7540
7546
|
// READ contract, NOT a generation cap. The generator writes exactly 3 angles
|
|
7541
7547
|
// (`replaceAngles` renumbers positions 0..2), but a duplicated angles run
|
|
@@ -8336,6 +8342,10 @@ var VideoRegenerateEstimationOptions = z40.object({
|
|
|
8336
8342
|
sceneCount: z40.number().int().positive().optional()
|
|
8337
8343
|
});
|
|
8338
8344
|
var ImageCreativeEstimationOptions = z40.object({
|
|
8345
|
+
subject: z40.enum([
|
|
8346
|
+
"product",
|
|
8347
|
+
"service"
|
|
8348
|
+
]).optional(),
|
|
8339
8349
|
nVariants: z40.number().int().positive().optional(),
|
|
8340
8350
|
generateAdCopy: z40.boolean().optional(),
|
|
8341
8351
|
/** Literal model name (e.g. 'gpt-image/1.5', 'nano-banana-2'). Defaults to the premium ad-creative model. */
|
|
@@ -9233,6 +9243,7 @@ var VideoMixQaJobSchema = z46.object({
|
|
|
9233
9243
|
// jobId for retry uniqueness) but the worker only reads mixSceneTaskId.
|
|
9234
9244
|
externalId: z46.string().min(1).optional()
|
|
9235
9245
|
});
|
|
9246
|
+
var BrandExtractLocaleSchema = z46.string().regex(/^[A-Za-z]{2,3}(?:[-_][A-Za-z0-9]{2,8})?$/, "invalid locale");
|
|
9236
9247
|
var BrandExtractJobSchema = z46.object({
|
|
9237
9248
|
brandId: z46.string().uuid(),
|
|
9238
9249
|
// Generation is part of the durable paid-spend identity. Default 1 keeps
|
|
@@ -9248,7 +9259,10 @@ var BrandExtractJobSchema = z46.object({
|
|
|
9248
9259
|
"shopify_sync"
|
|
9249
9260
|
]).default("url_extract"),
|
|
9250
9261
|
shopifyShopId: z46.string().optional(),
|
|
9251
|
-
documents: z46.array(BrandExtractDocumentSchema).max(3).default([])
|
|
9262
|
+
documents: z46.array(BrandExtractDocumentSchema).max(3).default([]),
|
|
9263
|
+
// Requesting user's UI locale (BCP-47, e.g. "es", "en-US"). Fallback for the
|
|
9264
|
+
// brand kit's output language when the brand's own text is inconclusive.
|
|
9265
|
+
locale: BrandExtractLocaleSchema.optional()
|
|
9252
9266
|
});
|
|
9253
9267
|
|
|
9254
9268
|
// ../../packages/types/src/chat-parse.ts
|
|
@@ -21588,19 +21602,46 @@ var DropiFinancialSyncResultSchema = z103.object({
|
|
|
21588
21602
|
}))
|
|
21589
21603
|
});
|
|
21590
21604
|
|
|
21591
|
-
// ../../packages/types/src/service-
|
|
21605
|
+
// ../../packages/types/src/service-image.ts
|
|
21592
21606
|
import { z as z104 } from "zod";
|
|
21607
|
+
var ServiceImageIntentSchema = z104.enum([
|
|
21608
|
+
"user_brief",
|
|
21609
|
+
"delegate_to_ai"
|
|
21610
|
+
]);
|
|
21611
|
+
var ServiceImageInputSchema = z104.object({
|
|
21612
|
+
instruction: z104.string().trim().max(4e3).default(""),
|
|
21613
|
+
intent: ServiceImageIntentSchema.default("user_brief")
|
|
21614
|
+
}).strict().refine((value) => value.intent === "delegate_to_ai" || value.instruction.length > 0, {
|
|
21615
|
+
message: "Cu\xE9ntanos qu\xE9 servicio quieres promocionar.",
|
|
21616
|
+
path: [
|
|
21617
|
+
"instruction"
|
|
21618
|
+
]
|
|
21619
|
+
});
|
|
21620
|
+
var ServiceImageContextSchema = z104.object({
|
|
21621
|
+
kind: z104.literal("service_image"),
|
|
21622
|
+
version: z104.literal(1),
|
|
21623
|
+
instruction: z104.string().max(4e3),
|
|
21624
|
+
intent: ServiceImageIntentSchema,
|
|
21625
|
+
businessName: z104.string().max(300),
|
|
21626
|
+
description: z104.string().max(2e4),
|
|
21627
|
+
brandCard: z104.string().max(2e4),
|
|
21628
|
+
palette: z104.array(z104.string()).max(20),
|
|
21629
|
+
referenceKeys: z104.array(z104.string()).max(10)
|
|
21630
|
+
}).strict();
|
|
21631
|
+
|
|
21632
|
+
// ../../packages/types/src/service-website-capture.ts
|
|
21633
|
+
import { z as z105 } from "zod";
|
|
21593
21634
|
var WEBSITE_CAPTURE_MAX_RESEARCH_BYTES = 1024 * 1024;
|
|
21594
21635
|
var WEBSITE_CAPTURE_MAX_FILES = 100;
|
|
21595
21636
|
var WEBSITE_CAPTURE_MAX_FILE_BYTES = 8 * 1024 * 1024;
|
|
21596
21637
|
var WEBSITE_CAPTURE_MAX_BUNDLE_BYTES = 30 * 1024 * 1024;
|
|
21597
|
-
var WebsiteCaptureCauseSchema =
|
|
21638
|
+
var WebsiteCaptureCauseSchema = z105.enum([
|
|
21598
21639
|
"site_blocked",
|
|
21599
21640
|
"site_unreachable",
|
|
21600
21641
|
"not_enough_content",
|
|
21601
21642
|
"internal"
|
|
21602
21643
|
]);
|
|
21603
|
-
var WebsiteCaptureStatusSchema =
|
|
21644
|
+
var WebsiteCaptureStatusSchema = z105.enum([
|
|
21604
21645
|
"queued",
|
|
21605
21646
|
"capturing",
|
|
21606
21647
|
"ready",
|
|
@@ -21622,128 +21663,128 @@ function normalizeWebsiteCaptureUrl(value) {
|
|
|
21622
21663
|
}
|
|
21623
21664
|
}
|
|
21624
21665
|
__name(normalizeWebsiteCaptureUrl, "normalizeWebsiteCaptureUrl");
|
|
21625
|
-
var WebsiteCaptureRequestSchema =
|
|
21626
|
-
url:
|
|
21666
|
+
var WebsiteCaptureRequestSchema = z105.object({
|
|
21667
|
+
url: z105.string().trim().max(2048).url().refine((value) => normalizeWebsiteCaptureUrl(value) !== null, "Use an HTTP(S) URL without credentials").transform((value) => normalizeWebsiteCaptureUrl(value)),
|
|
21627
21668
|
language: MotionGraphicsLanguageSchema
|
|
21628
21669
|
}).strict();
|
|
21629
|
-
var WebsiteCaptureResponseSchema =
|
|
21630
|
-
captureId:
|
|
21670
|
+
var WebsiteCaptureResponseSchema = z105.object({
|
|
21671
|
+
captureId: z105.string().uuid(),
|
|
21631
21672
|
status: WebsiteCaptureStatusSchema,
|
|
21632
|
-
expiresAt:
|
|
21633
|
-
previewUrl:
|
|
21673
|
+
expiresAt: z105.string().datetime(),
|
|
21674
|
+
previewUrl: z105.string().url().optional(),
|
|
21634
21675
|
cause: WebsiteCaptureCauseSchema.optional()
|
|
21635
21676
|
});
|
|
21636
21677
|
var WebsiteCaptureJobSchema = WebsiteCaptureRequestSchema.extend({
|
|
21637
|
-
captureId:
|
|
21638
|
-
attempt:
|
|
21639
|
-
leaseUntil:
|
|
21678
|
+
captureId: z105.string().uuid(),
|
|
21679
|
+
attempt: z105.number().int().positive(),
|
|
21680
|
+
leaseUntil: z105.string().datetime()
|
|
21640
21681
|
});
|
|
21641
|
-
var WebsiteCaptureClaimResponseSchema =
|
|
21682
|
+
var WebsiteCaptureClaimResponseSchema = z105.object({
|
|
21642
21683
|
capture: WebsiteCaptureJobSchema.nullable()
|
|
21643
21684
|
});
|
|
21644
21685
|
var attempt = {
|
|
21645
|
-
attempt:
|
|
21686
|
+
attempt: z105.number().int().positive()
|
|
21646
21687
|
};
|
|
21647
|
-
var digest =
|
|
21648
|
-
var WebsiteCaptureUploadRequestSchema =
|
|
21688
|
+
var digest = z105.string().regex(/^[a-f0-9]{64}$/);
|
|
21689
|
+
var WebsiteCaptureUploadRequestSchema = z105.object({
|
|
21649
21690
|
...attempt,
|
|
21650
|
-
contentLength:
|
|
21691
|
+
contentLength: z105.number().int().positive().max(WEBSITE_CAPTURE_MAX_BUNDLE_BYTES),
|
|
21651
21692
|
sha256: digest
|
|
21652
21693
|
}).strict();
|
|
21653
|
-
var WebsiteCaptureDoneRequestSchema =
|
|
21694
|
+
var WebsiteCaptureDoneRequestSchema = z105.object({
|
|
21654
21695
|
...attempt,
|
|
21655
21696
|
sha256: digest
|
|
21656
21697
|
}).strict();
|
|
21657
|
-
var WebsiteCaptureFailedRequestSchema =
|
|
21698
|
+
var WebsiteCaptureFailedRequestSchema = z105.object({
|
|
21658
21699
|
...attempt,
|
|
21659
21700
|
cause: WebsiteCaptureCauseSchema
|
|
21660
21701
|
}).strict();
|
|
21661
|
-
var WebsiteCaptureBundleSchema =
|
|
21662
|
-
version:
|
|
21663
|
-
files:
|
|
21664
|
-
path:
|
|
21665
|
-
base64:
|
|
21702
|
+
var WebsiteCaptureBundleSchema = z105.object({
|
|
21703
|
+
version: z105.literal(1),
|
|
21704
|
+
files: z105.array(z105.object({
|
|
21705
|
+
path: z105.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))$/),
|
|
21706
|
+
base64: z105.string().max(Math.ceil(WEBSITE_CAPTURE_MAX_FILE_BYTES / 3) * 4).regex(/^[A-Za-z0-9+/]*={0,2}$/).refine((value) => value.length % 4 === 0),
|
|
21666
21707
|
sha256: digest
|
|
21667
21708
|
}).strict()).min(1).max(WEBSITE_CAPTURE_MAX_FILES)
|
|
21668
21709
|
}).strict().refine((bundle) => new Set(bundle.files.map((file) => file.path)).size === bundle.files.length, "Duplicate capture file");
|
|
21669
|
-
var WebsiteCaptureScreenshotSchema =
|
|
21670
|
-
file:
|
|
21671
|
-
scrollTop:
|
|
21672
|
-
});
|
|
21673
|
-
var WebsiteCaptureAccessSchema =
|
|
21674
|
-
publicContentText:
|
|
21675
|
-
passwordGate:
|
|
21676
|
-
challengeGate:
|
|
21677
|
-
blockingOverlay:
|
|
21678
|
-
});
|
|
21679
|
-
var WebsiteCaptureResearchSchema =
|
|
21680
|
-
requestedUrl:
|
|
21681
|
-
capturedAt:
|
|
21682
|
-
locale:
|
|
21683
|
-
bodyTextTruncated:
|
|
21684
|
-
finalUrl:
|
|
21685
|
-
lang:
|
|
21686
|
-
title:
|
|
21687
|
-
description:
|
|
21688
|
-
openGraph:
|
|
21689
|
-
title:
|
|
21690
|
-
description:
|
|
21691
|
-
image:
|
|
21692
|
-
siteName:
|
|
21710
|
+
var WebsiteCaptureScreenshotSchema = z105.object({
|
|
21711
|
+
file: z105.string(),
|
|
21712
|
+
scrollTop: z105.number()
|
|
21713
|
+
});
|
|
21714
|
+
var WebsiteCaptureAccessSchema = z105.object({
|
|
21715
|
+
publicContentText: z105.string().max(8e3),
|
|
21716
|
+
passwordGate: z105.boolean(),
|
|
21717
|
+
challengeGate: z105.boolean(),
|
|
21718
|
+
blockingOverlay: z105.boolean()
|
|
21719
|
+
});
|
|
21720
|
+
var WebsiteCaptureResearchSchema = z105.object({
|
|
21721
|
+
requestedUrl: z105.string().url(),
|
|
21722
|
+
capturedAt: z105.string().datetime(),
|
|
21723
|
+
locale: z105.string(),
|
|
21724
|
+
bodyTextTruncated: z105.boolean(),
|
|
21725
|
+
finalUrl: z105.string().url(),
|
|
21726
|
+
lang: z105.string().nullable(),
|
|
21727
|
+
title: z105.string(),
|
|
21728
|
+
description: z105.string(),
|
|
21729
|
+
openGraph: z105.object({
|
|
21730
|
+
title: z105.string(),
|
|
21731
|
+
description: z105.string(),
|
|
21732
|
+
image: z105.string(),
|
|
21733
|
+
siteName: z105.string()
|
|
21693
21734
|
}),
|
|
21694
|
-
themeColor:
|
|
21695
|
-
headings:
|
|
21696
|
-
h1:
|
|
21697
|
-
h2:
|
|
21698
|
-
h3:
|
|
21735
|
+
themeColor: z105.string(),
|
|
21736
|
+
headings: z105.object({
|
|
21737
|
+
h1: z105.array(z105.string()),
|
|
21738
|
+
h2: z105.array(z105.string()),
|
|
21739
|
+
h3: z105.array(z105.string())
|
|
21699
21740
|
}),
|
|
21700
|
-
callsToAction:
|
|
21701
|
-
listItems:
|
|
21702
|
-
bodyText:
|
|
21741
|
+
callsToAction: z105.array(z105.string()),
|
|
21742
|
+
listItems: z105.array(z105.string()),
|
|
21743
|
+
bodyText: z105.string(),
|
|
21703
21744
|
access: WebsiteCaptureAccessSchema.optional(),
|
|
21704
|
-
consent:
|
|
21705
|
-
pressed:
|
|
21706
|
-
removed:
|
|
21745
|
+
consent: z105.object({
|
|
21746
|
+
pressed: z105.string().nullable(),
|
|
21747
|
+
removed: z105.number().nonnegative()
|
|
21707
21748
|
}).optional(),
|
|
21708
|
-
overlaysDismissed:
|
|
21709
|
-
style:
|
|
21710
|
-
bodyBackground:
|
|
21711
|
-
bodyColor:
|
|
21712
|
-
bodyFont:
|
|
21713
|
-
headingFont:
|
|
21714
|
-
headingColor:
|
|
21715
|
-
actionColors:
|
|
21716
|
-
color:
|
|
21717
|
-
uses:
|
|
21749
|
+
overlaysDismissed: z105.number().int().nonnegative().optional(),
|
|
21750
|
+
style: z105.object({
|
|
21751
|
+
bodyBackground: z105.string(),
|
|
21752
|
+
bodyColor: z105.string(),
|
|
21753
|
+
bodyFont: z105.string(),
|
|
21754
|
+
headingFont: z105.string().nullable(),
|
|
21755
|
+
headingColor: z105.string().nullable(),
|
|
21756
|
+
actionColors: z105.array(z105.object({
|
|
21757
|
+
color: z105.string(),
|
|
21758
|
+
uses: z105.number()
|
|
21718
21759
|
}))
|
|
21719
21760
|
}),
|
|
21720
|
-
images:
|
|
21721
|
-
file:
|
|
21722
|
-
src:
|
|
21723
|
-
alt:
|
|
21724
|
-
width:
|
|
21725
|
-
height:
|
|
21726
|
-
isOpenGraph:
|
|
21761
|
+
images: z105.array(z105.object({
|
|
21762
|
+
file: z105.string(),
|
|
21763
|
+
src: z105.string(),
|
|
21764
|
+
alt: z105.string(),
|
|
21765
|
+
width: z105.number().nullable(),
|
|
21766
|
+
height: z105.number().nullable(),
|
|
21767
|
+
isOpenGraph: z105.boolean()
|
|
21727
21768
|
})),
|
|
21728
|
-
logo:
|
|
21729
|
-
file:
|
|
21730
|
-
svg:
|
|
21731
|
-
width:
|
|
21732
|
-
height:
|
|
21769
|
+
logo: z105.object({
|
|
21770
|
+
file: z105.literal("logo.png"),
|
|
21771
|
+
svg: z105.literal("logo.svg").optional(),
|
|
21772
|
+
width: z105.number(),
|
|
21773
|
+
height: z105.number()
|
|
21733
21774
|
}).nullable(),
|
|
21734
|
-
fonts:
|
|
21735
|
-
family:
|
|
21736
|
-
weight:
|
|
21737
|
-
style:
|
|
21738
|
-
unicodeRange:
|
|
21739
|
-
file:
|
|
21775
|
+
fonts: z105.array(z105.object({
|
|
21776
|
+
family: z105.string(),
|
|
21777
|
+
weight: z105.string(),
|
|
21778
|
+
style: z105.string(),
|
|
21779
|
+
unicodeRange: z105.string().nullable(),
|
|
21780
|
+
file: z105.string().optional()
|
|
21740
21781
|
}).transform((font) => ({
|
|
21741
21782
|
...font,
|
|
21742
21783
|
file: font.file
|
|
21743
21784
|
}))),
|
|
21744
|
-
screenshots:
|
|
21745
|
-
desktop:
|
|
21746
|
-
mobile:
|
|
21785
|
+
screenshots: z105.object({
|
|
21786
|
+
desktop: z105.array(WebsiteCaptureScreenshotSchema),
|
|
21787
|
+
mobile: z105.array(WebsiteCaptureScreenshotSchema)
|
|
21747
21788
|
})
|
|
21748
21789
|
});
|
|
21749
21790
|
|
|
@@ -21989,7 +22030,7 @@ var ApiClient = class {
|
|
|
21989
22030
|
};
|
|
21990
22031
|
|
|
21991
22032
|
// src/index.ts
|
|
21992
|
-
var MCP_VERSION = "11.2.
|
|
22033
|
+
var MCP_VERSION = "11.2.1";
|
|
21993
22034
|
|
|
21994
22035
|
// src/meta-upload-app.ts
|
|
21995
22036
|
import { readFileSync } from "fs";
|
|
@@ -22061,7 +22102,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
|
|
|
22061
22102
|
__name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
|
|
22062
22103
|
|
|
22063
22104
|
// src/tools/tasks.ts
|
|
22064
|
-
import { z as
|
|
22105
|
+
import { z as z110 } from "zod";
|
|
22065
22106
|
|
|
22066
22107
|
// src/resolve-image.ts
|
|
22067
22108
|
import { lookup as dnsLookup } from "dns/promises";
|
|
@@ -22622,9 +22663,9 @@ async function resolveMediaRef(ref, opts) {
|
|
|
22622
22663
|
__name(resolveMediaRef, "resolveMediaRef");
|
|
22623
22664
|
|
|
22624
22665
|
// src/tools/shared.ts
|
|
22625
|
-
import { z as
|
|
22626
|
-
var Lang =
|
|
22627
|
-
var Country =
|
|
22666
|
+
import { z as z106 } from "zod";
|
|
22667
|
+
var Lang = z106.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);
|
|
22668
|
+
var Country = z106.string().min(2).max(3);
|
|
22628
22669
|
var LandingStrategyEnum = LandingStrategySchema;
|
|
22629
22670
|
var LandingImageFormatEnum = LandingImageFormatSchema;
|
|
22630
22671
|
var VideoPresetEnum = VideoPreset.extract([
|
|
@@ -22728,7 +22769,7 @@ function animationStyleApplies(videoPreset, angleNarratives) {
|
|
|
22728
22769
|
return ANIMATED_VIDEO_PRESETS.has(videoPreset ?? "") || (angleNarratives ?? []).some((n) => ANIMATED_NARRATIVE_STYLES.has(n));
|
|
22729
22770
|
}
|
|
22730
22771
|
__name(animationStyleApplies, "animationStyleApplies");
|
|
22731
|
-
var VideoTierEnum =
|
|
22772
|
+
var VideoTierEnum = z106.enum([
|
|
22732
22773
|
"basic"
|
|
22733
22774
|
]);
|
|
22734
22775
|
function resolveVideoTier(_tier) {
|
|
@@ -22786,10 +22827,10 @@ var ImageCreativeStyleEnum = ImageCreativeStyle;
|
|
|
22786
22827
|
var ImageCreativeArchetypeEnum = ImageCreativeArchetype;
|
|
22787
22828
|
var ImageCreativeVisualTreatmentEnum = ImageCreativeVisualTreatment;
|
|
22788
22829
|
var ImageCreativeAspectRatioEnum = ImageCreativeAspectRatio;
|
|
22789
|
-
var ImageRefSchema =
|
|
22790
|
-
url:
|
|
22791
|
-
path:
|
|
22792
|
-
assetId:
|
|
22830
|
+
var ImageRefSchema = z106.object({
|
|
22831
|
+
url: z106.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.'),
|
|
22832
|
+
path: z106.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`.'),
|
|
22833
|
+
assetId: z106.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.")
|
|
22793
22834
|
}).refine((v) => [
|
|
22794
22835
|
v.url,
|
|
22795
22836
|
v.path,
|
|
@@ -22797,11 +22838,11 @@ var ImageRefSchema = z105.object({
|
|
|
22797
22838
|
].filter(Boolean).length === 1, {
|
|
22798
22839
|
message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
|
|
22799
22840
|
});
|
|
22800
|
-
var ImagesInput =
|
|
22841
|
+
var ImagesInput = z106.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
|
|
22801
22842
|
const assetCount = images.filter((image) => Boolean(image.assetId)).length;
|
|
22802
22843
|
if (assetCount > 0 && assetCount !== images.length) {
|
|
22803
22844
|
ctx.addIssue({
|
|
22804
|
-
code:
|
|
22845
|
+
code: z106.ZodIssueCode.custom,
|
|
22805
22846
|
message: "all image entries must use assetId, or all must use URL/path sources"
|
|
22806
22847
|
});
|
|
22807
22848
|
}
|
|
@@ -22874,14 +22915,14 @@ async function submitCreative(api, opts) {
|
|
|
22874
22915
|
});
|
|
22875
22916
|
}
|
|
22876
22917
|
__name(submitCreative, "submitCreative");
|
|
22877
|
-
var ResearchTargetCountryEnum =
|
|
22918
|
+
var ResearchTargetCountryEnum = z106.enum([
|
|
22878
22919
|
"CO",
|
|
22879
22920
|
"MX",
|
|
22880
22921
|
"PE",
|
|
22881
22922
|
"EC",
|
|
22882
22923
|
"CL"
|
|
22883
22924
|
]);
|
|
22884
|
-
var ResearchCategoryEnum =
|
|
22925
|
+
var ResearchCategoryEnum = z106.enum([
|
|
22885
22926
|
"auto",
|
|
22886
22927
|
"automotive",
|
|
22887
22928
|
"kitchen",
|
|
@@ -24246,29 +24287,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
|
|
|
24246
24287
|
__name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
|
|
24247
24288
|
|
|
24248
24289
|
// src/tools/media-presentation.ts
|
|
24249
|
-
import { z as
|
|
24250
|
-
var HttpsPresentationUrlSchema =
|
|
24290
|
+
import { z as z107 } from "zod";
|
|
24291
|
+
var HttpsPresentationUrlSchema = z107.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
|
|
24251
24292
|
var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
|
|
24252
24293
|
const hostname = new URL(value).hostname.toLowerCase();
|
|
24253
24294
|
return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
|
|
24254
24295
|
}, "preview URL must be owned by ProductMaker");
|
|
24255
|
-
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) =>
|
|
24256
|
-
var PresentationImageSchema =
|
|
24257
|
-
kind:
|
|
24296
|
+
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z107.number().int().positive().max(maximum), "positiveIntAtMost");
|
|
24297
|
+
var PresentationImageSchema = z107.object({
|
|
24298
|
+
kind: z107.literal("image"),
|
|
24258
24299
|
url: HttpsPresentationUrlSchema,
|
|
24259
|
-
mimeType:
|
|
24300
|
+
mimeType: z107.enum([
|
|
24260
24301
|
"image/jpeg",
|
|
24261
24302
|
"image/png"
|
|
24262
24303
|
]),
|
|
24263
24304
|
byteSize: positiveIntAtMost(5 * 1024 * 1024),
|
|
24264
24305
|
width: positiveIntAtMost(16384),
|
|
24265
24306
|
height: positiveIntAtMost(16384),
|
|
24266
|
-
alt:
|
|
24307
|
+
alt: z107.string().trim().min(1).max(240)
|
|
24267
24308
|
}).strict();
|
|
24268
24309
|
var McpMediaPresentationSchema = PresentationImageSchema;
|
|
24269
|
-
var GalleryImageSchema =
|
|
24310
|
+
var GalleryImageSchema = z107.object({
|
|
24270
24311
|
url: ProductMakerPreviewUrlSchema,
|
|
24271
|
-
alt:
|
|
24312
|
+
alt: z107.string().trim().min(1).max(240)
|
|
24272
24313
|
});
|
|
24273
24314
|
var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
|
|
24274
24315
|
async function imageBlocks(image, transport) {
|
|
@@ -24325,12 +24366,12 @@ async function buildMcpMediaPresentationContent(rawPresentation, transport = "ht
|
|
|
24325
24366
|
];
|
|
24326
24367
|
}
|
|
24327
24368
|
__name(buildMcpMediaPresentationContent, "buildMcpMediaPresentationContent");
|
|
24328
|
-
var OwnedImagePreviewSchema =
|
|
24369
|
+
var OwnedImagePreviewSchema = z107.object({
|
|
24329
24370
|
url: HttpsPresentationUrlSchema.refine((value) => {
|
|
24330
24371
|
const url = new URL(value);
|
|
24331
24372
|
return !url.username && !url.password && !isPrivateHost(url.hostname);
|
|
24332
24373
|
}, "Preview URL must be public HTTPS without credentials"),
|
|
24333
|
-
alt:
|
|
24374
|
+
alt: z107.string().trim().min(1).max(240)
|
|
24334
24375
|
});
|
|
24335
24376
|
async function buildMcpImagePreviewContent(rawPreview, transport = "http") {
|
|
24336
24377
|
const preview2 = OwnedImagePreviewSchema.safeParse(rawPreview);
|
|
@@ -24413,7 +24454,7 @@ async function buildMcpImageGalleryContent(rawItems, transport = "http") {
|
|
|
24413
24454
|
__name(buildMcpImageGalleryContent, "buildMcpImageGalleryContent");
|
|
24414
24455
|
|
|
24415
24456
|
// src/tools/animated-video.ts
|
|
24416
|
-
import { z as
|
|
24457
|
+
import { z as z108 } from "zod";
|
|
24417
24458
|
|
|
24418
24459
|
// src/tools/paid-confirmation.ts
|
|
24419
24460
|
function describeMarketStudyChoice(enabled) {
|
|
@@ -24663,27 +24704,27 @@ function hookVariantsLabel(count) {
|
|
|
24663
24704
|
return count === 1 ? "1 versi\xF3n del gancho" : `${count} versiones del gancho`;
|
|
24664
24705
|
}
|
|
24665
24706
|
__name(hookVariantsLabel, "hookVariantsLabel");
|
|
24666
|
-
var DurationInput =
|
|
24667
|
-
var CreateAnimatedVideoInput =
|
|
24668
|
-
action:
|
|
24707
|
+
var DurationInput = z108.union(MOTION_GRAPHICS_DURATIONS.map((d) => z108.literal(d)));
|
|
24708
|
+
var CreateAnimatedVideoInput = z108.object({
|
|
24709
|
+
action: z108.enum([
|
|
24669
24710
|
"prepare",
|
|
24670
24711
|
"status",
|
|
24671
24712
|
"cancel",
|
|
24672
24713
|
"generate"
|
|
24673
24714
|
]).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."),
|
|
24674
|
-
websiteCaptureId:
|
|
24675
|
-
generationRequestId:
|
|
24676
|
-
confirmed:
|
|
24715
|
+
websiteCaptureId: z108.string().uuid().optional().describe("ID de la captura preparada. Obligatorio para status/cancel/generate; no inventarlo."),
|
|
24716
|
+
generationRequestId: z108.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."),
|
|
24717
|
+
confirmed: z108.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."),
|
|
24677
24718
|
// Plain text, not `.url()`: users type «cal.com», and the web accepts it.
|
|
24678
24719
|
// normalizeWebAddress (shared with the web) adds https:// and refuses
|
|
24679
24720
|
// anything that is not a public http(s) address.
|
|
24680
|
-
landingUrl:
|
|
24721
|
+
landingUrl: z108.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."),
|
|
24681
24722
|
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.'),
|
|
24682
24723
|
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.`),
|
|
24683
24724
|
language: MotionGraphicsLanguageSchema.optional().describe('Idioma de los textos del video: "es", "en" o "pt".'),
|
|
24684
|
-
notes:
|
|
24725
|
+
notes: z108.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)."),
|
|
24685
24726
|
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.`),
|
|
24686
|
-
music:
|
|
24727
|
+
music: z108.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.")
|
|
24687
24728
|
}).strict();
|
|
24688
24729
|
function captureNextAction(capture) {
|
|
24689
24730
|
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.";
|
|
@@ -24716,43 +24757,43 @@ var FORMAT_LABELS = {
|
|
|
24716
24757
|
square: "cuadrado 1:1",
|
|
24717
24758
|
horizontal: "horizontal 16:9"
|
|
24718
24759
|
};
|
|
24719
|
-
var AnimatedVideoResultSchema =
|
|
24720
|
-
status:
|
|
24760
|
+
var AnimatedVideoResultSchema = z108.object({
|
|
24761
|
+
status: z108.enum([
|
|
24721
24762
|
"pending",
|
|
24722
24763
|
"done",
|
|
24723
24764
|
"error"
|
|
24724
24765
|
]),
|
|
24725
|
-
serviceMode:
|
|
24726
|
-
finalMp4Url:
|
|
24727
|
-
error:
|
|
24728
|
-
motionGraphics:
|
|
24766
|
+
serviceMode: z108.literal("motion_graphics"),
|
|
24767
|
+
finalMp4Url: z108.string().optional(),
|
|
24768
|
+
error: z108.string().optional(),
|
|
24769
|
+
motionGraphics: z108.object({
|
|
24729
24770
|
stage: MotionGraphicsStageSchema,
|
|
24730
24771
|
format: MotionGraphicsFormatSchema,
|
|
24731
|
-
durationSec:
|
|
24732
|
-
width:
|
|
24733
|
-
height:
|
|
24772
|
+
durationSec: z108.number(),
|
|
24773
|
+
width: z108.number().optional(),
|
|
24774
|
+
height: z108.number().optional(),
|
|
24734
24775
|
language: MotionGraphicsLanguageSchema.optional(),
|
|
24735
|
-
queuedAt:
|
|
24736
|
-
jobsAhead:
|
|
24737
|
-
stageStartedAt:
|
|
24738
|
-
renderProgress:
|
|
24776
|
+
queuedAt: z108.string().optional(),
|
|
24777
|
+
jobsAhead: z108.number().int().nonnegative().optional(),
|
|
24778
|
+
stageStartedAt: z108.string().optional(),
|
|
24779
|
+
renderProgress: z108.number().optional(),
|
|
24739
24780
|
// AI clip fields (absent on a video paid before clips, or from an API
|
|
24740
24781
|
// that predates them). Lenient: an unreadable value is dropped
|
|
24741
24782
|
// instead of hiding the status.
|
|
24742
|
-
clipCount:
|
|
24743
|
-
clipsUsed:
|
|
24744
|
-
clipPriceCents:
|
|
24745
|
-
clipsRefunded:
|
|
24783
|
+
clipCount: z108.number().int().nonnegative().optional().catch(void 0),
|
|
24784
|
+
clipsUsed: z108.number().int().nonnegative().optional().catch(void 0),
|
|
24785
|
+
clipPriceCents: z108.number().finite().nonnegative().optional().catch(void 0),
|
|
24786
|
+
clipsRefunded: z108.number().int().nonnegative().optional().catch(void 0),
|
|
24746
24787
|
// Hook versions (absent from an API or a video before them): the
|
|
24747
24788
|
// count ordered and, once done, the signed URLs of the EXTRA versions
|
|
24748
24789
|
// (hook 2, hook 3); `finalMp4Url` is hook 1.
|
|
24749
|
-
hookVariants:
|
|
24750
|
-
variantUrls:
|
|
24790
|
+
hookVariants: z108.number().int().min(1).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX).optional().catch(void 0),
|
|
24791
|
+
variantUrls: z108.array(z108.string().min(1)).max(MOTION_GRAPHICS_HOOK_VARIANTS_MAX - 1).optional().catch(void 0),
|
|
24751
24792
|
// Extra hook versions given back, as the task recorded it once the
|
|
24752
24793
|
// refunds landed (absent until then, and from an API before it).
|
|
24753
|
-
variantsRefunded:
|
|
24754
|
-
activity:
|
|
24755
|
-
previewUrl:
|
|
24794
|
+
variantsRefunded: z108.number().int().nonnegative().optional().catch(void 0),
|
|
24795
|
+
activity: z108.array(MotionGraphicsActivitySchema).optional().catch(void 0),
|
|
24796
|
+
previewUrl: z108.string().optional()
|
|
24756
24797
|
}).passthrough()
|
|
24757
24798
|
}).passthrough();
|
|
24758
24799
|
function parseAnimatedVideoResult(value) {
|
|
@@ -25008,10 +25049,10 @@ function registerAnimatedVideoTools(server, api) {
|
|
|
25008
25049
|
__name(registerAnimatedVideoTools, "registerAnimatedVideoTools");
|
|
25009
25050
|
|
|
25010
25051
|
// src/tools/winning-product-image.ts
|
|
25011
|
-
import { z as
|
|
25012
|
-
var WinnerReferenceInput =
|
|
25013
|
-
runId:
|
|
25014
|
-
candidateSourceId:
|
|
25052
|
+
import { z as z109 } from "zod";
|
|
25053
|
+
var WinnerReferenceInput = z109.object({
|
|
25054
|
+
runId: z109.string().uuid(),
|
|
25055
|
+
candidateSourceId: z109.string().trim().min(1).max(160)
|
|
25015
25056
|
}).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
|
|
25016
25057
|
async function resolveWinnerImages(api, winnerReference, images) {
|
|
25017
25058
|
if (!winnerReference) return images;
|
|
@@ -25048,62 +25089,62 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
|
|
|
25048
25089
|
var CREATE_SERVICE_VIDEO_ON_MCP = PRODUCTMAKER_MCP_CAPABILITY_NAMES.includes("create_service_video");
|
|
25049
25090
|
var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
|
|
25050
25091
|
var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
|
|
25051
|
-
var CreateProductTaskInput =
|
|
25092
|
+
var CreateProductTaskInput = z110.object({
|
|
25052
25093
|
images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
|
|
25053
25094
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
25054
|
-
projectId:
|
|
25055
|
-
productUrl:
|
|
25095
|
+
projectId: z110.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
|
|
25096
|
+
productUrl: z110.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."),
|
|
25056
25097
|
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.'),
|
|
25057
25098
|
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.'),
|
|
25058
|
-
price:
|
|
25059
|
-
compareAtPrice:
|
|
25060
|
-
offer:
|
|
25061
|
-
paymentMethods:
|
|
25062
|
-
productContext:
|
|
25063
|
-
productLabel:
|
|
25099
|
+
price: z110.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.'),
|
|
25100
|
+
compareAtPrice: z110.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".'),
|
|
25101
|
+
offer: z110.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.'),
|
|
25102
|
+
paymentMethods: z110.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.'),
|
|
25103
|
+
productContext: z110.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."),
|
|
25104
|
+
productLabel: z110.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.'),
|
|
25064
25105
|
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.'),
|
|
25065
25106
|
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.'),
|
|
25066
|
-
durationSeconds:
|
|
25067
|
-
|
|
25068
|
-
|
|
25107
|
+
durationSeconds: z110.union([
|
|
25108
|
+
z110.literal(15),
|
|
25109
|
+
z110.literal(30)
|
|
25069
25110
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
25070
|
-
pauseForAngleReview:
|
|
25071
|
-
aiDecidesAll:
|
|
25111
|
+
pauseForAngleReview: z110.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."),
|
|
25112
|
+
aiDecidesAll: z110.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."),
|
|
25072
25113
|
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.'),
|
|
25073
25114
|
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.'),
|
|
25074
25115
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
25075
25116
|
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).'),
|
|
25076
|
-
videoAngleCount:
|
|
25117
|
+
videoAngleCount: z110.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."),
|
|
25077
25118
|
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.'),
|
|
25078
|
-
outputs:
|
|
25119
|
+
outputs: z110.array(z110.enum([
|
|
25079
25120
|
"landing",
|
|
25080
25121
|
"video",
|
|
25081
25122
|
"image"
|
|
25082
25123
|
])).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}`),
|
|
25083
|
-
includeInitialLandingGif:
|
|
25084
|
-
competitorScanEnabled:
|
|
25124
|
+
includeInitialLandingGif: z110.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."),
|
|
25125
|
+
competitorScanEnabled: z110.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."),
|
|
25085
25126
|
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.'),
|
|
25086
|
-
replicateWinnerWhenFound:
|
|
25087
|
-
brandId:
|
|
25088
|
-
actorId:
|
|
25127
|
+
replicateWinnerWhenFound: z110.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."),
|
|
25128
|
+
brandId: z110.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."),
|
|
25129
|
+
actorId: z110.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."),
|
|
25089
25130
|
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.'),
|
|
25090
|
-
creativeDirection:
|
|
25091
|
-
headline:
|
|
25092
|
-
subheadline:
|
|
25131
|
+
creativeDirection: z110.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.'),
|
|
25132
|
+
headline: z110.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."),
|
|
25133
|
+
subheadline: z110.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."),
|
|
25093
25134
|
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".'),
|
|
25094
25135
|
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".')
|
|
25095
25136
|
}).strict();
|
|
25096
|
-
var CreateServiceVideoInput =
|
|
25097
|
-
landingUrl:
|
|
25098
|
-
additionalContext:
|
|
25137
|
+
var CreateServiceVideoInput = z110.object({
|
|
25138
|
+
landingUrl: z110.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
|
|
25139
|
+
additionalContext: z110.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
|
|
25099
25140
|
language: Lang.describe("Idioma del video: es, en o pt."),
|
|
25100
|
-
voiceId:
|
|
25101
|
-
brandId:
|
|
25102
|
-
reviewMode:
|
|
25141
|
+
voiceId: z110.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.'),
|
|
25142
|
+
brandId: z110.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
|
|
25143
|
+
reviewMode: z110.enum([
|
|
25103
25144
|
"automatic",
|
|
25104
25145
|
"guided"
|
|
25105
25146
|
]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
|
|
25106
|
-
videoPreset:
|
|
25147
|
+
videoPreset: z110.enum([
|
|
25107
25148
|
"auto",
|
|
25108
25149
|
"ugc_dynamic",
|
|
25109
25150
|
"ugc_how_to",
|
|
@@ -25113,128 +25154,128 @@ var CreateServiceVideoInput = z109.object({
|
|
|
25113
25154
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
25114
25155
|
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.')
|
|
25115
25156
|
}).strict();
|
|
25116
|
-
var GetTaskStatusInput =
|
|
25117
|
-
taskId:
|
|
25118
|
-
waitSeconds:
|
|
25157
|
+
var GetTaskStatusInput = z110.object({
|
|
25158
|
+
taskId: z110.string().min(1),
|
|
25159
|
+
waitSeconds: z110.number().int().min(0).max(120).optional()
|
|
25119
25160
|
});
|
|
25120
|
-
var ListTasksInput =
|
|
25121
|
-
limit:
|
|
25122
|
-
offset:
|
|
25123
|
-
search:
|
|
25161
|
+
var ListTasksInput = z110.object({
|
|
25162
|
+
limit: z110.number().int().min(1).max(50).optional(),
|
|
25163
|
+
offset: z110.number().int().min(0).optional(),
|
|
25164
|
+
search: z110.string().optional()
|
|
25124
25165
|
});
|
|
25125
25166
|
var MCP_REVIEW_LIST_FIELD_MAX = IMAGE_WIZARD_LIST_FIELD_MAX;
|
|
25126
25167
|
var MCP_REVIEW_FEATURE_ITEM_MAX = IMAGE_FEATURE_ITEM_MAX;
|
|
25127
|
-
var EditTaskDraftInput =
|
|
25128
|
-
taskId:
|
|
25129
|
-
angleIndex:
|
|
25130
|
-
angle:
|
|
25131
|
-
angle:
|
|
25132
|
-
buyerPersona:
|
|
25133
|
-
actor:
|
|
25134
|
-
actorId:
|
|
25135
|
-
gender:
|
|
25168
|
+
var EditTaskDraftInput = z110.object({
|
|
25169
|
+
taskId: z110.string().min(1),
|
|
25170
|
+
angleIndex: z110.number().int().min(0),
|
|
25171
|
+
angle: z110.object({
|
|
25172
|
+
angle: z110.string().min(1).max(480),
|
|
25173
|
+
buyerPersona: z110.string().min(1).max(360),
|
|
25174
|
+
actor: z110.string().min(1).max(360).optional(),
|
|
25175
|
+
actorId: z110.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."),
|
|
25176
|
+
gender: z110.enum([
|
|
25136
25177
|
"female",
|
|
25137
25178
|
"male"
|
|
25138
25179
|
]).optional(),
|
|
25139
|
-
scriptNotes:
|
|
25180
|
+
scriptNotes: z110.string().max(2e3).optional()
|
|
25140
25181
|
})
|
|
25141
25182
|
});
|
|
25142
|
-
var PendingActionPayload =
|
|
25143
|
-
|
|
25144
|
-
kind:
|
|
25183
|
+
var PendingActionPayload = z110.discriminatedUnion("kind", [
|
|
25184
|
+
z110.object({
|
|
25185
|
+
kind: z110.literal("product_reference_set_approval"),
|
|
25145
25186
|
scope: ProductReferenceScopeEnum.optional(),
|
|
25146
|
-
scopeKey:
|
|
25147
|
-
scopeSnapshotId:
|
|
25148
|
-
expectedScopeHash:
|
|
25187
|
+
scopeKey: z110.string().min(1).max(120).optional(),
|
|
25188
|
+
scopeSnapshotId: z110.string().uuid().optional(),
|
|
25189
|
+
expectedScopeHash: z110.string().min(1).max(128).optional(),
|
|
25149
25190
|
decision: ProductReferenceResolutionDecisionEnum,
|
|
25150
25191
|
reason: ProductReferenceRejectionReasonEnum.optional(),
|
|
25151
|
-
affectedRefKeys:
|
|
25152
|
-
affectedPhotoNumbers:
|
|
25153
|
-
recoveryAction:
|
|
25192
|
+
affectedRefKeys: z110.array(z110.string().min(1).max(200)).min(1).optional(),
|
|
25193
|
+
affectedPhotoNumbers: z110.array(z110.number().int().positive()).min(1).optional(),
|
|
25194
|
+
recoveryAction: z110.enum([
|
|
25154
25195
|
"remove",
|
|
25155
25196
|
"replace",
|
|
25156
25197
|
"upload",
|
|
25157
25198
|
"return_to_selection"
|
|
25158
25199
|
]).optional()
|
|
25159
25200
|
}),
|
|
25160
|
-
|
|
25161
|
-
kind:
|
|
25162
|
-
selectedPhotoNumbers:
|
|
25201
|
+
z110.object({
|
|
25202
|
+
kind: z110.literal("product_reference_confirmation"),
|
|
25203
|
+
selectedPhotoNumbers: z110.array(z110.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."),
|
|
25163
25204
|
userChoice: ProductReferenceUserChoiceEnum.optional(),
|
|
25164
|
-
confirmedProductNames:
|
|
25205
|
+
confirmedProductNames: z110.array(z110.string().min(1).max(120)).min(2).max(8).optional(),
|
|
25165
25206
|
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."),
|
|
25166
25207
|
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."),
|
|
25167
|
-
useMultiSceneShowcase:
|
|
25208
|
+
useMultiSceneShowcase: z110.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
|
|
25168
25209
|
}),
|
|
25169
|
-
|
|
25170
|
-
kind:
|
|
25210
|
+
z110.object({
|
|
25211
|
+
kind: z110.literal("angle_review_approval"),
|
|
25171
25212
|
// All edits are optional — empty action body just approves the
|
|
25172
25213
|
// backend-generated draft as-is. Field shapes mirror the angle-review
|
|
25173
25214
|
// request contracts in @packages/types/wizard.ts; the handler routes to
|
|
25174
25215
|
// the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
|
|
25175
|
-
customAngle:
|
|
25216
|
+
customAngle: z110.string().min(1).max(480).optional(),
|
|
25176
25217
|
// Keep the shared MCP action within the strictest downstream contract:
|
|
25177
25218
|
// autopilot/image resume endpoints cap these fields at 1500 characters.
|
|
25178
|
-
painPoints:
|
|
25179
|
-
benefits:
|
|
25219
|
+
painPoints: z110.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
25220
|
+
benefits: z110.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
25180
25221
|
// Same policy as the two fields above: the strictest downstream contract
|
|
25181
25222
|
// wins. The image endpoint caps each feature at 240 while landing/video
|
|
25182
25223
|
// accept 300, and this single action routes to whichever the task is — so
|
|
25183
25224
|
// accepting 300 here turns a 250-character feature on an image task into
|
|
25184
25225
|
// an opaque HTTP 400 after the model already believed it had been saved.
|
|
25185
|
-
features:
|
|
25186
|
-
buyerPersona:
|
|
25226
|
+
features: z110.array(z110.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
|
|
25227
|
+
buyerPersona: z110.string().min(1).max(360).optional(),
|
|
25187
25228
|
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.'),
|
|
25188
|
-
actor:
|
|
25189
|
-
actorId:
|
|
25190
|
-
creativeDirection:
|
|
25191
|
-
selectedAngleNumbers:
|
|
25192
|
-
angleEdits:
|
|
25193
|
-
angleNumber:
|
|
25194
|
-
narrativeSelection:
|
|
25229
|
+
actor: z110.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."),
|
|
25230
|
+
actorId: z110.string().max(120).nullable().optional(),
|
|
25231
|
+
creativeDirection: z110.string().max(2e3).optional(),
|
|
25232
|
+
selectedAngleNumbers: z110.array(z110.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."),
|
|
25233
|
+
angleEdits: z110.array(z110.object({
|
|
25234
|
+
angleNumber: z110.number().int().positive(),
|
|
25235
|
+
narrativeSelection: z110.enum([
|
|
25195
25236
|
"market",
|
|
25196
25237
|
"guided"
|
|
25197
25238
|
]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
|
|
25198
|
-
angle:
|
|
25199
|
-
buyerPersona:
|
|
25239
|
+
angle: z110.string().min(1).max(480).optional(),
|
|
25240
|
+
buyerPersona: z110.string().min(1).max(360).optional(),
|
|
25200
25241
|
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.'),
|
|
25201
|
-
actor:
|
|
25202
|
-
actorId:
|
|
25203
|
-
creativeDirection:
|
|
25242
|
+
actor: z110.string().min(1).max(360).optional(),
|
|
25243
|
+
actorId: z110.string().max(120).nullable().optional(),
|
|
25244
|
+
creativeDirection: z110.string().max(2e3).optional()
|
|
25204
25245
|
}).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)."),
|
|
25205
|
-
gapDurationSeconds:
|
|
25206
|
-
|
|
25207
|
-
|
|
25246
|
+
gapDurationSeconds: z110.union([
|
|
25247
|
+
z110.literal(15),
|
|
25248
|
+
z110.literal(30)
|
|
25208
25249
|
]).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.")
|
|
25209
25250
|
}),
|
|
25210
|
-
|
|
25211
|
-
kind:
|
|
25212
|
-
angleId:
|
|
25213
|
-
angleNumber:
|
|
25214
|
-
content:
|
|
25215
|
-
creativeDirection:
|
|
25216
|
-
actor:
|
|
25251
|
+
z110.object({
|
|
25252
|
+
kind: z110.literal("service_angle_approval"),
|
|
25253
|
+
angleId: z110.string().uuid().optional(),
|
|
25254
|
+
angleNumber: z110.number().int().positive().optional(),
|
|
25255
|
+
content: z110.string().min(1).max(480).optional(),
|
|
25256
|
+
creativeDirection: z110.string().min(1).max(1500).optional(),
|
|
25257
|
+
actor: z110.string().min(1).max(360).optional()
|
|
25217
25258
|
}),
|
|
25218
|
-
|
|
25219
|
-
kind:
|
|
25220
|
-
voiceovers:
|
|
25221
|
-
visualDirections:
|
|
25222
|
-
voiceoversByScene:
|
|
25223
|
-
visualDirectionsByScene:
|
|
25259
|
+
z110.object({
|
|
25260
|
+
kind: z110.literal("service_script_approval"),
|
|
25261
|
+
voiceovers: z110.record(z110.string(), z110.string().min(1).max(600)).optional(),
|
|
25262
|
+
visualDirections: z110.record(z110.string(), z110.string().min(1).max(1200)).optional(),
|
|
25263
|
+
voiceoversByScene: z110.record(z110.string(), z110.string().min(1).max(600)).optional(),
|
|
25264
|
+
visualDirectionsByScene: z110.record(z110.string(), z110.string().min(1).max(1200)).optional()
|
|
25224
25265
|
})
|
|
25225
25266
|
]);
|
|
25226
|
-
var ResolvePendingActionInput =
|
|
25227
|
-
taskId:
|
|
25267
|
+
var ResolvePendingActionInput = z110.object({
|
|
25268
|
+
taskId: z110.string().min(1),
|
|
25228
25269
|
action: PendingActionPayload
|
|
25229
25270
|
}).strict();
|
|
25230
25271
|
function resolveVariantConfirmVideoTier(action) {
|
|
25231
25272
|
return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
|
|
25232
25273
|
}
|
|
25233
25274
|
__name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
|
|
25234
|
-
var StatusForResolveSchema =
|
|
25275
|
+
var StatusForResolveSchema = z110.object({
|
|
25235
25276
|
// Metadata used to select the backend resume contract. Older API responses
|
|
25236
25277
|
// may omit these fields, so the resolver keeps the generic fallback.
|
|
25237
|
-
kind:
|
|
25278
|
+
kind: z110.enum([
|
|
25238
25279
|
"autopilot",
|
|
25239
25280
|
"video",
|
|
25240
25281
|
"image",
|
|
@@ -25242,18 +25283,18 @@ var StatusForResolveSchema = z109.object({
|
|
|
25242
25283
|
"mix",
|
|
25243
25284
|
"service"
|
|
25244
25285
|
]).optional(),
|
|
25245
|
-
selectedOutputs:
|
|
25286
|
+
selectedOutputs: z110.array(z110.enum([
|
|
25246
25287
|
"landing",
|
|
25247
25288
|
"video",
|
|
25248
25289
|
"image"
|
|
25249
25290
|
])).optional(),
|
|
25250
|
-
videoAngleCount:
|
|
25251
|
-
ugcFormat:
|
|
25291
|
+
videoAngleCount: z110.number().int().min(1).max(3).optional(),
|
|
25292
|
+
ugcFormat: z110.enum([
|
|
25252
25293
|
"single_8s",
|
|
25253
25294
|
"single_15s",
|
|
25254
25295
|
"double_30s"
|
|
25255
25296
|
]).optional(),
|
|
25256
|
-
videoStyle:
|
|
25297
|
+
videoStyle: z110.enum([
|
|
25257
25298
|
"ugc",
|
|
25258
25299
|
"cartoon_3d",
|
|
25259
25300
|
"product_only",
|
|
@@ -25263,13 +25304,13 @@ var StatusForResolveSchema = z109.object({
|
|
|
25263
25304
|
videoQuality: VideoQualityEnum.optional(),
|
|
25264
25305
|
videoRouteId: VideoRouteIdEnum.optional(),
|
|
25265
25306
|
videoModel: TaskVideoModelEnum.optional(),
|
|
25266
|
-
videoTier:
|
|
25307
|
+
videoTier: z110.enum([
|
|
25267
25308
|
"legacy",
|
|
25268
25309
|
"standard",
|
|
25269
25310
|
"pro",
|
|
25270
25311
|
"single_call"
|
|
25271
25312
|
]).optional(),
|
|
25272
|
-
videoResolution:
|
|
25313
|
+
videoResolution: z110.enum([
|
|
25273
25314
|
"480p",
|
|
25274
25315
|
"720p"
|
|
25275
25316
|
]).optional(),
|
|
@@ -25277,60 +25318,60 @@ var StatusForResolveSchema = z109.object({
|
|
|
25277
25318
|
// A task created before a narrative was blocked/hidden must still parse,
|
|
25278
25319
|
// or resolve_pending_action could never approve it.
|
|
25279
25320
|
narrativeStyle: NarrativeStyle.optional(),
|
|
25280
|
-
pauseForVideoScriptReview:
|
|
25281
|
-
pendingUserAction:
|
|
25282
|
-
kind:
|
|
25283
|
-
candidateGrouping:
|
|
25284
|
-
selectedImageUrls:
|
|
25285
|
-
proposedProductNames:
|
|
25321
|
+
pauseForVideoScriptReview: z110.boolean().optional(),
|
|
25322
|
+
pendingUserAction: z110.object({
|
|
25323
|
+
kind: z110.string(),
|
|
25324
|
+
candidateGrouping: z110.string().optional(),
|
|
25325
|
+
selectedImageUrls: z110.array(z110.string()).optional(),
|
|
25326
|
+
proposedProductNames: z110.array(z110.string()).optional(),
|
|
25286
25327
|
// Adaptive reference questions are server-owned. Echo only the evidence
|
|
25287
25328
|
// identity and the choices shown by the current snapshot; never accept a
|
|
25288
25329
|
// client-supplied reference set as authorization.
|
|
25289
|
-
options:
|
|
25290
|
-
mode:
|
|
25330
|
+
options: z110.array(ProductReferenceUserChoiceEnum).max(4).optional(),
|
|
25331
|
+
mode: z110.enum([
|
|
25291
25332
|
"question",
|
|
25292
25333
|
"visual_recovery"
|
|
25293
25334
|
]).optional(),
|
|
25294
25335
|
/** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
|
|
25295
|
-
canKeepSelection:
|
|
25296
|
-
decisionKey:
|
|
25297
|
-
questionOrdinal:
|
|
25298
|
-
questionCeiling:
|
|
25299
|
-
|
|
25300
|
-
|
|
25336
|
+
canKeepSelection: z110.boolean().optional(),
|
|
25337
|
+
decisionKey: z110.string().optional(),
|
|
25338
|
+
questionOrdinal: z110.number().int().min(1).max(5).optional(),
|
|
25339
|
+
questionCeiling: z110.union([
|
|
25340
|
+
z110.literal(3),
|
|
25341
|
+
z110.literal(5)
|
|
25301
25342
|
]).optional(),
|
|
25302
|
-
referenceEvidenceVersion:
|
|
25303
|
-
expectedEvidenceHash:
|
|
25304
|
-
question:
|
|
25305
|
-
prompt:
|
|
25306
|
-
helpText:
|
|
25307
|
-
options:
|
|
25343
|
+
referenceEvidenceVersion: z110.number().int().positive().optional(),
|
|
25344
|
+
expectedEvidenceHash: z110.string().optional(),
|
|
25345
|
+
question: z110.object({
|
|
25346
|
+
prompt: z110.string().min(1).max(240),
|
|
25347
|
+
helpText: z110.string().min(1).max(300).optional(),
|
|
25348
|
+
options: z110.array(z110.object({
|
|
25308
25349
|
value: ProductReferenceUserChoiceEnum,
|
|
25309
|
-
label:
|
|
25310
|
-
description:
|
|
25350
|
+
label: z110.string().min(1).max(120),
|
|
25351
|
+
description: z110.string().min(1).max(240).optional()
|
|
25311
25352
|
})).min(2).max(4)
|
|
25312
25353
|
}).optional(),
|
|
25313
25354
|
scope: ProductReferenceScopeEnum.optional(),
|
|
25314
|
-
scopeKey:
|
|
25315
|
-
scopeSnapshotId:
|
|
25316
|
-
scopeHash:
|
|
25317
|
-
baseReferenceSetHash:
|
|
25318
|
-
phase:
|
|
25355
|
+
scopeKey: z110.string().optional(),
|
|
25356
|
+
scopeSnapshotId: z110.string().uuid().optional(),
|
|
25357
|
+
scopeHash: z110.string().optional(),
|
|
25358
|
+
baseReferenceSetHash: z110.string().optional(),
|
|
25359
|
+
phase: z110.enum([
|
|
25319
25360
|
"preparation",
|
|
25320
25361
|
"final"
|
|
25321
25362
|
]).optional(),
|
|
25322
|
-
selectedRefKeys:
|
|
25323
|
-
allowedDecisions:
|
|
25324
|
-
previews:
|
|
25325
|
-
refKey:
|
|
25363
|
+
selectedRefKeys: z110.array(z110.string().min(1).max(200)).optional(),
|
|
25364
|
+
allowedDecisions: z110.array(ProductReferenceResolutionDecisionEnum).optional(),
|
|
25365
|
+
previews: z110.array(z110.object({
|
|
25366
|
+
refKey: z110.string().min(1).max(200)
|
|
25326
25367
|
}).passthrough()).optional(),
|
|
25327
|
-
customAngleDraft:
|
|
25328
|
-
painPointsDraft:
|
|
25329
|
-
benefitsDraft:
|
|
25330
|
-
featuresDraft:
|
|
25331
|
-
angleOptions:
|
|
25332
|
-
index:
|
|
25333
|
-
angle:
|
|
25368
|
+
customAngleDraft: z110.string().optional(),
|
|
25369
|
+
painPointsDraft: z110.string().optional(),
|
|
25370
|
+
benefitsDraft: z110.string().optional(),
|
|
25371
|
+
featuresDraft: z110.array(z110.string()).optional(),
|
|
25372
|
+
angleOptions: z110.array(z110.object({
|
|
25373
|
+
index: z110.number().int().nonnegative(),
|
|
25374
|
+
angle: z110.string().min(1)
|
|
25334
25375
|
}).passthrough()).min(1).max(5).optional(),
|
|
25335
25376
|
// Recommendation consumed only when the caller explicitly sends
|
|
25336
25377
|
// gapDurationSeconds: 30 in the angle approval action.
|
|
@@ -25340,17 +25381,17 @@ var StatusForResolveSchema = z109.object({
|
|
|
25340
25381
|
// keys. `actorId` (the saved custom actor the picker stored) was silently
|
|
25341
25382
|
// dropped here, so the approval handler below could not echo it back on the
|
|
25342
25383
|
// PATCH — the selection looked accepted and reached no render.
|
|
25343
|
-
angles:
|
|
25344
|
-
id:
|
|
25345
|
-
content:
|
|
25346
|
-
creativeDirection:
|
|
25347
|
-
actor:
|
|
25348
|
-
actorId:
|
|
25384
|
+
angles: z110.array(z110.object({
|
|
25385
|
+
id: z110.string().uuid(),
|
|
25386
|
+
content: z110.string(),
|
|
25387
|
+
creativeDirection: z110.string(),
|
|
25388
|
+
actor: z110.string(),
|
|
25389
|
+
actorId: z110.string().nullable().optional()
|
|
25349
25390
|
}).passthrough()).optional(),
|
|
25350
|
-
panels:
|
|
25351
|
-
beatId:
|
|
25352
|
-
voiceover:
|
|
25353
|
-
visualDirection:
|
|
25391
|
+
panels: z110.array(z110.object({
|
|
25392
|
+
beatId: z110.string(),
|
|
25393
|
+
voiceover: z110.string(),
|
|
25394
|
+
visualDirection: z110.string()
|
|
25354
25395
|
}).passthrough()).optional()
|
|
25355
25396
|
}).optional()
|
|
25356
25397
|
}).passthrough();
|
|
@@ -25702,8 +25743,8 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
25702
25743
|
server.registerTool("verify_landing_commerce", {
|
|
25703
25744
|
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.",
|
|
25704
25745
|
inputSchema: {
|
|
25705
|
-
taskId:
|
|
25706
|
-
editId:
|
|
25746
|
+
taskId: z110.string().uuid(),
|
|
25747
|
+
editId: z110.string().uuid()
|
|
25707
25748
|
},
|
|
25708
25749
|
annotations: OVERWRITES_EXTERNAL
|
|
25709
25750
|
}, async (input) => {
|
|
@@ -26343,7 +26384,7 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
26343
26384
|
__name(registerTaskTools, "registerTaskTools");
|
|
26344
26385
|
|
|
26345
26386
|
// src/tools/creatives.ts
|
|
26346
|
-
import { z as
|
|
26387
|
+
import { z as z111 } from "zod";
|
|
26347
26388
|
var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
|
|
26348
26389
|
var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
|
|
26349
26390
|
var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
|
|
@@ -26354,72 +26395,72 @@ var CreativeRefs = {
|
|
|
26354
26395
|
images: ImagesInput,
|
|
26355
26396
|
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.'),
|
|
26356
26397
|
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.'),
|
|
26357
|
-
price:
|
|
26358
|
-
offer:
|
|
26359
|
-
compareAtPrice:
|
|
26360
|
-
productContext:
|
|
26361
|
-
productLabel:
|
|
26362
|
-
buyerPersona:
|
|
26363
|
-
isCombo:
|
|
26364
|
-
competitorScanEnabled:
|
|
26365
|
-
brandId:
|
|
26398
|
+
price: z111.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.'),
|
|
26399
|
+
offer: z111.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.'),
|
|
26400
|
+
compareAtPrice: z111.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
|
|
26401
|
+
productContext: z111.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."),
|
|
26402
|
+
productLabel: z111.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.'),
|
|
26403
|
+
buyerPersona: z111.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.'),
|
|
26404
|
+
isCombo: z111.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
|
|
26405
|
+
competitorScanEnabled: z111.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."),
|
|
26406
|
+
brandId: z111.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.")
|
|
26366
26407
|
};
|
|
26367
|
-
var VideoPresenter =
|
|
26368
|
-
|
|
26369
|
-
mode:
|
|
26408
|
+
var VideoPresenter = z111.discriminatedUnion("mode", [
|
|
26409
|
+
z111.object({
|
|
26410
|
+
mode: z111.literal("none")
|
|
26370
26411
|
}).strict(),
|
|
26371
|
-
|
|
26372
|
-
mode:
|
|
26373
|
-
actorId:
|
|
26412
|
+
z111.object({
|
|
26413
|
+
mode: z111.literal("saved_actor"),
|
|
26414
|
+
actorId: z111.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
|
|
26374
26415
|
}).strict(),
|
|
26375
|
-
|
|
26376
|
-
mode:
|
|
26377
|
-
description:
|
|
26416
|
+
z111.object({
|
|
26417
|
+
mode: z111.literal("described"),
|
|
26418
|
+
description: z111.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
|
|
26378
26419
|
}).strict()
|
|
26379
26420
|
]);
|
|
26380
|
-
var VideoCreativeSetup =
|
|
26381
|
-
|
|
26382
|
-
mode:
|
|
26421
|
+
var VideoCreativeSetup = z111.discriminatedUnion("mode", [
|
|
26422
|
+
z111.object({
|
|
26423
|
+
mode: z111.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
|
|
26383
26424
|
}).strict(),
|
|
26384
|
-
|
|
26385
|
-
mode:
|
|
26425
|
+
z111.object({
|
|
26426
|
+
mode: z111.literal("guided"),
|
|
26386
26427
|
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.'),
|
|
26387
|
-
buyerPersona:
|
|
26428
|
+
buyerPersona: z111.string().trim().min(1).max(360),
|
|
26388
26429
|
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.'),
|
|
26389
26430
|
presenter: VideoPresenter,
|
|
26390
|
-
creativeDirection:
|
|
26431
|
+
creativeDirection: z111.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
|
|
26391
26432
|
}).strict()
|
|
26392
26433
|
]);
|
|
26393
|
-
var VideoInput =
|
|
26434
|
+
var VideoInput = z111.object({
|
|
26394
26435
|
images: CreativeRefs.images.optional(),
|
|
26395
26436
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
26396
|
-
title:
|
|
26397
|
-
primaryAngle:
|
|
26437
|
+
title: z111.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
|
|
26438
|
+
primaryAngle: z111.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".'),
|
|
26398
26439
|
language: CreativeRefs.language,
|
|
26399
26440
|
country: CreativeRefs.country,
|
|
26400
|
-
aspectRatio:
|
|
26441
|
+
aspectRatio: z111.enum([
|
|
26401
26442
|
"9:16",
|
|
26402
26443
|
"16:9",
|
|
26403
26444
|
"Auto"
|
|
26404
26445
|
]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
|
|
26405
26446
|
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.'),
|
|
26406
|
-
durationSeconds:
|
|
26407
|
-
videoAngleCount:
|
|
26447
|
+
durationSeconds: z111.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."),
|
|
26448
|
+
videoAngleCount: z111.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."),
|
|
26408
26449
|
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.'),
|
|
26409
26450
|
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."),
|
|
26410
26451
|
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.'),
|
|
26411
26452
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
|
|
26412
26453
|
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.'),
|
|
26413
|
-
features:
|
|
26454
|
+
features: z111.array(z111.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
|
|
26414
26455
|
price: CreativeRefs.price,
|
|
26415
26456
|
offer: CreativeRefs.offer,
|
|
26416
26457
|
productContext: CreativeRefs.productContext,
|
|
26417
26458
|
productLabel: CreativeRefs.productLabel,
|
|
26418
|
-
cta:
|
|
26419
|
-
scriptNotes:
|
|
26459
|
+
cta: z111.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.'),
|
|
26460
|
+
scriptNotes: z111.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.'),
|
|
26420
26461
|
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.'),
|
|
26421
26462
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
26422
|
-
replicateWinnerWhenFound:
|
|
26463
|
+
replicateWinnerWhenFound: z111.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."),
|
|
26423
26464
|
brandId: CreativeRefs.brandId
|
|
26424
26465
|
}).strict();
|
|
26425
26466
|
var FreeVideoQualityEnum = VideoQualityEnum;
|
|
@@ -26437,7 +26478,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
|
|
|
26437
26478
|
length: 29
|
|
26438
26479
|
}, (_, index) => index + 2)
|
|
26439
26480
|
};
|
|
26440
|
-
var FreeVideoModelIdEnum =
|
|
26481
|
+
var FreeVideoModelIdEnum = z111.enum([
|
|
26441
26482
|
"grok-imagine-video-1-5-preview",
|
|
26442
26483
|
"minimax-h3/reference-to-video",
|
|
26443
26484
|
"wan/3-0-video",
|
|
@@ -26448,66 +26489,66 @@ var FREE_SELECTABLE_MODEL_IDS = [
|
|
|
26448
26489
|
"minimax-h3/reference-to-video",
|
|
26449
26490
|
"wan/3-0-video"
|
|
26450
26491
|
];
|
|
26451
|
-
var FreeVideoInput =
|
|
26492
|
+
var FreeVideoInput = z111.object({
|
|
26452
26493
|
images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
|
|
26453
|
-
rawPrompt:
|
|
26494
|
+
rawPrompt: z111.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."),
|
|
26454
26495
|
language: CreativeRefs.language,
|
|
26455
26496
|
quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
|
|
26456
26497
|
// Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
|
|
26457
26498
|
// parsed ONLY so the handler can reject it with a message naming its
|
|
26458
26499
|
// replacement — dropping it silently would turn a caller's explicit
|
|
26459
26500
|
// Pro++ pick into a quiet fallback to Wan.
|
|
26460
|
-
freeProModel:
|
|
26501
|
+
freeProModel: z111.enum([
|
|
26461
26502
|
"wan",
|
|
26462
26503
|
"seedance"
|
|
26463
26504
|
]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
|
|
26464
26505
|
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.'),
|
|
26465
|
-
durationSeconds:
|
|
26506
|
+
durationSeconds: z111.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."),
|
|
26466
26507
|
videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
|
|
26467
|
-
generateAiMusic:
|
|
26508
|
+
generateAiMusic: z111.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.'),
|
|
26468
26509
|
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.'),
|
|
26469
|
-
addSubtitles:
|
|
26470
|
-
idempotencyKey:
|
|
26510
|
+
addSubtitles: z111.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
|
|
26511
|
+
idempotencyKey: z111.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.")
|
|
26471
26512
|
}).strict();
|
|
26472
26513
|
var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
|
|
26473
|
-
var ImageCreativeSetup =
|
|
26474
|
-
|
|
26475
|
-
mode:
|
|
26514
|
+
var ImageCreativeSetup = z111.discriminatedUnion("mode", [
|
|
26515
|
+
z111.object({
|
|
26516
|
+
mode: z111.literal("automatic")
|
|
26476
26517
|
}).strict(),
|
|
26477
|
-
|
|
26478
|
-
mode:
|
|
26479
|
-
creativeArchetype:
|
|
26518
|
+
z111.object({
|
|
26519
|
+
mode: z111.literal("guided"),
|
|
26520
|
+
creativeArchetype: z111.union([
|
|
26480
26521
|
ImageCreativeArchetypeEnum,
|
|
26481
|
-
|
|
26522
|
+
z111.literal("ai_decides")
|
|
26482
26523
|
]),
|
|
26483
|
-
visualTreatment:
|
|
26524
|
+
visualTreatment: z111.union([
|
|
26484
26525
|
ImageCreativeVisualTreatmentEnum,
|
|
26485
|
-
|
|
26526
|
+
z111.literal("ai_decides")
|
|
26486
26527
|
]),
|
|
26487
26528
|
aspectRatio: ImageCreativeAspectRatioEnum,
|
|
26488
|
-
nVariants:
|
|
26489
|
-
|
|
26490
|
-
|
|
26491
|
-
|
|
26492
|
-
|
|
26493
|
-
|
|
26529
|
+
nVariants: z111.union([
|
|
26530
|
+
z111.literal(1),
|
|
26531
|
+
z111.literal(2),
|
|
26532
|
+
z111.literal(3),
|
|
26533
|
+
z111.literal(4),
|
|
26534
|
+
z111.literal(6)
|
|
26494
26535
|
]),
|
|
26495
|
-
imageModel:
|
|
26496
|
-
styleMix:
|
|
26497
|
-
generateAdCopy:
|
|
26498
|
-
competitorScanEnabled:
|
|
26499
|
-
productContext:
|
|
26500
|
-
creativeDirection:
|
|
26501
|
-
brandColors:
|
|
26502
|
-
headline:
|
|
26503
|
-
subheadline:
|
|
26536
|
+
imageModel: z111.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.'),
|
|
26537
|
+
styleMix: z111.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
|
|
26538
|
+
generateAdCopy: z111.boolean(),
|
|
26539
|
+
competitorScanEnabled: z111.boolean(),
|
|
26540
|
+
productContext: z111.string().trim().min(1).max(3e3).nullable(),
|
|
26541
|
+
creativeDirection: z111.string().trim().min(1).max(500).nullable(),
|
|
26542
|
+
brandColors: z111.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.'),
|
|
26543
|
+
headline: z111.string().trim().min(1).max(120).nullable(),
|
|
26544
|
+
subheadline: z111.string().trim().min(1).max(160).nullable()
|
|
26504
26545
|
}).strict()
|
|
26505
26546
|
]).superRefine((setup, context) => {
|
|
26506
26547
|
if (setup.mode !== "guided") return;
|
|
26507
26548
|
const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
|
|
26508
26549
|
if (needsStyleMix && setup.styleMix === null) {
|
|
26509
26550
|
context.addIssue({
|
|
26510
|
-
code:
|
|
26551
|
+
code: z111.ZodIssueCode.custom,
|
|
26511
26552
|
path: [
|
|
26512
26553
|
"styleMix"
|
|
26513
26554
|
],
|
|
@@ -26516,7 +26557,7 @@ var ImageCreativeSetup = z110.discriminatedUnion("mode", [
|
|
|
26516
26557
|
}
|
|
26517
26558
|
if (!needsStyleMix && setup.styleMix !== null) {
|
|
26518
26559
|
context.addIssue({
|
|
26519
|
-
code:
|
|
26560
|
+
code: z111.ZodIssueCode.custom,
|
|
26520
26561
|
path: [
|
|
26521
26562
|
"styleMix"
|
|
26522
26563
|
],
|
|
@@ -26525,7 +26566,7 @@ var ImageCreativeSetup = z110.discriminatedUnion("mode", [
|
|
|
26525
26566
|
}
|
|
26526
26567
|
if (imageResolutionOf(setup.imageModel) === "2k" && setup.aspectRatio === "4:5") {
|
|
26527
26568
|
context.addIssue({
|
|
26528
|
-
code:
|
|
26569
|
+
code: z111.ZodIssueCode.custom,
|
|
26529
26570
|
path: [
|
|
26530
26571
|
"aspectRatio"
|
|
26531
26572
|
],
|
|
@@ -26533,55 +26574,55 @@ var ImageCreativeSetup = z110.discriminatedUnion("mode", [
|
|
|
26533
26574
|
});
|
|
26534
26575
|
}
|
|
26535
26576
|
});
|
|
26536
|
-
var LandingCreativeSetup =
|
|
26537
|
-
|
|
26538
|
-
mode:
|
|
26577
|
+
var LandingCreativeSetup = z111.discriminatedUnion("mode", [
|
|
26578
|
+
z111.object({
|
|
26579
|
+
mode: z111.literal("automatic")
|
|
26539
26580
|
}).strict(),
|
|
26540
|
-
|
|
26541
|
-
mode:
|
|
26581
|
+
z111.object({
|
|
26582
|
+
mode: z111.literal("guided"),
|
|
26542
26583
|
landingStrategy: LandingStrategyEnum,
|
|
26543
26584
|
landingImageFormat: LandingImageFormatEnum,
|
|
26544
|
-
competitorScanEnabled:
|
|
26545
|
-
paymentMethods:
|
|
26546
|
-
productContext:
|
|
26547
|
-
creativeDirection:
|
|
26548
|
-
headline:
|
|
26549
|
-
subheadline:
|
|
26585
|
+
competitorScanEnabled: z111.boolean(),
|
|
26586
|
+
paymentMethods: z111.string().trim().min(1).max(240).nullable(),
|
|
26587
|
+
productContext: z111.string().trim().min(1).max(3e3).nullable(),
|
|
26588
|
+
creativeDirection: z111.string().trim().min(1).max(500).nullable(),
|
|
26589
|
+
headline: z111.string().trim().min(1).max(120).nullable(),
|
|
26590
|
+
subheadline: z111.string().trim().min(1).max(160).nullable()
|
|
26550
26591
|
}).strict()
|
|
26551
26592
|
]);
|
|
26552
|
-
var ImageInput =
|
|
26593
|
+
var ImageInput = z111.object({
|
|
26553
26594
|
images: CreativeRefs.images.optional(),
|
|
26554
26595
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
26555
|
-
productTitle:
|
|
26556
|
-
primaryAngle:
|
|
26596
|
+
productTitle: z111.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
|
|
26597
|
+
primaryAngle: z111.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.'),
|
|
26557
26598
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
26558
26599
|
language: CreativeRefs.language,
|
|
26559
26600
|
country: CreativeRefs.country,
|
|
26560
26601
|
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."),
|
|
26561
26602
|
imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
|
|
26562
|
-
features:
|
|
26603
|
+
features: z111.array(z111.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
|
|
26563
26604
|
price: CreativeRefs.price,
|
|
26564
|
-
omitPrice:
|
|
26605
|
+
omitPrice: z111.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."),
|
|
26565
26606
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
26566
26607
|
offer: CreativeRefs.offer,
|
|
26567
26608
|
productLabel: CreativeRefs.productLabel,
|
|
26568
26609
|
isCombo: CreativeRefs.isCombo,
|
|
26569
26610
|
brandId: CreativeRefs.brandId
|
|
26570
26611
|
});
|
|
26571
|
-
var EditImageCreativeInput =
|
|
26572
|
-
taskId:
|
|
26573
|
-
variantIndex:
|
|
26574
|
-
clientRequestId:
|
|
26575
|
-
instruction:
|
|
26612
|
+
var EditImageCreativeInput = z111.object({
|
|
26613
|
+
taskId: z111.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
|
|
26614
|
+
variantIndex: z111.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
|
|
26615
|
+
clientRequestId: z111.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."),
|
|
26616
|
+
instruction: z111.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".')
|
|
26576
26617
|
});
|
|
26577
|
-
var LandingInput =
|
|
26578
|
-
includeInitialLandingGif:
|
|
26618
|
+
var LandingInput = z111.object({
|
|
26619
|
+
includeInitialLandingGif: z111.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."),
|
|
26579
26620
|
images: CreativeRefs.images.optional(),
|
|
26580
26621
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
26581
26622
|
language: CreativeRefs.language,
|
|
26582
26623
|
country: CreativeRefs.country,
|
|
26583
26624
|
creativeSetup: LandingCreativeSetup.describe("Configuraci\xF3n obligatoria de landing cl\xE1sica equivalente al wizard web. No expone landing editable/code mientras siga siendo admin-only."),
|
|
26584
|
-
salesAngle:
|
|
26625
|
+
salesAngle: z111.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.'),
|
|
26585
26626
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
26586
26627
|
price: CreativeRefs.price,
|
|
26587
26628
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
@@ -26863,8 +26904,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
26863
26904
|
server.registerTool("get_image_edit_status", {
|
|
26864
26905
|
description: imageEditStatusGuidance.summary,
|
|
26865
26906
|
inputSchema: {
|
|
26866
|
-
taskId:
|
|
26867
|
-
operationId:
|
|
26907
|
+
taskId: z111.string().uuid(),
|
|
26908
|
+
operationId: z111.string().uuid()
|
|
26868
26909
|
},
|
|
26869
26910
|
annotations: READS_INTERNAL
|
|
26870
26911
|
}, async (input) => {
|
|
@@ -26921,10 +26962,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
26921
26962
|
__name(registerCreativeTools, "registerCreativeTools");
|
|
26922
26963
|
|
|
26923
26964
|
// src/tools/creative-variants.ts
|
|
26924
|
-
import { z as
|
|
26965
|
+
import { z as z112 } from "zod";
|
|
26925
26966
|
var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
|
|
26926
26967
|
var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
|
|
26927
|
-
var LandingSectionKeyEnum =
|
|
26968
|
+
var LandingSectionKeyEnum = z112.enum([
|
|
26928
26969
|
"problem_hook",
|
|
26929
26970
|
"problem_cost",
|
|
26930
26971
|
"solution_mechanism",
|
|
@@ -26964,24 +27005,24 @@ var LandingSectionKeyEnum = z111.enum([
|
|
|
26964
27005
|
"lifestyle_fit",
|
|
26965
27006
|
"join_lifestyle"
|
|
26966
27007
|
]);
|
|
26967
|
-
var CreativeVariantKindEnum =
|
|
27008
|
+
var CreativeVariantKindEnum = z112.enum([
|
|
26968
27009
|
"video",
|
|
26969
27010
|
"image",
|
|
26970
27011
|
"landing"
|
|
26971
27012
|
]);
|
|
26972
|
-
var EstimateCreativeVariantInputBase =
|
|
26973
|
-
sourceTaskId:
|
|
27013
|
+
var EstimateCreativeVariantInputBase = z112.object({
|
|
27014
|
+
sourceTaskId: z112.string().uuid().describe("ID de la tarea original completada."),
|
|
26974
27015
|
kind: CreativeVariantKindEnum,
|
|
26975
27016
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
|
|
26976
27017
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
|
|
26977
|
-
nVariants:
|
|
27018
|
+
nVariants: z112.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
26978
27019
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
|
|
26979
|
-
instructions:
|
|
27020
|
+
instructions: z112.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.")
|
|
26980
27021
|
}).strict();
|
|
26981
27022
|
var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
26982
27023
|
if (input.kind === "video" && input.nVariants !== void 0) {
|
|
26983
27024
|
ctx.addIssue({
|
|
26984
|
-
code:
|
|
27025
|
+
code: z112.ZodIssueCode.custom,
|
|
26985
27026
|
path: [
|
|
26986
27027
|
"nVariants"
|
|
26987
27028
|
],
|
|
@@ -26991,7 +27032,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
26991
27032
|
if (input.kind !== "video") {
|
|
26992
27033
|
if (input.videoPreset !== void 0) {
|
|
26993
27034
|
ctx.addIssue({
|
|
26994
|
-
code:
|
|
27035
|
+
code: z112.ZodIssueCode.custom,
|
|
26995
27036
|
path: [
|
|
26996
27037
|
"videoPreset"
|
|
26997
27038
|
],
|
|
@@ -27000,7 +27041,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
27000
27041
|
}
|
|
27001
27042
|
if (input.videoResolution !== void 0) {
|
|
27002
27043
|
ctx.addIssue({
|
|
27003
|
-
code:
|
|
27044
|
+
code: z112.ZodIssueCode.custom,
|
|
27004
27045
|
path: [
|
|
27005
27046
|
"videoResolution"
|
|
27006
27047
|
],
|
|
@@ -27010,7 +27051,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
27010
27051
|
}
|
|
27011
27052
|
if (input.kind !== "image" && input.nVariants !== void 0) {
|
|
27012
27053
|
ctx.addIssue({
|
|
27013
|
-
code:
|
|
27054
|
+
code: z112.ZodIssueCode.custom,
|
|
27014
27055
|
path: [
|
|
27015
27056
|
"nVariants"
|
|
27016
27057
|
],
|
|
@@ -27020,7 +27061,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
27020
27061
|
if (input.kind !== "landing") {
|
|
27021
27062
|
if (input.sectionKey !== void 0) {
|
|
27022
27063
|
ctx.addIssue({
|
|
27023
|
-
code:
|
|
27064
|
+
code: z112.ZodIssueCode.custom,
|
|
27024
27065
|
path: [
|
|
27025
27066
|
"sectionKey"
|
|
27026
27067
|
],
|
|
@@ -27029,7 +27070,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
27029
27070
|
}
|
|
27030
27071
|
if (input.instructions !== void 0) {
|
|
27031
27072
|
ctx.addIssue({
|
|
27032
|
-
code:
|
|
27073
|
+
code: z112.ZodIssueCode.custom,
|
|
27033
27074
|
path: [
|
|
27034
27075
|
"instructions"
|
|
27035
27076
|
],
|
|
@@ -27038,31 +27079,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
27038
27079
|
}
|
|
27039
27080
|
}
|
|
27040
27081
|
});
|
|
27041
|
-
var CreateCreativeVariantInputBase =
|
|
27042
|
-
sourceTaskId:
|
|
27082
|
+
var CreateCreativeVariantInputBase = z112.object({
|
|
27083
|
+
sourceTaskId: z112.string().uuid().describe("ID de la tarea original completada."),
|
|
27043
27084
|
kind: CreativeVariantKindEnum,
|
|
27044
|
-
confirm:
|
|
27045
|
-
clientRequestId:
|
|
27046
|
-
angle:
|
|
27047
|
-
buyerPersona:
|
|
27048
|
-
scriptNotes:
|
|
27049
|
-
creativeDirection:
|
|
27085
|
+
confirm: z112.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
|
|
27086
|
+
clientRequestId: z112.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."),
|
|
27087
|
+
angle: z112.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
|
|
27088
|
+
buyerPersona: z112.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
|
|
27089
|
+
scriptNotes: z112.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
|
|
27090
|
+
creativeDirection: z112.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
|
|
27050
27091
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
|
|
27051
27092
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
|
|
27052
|
-
generateAiMusic:
|
|
27053
|
-
nVariants:
|
|
27093
|
+
generateAiMusic: z112.boolean().optional().describe("Opcional para video."),
|
|
27094
|
+
nVariants: z112.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
27054
27095
|
imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
|
|
27055
27096
|
creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
|
|
27056
27097
|
visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
|
|
27057
27098
|
aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
|
|
27058
|
-
styleMix:
|
|
27099
|
+
styleMix: z112.boolean().optional().describe("Opcional para imagen."),
|
|
27059
27100
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
|
|
27060
|
-
instructions:
|
|
27101
|
+
instructions: z112.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.")
|
|
27061
27102
|
}).strict();
|
|
27062
27103
|
var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
27063
27104
|
if ((input.kind === "video" || input.kind === "image") && !input.angle) {
|
|
27064
27105
|
ctx.addIssue({
|
|
27065
|
-
code:
|
|
27106
|
+
code: z112.ZodIssueCode.custom,
|
|
27066
27107
|
path: [
|
|
27067
27108
|
"angle"
|
|
27068
27109
|
],
|
|
@@ -27071,7 +27112,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
27071
27112
|
}
|
|
27072
27113
|
if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
|
|
27073
27114
|
ctx.addIssue({
|
|
27074
|
-
code:
|
|
27115
|
+
code: z112.ZodIssueCode.custom,
|
|
27075
27116
|
path: [
|
|
27076
27117
|
"instructions"
|
|
27077
27118
|
],
|
|
@@ -27117,7 +27158,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
27117
27158
|
for (const field of fieldsByKind[input.kind]) {
|
|
27118
27159
|
if (input[field] !== void 0) {
|
|
27119
27160
|
ctx.addIssue({
|
|
27120
|
-
code:
|
|
27161
|
+
code: z112.ZodIssueCode.custom,
|
|
27121
27162
|
path: [
|
|
27122
27163
|
field
|
|
27123
27164
|
],
|
|
@@ -27250,13 +27291,13 @@ function registerCreativeVariantTools(server, api) {
|
|
|
27250
27291
|
__name(registerCreativeVariantTools, "registerCreativeVariantTools");
|
|
27251
27292
|
|
|
27252
27293
|
// src/tools/script-review.ts
|
|
27253
|
-
import { z as
|
|
27294
|
+
import { z as z113 } from "zod";
|
|
27254
27295
|
var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
|
|
27255
27296
|
var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
|
|
27256
27297
|
var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
|
|
27257
|
-
var GetVideoScriptInput =
|
|
27258
|
-
taskId:
|
|
27259
|
-
angleKey:
|
|
27298
|
+
var GetVideoScriptInput = z113.object({
|
|
27299
|
+
taskId: z113.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
|
|
27300
|
+
angleKey: z113.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.')
|
|
27260
27301
|
}).strict();
|
|
27261
27302
|
var ApproveVideoScriptInput = ApproveVideoScriptCapabilityRequest;
|
|
27262
27303
|
var RegenerateVideoScriptInput = RegenerateVideoScriptCapabilityRequest.extend({
|
|
@@ -27339,7 +27380,7 @@ function registerScriptReviewTools(server, api) {
|
|
|
27339
27380
|
__name(registerScriptReviewTools, "registerScriptReviewTools");
|
|
27340
27381
|
|
|
27341
27382
|
// src/tools/connections.ts
|
|
27342
|
-
import { z as
|
|
27383
|
+
import { z as z114 } from "zod";
|
|
27343
27384
|
var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
|
|
27344
27385
|
var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
|
|
27345
27386
|
var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
|
|
@@ -27348,7 +27389,7 @@ var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list
|
|
|
27348
27389
|
function registerConnectionTools(server, api) {
|
|
27349
27390
|
server.registerTool("list_shopify_shops", {
|
|
27350
27391
|
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.",
|
|
27351
|
-
inputSchema:
|
|
27392
|
+
inputSchema: z114.object({}).shape,
|
|
27352
27393
|
annotations: READS_INTERNAL
|
|
27353
27394
|
}, async () => {
|
|
27354
27395
|
try {
|
|
@@ -27360,10 +27401,10 @@ function registerConnectionTools(server, api) {
|
|
|
27360
27401
|
});
|
|
27361
27402
|
server.registerTool("list_shopify_products", {
|
|
27362
27403
|
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.',
|
|
27363
|
-
inputSchema:
|
|
27364
|
-
shopDomain:
|
|
27365
|
-
query:
|
|
27366
|
-
taskId:
|
|
27404
|
+
inputSchema: z114.object({
|
|
27405
|
+
shopDomain: z114.string().min(3).max(120),
|
|
27406
|
+
query: z114.string().trim().max(120).optional(),
|
|
27407
|
+
taskId: z114.string().uuid().optional()
|
|
27367
27408
|
}).shape,
|
|
27368
27409
|
annotations: READS_EXTERNAL
|
|
27369
27410
|
}, async ({ shopDomain, query, taskId }) => {
|
|
@@ -27381,7 +27422,7 @@ function registerConnectionTools(server, api) {
|
|
|
27381
27422
|
});
|
|
27382
27423
|
server.registerTool("list_meta_ad_accounts", {
|
|
27383
27424
|
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.",
|
|
27384
|
-
inputSchema:
|
|
27425
|
+
inputSchema: z114.object({}).shape,
|
|
27385
27426
|
annotations: READS_EXTERNAL
|
|
27386
27427
|
}, async () => {
|
|
27387
27428
|
try {
|
|
@@ -27393,7 +27434,7 @@ function registerConnectionTools(server, api) {
|
|
|
27393
27434
|
});
|
|
27394
27435
|
server.registerTool("list_meta_destinations", {
|
|
27395
27436
|
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.",
|
|
27396
|
-
inputSchema:
|
|
27437
|
+
inputSchema: z114.object({}).shape,
|
|
27397
27438
|
annotations: READS_EXTERNAL,
|
|
27398
27439
|
_meta: {
|
|
27399
27440
|
"openai/widgetAccessible": true
|
|
@@ -27408,7 +27449,7 @@ function registerConnectionTools(server, api) {
|
|
|
27408
27449
|
});
|
|
27409
27450
|
server.registerTool("list_tiktok_advertisers", {
|
|
27410
27451
|
description: listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.",
|
|
27411
|
-
inputSchema:
|
|
27452
|
+
inputSchema: z114.object({}).shape,
|
|
27412
27453
|
annotations: READS_EXTERNAL
|
|
27413
27454
|
}, async () => {
|
|
27414
27455
|
try {
|
|
@@ -27422,7 +27463,7 @@ function registerConnectionTools(server, api) {
|
|
|
27422
27463
|
__name(registerConnectionTools, "registerConnectionTools");
|
|
27423
27464
|
|
|
27424
27465
|
// src/tools/actors.ts
|
|
27425
|
-
import { z as
|
|
27466
|
+
import { z as z115 } from "zod";
|
|
27426
27467
|
var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
|
|
27427
27468
|
var actorVoiceGuidance = {
|
|
27428
27469
|
capabilities: getProductMakerCapabilityModelGuidance("get_actor_voice_capabilities"),
|
|
@@ -27462,7 +27503,7 @@ function sanitizeVoiceResult(value) {
|
|
|
27462
27503
|
__name(sanitizeVoiceResult, "sanitizeVoiceResult");
|
|
27463
27504
|
function registerActorTools(server, api) {
|
|
27464
27505
|
const actor = {
|
|
27465
|
-
actorId:
|
|
27506
|
+
actorId: z115.string().min(1).max(64)
|
|
27466
27507
|
};
|
|
27467
27508
|
const safe = /* @__PURE__ */ __name(async (request) => {
|
|
27468
27509
|
try {
|
|
@@ -27491,8 +27532,8 @@ function registerActorTools(server, api) {
|
|
|
27491
27532
|
inputSchema: {
|
|
27492
27533
|
...actor,
|
|
27493
27534
|
draft: ActorVoiceDraftSchema,
|
|
27494
|
-
requestKey:
|
|
27495
|
-
acceptedQuoteId:
|
|
27535
|
+
requestKey: z115.string().trim().min(1).max(128),
|
|
27536
|
+
acceptedQuoteId: z115.string().trim().min(1).max(128)
|
|
27496
27537
|
},
|
|
27497
27538
|
annotations: CREATES_PAID
|
|
27498
27539
|
}, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/previews`, body)));
|
|
@@ -27500,7 +27541,7 @@ function registerActorTools(server, api) {
|
|
|
27500
27541
|
description: actorVoiceGuidance.get.summary,
|
|
27501
27542
|
inputSchema: {
|
|
27502
27543
|
...actor,
|
|
27503
|
-
candidateId:
|
|
27544
|
+
candidateId: z115.string().min(1).max(64)
|
|
27504
27545
|
},
|
|
27505
27546
|
annotations: READS_INTERNAL
|
|
27506
27547
|
}, async ({ actorId, candidateId }) => safe(api.getJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/previews/${encodeURIComponent(candidateId)}`)));
|
|
@@ -27508,15 +27549,15 @@ function registerActorTools(server, api) {
|
|
|
27508
27549
|
description: actorVoiceGuidance.approve.summary,
|
|
27509
27550
|
inputSchema: {
|
|
27510
27551
|
...actor,
|
|
27511
|
-
candidateId:
|
|
27512
|
-
expectedRevision:
|
|
27513
|
-
expectedApprovedRevision:
|
|
27552
|
+
candidateId: z115.string().min(1).max(64),
|
|
27553
|
+
expectedRevision: z115.number().int().positive(),
|
|
27554
|
+
expectedApprovedRevision: z115.number().int().positive().nullable().optional()
|
|
27514
27555
|
},
|
|
27515
27556
|
annotations: CREATES_INTERNAL
|
|
27516
27557
|
}, async ({ actorId, ...body }) => safe(api.postJson(`/v1/actors/${encodeURIComponent(actorId)}/voice/approve`, body)));
|
|
27517
27558
|
server.registerTool("list_actors", {
|
|
27518
27559
|
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.",
|
|
27519
|
-
inputSchema:
|
|
27560
|
+
inputSchema: z115.object({}).shape,
|
|
27520
27561
|
annotations: READS_INTERNAL
|
|
27521
27562
|
}, async () => {
|
|
27522
27563
|
try {
|
|
@@ -27549,7 +27590,7 @@ function registerActorTools(server, api) {
|
|
|
27549
27590
|
__name(registerActorTools, "registerActorTools");
|
|
27550
27591
|
|
|
27551
27592
|
// src/tools/publish.ts
|
|
27552
|
-
import { z as
|
|
27593
|
+
import { z as z116 } from "zod";
|
|
27553
27594
|
|
|
27554
27595
|
// src/tools/meta-publish-attempt-id.ts
|
|
27555
27596
|
var META_PUBLISH_NAMESPACE = "7b19c9ac-b4eb-4db1-970e-c2f24ce30b98";
|
|
@@ -27588,40 +27629,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
|
|
|
27588
27629
|
var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
|
|
27589
27630
|
var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
|
|
27590
27631
|
var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
|
|
27591
|
-
var ShopifyInput =
|
|
27592
|
-
taskId:
|
|
27593
|
-
shopDomain:
|
|
27632
|
+
var ShopifyInput = z116.object({
|
|
27633
|
+
taskId: z116.string().min(1),
|
|
27634
|
+
shopDomain: z116.string().min(1),
|
|
27594
27635
|
/** Override: number of landing images to include. Default = ALL images the
|
|
27595
27636
|
* task generated (the MCP fetches /v1/results first to count). Bounded
|
|
27596
27637
|
* generously here; the backend validates each index against
|
|
27597
27638
|
* landing.images.length and rejects out-of-range. */
|
|
27598
|
-
numLandingImages:
|
|
27599
|
-
variantIndex:
|
|
27639
|
+
numLandingImages: z116.number().int().min(1).max(20).optional(),
|
|
27640
|
+
variantIndex: z116.number().int().min(0).optional(),
|
|
27600
27641
|
/** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
|
|
27601
27642
|
* When true, the landing renders variant-picker pills; when false, it ships
|
|
27602
27643
|
* a single-option product page. Defaults to false. */
|
|
27603
|
-
showVariantPicker:
|
|
27644
|
+
showVariantPicker: z116.boolean().optional(),
|
|
27604
27645
|
/** Default `auto` updates the product previously published for this task and
|
|
27605
27646
|
* shop. Use `existing` with targetProductId to choose another product, or
|
|
27606
27647
|
* `new` only when the user explicitly wants a duplicate/new listing. */
|
|
27607
|
-
publicationMode:
|
|
27648
|
+
publicationMode: z116.enum([
|
|
27608
27649
|
"auto",
|
|
27609
27650
|
"existing",
|
|
27610
27651
|
"new"
|
|
27611
27652
|
]).optional(),
|
|
27612
27653
|
/** Shopify product GID, numeric id, or admin product URL. Required when
|
|
27613
27654
|
* publicationMode is `existing`. */
|
|
27614
|
-
targetProductId:
|
|
27655
|
+
targetProductId: z116.string().trim().min(1).max(300).optional(),
|
|
27615
27656
|
/** Add an announcement bar text above add-to-cart (optional). */
|
|
27616
|
-
announcementBarEnabled:
|
|
27617
|
-
announcementBarText:
|
|
27657
|
+
announcementBarEnabled: z116.boolean().optional(),
|
|
27658
|
+
announcementBarText: z116.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
|
|
27618
27659
|
commerceCorrection: PublishCommerceCorrectionSchema.optional().describe("Complete seller-confirmed commerce values, with the revision and fingerprint returned in recovery. Never invent missing prices or convert currency."),
|
|
27619
|
-
confirmed:
|
|
27660
|
+
confirmed: z116.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
|
|
27620
27661
|
});
|
|
27621
27662
|
var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
|
|
27622
27663
|
if (value.commerceCorrection && value.confirmed !== true) {
|
|
27623
27664
|
ctx.addIssue({
|
|
27624
|
-
code:
|
|
27665
|
+
code: z116.ZodIssueCode.custom,
|
|
27625
27666
|
path: [
|
|
27626
27667
|
"confirmed"
|
|
27627
27668
|
],
|
|
@@ -27630,7 +27671,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
27630
27671
|
}
|
|
27631
27672
|
if (value.announcementBarEnabled && !value.announcementBarText) {
|
|
27632
27673
|
ctx.addIssue({
|
|
27633
|
-
code:
|
|
27674
|
+
code: z116.ZodIssueCode.custom,
|
|
27634
27675
|
path: [
|
|
27635
27676
|
"announcementBarText"
|
|
27636
27677
|
],
|
|
@@ -27639,7 +27680,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
27639
27680
|
}
|
|
27640
27681
|
if (!value.announcementBarEnabled && value.announcementBarText) {
|
|
27641
27682
|
ctx.addIssue({
|
|
27642
|
-
code:
|
|
27683
|
+
code: z116.ZodIssueCode.custom,
|
|
27643
27684
|
path: [
|
|
27644
27685
|
"announcementBarText"
|
|
27645
27686
|
],
|
|
@@ -27653,91 +27694,91 @@ function parseShopifyInput(rawInput) {
|
|
|
27653
27694
|
return parsed.data;
|
|
27654
27695
|
}
|
|
27655
27696
|
__name(parseShopifyInput, "parseShopifyInput");
|
|
27656
|
-
var McpCampaignConfig =
|
|
27697
|
+
var McpCampaignConfig = z116.object({
|
|
27657
27698
|
/** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
|
|
27658
27699
|
* converts to the account currency server-side. Do NOT pre-convert: on a COP
|
|
27659
27700
|
* account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
|
|
27660
|
-
dailyBudgetUsd:
|
|
27701
|
+
dailyBudgetUsd: z116.number().positive().optional(),
|
|
27661
27702
|
/** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
|
|
27662
27703
|
* normalizes at validation). Meta accepts max 1 (single-country ad set).
|
|
27663
27704
|
* TikTok takes only the first entry. */
|
|
27664
|
-
targetCountries:
|
|
27665
|
-
campaignName:
|
|
27705
|
+
targetCountries: z116.array(CountryIso2Schema).max(1).optional(),
|
|
27706
|
+
campaignName: z116.string().trim().min(1).max(100).optional()
|
|
27666
27707
|
});
|
|
27667
27708
|
var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
|
|
27668
|
-
var MetaInput =
|
|
27669
|
-
taskId:
|
|
27709
|
+
var MetaInput = z116.object({
|
|
27710
|
+
taskId: z116.string().min(1),
|
|
27670
27711
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
27671
|
-
portfolioId:
|
|
27712
|
+
portfolioId: z116.string().trim().min(1),
|
|
27672
27713
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
27673
|
-
pageId:
|
|
27714
|
+
pageId: z116.string().trim().min(1),
|
|
27674
27715
|
adAccountId: McpAdAccountId,
|
|
27675
|
-
pixelId:
|
|
27676
|
-
landingUrl:
|
|
27716
|
+
pixelId: z116.string().min(1).optional(),
|
|
27717
|
+
landingUrl: z116.string().url().optional(),
|
|
27677
27718
|
/** Select which angles to publish by 0-based index. Omit to publish all
|
|
27678
27719
|
* successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
|
|
27679
|
-
angleIndexes:
|
|
27720
|
+
angleIndexes: z116.array(z116.number().int().nonnegative()).optional(),
|
|
27680
27721
|
campaignConfig: McpCampaignConfig.optional(),
|
|
27681
27722
|
/** Override the ad's primary text (body copy). If omitted, ProductMaker
|
|
27682
27723
|
* uses the auto-generated copy attached to the task. Capped at 500 chars
|
|
27683
27724
|
* (Meta's primary-text limit). */
|
|
27684
|
-
primaryText:
|
|
27725
|
+
primaryText: z116.string().trim().min(1).max(500).optional(),
|
|
27685
27726
|
/** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
|
|
27686
27727
|
* (wa.me) instead of a landing page. */
|
|
27687
|
-
phoneNumber:
|
|
27728
|
+
phoneNumber: z116.string().min(8).max(32).optional()
|
|
27688
27729
|
});
|
|
27689
|
-
var GroupedTaskSource =
|
|
27690
|
-
type:
|
|
27691
|
-
taskId:
|
|
27692
|
-
angleIndex:
|
|
27693
|
-
videoVariant:
|
|
27730
|
+
var GroupedTaskSource = z116.object({
|
|
27731
|
+
type: z116.literal("task"),
|
|
27732
|
+
taskId: z116.string().min(1),
|
|
27733
|
+
angleIndex: z116.number().int().min(0).optional(),
|
|
27734
|
+
videoVariant: z116.enum([
|
|
27694
27735
|
"with_subtitles",
|
|
27695
27736
|
"without_subtitles"
|
|
27696
27737
|
]).optional(),
|
|
27697
|
-
imageVariantIndex:
|
|
27698
|
-
});
|
|
27699
|
-
var GroupedMediaSource =
|
|
27700
|
-
type:
|
|
27701
|
-
url:
|
|
27702
|
-
path:
|
|
27703
|
-
thumbnailUrl:
|
|
27704
|
-
thumbnailPath:
|
|
27738
|
+
imageVariantIndex: z116.number().int().min(0).optional()
|
|
27739
|
+
});
|
|
27740
|
+
var GroupedMediaSource = z116.object({
|
|
27741
|
+
type: z116.literal("media"),
|
|
27742
|
+
url: z116.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
|
|
27743
|
+
path: z116.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".'),
|
|
27744
|
+
thumbnailUrl: z116.string().url().optional(),
|
|
27745
|
+
thumbnailPath: z116.string().min(1).optional()
|
|
27705
27746
|
}).refine((value) => Boolean(value.url) !== Boolean(value.path), {
|
|
27706
27747
|
message: "media source needs exactly one of `url` or `path`"
|
|
27707
27748
|
}).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
|
|
27708
27749
|
message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
|
|
27709
27750
|
});
|
|
27710
|
-
var GroupedUploadedAssetSource =
|
|
27711
|
-
type:
|
|
27751
|
+
var GroupedUploadedAssetSource = z116.object({
|
|
27752
|
+
type: z116.literal("asset"),
|
|
27712
27753
|
/** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
|
|
27713
|
-
assetId:
|
|
27714
|
-
thumbnailAssetId:
|
|
27754
|
+
assetId: z116.string().uuid(),
|
|
27755
|
+
thumbnailAssetId: z116.string().uuid().optional()
|
|
27715
27756
|
});
|
|
27716
|
-
var GroupedCreative =
|
|
27717
|
-
type:
|
|
27757
|
+
var GroupedCreative = z116.object({
|
|
27758
|
+
type: z116.enum([
|
|
27718
27759
|
"image",
|
|
27719
27760
|
"video"
|
|
27720
27761
|
]),
|
|
27721
|
-
source:
|
|
27762
|
+
source: z116.union([
|
|
27722
27763
|
GroupedTaskSource,
|
|
27723
27764
|
GroupedMediaSource,
|
|
27724
27765
|
GroupedUploadedAssetSource
|
|
27725
27766
|
]),
|
|
27726
|
-
title:
|
|
27727
|
-
description:
|
|
27767
|
+
title: z116.string().max(120).optional(),
|
|
27768
|
+
description: z116.string().max(500).optional(),
|
|
27728
27769
|
cta: MetaCtaType.optional(),
|
|
27729
|
-
creativeId:
|
|
27770
|
+
creativeId: z116.string().min(1).optional()
|
|
27730
27771
|
});
|
|
27731
|
-
var GroupedCampaignConfigBase =
|
|
27772
|
+
var GroupedCampaignConfigBase = z116.object({
|
|
27732
27773
|
campaignType: MetaCampaignType.default("sales"),
|
|
27733
27774
|
optimizationMode: MetaOptimizationMode.default("advantage_plus"),
|
|
27734
27775
|
budgetMode: MetaBudgetMode.optional(),
|
|
27735
|
-
campaignDailyBudget:
|
|
27736
|
-
adSets:
|
|
27737
|
-
tempId:
|
|
27738
|
-
name:
|
|
27739
|
-
dailyBudget:
|
|
27740
|
-
creativeIds:
|
|
27776
|
+
campaignDailyBudget: z116.number().int().positive().optional(),
|
|
27777
|
+
adSets: z116.array(z116.object({
|
|
27778
|
+
tempId: z116.string().min(1).max(80),
|
|
27779
|
+
name: z116.string().min(1).max(100),
|
|
27780
|
+
dailyBudget: z116.number().int().positive().optional(),
|
|
27781
|
+
creativeIds: z116.array(z116.string().min(1)).min(1)
|
|
27741
27782
|
})).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
|
|
27742
27783
|
/**
|
|
27743
27784
|
* Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
|
|
@@ -27745,17 +27786,17 @@ var GroupedCampaignConfigBase = z115.object({
|
|
|
27745
27786
|
* opaque `invalid_literal` and made the WhatsApp destination — supported by
|
|
27746
27787
|
* the API since #849 — unreachable from this tool.
|
|
27747
27788
|
*/
|
|
27748
|
-
destination:
|
|
27749
|
-
|
|
27750
|
-
type:
|
|
27751
|
-
landingUrl:
|
|
27789
|
+
destination: z116.discriminatedUnion("type", [
|
|
27790
|
+
z116.object({
|
|
27791
|
+
type: z116.literal("landing"),
|
|
27792
|
+
landingUrl: z116.string().url()
|
|
27752
27793
|
}),
|
|
27753
|
-
|
|
27754
|
-
type:
|
|
27755
|
-
phoneNumber:
|
|
27794
|
+
z116.object({
|
|
27795
|
+
type: z116.literal("whatsapp"),
|
|
27796
|
+
phoneNumber: z116.string().min(8).max(32)
|
|
27756
27797
|
})
|
|
27757
27798
|
]),
|
|
27758
|
-
saveAsDefault:
|
|
27799
|
+
saveAsDefault: z116.boolean().default(false),
|
|
27759
27800
|
budgetPolicy: MetaBudgetPolicy.optional()
|
|
27760
27801
|
});
|
|
27761
27802
|
function resolveBudgetMode(value) {
|
|
@@ -27769,7 +27810,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
27769
27810
|
const budgetMode = resolveBudgetMode(value);
|
|
27770
27811
|
if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
|
|
27771
27812
|
ctx.addIssue({
|
|
27772
|
-
code:
|
|
27813
|
+
code: z116.ZodIssueCode.custom,
|
|
27773
27814
|
path: [
|
|
27774
27815
|
"campaignDailyBudget"
|
|
27775
27816
|
],
|
|
@@ -27780,7 +27821,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
27780
27821
|
value.adSets.forEach((adSet, index) => {
|
|
27781
27822
|
if (adSet.dailyBudget === void 0) {
|
|
27782
27823
|
ctx.addIssue({
|
|
27783
|
-
code:
|
|
27824
|
+
code: z116.ZodIssueCode.custom,
|
|
27784
27825
|
path: [
|
|
27785
27826
|
"adSets",
|
|
27786
27827
|
index,
|
|
@@ -27795,28 +27836,28 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
27795
27836
|
...value,
|
|
27796
27837
|
budgetMode: resolveBudgetMode(value)
|
|
27797
27838
|
}));
|
|
27798
|
-
var PublishCreativesToMetaInputBase =
|
|
27799
|
-
creatives:
|
|
27839
|
+
var PublishCreativesToMetaInputBase = z116.object({
|
|
27840
|
+
creatives: z116.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
|
|
27800
27841
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
27801
|
-
portfolioId:
|
|
27842
|
+
portfolioId: z116.string().trim().min(1),
|
|
27802
27843
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
27803
|
-
pageId:
|
|
27844
|
+
pageId: z116.string().trim().min(1),
|
|
27804
27845
|
adAccountId: McpAdAccountId,
|
|
27805
|
-
pixelId:
|
|
27846
|
+
pixelId: z116.string().min(1).optional(),
|
|
27806
27847
|
/** Required unless `campaignConfig.destination` is whatsapp — see the
|
|
27807
27848
|
* superRefine below. Mirrors the API's `FacebookCreateCampaignFromTasksBodySchema`. */
|
|
27808
|
-
landingUrl:
|
|
27849
|
+
landingUrl: z116.string().url().optional(),
|
|
27809
27850
|
/** ISO-2 code or resolvable country name — mirrors the API contract
|
|
27810
27851
|
* (CountryIso2Schema), which normalizes names to alpha-2 at validation. */
|
|
27811
27852
|
targetCountry: CountryIso2Schema,
|
|
27812
|
-
campaignName:
|
|
27853
|
+
campaignName: z116.string().trim().min(1).max(100),
|
|
27813
27854
|
campaignConfig: GroupedCampaignConfig.optional()
|
|
27814
27855
|
});
|
|
27815
27856
|
var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
|
|
27816
27857
|
const destination = value.campaignConfig?.destination;
|
|
27817
27858
|
if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
|
|
27818
27859
|
ctx.addIssue({
|
|
27819
|
-
code:
|
|
27860
|
+
code: z116.ZodIssueCode.custom,
|
|
27820
27861
|
path: [
|
|
27821
27862
|
"landingUrl"
|
|
27822
27863
|
],
|
|
@@ -27825,7 +27866,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
27825
27866
|
}
|
|
27826
27867
|
if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
|
|
27827
27868
|
ctx.addIssue({
|
|
27828
|
-
code:
|
|
27869
|
+
code: z116.ZodIssueCode.custom,
|
|
27829
27870
|
path: [
|
|
27830
27871
|
"campaignConfig",
|
|
27831
27872
|
"destination",
|
|
@@ -27844,16 +27885,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
27844
27885
|
}
|
|
27845
27886
|
return value;
|
|
27846
27887
|
});
|
|
27847
|
-
var PresignUploadResponseSchema =
|
|
27848
|
-
uploadUrl:
|
|
27888
|
+
var PresignUploadResponseSchema = z116.object({
|
|
27889
|
+
uploadUrl: z116.string().url().refine((value) => {
|
|
27849
27890
|
const url = new URL(value);
|
|
27850
27891
|
return !url.username && !url.password && url.protocol === "https:";
|
|
27851
27892
|
}, "presigned upload URL must be HTTPS without embedded credentials"),
|
|
27852
|
-
publicUrl:
|
|
27893
|
+
publicUrl: z116.string().url().refine((value) => {
|
|
27853
27894
|
const url = new URL(value);
|
|
27854
27895
|
return !url.username && !url.password;
|
|
27855
27896
|
}, "public media URL must not contain embedded credentials"),
|
|
27856
|
-
stagingAssetId:
|
|
27897
|
+
stagingAssetId: z116.string().uuid()
|
|
27857
27898
|
});
|
|
27858
27899
|
async function uploadResolvedMedia(api, media, assetRole) {
|
|
27859
27900
|
if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
|
|
@@ -27878,16 +27919,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
|
|
|
27878
27919
|
return uploadResolvedMedia(api, media, assetRole);
|
|
27879
27920
|
}
|
|
27880
27921
|
__name(resolveAndUploadMedia, "resolveAndUploadMedia");
|
|
27881
|
-
var TikTokInput =
|
|
27882
|
-
taskId:
|
|
27883
|
-
advertiserId:
|
|
27884
|
-
pixelId:
|
|
27885
|
-
landingUrl:
|
|
27886
|
-
angleIndexes:
|
|
27922
|
+
var TikTokInput = z116.object({
|
|
27923
|
+
taskId: z116.string().min(1),
|
|
27924
|
+
advertiserId: z116.string().min(1),
|
|
27925
|
+
pixelId: z116.string().min(1).optional(),
|
|
27926
|
+
landingUrl: z116.string().url().optional(),
|
|
27927
|
+
angleIndexes: z116.array(z116.number().int().nonnegative()).optional(),
|
|
27887
27928
|
campaignConfig: McpCampaignConfig.optional(),
|
|
27888
27929
|
/** Override the ad's description (TikTok's body copy). If omitted,
|
|
27889
27930
|
* ProductMaker uses the auto-generated copy attached to the task. */
|
|
27890
|
-
primaryText:
|
|
27931
|
+
primaryText: z116.string().trim().min(1).max(500).optional()
|
|
27891
27932
|
});
|
|
27892
27933
|
function registerPublishTools(server, api, opts = {}) {
|
|
27893
27934
|
const transport = opts.transport ?? "http";
|
|
@@ -28239,39 +28280,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
|
|
|
28239
28280
|
|
|
28240
28281
|
// src/tools/meta-upload.ts
|
|
28241
28282
|
import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
|
|
28242
|
-
import { z as
|
|
28283
|
+
import { z as z117 } from "zod";
|
|
28243
28284
|
var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
|
|
28244
|
-
var UploadSessionInputBase =
|
|
28245
|
-
mediaKind:
|
|
28285
|
+
var UploadSessionInputBase = z117.object({
|
|
28286
|
+
mediaKind: z117.enum([
|
|
28246
28287
|
"image",
|
|
28247
28288
|
"video",
|
|
28248
28289
|
"mixed"
|
|
28249
28290
|
]).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."),
|
|
28250
|
-
assetRole:
|
|
28291
|
+
assetRole: z117.enum([
|
|
28251
28292
|
"media",
|
|
28252
28293
|
"thumbnail"
|
|
28253
28294
|
]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
|
|
28254
|
-
uploadPurpose:
|
|
28295
|
+
uploadPurpose: z117.enum([
|
|
28255
28296
|
"product_reference",
|
|
28256
28297
|
"creative",
|
|
28257
28298
|
"generic"
|
|
28258
28299
|
]).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."),
|
|
28259
|
-
maxFiles:
|
|
28300
|
+
maxFiles: z117.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
|
|
28260
28301
|
});
|
|
28261
|
-
var OpenAiFileReference =
|
|
28262
|
-
download_url:
|
|
28263
|
-
file_id:
|
|
28264
|
-
mime_type:
|
|
28265
|
-
file_name:
|
|
28302
|
+
var OpenAiFileReference = z117.object({
|
|
28303
|
+
download_url: z117.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."),
|
|
28304
|
+
file_id: z117.string().min(1),
|
|
28305
|
+
mime_type: z117.string().min(1).optional(),
|
|
28306
|
+
file_name: z117.string().min(1).optional()
|
|
28266
28307
|
});
|
|
28267
28308
|
var UploadSessionToolInputShape = {
|
|
28268
28309
|
...UploadSessionInputBase.shape,
|
|
28269
|
-
files:
|
|
28310
|
+
files: z117.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.")
|
|
28270
28311
|
};
|
|
28271
|
-
var UploadSessionToolInput =
|
|
28312
|
+
var UploadSessionToolInput = z117.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
|
|
28272
28313
|
if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
|
|
28273
28314
|
ctx.addIssue({
|
|
28274
|
-
code:
|
|
28315
|
+
code: z117.ZodIssueCode.custom,
|
|
28275
28316
|
path: [
|
|
28276
28317
|
"mediaKind"
|
|
28277
28318
|
],
|
|
@@ -28280,7 +28321,7 @@ var UploadSessionToolInput = z116.object(UploadSessionToolInputShape).superRefin
|
|
|
28280
28321
|
}
|
|
28281
28322
|
if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
|
|
28282
28323
|
ctx.addIssue({
|
|
28283
|
-
code:
|
|
28324
|
+
code: z117.ZodIssueCode.custom,
|
|
28284
28325
|
path: [
|
|
28285
28326
|
"maxFiles"
|
|
28286
28327
|
],
|
|
@@ -28289,7 +28330,7 @@ var UploadSessionToolInput = z116.object(UploadSessionToolInputShape).superRefin
|
|
|
28289
28330
|
}
|
|
28290
28331
|
if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
|
|
28291
28332
|
ctx.addIssue({
|
|
28292
|
-
code:
|
|
28333
|
+
code: z117.ZodIssueCode.custom,
|
|
28293
28334
|
path: [
|
|
28294
28335
|
"maxFiles"
|
|
28295
28336
|
],
|
|
@@ -28297,38 +28338,38 @@ var UploadSessionToolInput = z116.object(UploadSessionToolInputShape).superRefin
|
|
|
28297
28338
|
});
|
|
28298
28339
|
}
|
|
28299
28340
|
});
|
|
28300
|
-
var UploadSessionResponse =
|
|
28301
|
-
sessionId:
|
|
28302
|
-
uploadPageUrl:
|
|
28303
|
-
mediaKind:
|
|
28341
|
+
var UploadSessionResponse = z117.object({
|
|
28342
|
+
sessionId: z117.string().uuid(),
|
|
28343
|
+
uploadPageUrl: z117.string().url(),
|
|
28344
|
+
mediaKind: z117.enum([
|
|
28304
28345
|
"image",
|
|
28305
28346
|
"video",
|
|
28306
28347
|
"mixed"
|
|
28307
28348
|
]),
|
|
28308
|
-
assetRole:
|
|
28349
|
+
assetRole: z117.enum([
|
|
28309
28350
|
"media",
|
|
28310
28351
|
"thumbnail"
|
|
28311
28352
|
]),
|
|
28312
|
-
maxFiles:
|
|
28313
|
-
expiresAt:
|
|
28353
|
+
maxFiles: z117.number().int().positive(),
|
|
28354
|
+
expiresAt: z117.string().datetime()
|
|
28314
28355
|
});
|
|
28315
|
-
var UploadStatusInput =
|
|
28316
|
-
sessionId:
|
|
28356
|
+
var UploadStatusInput = z117.object({
|
|
28357
|
+
sessionId: z117.string().uuid().describe("The sessionId returned by request_media_upload.")
|
|
28317
28358
|
});
|
|
28318
|
-
var UniversalUploadStatusResponse =
|
|
28319
|
-
|
|
28320
|
-
status:
|
|
28321
|
-
assets:
|
|
28359
|
+
var UniversalUploadStatusResponse = z117.discriminatedUnion("status", [
|
|
28360
|
+
z117.object({
|
|
28361
|
+
status: z117.literal("pending"),
|
|
28362
|
+
assets: z117.array(z117.never()).length(0)
|
|
28322
28363
|
}),
|
|
28323
|
-
|
|
28324
|
-
status:
|
|
28325
|
-
assets:
|
|
28326
|
-
assetId:
|
|
28327
|
-
mediaKind:
|
|
28364
|
+
z117.object({
|
|
28365
|
+
status: z117.literal("uploaded"),
|
|
28366
|
+
assets: z117.array(z117.object({
|
|
28367
|
+
assetId: z117.string().uuid(),
|
|
28368
|
+
mediaKind: z117.enum([
|
|
28328
28369
|
"image",
|
|
28329
28370
|
"video"
|
|
28330
28371
|
]),
|
|
28331
|
-
assetRole:
|
|
28372
|
+
assetRole: z117.enum([
|
|
28332
28373
|
"media",
|
|
28333
28374
|
"thumbnail"
|
|
28334
28375
|
])
|
|
@@ -28336,13 +28377,13 @@ var UniversalUploadStatusResponse = z116.discriminatedUnion("status", [
|
|
|
28336
28377
|
})
|
|
28337
28378
|
]);
|
|
28338
28379
|
var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
|
|
28339
|
-
uploadPurpose:
|
|
28380
|
+
uploadPurpose: z117.enum([
|
|
28340
28381
|
"product_reference",
|
|
28341
28382
|
"creative",
|
|
28342
28383
|
"generic"
|
|
28343
28384
|
]),
|
|
28344
|
-
checkToolName:
|
|
28345
|
-
resolveEndpoint:
|
|
28385
|
+
checkToolName: z117.literal("check_media_upload"),
|
|
28386
|
+
resolveEndpoint: z117.string().url()
|
|
28346
28387
|
});
|
|
28347
28388
|
function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
|
|
28348
28389
|
const url = new URL(uploadPageUrl);
|
|
@@ -28433,15 +28474,15 @@ function registerMediaUploadTools(server, api) {
|
|
|
28433
28474
|
__name(registerMediaUploadTools, "registerMediaUploadTools");
|
|
28434
28475
|
|
|
28435
28476
|
// src/tools/campaigns.ts
|
|
28436
|
-
import { z as
|
|
28477
|
+
import { z as z118 } from "zod";
|
|
28437
28478
|
var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
|
|
28438
28479
|
var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
|
|
28439
|
-
var MetaStatusInput =
|
|
28440
|
-
campaignId:
|
|
28480
|
+
var MetaStatusInput = z118.object({
|
|
28481
|
+
campaignId: z118.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
|
|
28441
28482
|
});
|
|
28442
|
-
var TikTokStatusInput =
|
|
28443
|
-
campaignId:
|
|
28444
|
-
advertiserId:
|
|
28483
|
+
var TikTokStatusInput = z118.object({
|
|
28484
|
+
campaignId: z118.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
|
|
28485
|
+
advertiserId: z118.string().min(1).describe("The same advertiserId used to publish the campaign.")
|
|
28445
28486
|
});
|
|
28446
28487
|
function registerCampaignTools(server, api) {
|
|
28447
28488
|
server.registerTool("get_meta_campaign_status", {
|
|
@@ -28546,10 +28587,10 @@ function renderTikTokStatusMarkdown(r) {
|
|
|
28546
28587
|
__name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
|
|
28547
28588
|
|
|
28548
28589
|
// ../../packages/product-economics/src/product-costing.ts
|
|
28549
|
-
import { z as
|
|
28590
|
+
import { z as z120 } from "zod";
|
|
28550
28591
|
|
|
28551
28592
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
28552
|
-
import { z as
|
|
28593
|
+
import { z as z119 } from "zod";
|
|
28553
28594
|
|
|
28554
28595
|
// ../../packages/product-economics/src/product-costing-shipping-references.json
|
|
28555
28596
|
var product_costing_shipping_references_default = {
|
|
@@ -28613,21 +28654,21 @@ var product_costing_shipping_references_default = {
|
|
|
28613
28654
|
};
|
|
28614
28655
|
|
|
28615
28656
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
28616
|
-
var ShippingReferenceSchema =
|
|
28617
|
-
reference:
|
|
28618
|
-
min:
|
|
28619
|
-
max:
|
|
28620
|
-
updatedAt:
|
|
28621
|
-
confidence:
|
|
28657
|
+
var ShippingReferenceSchema = z119.object({
|
|
28658
|
+
reference: z119.number().positive(),
|
|
28659
|
+
min: z119.number().nonnegative(),
|
|
28660
|
+
max: z119.number().positive(),
|
|
28661
|
+
updatedAt: z119.string().date(),
|
|
28662
|
+
confidence: z119.enum([
|
|
28622
28663
|
"high",
|
|
28623
28664
|
"medium",
|
|
28624
28665
|
"medium-low"
|
|
28625
28666
|
]),
|
|
28626
|
-
sources:
|
|
28667
|
+
sources: z119.array(z119.string().url().startsWith("https://")).min(1).max(3)
|
|
28627
28668
|
}).superRefine(({ reference, min, max }, context) => {
|
|
28628
28669
|
if (min > reference || reference > max) {
|
|
28629
28670
|
context.addIssue({
|
|
28630
|
-
code:
|
|
28671
|
+
code: z119.ZodIssueCode.custom,
|
|
28631
28672
|
message: "shipping_reference_outside_range",
|
|
28632
28673
|
path: [
|
|
28633
28674
|
"reference"
|
|
@@ -28635,7 +28676,7 @@ var ShippingReferenceSchema = z118.object({
|
|
|
28635
28676
|
});
|
|
28636
28677
|
}
|
|
28637
28678
|
});
|
|
28638
|
-
var SHIPPING_REFERENCES =
|
|
28679
|
+
var SHIPPING_REFERENCES = z119.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
|
|
28639
28680
|
var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
|
|
28640
28681
|
var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
|
|
28641
28682
|
"MX",
|
|
@@ -28817,18 +28858,18 @@ function getProductCostingCountryName(country) {
|
|
|
28817
28858
|
__name(getProductCostingCountryName, "getProductCostingCountryName");
|
|
28818
28859
|
|
|
28819
28860
|
// ../../packages/product-economics/src/product-costing.ts
|
|
28820
|
-
var ProductCostingInputSchema =
|
|
28821
|
-
country:
|
|
28822
|
-
supplierCost:
|
|
28823
|
-
shippingCost:
|
|
28824
|
-
returnRate:
|
|
28825
|
-
cancellationRate:
|
|
28826
|
-
adsManagerCpa:
|
|
28827
|
-
desiredMargin:
|
|
28861
|
+
var ProductCostingInputSchema = z120.object({
|
|
28862
|
+
country: z120.string().refine(isProductCostingCountryCode, "unsupported_country"),
|
|
28863
|
+
supplierCost: z120.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
|
|
28864
|
+
shippingCost: z120.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
|
|
28865
|
+
returnRate: z120.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
28866
|
+
cancellationRate: z120.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
28867
|
+
adsManagerCpa: z120.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
|
|
28868
|
+
desiredMargin: z120.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
|
|
28828
28869
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
28829
28870
|
if (returnRate + cancellationRate >= 1) {
|
|
28830
28871
|
context.addIssue({
|
|
28831
|
-
code:
|
|
28872
|
+
code: z120.ZodIssueCode.custom,
|
|
28832
28873
|
message: "delivery_rate_positive",
|
|
28833
28874
|
path: [
|
|
28834
28875
|
"cancellationRate"
|
|
@@ -28925,15 +28966,15 @@ function calculateProductCosting(rawInput) {
|
|
|
28925
28966
|
__name(calculateProductCosting, "calculateProductCosting");
|
|
28926
28967
|
|
|
28927
28968
|
// src/tools/product-costing.ts
|
|
28928
|
-
import { z as
|
|
28969
|
+
import { z as z121 } from "zod";
|
|
28929
28970
|
var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
|
|
28930
|
-
var optionalAmount = /* @__PURE__ */ __name((description) =>
|
|
28931
|
-
var optionalPercent = /* @__PURE__ */ __name((description) =>
|
|
28932
|
-
var ProductCostingToolInput =
|
|
28933
|
-
country:
|
|
28971
|
+
var optionalAmount = /* @__PURE__ */ __name((description) => z121.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
|
|
28972
|
+
var optionalPercent = /* @__PURE__ */ __name((description) => z121.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
|
|
28973
|
+
var ProductCostingToolInput = z121.object({
|
|
28974
|
+
country: z121.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
|
|
28934
28975
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
28935
28976
|
}).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
|
|
28936
|
-
supplierCost:
|
|
28977
|
+
supplierCost: z121.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."),
|
|
28937
28978
|
supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
|
|
28938
28979
|
shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
|
|
28939
28980
|
shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
|
|
@@ -29096,7 +29137,7 @@ function formatPercent(value) {
|
|
|
29096
29137
|
__name(formatPercent, "formatPercent");
|
|
29097
29138
|
|
|
29098
29139
|
// src/tools/product-research.ts
|
|
29099
|
-
import { z as
|
|
29140
|
+
import { z as z122 } from "zod";
|
|
29100
29141
|
|
|
29101
29142
|
// src/tools/product-research-idempotency.ts
|
|
29102
29143
|
var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
|
|
@@ -29467,17 +29508,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
|
|
|
29467
29508
|
]);
|
|
29468
29509
|
var POLL_INTERVAL_MS = 5e3;
|
|
29469
29510
|
var MAX_WAIT_SECONDS = 120;
|
|
29470
|
-
var FindInput =
|
|
29511
|
+
var FindInput = z122.object({
|
|
29471
29512
|
targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
|
|
29472
29513
|
categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
|
|
29473
|
-
confirmed:
|
|
29474
|
-
waitSeconds:
|
|
29514
|
+
confirmed: z122.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
|
|
29515
|
+
waitSeconds: z122.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
|
|
29475
29516
|
});
|
|
29476
|
-
var GetInput =
|
|
29477
|
-
runId:
|
|
29517
|
+
var GetInput = z122.object({
|
|
29518
|
+
runId: z122.string().uuid().describe("ID del run devuelto por find_winning_products.")
|
|
29478
29519
|
});
|
|
29479
|
-
var ListInput =
|
|
29480
|
-
limit:
|
|
29520
|
+
var ListInput = z122.object({
|
|
29521
|
+
limit: z122.number().int().min(1).max(20).default(10)
|
|
29481
29522
|
});
|
|
29482
29523
|
function textResult(text2) {
|
|
29483
29524
|
return {
|
|
@@ -29616,17 +29657,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
|
|
|
29616
29657
|
__name(registerProductResearchTools, "registerProductResearchTools");
|
|
29617
29658
|
|
|
29618
29659
|
// src/tools/dropshipping-projects.ts
|
|
29619
|
-
import { z as
|
|
29660
|
+
import { z as z123 } from "zod";
|
|
29620
29661
|
var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
|
|
29621
29662
|
var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
|
|
29622
29663
|
var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
|
|
29623
|
-
var ProjectId =
|
|
29624
|
-
var DropshippingProjectStatus =
|
|
29664
|
+
var ProjectId = z123.string().uuid();
|
|
29665
|
+
var DropshippingProjectStatus = z123.enum([
|
|
29625
29666
|
"active",
|
|
29626
29667
|
"completed",
|
|
29627
29668
|
"archived"
|
|
29628
29669
|
]);
|
|
29629
|
-
var DropshippingProjectPhase =
|
|
29670
|
+
var DropshippingProjectPhase = z123.enum([
|
|
29630
29671
|
"research",
|
|
29631
29672
|
"costing",
|
|
29632
29673
|
"media",
|
|
@@ -29635,21 +29676,21 @@ var DropshippingProjectPhase = z122.enum([
|
|
|
29635
29676
|
"advertising",
|
|
29636
29677
|
"complete"
|
|
29637
29678
|
]);
|
|
29638
|
-
var DropshippingRewardMilestone =
|
|
29679
|
+
var DropshippingRewardMilestone = z123.enum([
|
|
29639
29680
|
"product_selected",
|
|
29640
29681
|
"costing_saved",
|
|
29641
29682
|
"product_media_ready",
|
|
29642
29683
|
"creatives_completed",
|
|
29643
29684
|
"campaign_created"
|
|
29644
29685
|
]);
|
|
29645
|
-
var TargetCountry =
|
|
29686
|
+
var TargetCountry = z123.enum([
|
|
29646
29687
|
"CO",
|
|
29647
29688
|
"MX",
|
|
29648
29689
|
"PE",
|
|
29649
29690
|
"EC",
|
|
29650
29691
|
"CL"
|
|
29651
29692
|
]);
|
|
29652
|
-
var ResearchCategory =
|
|
29693
|
+
var ResearchCategory = z123.enum([
|
|
29653
29694
|
"auto",
|
|
29654
29695
|
"automotive",
|
|
29655
29696
|
"kitchen",
|
|
@@ -29664,7 +29705,7 @@ var ResearchCategory = z122.enum([
|
|
|
29664
29705
|
"garden",
|
|
29665
29706
|
"cleaning"
|
|
29666
29707
|
]);
|
|
29667
|
-
var HttpUrl3 =
|
|
29708
|
+
var HttpUrl3 = z123.string().url().max(2e3).refine((value) => {
|
|
29668
29709
|
try {
|
|
29669
29710
|
return [
|
|
29670
29711
|
"http:",
|
|
@@ -29674,45 +29715,45 @@ var HttpUrl3 = z122.string().url().max(2e3).refine((value) => {
|
|
|
29674
29715
|
return false;
|
|
29675
29716
|
}
|
|
29676
29717
|
}, "URL must use HTTP(S)");
|
|
29677
|
-
var ResearchCandidateOrigin =
|
|
29678
|
-
type:
|
|
29718
|
+
var ResearchCandidateOrigin = z123.object({
|
|
29719
|
+
type: z123.literal("research_candidate"),
|
|
29679
29720
|
runId: ProjectId,
|
|
29680
|
-
candidateSourceId:
|
|
29721
|
+
candidateSourceId: z123.string().min(1).max(160)
|
|
29681
29722
|
});
|
|
29682
|
-
var TaskOrigin =
|
|
29683
|
-
type:
|
|
29723
|
+
var TaskOrigin = z123.object({
|
|
29724
|
+
type: z123.literal("task"),
|
|
29684
29725
|
taskId: ProjectId
|
|
29685
29726
|
});
|
|
29686
|
-
var ManualOrigin =
|
|
29687
|
-
type:
|
|
29727
|
+
var ManualOrigin = z123.object({
|
|
29728
|
+
type: z123.literal("manual"),
|
|
29688
29729
|
clientRequestId: ProjectId,
|
|
29689
|
-
country:
|
|
29730
|
+
country: z123.string().min(2).max(3).optional()
|
|
29690
29731
|
});
|
|
29691
|
-
var StartProjectInput =
|
|
29692
|
-
origin:
|
|
29732
|
+
var StartProjectInput = z123.object({
|
|
29733
|
+
origin: z123.discriminatedUnion("type", [
|
|
29693
29734
|
ResearchCandidateOrigin,
|
|
29694
29735
|
TaskOrigin,
|
|
29695
29736
|
ManualOrigin
|
|
29696
29737
|
]),
|
|
29697
|
-
productName:
|
|
29738
|
+
productName: z123.string().trim().min(1).max(240).optional(),
|
|
29698
29739
|
productUrl: HttpUrl3.optional(),
|
|
29699
|
-
country:
|
|
29700
|
-
languageCode:
|
|
29740
|
+
country: z123.string().min(2).max(3).optional(),
|
|
29741
|
+
languageCode: z123.string().min(2).max(16).optional()
|
|
29701
29742
|
}).strict();
|
|
29702
|
-
var CostProjectInput =
|
|
29743
|
+
var CostProjectInput = z123.object({
|
|
29703
29744
|
projectId: ProjectId,
|
|
29704
|
-
version:
|
|
29705
|
-
country:
|
|
29745
|
+
version: z123.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
|
|
29746
|
+
country: z123.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
|
|
29706
29747
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
29707
29748
|
}).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
|
|
29708
|
-
supplierCost:
|
|
29709
|
-
shippingCost:
|
|
29710
|
-
returnRate:
|
|
29711
|
-
cancellationRate:
|
|
29712
|
-
adsManagerCpa:
|
|
29713
|
-
desiredMargin:
|
|
29714
|
-
});
|
|
29715
|
-
var GuideInput =
|
|
29749
|
+
supplierCost: z123.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."),
|
|
29750
|
+
shippingCost: z123.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
|
|
29751
|
+
returnRate: z123.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."),
|
|
29752
|
+
cancellationRate: z123.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."),
|
|
29753
|
+
adsManagerCpa: z123.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
|
|
29754
|
+
desiredMargin: z123.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
|
|
29755
|
+
});
|
|
29756
|
+
var GuideInput = z123.object({
|
|
29716
29757
|
projectId: ProjectId.optional()
|
|
29717
29758
|
}).strict();
|
|
29718
29759
|
var NEXT_ACTION_KINDS = [
|
|
@@ -29730,29 +29771,29 @@ var NEXT_ACTION_KINDS = [
|
|
|
29730
29771
|
"repair_meta_campaign",
|
|
29731
29772
|
"review_paused_campaign"
|
|
29732
29773
|
];
|
|
29733
|
-
var DropshippingProjectNextAction =
|
|
29734
|
-
kind:
|
|
29735
|
-
href:
|
|
29774
|
+
var DropshippingProjectNextAction = z123.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z123.object({
|
|
29775
|
+
kind: z123.literal(kind),
|
|
29776
|
+
href: z123.string().min(1)
|
|
29736
29777
|
})));
|
|
29737
|
-
var CostingInputSchema =
|
|
29738
|
-
country:
|
|
29739
|
-
supplierCost:
|
|
29740
|
-
shippingCost:
|
|
29741
|
-
returnRate:
|
|
29742
|
-
cancellationRate:
|
|
29743
|
-
adsManagerCpa:
|
|
29744
|
-
desiredMargin:
|
|
29778
|
+
var CostingInputSchema = z123.object({
|
|
29779
|
+
country: z123.string().min(2).max(3),
|
|
29780
|
+
supplierCost: z123.number().finite().positive(),
|
|
29781
|
+
shippingCost: z123.number().finite().nonnegative(),
|
|
29782
|
+
returnRate: z123.number().finite().min(0).lt(1),
|
|
29783
|
+
cancellationRate: z123.number().finite().min(0).lt(1),
|
|
29784
|
+
adsManagerCpa: z123.number().finite().nonnegative(),
|
|
29785
|
+
desiredMargin: z123.number().finite().min(0).lt(1)
|
|
29745
29786
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
29746
29787
|
if (returnRate + cancellationRate >= 1) context.addIssue({
|
|
29747
|
-
code:
|
|
29788
|
+
code: z123.ZodIssueCode.custom,
|
|
29748
29789
|
path: [
|
|
29749
29790
|
"cancellationRate"
|
|
29750
29791
|
]
|
|
29751
29792
|
});
|
|
29752
29793
|
});
|
|
29753
|
-
var FiniteCostingNumber =
|
|
29754
|
-
var CostingResultSchema =
|
|
29755
|
-
country:
|
|
29794
|
+
var FiniteCostingNumber = z123.number().finite();
|
|
29795
|
+
var CostingResultSchema = z123.object({
|
|
29796
|
+
country: z123.string().min(2).max(3),
|
|
29756
29797
|
deliveryRate: FiniteCostingNumber,
|
|
29757
29798
|
adjustedShippingCost: FiniteCostingNumber,
|
|
29758
29799
|
adjustedCpa: FiniteCostingNumber,
|
|
@@ -29765,45 +29806,45 @@ var CostingResultSchema = z122.object({
|
|
|
29765
29806
|
estimatedProfit: FiniteCostingNumber,
|
|
29766
29807
|
actualMargin: FiniteCostingNumber,
|
|
29767
29808
|
breakEvenAdsManagerCpa: FiniteCostingNumber,
|
|
29768
|
-
wasPriceAutoAdjusted:
|
|
29769
|
-
profitabilityStatus:
|
|
29770
|
-
});
|
|
29771
|
-
var RewardProgressSchema =
|
|
29772
|
-
campaignKey:
|
|
29773
|
-
totalCredits:
|
|
29774
|
-
earnedCredits:
|
|
29775
|
-
milestones:
|
|
29809
|
+
wasPriceAutoAdjusted: z123.boolean(),
|
|
29810
|
+
profitabilityStatus: z123.literal("healthy")
|
|
29811
|
+
});
|
|
29812
|
+
var RewardProgressSchema = z123.object({
|
|
29813
|
+
campaignKey: z123.literal("dropshipping-launch-v1"),
|
|
29814
|
+
totalCredits: z123.number().int().positive(),
|
|
29815
|
+
earnedCredits: z123.number().int().nonnegative(),
|
|
29816
|
+
milestones: z123.array(z123.object({
|
|
29776
29817
|
milestone: DropshippingRewardMilestone,
|
|
29777
|
-
credits:
|
|
29778
|
-
available:
|
|
29779
|
-
earned:
|
|
29818
|
+
credits: z123.number().int().positive(),
|
|
29819
|
+
available: z123.boolean().optional(),
|
|
29820
|
+
earned: z123.boolean(),
|
|
29780
29821
|
grantId: ProjectId.nullable(),
|
|
29781
|
-
grantedAt:
|
|
29822
|
+
grantedAt: z123.string().datetime().nullable()
|
|
29782
29823
|
})).length(DropshippingRewardMilestone.options.length)
|
|
29783
29824
|
});
|
|
29784
|
-
var ProjectResponseSchema =
|
|
29825
|
+
var ProjectResponseSchema = z123.object({
|
|
29785
29826
|
id: ProjectId,
|
|
29786
29827
|
taskId: ProjectId.nullable(),
|
|
29787
29828
|
status: DropshippingProjectStatus,
|
|
29788
|
-
originKey:
|
|
29829
|
+
originKey: z123.string().min(1),
|
|
29789
29830
|
researchRunId: ProjectId.nullable(),
|
|
29790
|
-
candidateSourceId:
|
|
29791
|
-
productName:
|
|
29831
|
+
candidateSourceId: z123.string().nullable(),
|
|
29832
|
+
productName: z123.string().nullable(),
|
|
29792
29833
|
productUrl: HttpUrl3.nullable(),
|
|
29793
29834
|
referenceImageUrl: HttpUrl3.nullable(),
|
|
29794
|
-
targetCountry:
|
|
29795
|
-
languageCode:
|
|
29796
|
-
hasReferenceImage:
|
|
29797
|
-
hasWinnerReferenceImage:
|
|
29835
|
+
targetCountry: z123.string().nullable(),
|
|
29836
|
+
languageCode: z123.string().nullable(),
|
|
29837
|
+
hasReferenceImage: z123.boolean(),
|
|
29838
|
+
hasWinnerReferenceImage: z123.boolean(),
|
|
29798
29839
|
costingInput: CostingInputSchema.nullable(),
|
|
29799
29840
|
costingResult: CostingResultSchema.nullable(),
|
|
29800
|
-
costingVersion:
|
|
29801
|
-
version:
|
|
29841
|
+
costingVersion: z123.number().int().positive().nullable(),
|
|
29842
|
+
version: z123.number().int().positive(),
|
|
29802
29843
|
phase: DropshippingProjectPhase,
|
|
29803
29844
|
nextAction: DropshippingProjectNextAction.nullable(),
|
|
29804
29845
|
rewards: RewardProgressSchema,
|
|
29805
|
-
createdAt:
|
|
29806
|
-
updatedAt:
|
|
29846
|
+
createdAt: z123.string().datetime(),
|
|
29847
|
+
updatedAt: z123.string().datetime()
|
|
29807
29848
|
}).passthrough();
|
|
29808
29849
|
var NEXT_ACTION_GUIDANCE = {
|
|
29809
29850
|
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.",
|
|
@@ -29923,58 +29964,58 @@ function registerDropshippingProjectTools(server, api) {
|
|
|
29923
29964
|
__name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
|
|
29924
29965
|
|
|
29925
29966
|
// src/tools/daily-control.ts
|
|
29926
|
-
import { z as
|
|
29967
|
+
import { z as z124 } from "zod";
|
|
29927
29968
|
var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
|
|
29928
29969
|
var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
|
|
29929
29970
|
var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
|
|
29930
|
-
var ProviderCampaignIdentifier =
|
|
29931
|
-
var DateOnly =
|
|
29932
|
-
var DailyControlInput =
|
|
29971
|
+
var ProviderCampaignIdentifier = z124.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
|
|
29972
|
+
var DateOnly = z124.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
29973
|
+
var DailyControlInput = z124.object({
|
|
29933
29974
|
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."),
|
|
29934
|
-
days:
|
|
29935
|
-
projectId:
|
|
29975
|
+
days: z124.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
|
|
29976
|
+
projectId: z124.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
|
|
29936
29977
|
}).strict();
|
|
29937
|
-
var LinkCampaignInput =
|
|
29938
|
-
projectId:
|
|
29939
|
-
provider:
|
|
29978
|
+
var LinkCampaignInput = z124.object({
|
|
29979
|
+
projectId: z124.string().uuid(),
|
|
29980
|
+
provider: z124.enum([
|
|
29940
29981
|
"meta",
|
|
29941
29982
|
"tiktok"
|
|
29942
29983
|
]),
|
|
29943
29984
|
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."),
|
|
29944
29985
|
campaignId: ProviderCampaignIdentifier
|
|
29945
29986
|
}).strict();
|
|
29946
|
-
var ReportReturnsInput =
|
|
29947
|
-
projectId:
|
|
29987
|
+
var ReportReturnsInput = z124.object({
|
|
29988
|
+
projectId: z124.string().uuid(),
|
|
29948
29989
|
date: DateOnly,
|
|
29949
|
-
returnedOrders:
|
|
29950
|
-
note:
|
|
29990
|
+
returnedOrders: z124.number().int().min(0).max(1e5),
|
|
29991
|
+
note: z124.string().trim().max(280).optional()
|
|
29951
29992
|
}).strict();
|
|
29952
|
-
var DailyControlStatusMirror = DailyControlStatusEnum.or(
|
|
29953
|
-
var DailyControlLightMirror = DailyControlLightEnum.or(
|
|
29954
|
-
var DailyControlSourceMirror = DailyControlSourceEnum.or(
|
|
29955
|
-
var DailyControlVerdictMirror = DailyControlVerdictEnum.or(
|
|
29956
|
-
var DailyControlDayMirror =
|
|
29957
|
-
date:
|
|
29958
|
-
returnedOrders:
|
|
29993
|
+
var DailyControlStatusMirror = DailyControlStatusEnum.or(z124.string());
|
|
29994
|
+
var DailyControlLightMirror = DailyControlLightEnum.or(z124.string());
|
|
29995
|
+
var DailyControlSourceMirror = DailyControlSourceEnum.or(z124.string());
|
|
29996
|
+
var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z124.string());
|
|
29997
|
+
var DailyControlDayMirror = z124.object({
|
|
29998
|
+
date: z124.string(),
|
|
29999
|
+
returnedOrders: z124.number(),
|
|
29959
30000
|
returnedSource: DailyControlSourceMirror,
|
|
29960
30001
|
cancelledSource: DailyControlSourceMirror,
|
|
29961
|
-
hasEstimates:
|
|
30002
|
+
hasEstimates: z124.boolean(),
|
|
29962
30003
|
light: DailyControlLightMirror
|
|
29963
30004
|
}).passthrough();
|
|
29964
|
-
var DailyControlProductMirror =
|
|
29965
|
-
projectId:
|
|
29966
|
-
productName:
|
|
30005
|
+
var DailyControlProductMirror = z124.object({
|
|
30006
|
+
projectId: z124.string().uuid(),
|
|
30007
|
+
productName: z124.string().nullable(),
|
|
29967
30008
|
status: DailyControlStatusMirror,
|
|
29968
|
-
statusMessage:
|
|
29969
|
-
days:
|
|
30009
|
+
statusMessage: z124.string().nullable(),
|
|
30010
|
+
days: z124.array(DailyControlDayMirror),
|
|
29970
30011
|
verdict: DailyControlVerdictMirror.nullable(),
|
|
29971
|
-
rationale:
|
|
30012
|
+
rationale: z124.string().nullable()
|
|
29972
30013
|
}).passthrough();
|
|
29973
|
-
var DailyControlResponseMirror =
|
|
29974
|
-
since:
|
|
29975
|
-
until:
|
|
29976
|
-
products:
|
|
29977
|
-
archivedProjectSpend:
|
|
30014
|
+
var DailyControlResponseMirror = z124.object({
|
|
30015
|
+
since: z124.string(),
|
|
30016
|
+
until: z124.string(),
|
|
30017
|
+
products: z124.array(DailyControlProductMirror),
|
|
30018
|
+
archivedProjectSpend: z124.array(z124.unknown())
|
|
29978
30019
|
}).passthrough();
|
|
29979
30020
|
var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
|
|
29980
30021
|
function withWarnings(response) {
|
|
@@ -30049,7 +30090,7 @@ __name(registerDailyControlTools, "registerDailyControlTools");
|
|
|
30049
30090
|
// src/tools/product-control.ts
|
|
30050
30091
|
import { readFile, stat } from "fs/promises";
|
|
30051
30092
|
import { basename as basename2, isAbsolute, resolve as resolve3 } from "path";
|
|
30052
|
-
import { z as
|
|
30093
|
+
import { z as z125 } from "zod";
|
|
30053
30094
|
var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
|
|
30054
30095
|
var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
|
|
30055
30096
|
var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
|
|
@@ -30062,36 +30103,36 @@ var createOperationGuidance = getProductMakerCapabilityModelGuidance("create_ope
|
|
|
30062
30103
|
var mergeProductsGuidance = getProductMakerCapabilityModelGuidance("merge_products");
|
|
30063
30104
|
var syncShopifyOrdersGuidance = getProductMakerCapabilityModelGuidance("sync_shopify_orders");
|
|
30064
30105
|
var importOrdersFileGuidance = getProductMakerCapabilityModelGuidance("import_orders_file");
|
|
30065
|
-
var DateOnly2 =
|
|
30106
|
+
var DateOnly2 = z125.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
30066
30107
|
var IMPORT_BATCH_MAX2 = 50;
|
|
30067
|
-
var ProductControlListInput =
|
|
30068
|
-
days:
|
|
30108
|
+
var ProductControlListInput = z125.object({
|
|
30109
|
+
days: z125.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
|
|
30069
30110
|
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."),
|
|
30070
|
-
shopDomain:
|
|
30111
|
+
shopDomain: z125.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
|
|
30071
30112
|
}).strict();
|
|
30072
|
-
var ImportableProductsInput =
|
|
30073
|
-
q:
|
|
30074
|
-
after:
|
|
30075
|
-
shopDomain:
|
|
30113
|
+
var ImportableProductsInput = z125.object({
|
|
30114
|
+
q: z125.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
|
|
30115
|
+
after: z125.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
|
|
30116
|
+
shopDomain: z125.string().min(1).optional()
|
|
30076
30117
|
}).strict();
|
|
30077
|
-
var ImportProductControlsInput =
|
|
30078
|
-
shopifyProductIds:
|
|
30118
|
+
var ImportProductControlsInput = z125.object({
|
|
30119
|
+
shopifyProductIds: z125.array(z125.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."),
|
|
30079
30120
|
// Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
|
|
30080
30121
|
// sin decir a cuál archivaría el producto bajo la tienda equivocada.
|
|
30081
|
-
shopDomain:
|
|
30122
|
+
shopDomain: z125.string().min(1)
|
|
30082
30123
|
}).strict();
|
|
30083
|
-
var SetProductCostingInput =
|
|
30084
|
-
shopDomain:
|
|
30085
|
-
shopifyProductId:
|
|
30086
|
-
targetCountry:
|
|
30087
|
-
supplierCost:
|
|
30088
|
-
shippingCost:
|
|
30089
|
-
returnRate:
|
|
30090
|
-
cancellationRate:
|
|
30124
|
+
var SetProductCostingInput = z125.object({
|
|
30125
|
+
shopDomain: z125.string().min(1),
|
|
30126
|
+
shopifyProductId: z125.string().min(1).max(64),
|
|
30127
|
+
targetCountry: z125.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
|
|
30128
|
+
supplierCost: z125.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
|
|
30129
|
+
shippingCost: z125.number().finite().nonnegative(),
|
|
30130
|
+
returnRate: z125.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
|
|
30131
|
+
cancellationRate: z125.number().finite().min(0).lt(1)
|
|
30091
30132
|
}).strict();
|
|
30092
|
-
var Count =
|
|
30093
|
-
var ReportProductCountsInput =
|
|
30094
|
-
productControlId:
|
|
30133
|
+
var Count = z125.number().int().min(0).max(1e5).nullable().optional();
|
|
30134
|
+
var ReportProductCountsInput = z125.object({
|
|
30135
|
+
productControlId: z125.string().uuid().describe("El identificador que devuelve get_product_control."),
|
|
30095
30136
|
date: DateOnly2,
|
|
30096
30137
|
orders: Count.describe("Pedidos que entraron ese d\xEDa."),
|
|
30097
30138
|
cancelledOrders: Count,
|
|
@@ -30101,36 +30142,36 @@ var ReportProductCountsInput = z124.object({
|
|
|
30101
30142
|
}).strict();
|
|
30102
30143
|
var MAX_ORDERS_FILE_BYTES = 8 * 1024 * 1024;
|
|
30103
30144
|
var SyncShopifyOrdersInput = SyncShopifyOrdersSchema;
|
|
30104
|
-
var ImportOrdersFileInput =
|
|
30145
|
+
var ImportOrdersFileInput = z125.object({
|
|
30105
30146
|
/** Ruta ABSOLUTA en la máquina de quien usa el MCP. */
|
|
30106
|
-
path:
|
|
30107
|
-
operationId:
|
|
30147
|
+
path: z125.string().min(1),
|
|
30148
|
+
operationId: z125.string().uuid().optional(),
|
|
30108
30149
|
/** Solo mirar: devuelve el resumen y no escribe nada. */
|
|
30109
|
-
dryRun:
|
|
30150
|
+
dryRun: z125.boolean().optional()
|
|
30110
30151
|
}).strict();
|
|
30111
|
-
var CreateOperationInput =
|
|
30112
|
-
countryCode:
|
|
30113
|
-
label:
|
|
30152
|
+
var CreateOperationInput = z125.object({
|
|
30153
|
+
countryCode: z125.string().length(2),
|
|
30154
|
+
label: z125.string().trim().min(1).max(60).optional()
|
|
30114
30155
|
}).strict();
|
|
30115
|
-
var MergeProductsInput =
|
|
30116
|
-
sourceId:
|
|
30117
|
-
targetId:
|
|
30156
|
+
var MergeProductsInput = z125.object({
|
|
30157
|
+
sourceId: z125.string().uuid(),
|
|
30158
|
+
targetId: z125.string().uuid()
|
|
30118
30159
|
}).strict();
|
|
30119
|
-
var SetMonthlyExpenseInput =
|
|
30120
|
-
month:
|
|
30160
|
+
var SetMonthlyExpenseInput = z125.object({
|
|
30161
|
+
month: z125.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
|
|
30121
30162
|
label: SaveMonthlyExpenseSchema.shape.label,
|
|
30122
|
-
amount:
|
|
30123
|
-
operationId:
|
|
30163
|
+
amount: z125.number().finite().min(0),
|
|
30164
|
+
operationId: z125.string().uuid().optional()
|
|
30124
30165
|
}).strict();
|
|
30125
|
-
var SetAdSpendInput =
|
|
30126
|
-
month:
|
|
30127
|
-
operationId:
|
|
30166
|
+
var SetAdSpendInput = z125.object({
|
|
30167
|
+
month: z125.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).optional(),
|
|
30168
|
+
operationId: z125.string().uuid().optional(),
|
|
30128
30169
|
/** null RETIRA la corrección; cero afirma que no pautó. */
|
|
30129
|
-
amount:
|
|
30170
|
+
amount: z125.number().finite().min(0).nullable()
|
|
30130
30171
|
}).strict();
|
|
30131
|
-
var GetFinancesInput =
|
|
30132
|
-
month:
|
|
30133
|
-
operationId:
|
|
30172
|
+
var GetFinancesInput = z125.object({
|
|
30173
|
+
month: z125.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."),
|
|
30174
|
+
operationId: z125.string().uuid().optional().describe("El negocio, si tiene mas de uno. Con uno solo no hace falta decirlo.")
|
|
30134
30175
|
}).strict();
|
|
30135
30176
|
function registerProductControlTools(server, api, { transport = "http" } = {}) {
|
|
30136
30177
|
server.registerTool("get_product_control", {
|
|
@@ -30320,28 +30361,28 @@ function registerProductControlTools(server, api, { transport = "http" } = {}) {
|
|
|
30320
30361
|
__name(registerProductControlTools, "registerProductControlTools");
|
|
30321
30362
|
|
|
30322
30363
|
// src/tools/market-study-estimate.ts
|
|
30323
|
-
import { z as
|
|
30364
|
+
import { z as z126 } from "zod";
|
|
30324
30365
|
var estimateMarketStudyGuidance = getProductMakerCapabilityModelGuidance("estimate_market_study_cost");
|
|
30325
|
-
var ProductTaskOutputEnum =
|
|
30366
|
+
var ProductTaskOutputEnum = z126.enum([
|
|
30326
30367
|
"landing",
|
|
30327
30368
|
"video",
|
|
30328
30369
|
"image"
|
|
30329
30370
|
]);
|
|
30330
|
-
var EstimateMarketStudyInput =
|
|
30331
|
-
kind:
|
|
30371
|
+
var EstimateMarketStudyInput = z126.object({
|
|
30372
|
+
kind: z126.enum([
|
|
30332
30373
|
"video",
|
|
30333
30374
|
"product_task"
|
|
30334
30375
|
]).describe('"video" para generate_video_creative; "product_task" para create_product_task.'),
|
|
30335
|
-
videoAngleCount:
|
|
30336
|
-
durationSeconds:
|
|
30376
|
+
videoAngleCount: z126.number().int().min(1).max(3).describe("Los mismos 1, 2 o 3 videos que vas a pedir al crear."),
|
|
30377
|
+
durationSeconds: z126.number().int().min(4).max(30).default(15).describe("La misma duraci\xF3n que enviar\xE1s al crear."),
|
|
30337
30378
|
videoStructure: VideoStructureEnum.default("single_take"),
|
|
30338
30379
|
videoQuality: VideoQualityEnum.default("economy"),
|
|
30339
30380
|
videoResolution: VideoResolutionEnum.default("480p"),
|
|
30340
|
-
productImageCount:
|
|
30381
|
+
productImageCount: z126.number().int().min(1).max(5).optional().describe("Cantidad de fotos del producto que adjuntar\xE1s (1-5)."),
|
|
30341
30382
|
outputs: ProductTaskOutputEnum.array().min(1).max(3).optional().describe('Solo para kind="product_task": los mismos outputs de create_product_task. Default: todos.'),
|
|
30342
|
-
generateAiMusic:
|
|
30383
|
+
generateAiMusic: z126.boolean().optional(),
|
|
30343
30384
|
generateAiEdit: AiEditRequestSchema.optional(),
|
|
30344
|
-
replicateWinnerWhenFound:
|
|
30385
|
+
replicateWinnerWhenFound: z126.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.")
|
|
30345
30386
|
}).strict();
|
|
30346
30387
|
function buildMarketStudyEstimateRequests(input) {
|
|
30347
30388
|
const quotesVideo = input.kind === "video" || (input.outputs ?? [
|